- 自分の AWS アカウントのコンソールにログインする。(できれば EC2-Classic に対応していないアカウントが望ましいです)
- 東京リージョンのコンソールが表示されるようにしておく
- 自分の GitHub アカウントにログインする。
- Git をインストール及びセットアップする。(自分の自分のリポジトリからのクローンおよびプッシュが行える状態にしておいてください。)
- コンソールから起動しコードの編集が行えるエディタ(Vim, Emacs, VSCode 等)
CodePipeline を使用してデプロイの自動化が簡単に行えることを体感していただき、実際にデプロイの自動化に取り組むきっかけにしていただく。
$1 未満
- 構成の簡単な紹介
- サンプルアプリケーションのフォーク及びクローン
- ハンズオン用環境構築用の CloudFormation の実行
- 手動デプロイしてみる(講師が実演します)
- CodePipeline によるパイプラインの構築および自動デプロイの実行
- テストが失敗すると自動デプロイが止まるのを確認
- 再度正しいコードに戻して自動デプロイ
今回は上記の図のような構成を構築します。
- GitHub にコードがプッシュされると CodePipeline での処理が開始されます。
- CodeBuild ではテスト、Docker イメージの作成および作成したイメージの ECR へのプッシュを行います。
- CodeBuild での処理が成功したら ECS に新しいバージョンのイメージがデプロイされます。
まずは、このリポジトリをフォークし、自分のアカウントにリポジトリを作成します。 サンプルアプリケーションは、Laravel のサンプルコードのタスク管理システムをほぼそのまま使用しました。
このリポジトリの右上の Fork
というボタンからフォークを実行します。
自分の GitHub アカウント上に作成されたフォークしたリポジトリから、ローカルの PC にクローンします。 作業用のディレクトリで以下のコマンドを実行します。
$ git clone [email protected]:<ご自分のgithubのアカウント名>/ci-cd-hands-on-laravel.git
クローンされたリポジトリのディレクトリに移動して中身を確認し、クローンが正しく行われたことを確認します。
$ cd ci-cd-handson-laravel
$ ls
README.md cloudformation nginx
buildspec.pr.yml codebuild_build.sh src
buildspec.yml laravel template
今回 ECS でアプリケーションを動作させるにあたってサービスにリンクしたロールが作成されている必要があります。
そのため、IAM のコンソールを開き、AWSServiceRoleForECS
というロールがあるかを確認してください。
ない場合はサービスにリンクしたロールがない状態ですので、タスクが失敗してしまいます。
その場合は、以下のコマンドを実行するか
aws iam create-service-linked-role --aws-service-name ecs.amazonaws.com
空の ECS のクラスタを作成し、すぐに削除するなどして ECS のサービスにリンクしたロールが作成された状態にします。
上のリンクより、ハンズオン用の環境を構築するための CloudFormation を実行します。
この、CloudFormation によって、以下の図ような構成の環境が作成されます。
アプリケーションの動作環境以外に後で CodeBuild で使用するための IAM Role を作成しています。
作成したスタックが CREATE_COMPLETE
の状態になるまで待ちます。
作成したスタックの出力にALBDNSName
というキーで出力された値が、今回のサンプルアプリケーションのアクセス先の URL です。アドレスバーにコピペして、サンプルアプリケーションの動作を確認します。
ecs-deploy のようなデプロイに便利なツールもありますが、CodeBuild で行う処理との対比をわかりやすくするため、ここではそういったものは使わずにデプロイを実行します。
まずはデプロイされたことがわかりやすくするため、画面を修正します。
$ composer install
$ vim template/views/index.ejs
$ composer run test
$ git commit -am "manual deploy"
つぎに以下のコマンドを実行し、手動でデプロイを実行します。
まず、手元で Docker イメージを構築し、ECR にプッシュします。
$ cd laravel
$ $(aws ecr get-login --no-include-email --region ap-northeast-1)
$ IMAGE_REPOSITORY_NAME=`aws ssm get-parameter --name "IMAGE_REPOSITORY_NAME"| jq -r .Parameter.Value`
$ IMAGE_TAG=`git rev-parse HEAD`
$ docker build -t $IMAGE_REPOSITORY_NAME:$IMAGE_TAG .
$ docker push $IMAGE_REPOSITORY_NAME:$IMAGE_TAG
$ echo $IMAGE_REPOSITORY_NAME:$IMAGE_TAG
ECS の設定の修正で使用するため、イメージをプッシュしたリポジトリとタグの値を覚えておきます。
ここまでの操作の中でも、プッシュする対象とは異なるブランチで作業を行っていた場合や、リモートブランチとの同期を忘れるなどした場合には意図したものとは異なるソースコードをデプロイしてしまうリスクがあります。
つぎに、コンソールの操作に移り、実際に ECS へのデプロイを行っていきます。
マネジメントコンソールから ECS の画面に移動します。
まず、タスク定義の新しいリビジョンを作成します。
環境構築用スタックによって作成されたタスクの新しいリビジョンの作成画面を表示します。 コンテナ名 phpfpm の設定画面に移動し、イメージの指定を先程プッシュしたイメージのものに書き換え新しいリビジョンを作成します。
次に、環境構築用スタックによって作成されたサービスの編集画面に移動し、新しいタスク定義のリビジョンを指定するように編集をおこない、サービスの更新を実行します。
しばらくすると新しいタスク定義に基づくタスクが実行され、コードの修正が反映されます。
手動でのデプロイが大変だと感じてもらったところで、CodePipeline/CodeBuild を使用したパイプラインを作成していきます。
今回作成するパイプラインは以下図の左側の部分です。
では、早速作成していきましょう。
マネジメントコンソールのトップ画面より「CodePipeline」をクリックします。
まだパイプラインを作成していない場合は以下のような画面が表示されるので「今すぐ始める」をクリックします。
パイプラインのセットアップが開始するのでパイプライン名としてhands-on-pipeline
と入力して「次のステップ」をクリックします。
ソースプロバイダのセットアップが始まるので以下の表のように入力後、「次のステップ」をクリックします。
入力項目 | 値 |
---|---|
ソースプロバイダ | GitHub |
リポジトリ | フォークしておいたリポジトリ |
ブランチ | master |
ビルドプロバイダのセットアップが始まるので以下の表のように入力後、「ビルドプロジェクトの保存」をクリックしてから「次のステップ」をクリックします。
入力項目 | 値 |
---|---|
ビルドプロバイダ | AWS CodeBuild |
プロジェクトの設定 | 新しいビルドプロジェクトを作成 |
プロジェクト名 | hands-on-project |
環境イメージ | カスタム Docker イメージの指定 |
環境タイプ | Linux |
Custom image type | Other |
カスタムイメージタイプ | katainaka0503/codebuild-php:latest |
ビルド仕様 | ソースコードのルートディレクトリの buildspec.yml を使用 |
キャッシュ タイプ | タイプ: AmazonS3 , 場所: 環境構築用スタックのCodeBuildCachePlace の値 |
CodeBuild サービスロール | アカウントから既存のロールを選択します を選択し環境構築用スタックの出力の値を入力 |
VPC | No VPC |
特権付与(アドバンスト内) | ✔ |
環境変数(アドバンスト内) | 名前:IMAGE_REPOSITORY_NAME , 値: IMAGE_REPOSITORY_NAME , Type: パラメータストア |
デプロイプロバイダのセットアップが始まるのでプロバイダに「Amazon ECS」を入力後、「AWS CodeDeploy に新たにアプリケーションを作成します。」のリンクをクリックします。
入力項目 | 値 |
---|---|
デプロイプロバイダ | Amazon ECS |
クラスター名 | hands-on-environment-ECSCluster |
サービス名 | hands-on-environment-ECSService |
イメージのファイル名 | imagedefinitions.json |
CodePipeline にアタッチする IAM Role の画面に変わるので、「ロールの作成」をクリック後、遷移する画面で「許可」をクリックします。
IAM Role の作成が完了したら「次のステップ」をクリックします。
最後に確認画面が表示されるので、内容を確認後、「パイプラインの作成」をクリックします。
すると、パイプラインが自動で開始されます。
Staging
ステージまで緑色になり、デプロイが完了したところで一度正常にページにアクセスできることを確認します。
バグが混入した際に、テストで処理が失敗し、デプロイが途中で止まることを確認するため、フォークしたリポジトリのコードを修正します。
エディタで、laravel/app/Http/routes.php
を開きます。
意図的にバグを混入させるため、23 行目の
'tasks' => Task::orderBy('created_at', 'asc')->get()
と書かれた行を
## 'tasks' => [] #Task::orderBy('created_at', 'asc')->get()
のようにロジック部をコメントアウトし、代わりに空の配列を返すようにします。
修正が終わったらコミットし、GitHub 上にプッシュします。
$ git commit -am bug
$ git push origin master
GitHub にプッシュすると、CodePipeline での処理が開始されます。 しかし、CodeBuild でテストが失敗し、ECS へのデプロイは実行されません。
テストが自動で実行される環境が構築されていたため、バグの混入したバージョンがデプロイされるのを防ぐことができました!
先程の修正をもとに戻すため、vim laravel/app/Http/routes.php
を開きます。
## 'tasks' => [] #Task::orderBy('created_at', 'asc')->get()
のように先程編集した行を
'tasks' => Task::orderBy('created_at', 'asc')->get()
のように修正し、GitHub にプッシュします。
$ git commit -am fixbug
$ git push origin master
同様に自動で CodePipeline 上での処理が開始されます。
今度はテストが成功するため、デプロイが行われました。
CodePipeline を使用することでデプロイやテストが自動で実行されるようになりました。
煩雑な手作業が自動化されることで人為的ミスを削減し、デプロイにかかる時間を短縮できます。
ハンズオンで作成した環境を削除したい場合は以下の手順を参考にしてください。 リソース間の依存関係がある関係で削除に失敗することがあるため、 CloudFormation スタックおよびクローンした GitHub のリポジトリは最後に削除を行ってください。
パイプラインの画面から編集ボタンをクリック、
表示された編集画面で削除ボタンをクリックし、表示された確認ダイアログにパイプライン名hands-on-pipeline
を入力して削除します。
CodeBuild の画面から、プロジェクトhands-on-project
を選択した状態で、アクションのドロップダウンリストから削除をクリックします。
CodeBuild用のロールhands-on-environment-CodeBuild-ServiceRole
を削除します。
hands-on-environment-CodeBuild-ServiceRole
という名前のロールを選択し、ロールを削除します。
CodePipelineでの他のプロジェクトが存在しない場合はAWS-CodePipeline-Service
という名前のロールも同様の手順で削除しましょう。
hands-on-environment-codebuildcachebucket-***
という名前のバケットの画面に移動し、
中身のオブジェクトをすべて削除します。
codepipeline-ap-northeast-1-****
バケットの中身を確認し、
もし、hands-on-xxx
のフォルダだけしかなければ、バケット自体を削除します。
他のフォルダがあれば、フォルダ以下を削除します。
ECSの画面の左側にある、リポジトリのリンクをクリックし、hands-***
という名前のリポジトリの画面の移動します。
そして、すべてのイメージを選択し、削除を行います。リポジトリ自体は削除しなくても大丈夫です。
CloudFormationのコンソールから、hands-on-environment
という名前のスタックを選択し、削除します
ECSの画面の左側にある、タスク定義のリンクをクリックし、hands-on-environment-****
という名前のタスク定義の画面に移動します。
すべてのタスク定義を選択し、登録解除します。
フォーク先リポジトリのSettingを開き、
一番下のDelete this Repositoryというボタンをクリック、確認ダイアログにリポジトリ名を入力して削除します。