はじめに
本記事はAWSのサービスを使ってCI/CD環境を構築する際に私が実施した手順をメモしたものである。似たような記事は既にいくつか存在するが、 この記事を見たらハマることなくCI/CD環境を構築できた! というものがなく結構苦労したので、個人的な備忘録も兼ねて記事を書くことにした。
前提
以下ではAWSのアカウントは既に取得済みであるとして話を進める。
アカウントを取得していない場合は AWSアカウントを取得したら速攻でやっておくべき初期設定まとめ を参照してIAMユーザーを作成しておくこと。本記事では、上記記事の 管理用のIAMユーザ作成 で作成したユーザーを利用している。
全体像
本記事で実現したいことの全体像を掲載する。下記イメージは CodePipeline で CodeCommit/CodeBuild/CodeDeploy を繋げてデリバリプロセスを自動化してみた #reinvent から拝借した。
IAMユーザーにポリシーをアタッチする
IAMのページを開き、左メニューにある「ユーザー」を選択する。
IAMユーザーに AmazonS3FullAccess と AWSCodeDeployFullAccess のポリシーをアタッチする。前者はS3に関する全権限を、後者はCodeDeployに関する全権限をIAMユーザーに付与するポリシーである。
以上でポリシーのアタッチは終了である。
CodeCommitにリポジトリを作成する
「サービス」を選択して「codecommit」と入力すると表示される「CodeCommit」をクリックする。
「リポジトリ名」に任意の名前(ここでは CodeDeploySample とする)を入力して、「作成」ボタンを押下する。
先ほど作成したリポジトリが表示されれば、CodeCommitにリポジトリを作成する作業は終了である。
S3バケットを作成する
「サービス」を選択して「s3」と入力すると表示される「S3」をクリックする。
「バケット名」に任意の名前(ここでは bucket-for-code-deploy とする)を入力して「次へ」ボタンを押下する。
「オプションの設定」と「アクセス許可の設定」は全て デフォルト の設定を利用する。
以上でS3バケットを作成する作業は終了である。
CodeBuildにビルドプロジェクトを作成する
「サービス」を選択して「codebuild」と入力すると表示される「CodeBuild」をクリックする。
「プロジェクトの設定」の「プロジェクト名」に任意の名前(ここでは CodeBuildSample とする)を入力する。 追加設定は不要 である。
「送信元」の「ソースプロバイダ」に AWS CodeCommit を、「リポジトリ」に先ほど作成したリポジトリ CodeDeploySample を設定する。 追加設定は不要 である。
「環境」の「オペレーティングシステム」に Ubuntu を、「ランタイム」に Standard を、「イメージ」に aws/codebuild/standard:2.0 を、「イメージのバージョン」に aws/codebuild/standard:2.0-1.10.0 を設定する。その他の項目は デフォルト の設定を利用する。
「Buildspec」は全て デフォルト の設定を利用する。
「アーティファクト」の「タイプ」に Amazon S3 を、「バケット名」に先ほど作成したS3バケット名 bucket-for-code-deploy を設定する。その他の項目は デフォルト の設定を利用する。
以上の設定が済んだら「ビルドプロジェクトを作成する」ボタンを押下すると、ビルドプロジェクトが作成される。
以上でビルドプロジェクトを作成する作業は終了である。
デプロイ先のEC2インスタンスを作成する
「サービス」を選択して「ec2」と入力すると表示される「EC2」をクリックする。
インスタンスタイプとして 無料利用枠の対象 となっているものを選択して、「5. タグの追加」をクリックする。
「キー」と「値」に任意の値(ここでは deploy と code-deploy とする)を設定して、「6. セキュリティグループの設定」をクリックする。
「ルールの追加」ボタンを押下してタイプ「カスタムTCP」を追加する(ポート範囲を 8080 とする)。追加したら「7. 確認」をクリックする。
新しいキーペアの作成 を選択して「キーペア名」に任意の設定(ここでは code-deploy とする)を入力して、「キーペアのダウンロード」ボタンを押下する。ダウンロードすると「インスタンスの作成」ボタンが押下できるようになるので、「インスタンスの作成」ボタンを押下する。
ダウンロードしたファイル( code-deploy.pem )を任意のディレクトリ(ここでは ~/.ssh/
とする)に移動する。
以上でデプロイ先のEC2インスタンスを作成する作業は終了である。
CodeDeploy用のロールを作成する
「サービス」を選択して「iam」と入力すると表示される「IAM」をクリックする。
ロールを使用するサービスとして、画面下にある「CodeDeploy」を選択する。選択すると「ユースケースの選択」が表示されるので「CodeDeploy」を選択して、「次のステップ:アクセス権限」ボタンを押下する。
「ロール名」に任意の設定(ここでは CodeDeployRoleAPI とする)を入力して、「ロールの作成」ボタンを押下する。
以上でCodeDeploy用のロールを作成する作業は終了である。
CodeDeployエージェントをEC2インスタンスにインストールする
「サービス」を選択して「ec2」と入力すると表示される「EC2」をクリックする。
左メニューにある「インスタンス」をクリックする。対象のEC2インスタンスが起動していない場合は「アクション」ボタンを押下して「インスタンスの状態」 → 「開始」を選択して、EC2インスタンスが起動するのを待つ。EC2インスタンスが起動したら「パブリック DNS(IPv4)」の値をコピーする。
ターミナルから以下のコマンドを実行してEC2インスタンスにsshログインする。下記コマンドの ~/.ssh/code-deploy.pem
は「デプロイ先のEC2インスタンスを作成する」でダウンロードしたファイル名に合わせて修正をする。また <your-public-dns>
には先ほどコピーした値を入力する。
$ ssh -i ~/.ssh/code-deploy.pem ec2-user@<your-public-dns>
以下のようなアクセス権エラーが出た場合は $ chmod 700 ~/.ssh/code-deploy.pem
として権限を付与する。
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for 'code-deploy.pem' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "code-deploy.pem": bad permissions
sshログインできたら以下のコマンドを実行してCodeDeployエージェントをインストールする。
$ sudo yum update
$ sudo yum install ruby
$ cd /home/ec2-user
$ wget https://aws-codedeploy-us-east-1.s3.amazonaws.com/latest/install
$ chmod +x ./install
$ sudo ./install auto
以上でCodeDeployエージェントをEC2インスタンスにインストールする作業は終了である。
EC2インスタンスのロールを作成する
「サービス」を選択して「ec2」と入力すると表示される「EC2」をクリックする。
対象のEC2インスタンスを選択して右クリック「インスタンスの設定」 → 「IAMロールの割り当て/置換」を選択する。
「EC2」を選択して「次のステップ:アクセス権限」ボタンを押下する。
「JSON」タブを選択して下記のJSONを入力後に「ポリシーの確認」ボタンを押下する。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": [
"arn:aws:s3:::codedeploy-bucket/*",
"arn:aws:s3:::aws-codedeploy-us-east-2/*",
"arn:aws:s3:::aws-codedeploy-us-east-1/*",
"arn:aws:s3:::aws-codedeploy-us-west-1/*",
"arn:aws:s3:::aws-codedeploy-us-west-2/*",
"arn:aws:s3:::aws-codedeploy-ca-central-1/*",
"arn:aws:s3:::aws-codedeploy-eu-west-1/*",
"arn:aws:s3:::aws-codedeploy-eu-west-2/*",
"arn:aws:s3:::aws-codedeploy-eu-west-3/*",
"arn:aws:s3:::aws-codedeploy-eu-central-1/*",
"arn:aws:s3:::aws-codedeploy-ap-northeast-1/*",
"arn:aws:s3:::aws-codedeploy-ap-northeast-2/*",
"arn:aws:s3:::aws-codedeploy-ap-southeast-1/*",
"arn:aws:s3:::aws-codedeploy-ap-southeast-2/*",
"arn:aws:s3:::aws-codedeploy-ap-south-1/*",
"arn:aws:s3:::aws-codedeploy-sa-east-1/*"
]
}
]
}
「名前」に任意の名前(ここでは CodeDeploy-EC2-PermissionsAPI とする)を入力して、「ポリシーの作成」ボタンを押下する。
再度「ロールの作成」画面に戻り、先ほど作成したポリシー CodeDeploy-EC2-PermissionsAPI にチェックを入れる(「ポリシーのフィルタ」でフィルタリングすると見つけやすい)。続いて AmazonEC2RoleforAWSCodeDeploy にもチェックを入れて、「次のステップ:タグ」ボタンを押下する。
「ロール名」に任意の名前(ここでは CodeDeploy-EC2-Instance-Profile-API とする)を入力して、「ロールの作成」ボタンを押下する。
再度「IAM ロールの割り当て/置換」画面を開き、「IAMロール」に先ほど作成したロールを指定して、「適用」ボタンを押下する。
EC2インスタンスにsshログインしているターミナルから以下のコマンドを実行して、CodeDeployエージェントを再起動する。再起動する理由は IAM Roleを後からアタッチしたEC2でAWS CodeDeployに失敗する ことを防ぐため。
$ sudo service codedeploy-agent restart
以上でEC2インスタンスのロールを作成する作業は終了である。
CodeDeployの設定をする
「サービス」を選択して「codedeploy」と入力すると表示される「CodeDeploy」をクリックする。
左メニューにある「開始方法」を選択して、「アプリケーションの作成」ボタンを押下する。
「アプリケーション名」に任意の名前(ここでは CodeDeploySample とする)を、「コンピューティングプラットフォーム」に EC2/オンプレミス を設定したら、「アプリケーションの作成」ボタンを押下する。
アプリケーションの作成に成功したら「デプロイグループの作成」ボタンを押下する。
「デプロイグループ名」に任意の名前(ここでは CodeDeploySampleGroup とする)を入力する。
「サービスロール」に「CodeDeploy用のロールを作成する」で作成したロール( CodeDeployRoleAPI )を設定する。
Amazon EC2インスタンス にチェックを入れて、「タググループ 1」の「キー」と「値」に、「デプロイ先のEC2インスタンスを作成する」で設定した値( deploy と code-deploy )を設定する。
「デプロイタイプ」は デフォルト の設定値を利用する。
「ロードバランサー」は 無効 にする。
以上の設定が終了したら「デプロイグループを作成する」ボタンを押下して、CodeDeployの設定をする作業は終了である。
CodeCommitの設定をする
IAMのページを開き、左メニューにある「ユーザー」を選択する。
「認証情報」タブを開いて、「アクセスキーの作成」ボタンを押下する。このあと必要になるため、 アクセスキー と シークレットアクセスキー をメモしておく。
ターミナルから以下のコマンドを実行して awscli
をインストールする。
$ brew install awscli
続いて以下のコマンドを実行する。途中でキー情報を聞かれるので、先ほどメモした内容を回答する。リージョンには ap-northeast-1 を、「デフォルトのアウトプットフォーマット」には json を回答する。
$ aws configure
続いて以下2つのコマンドを実行する。
$ git config --global credential.helper '!aws codecommit credential-helper $@'
$ git config --global credential.UseHttpPath true
最後に macユーザーの方のみ、 gitのcredential.helperを理解してCodeCommitの403エラーを回避してみた の「対処法」に記載の内容を実施する。
以上でCodeCommitの設定をする作業は終了である。
サンプルプロジェクトを用意する
EC2インスタンスにデプロイする用のサンプルプロジェクトを用意する。プロジェクトは各自がデプロイしたいものを使って構わないが、ここでは GitHub にある Spring Boot
で作成したHello Worldをサンプルプロジェクトとする。
用意したプロジェクトには、以下2つのファイルが含まれていなくてはならない。配置場所はプロジェクトのルートディレクトリである必要がある。
-
buildspec.yml
- ビルドの設定を記述するファイルである
- ファイルの中身は必要に応じて修正すること
-
appspec.yml
- デプロイの設定を記述するファイルである
- ファイルの中身は必要に応じて修正すること
また、本サンプルプロジェクトでは、アプリケーションを起動する際に実行するスクリプト(本サンプルでは何もしない)を scripts/start_hello_spring_boot.sh
に配置してある。こちらも必要に応じて各自用意・修正すること。
用意したサンプルプロジェクトを「CodeCommitにリポジトリを作成する」で作成したリポジトリ( CodeDeploySample )に push
する。
以上でサンプルプロジェクトを用意する作業は終了である。
CodePipelineの設定をする
「サービス」を選択して「codepipeline」と入力すると表示される「CodePipeline」をクリックする。
左メニューにある「開始方法」を選択して、「パイプラインの作成」ボタンを押下する。
「パイプライン名」に任意の名前(ここでは CodePipelineSample とする)を入力して、「次に」ボタンを押下する。
「ソースプロバイダー」に AWS CodeCommit を、「リポジトリ名」に「CodeCommitにリポジトリを作成する」で作成したリポジトリ名( CodeDeploySample )を、「ブランチ名」に任意のブランチ名(ここでは master とする)を設定する。設定が完了したら「次に」ボタンを押下する。
「プロバイダーを構築する」に AWS CodeBuild を、「リージョン」に アジアパシフィック(東京) を、「プロジェクト名」に「CodeBuildにビルドプロジェクトを作成する」で作成したプロジェクト名( CodeBuildSample )を設定する。設定が完了したら「次に」ボタンを押下する。
「デプロイプロバイダー」に AWS CodeCommit を、「リージョン」に アジアパシフィック(東京) を、「アプリケーション名」と「デプロイグループ」には「CodeDeployの設定をする」で設定した値( CodeDeploySample と CodeDeploySampleGroup )をそれぞれ設定する。設定が完了したら「次に」ボタンを押下する。
「パイプラインを作成する」ボタンを押下すると、ビルド・デプロイが実行される。
全て成功すればCI/CD環境の構築は完了である。もしエラーが出た場合はEC2インスタンスにログインをして、ログファイル /var/log/aws/codedeploy-agent/codedeploy-agent.log
の情報をもとにエラーを解決する。