本連載では、AWSリソース基盤構築の自動化を実践しています。現在は、第2回から解説してきた継続的インテグレーション環境をCloudFormationを使って自動構築する方法について解説しています。
前回は、LambdaをデプロイするCloudFormationやLambdaファンクションを実行するカスタムリソーステンプレートを作成/実行しました。続く今回は、SonarQubeServerの起動スクリプトやDockerfile、ECSタスク、サービステンプレートを作成し、サーバを起動してみます。
なお、実際のソースコードはGitHub上にコミットしています。以降のソースコードでは本質的でない記述を一部省略しているので、実行コードを作成する場合は、必要に応じて適宜GitHub上のソースコードも参照してください。
SonarQubeServerを起動するスクリプトとDockerfile
既に第2回でDockerfileや起動スクリプトは実装しましたが、自動構築するにあたり、RDSへ接続するためのエンドポイントやパスワードはCloudFormationのスタックやSystems Manager Parameter Storeから取得する方法に変えています。そのため、以下のように起動スクリプトを変更します。
#!/usr/bin/env bash
# omit
# エンドポイントとユーザー名をECSの環境変数として受け取り、SONARQUBE_JDBC_URLとして定義
export SONARQUBE_JDBC_URL="jdbc:postgresql://$SONARQUBE_RDS_ENDPOINT/$SONARQUBE_RDS_USERNAME"
# omit
exec java -jar lib/sonar-application-$SONAR_VERSION.jar \
-Dsonar.log.console=true \
-Dsonar.jdbc.username="$SONARQUBE_RDS_USERNAME" \
-Dsonar.jdbc.password="$SONARQUBE_RDS_PASSWORD" \
-Dsonar.jdbc.url="$SONARQUBE_JDBC_URL" \
-Dsonar.web.javaAdditionalOpts="$SONARQUBE_WEB_JVM_OPTS -Djava.security.egd=file:/dev/./urandom" \
"${sq_opts[@]}" \
"$@"
また、Dockerfileではエンドポイントやパスワードなどを、ECSタスク定義からは環境変数を取得するため、従来の変数の設定をやめてユーザー名とホームディレクトリ以外を削除します。
# omit
ENV SONAR_VERSION=7.7 \
SONARQUBE_HOME=/usr/local/sonarqube \
SONARQUBE_RDS_USERNAME=sonar
# omit
第2回同様、Docker buildコマンドを実行して新しくコンテナイメージをビルドし、DockerHubへプッシュしておきます。
SobarQubeECSタスク定義とターゲットグループ、ECSサービスのテンプレート
次に、ECSタスク定義とターゲットグループのテンプレートを作成します。実装したものはGitHub上にコミットしていますが、このテンプレートの内容は第39回で解説したものとほぼ同じです。ただし、ECSタスク定義やECSサービスは以下の通り、コンテナイメージやポート、環境変数、シークレットパラメータの設定を変更して実装しています。
#omit
Mappings:
SonarQubeTaskDefinitionMap:
Task:
"Memory" : 2048
"Cpu" : 1024
"ContainerName" : "debugroom-mynavi-sonarqube-cfn-server"
"ContainerImage" : "debugroom/sonarqube-server-cfn:latest"
"ContainerPort" : 9000
"HostPort" : 0
"ContainerMemory" : 2048
"Profile" : "dev"
# omit
SonarQubeECSTaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: sonarqube-server
RequiresCompatibilities:
- EC2
Memory: !FindInMap [SonarQubeTaskDefinitionMap, Task, Memory]
Cpu: !FindInMap [SonarQubeTaskDefinitionMap, Task, Cpu]
NetworkMode: bridge
ExecutionRoleArn: !GetAtt ECSTaskExecutionRole.Arn
TaskRoleArn: !GetAtt SonarQubeECSTaskRole.Arn
ContainerDefinitions:
- Name: !FindInMap [SonarQubeTaskDefinitionMap, Task, ContainerName]
Image: !FindInMap [SonarQubeTaskDefinitionMap, Task, ContainerImage]
PortMappings:
- ContainerPort: !FindInMap [SonarQubeTaskDefinitionMap, Task, ContainerPort]
HostPort: !FindInMap [SonarQubeTaskDefinitionMap, Task, HostPort]
Memory: !FindInMap [SonarQubeTaskDefinitionMap, Task, ContainerMemory]
Environment:
- Name: SONARQUBE_RDS_ENDPOINT
Value:
Fn::ImportValue: !Sub ${VPCName}-RDS-Endpoint
Secrets:
- Name: SONARQUBE_RDS_PASSWORD
ValueFrom: !Sub "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/mynavi-sonarqube-rds-sonar-password"
# omit
# omit
Resources:
SonarQubeService:
Type: AWS::ECS::Service
Properties:
Cluster:
Fn::ImportValue: !Sub ${VPCName}-PublicEcsCluster
DesiredCount: 1
HealthCheckGracePeriodSeconds: 60
TaskDefinition:
Fn::ImportValue: !Sub ${VPCName}-SonarQubeEcsTaskDefinition
LaunchType: EC2
LoadBalancers:
- ContainerName: "debugroom-mynavi-sonarqube-cfn-server"
ContainerPort: 9000
TargetGroupArn:
Fn::ImportValue: !Sub ${VPCName}-SonarQube-TargetGroup
このテンプレートを実行すると、SonarQubeServerが起動します。
なお、実行時にエラーが発生した場合は、Systems Manager/Session ManagerでECSクラスタへログインし、Docker logsコマンドなどで起動エラーになった原因を調べることが可能です。
* * *
今回は、SonarQubeServerを起動するCloudFormationテンプレートを実装し、起動するところまで説明しました。次回以降は、AWS CodeBuildを使ったアプリケーションのビルドをCloudFormationを使って自動化してみます。
著者紹介
川畑 光平(KAWABATA Kohei) - NTTデータ
金融機関システム業務アプリケーション開発・システム基盤担当、ソフトウェア開発自動化関連の研究開発を経て、デジタル技術関連の研究開発・推進に従事。
Red Hat Certified Engineer、Pivotal Certified Spring Professional、AWS Certified Solutions Architect Professional等の資格を持ち、アプリケーション基盤・クラウドなど様々な開発プロジェクト支援にも携わる。AWS Top Engineers & Ambassadors選出。
本連載の内容に対するご意見・ご質問は Facebook まで。