CodeDeploy,CodePipelineで、S3に置いたソースコードをEC2インスタンスにデプロイするパイプラインを作ってみた

Codeシリーズ触ってみよう!ということでAWS公式チュートリアル「シンプルなパイプラインを作成する (Amazon S3 バケットの場合)」をやってみたレポートです。
2019.08.23

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、大阪オフィスのかずえです。 Codeシリーズ触ってみよう!ということで以下AWS公式チュートリアルをやってみたレポートです。

チュートリアル: シンプルなパイプラインを作成する (Amazon S3 バケットの場合)

やること

ZIPで固めたソースコードをS3にアップすると、複数のEC2インスタンスに自動デプロイされる仕組みを作ります。

さらに、実際の現場ではいきなり本番環境にデプロイするなんてことはあまりないですよね。ということでデプロイ対象をもう一つ作成し、ステージング環境へデプロイ→本番環境へデプロイみたいな仕組みを作ります。

仕組みの説明

この仕組みにはCodeDeployとCodePipelineが使われています。

CodeDeployでEC2インスタンスをデプロイ対象とする場合は、該当インスタンスにCodeDeployAgentがインストールされている必要があります。こいつが外部からデプロイファイルを取得したりするわけです。

また、ソースコードを置くS3バケットはバージョニングを有効にする必要があります。また、裏でCloudWatch Eventルールが作成され、こいつがS3バケット上にソースコードが置かれたことを検知し、CodePipeline経由でCodeDeploy(CodeDeployAgent)に伝播し、デプロイ処理が行われます。

CodePipelineはこの全体の流れ(パイプライン)を定義しているとも言えます。

図にすると以下のような感じです。

手順

ステップ 1: アプリケーションの Amazon S3 バケットを作成する

バージョニングを有効にしたS3バケットを作成し、そこにGitHubにあるサンプルコードを置きます。

基本的には チュートリアルページに書かれている通り で問題なく進めるかと思います。

注意しないといけない点は以下です。

バケット作成時

  • バケット名はユニーク(一意)である必要があるので、チュートリアルページに書かれている「awscodepipeline-demobucket-example-date」を指定するとエラーになります(すでに誰かがこの名前でバケットを作っているということです) 別の名前にしましょう。今回私は「kazue-awscodepipeline-demobucket」としました。
  • 「オプションの作成」ページで「バージョニング」のチェックボックスにチェックを入れましょう。

GitHub リポジトリからサンプルをダウンロード

  • Amazon Linux インスタンスにデプロイする場合とWindows Server インスタンスにデプロイする場合2種類記載されていますが、今回はWindows Serverインスタンスにデプロイすることにします。(後のステップがWindowsの場合の記載だったので)

詳解:サンプルコードの中身を見てみよう

zipファイルを解凍してみると、中はこのようなファイル構成になっていました。

$ tree AWSCodePipeline-S3-AWSCodeDeploy_Windows
AWSCodePipeline-S3-AWSCodeDeploy_Windows
├── LICENSE
├── README.md
├── appspec.yml
├── before-install.bat
└── index.html

ここで注目すべきは appspec.yml です。これが各インスタンスへのデプロイ内容を定義しています。ファイル内容は以下です。

version: 0.0
os: windows
files:
- source: \index.html
destination: C:\inetpub\wwwroot
hooks:
BeforeInstall:
- location: \before-install.bat
timeout: 900

詳しい記述内容については割愛します。後述のリンクを参照ください。ですが、詳しいことはわからなくても

  • 同階層のindex.htmlを、インスタンスのC:\inetpub\wwwroot に配置する
  • その前に、これまた同階層にあるバッチファイルbefore-install.bat を実行する

という処理内容であるということはわかると思います。

appspec.ymlについての詳細

ステップ 2: Amazon EC2 Windows インスタンスを作成して CodeDeploy エージェントをインストールする

デプロイ先のEC2インスタンスを作成します。 前述の通りインスタンスにはCodeDeploy エージェントがインストールされている必要がありますので、ユーザーデータ内でインスタンス起動時にあわせてインストールします。

インスタンスを配置するVPCのサブネットはパブリックサブネット、もしくはNat Gatewayなどでインターネットに出れるサブネットにする必要があります。もう少し具体的に書くと、対象のインスタンスはポート 443 経由で HTTPS を使用してアウトバウンドの通信が必要です。これが実現できるようにしてください。

詳解:ユーザーデータの処理内容

New-Item -Path c:\temp -ItemType "directory" -Force
powershell.exe -Command Read-S3Object -BucketName bucket-name/latest -Key codedeploy-agent.msi -File c:\temp\codedeploy-agent.msi
Start-Process -Wait -FilePath c:\temp\codedeploy-agent.msi -WindowStyle Hidden
  • 一行目で c:\temp フォルダを作成しています。
  • 二行目で S3バケット上にあるCodeDeploy エージェントファイルをダウンロードして c:\temp\codedeploy-agent.msi に配置しています。
  • 三行目で先ほど配置した codedeploy-agent.msi を実行してプロセスを起動しています。

ステップ 3: CodeDeploy でアプリケーションを作成する

CodeDeployの用語説明

まずはざっくりCodeDeployの主要概念を理解しましょう。そのほうがこの先の工程が理解しやすいと思います。

アプリケーション

最上位概念です。その名の通り、CodeDeployを使いたいアプリケーションのことです。何かしらのECサイトとか、コーポレイトサイトとか、そのくらいの単位のものとお考えください。 この下に複数のデプロイグループと複数のリビジョンが紐付きます。

デプロイグループ

EC2インスタンスにデプロイする場合、これはデプロイ対象となるインスタンス群のことです。

例えば本番環境とステージング環境が存在する場合、2グループ作成する必要があります。

リビジョン

前述のappspec.yml(AppSpec ファイル)とそこから参照されるアプリケーションファイルの組み合わせです。

デプロイ(デプロイメント)

リビジョンの内容をデプロイグループのインスタンスに反映(デプロイ)するアクションのことです。

CodeDeploy のサービスロールを作成

早速CodeDeployでアプリケーションを作成しましょう、と行きたいところですが、途中でデプロイメントグループに紐付けるIAMロールを聞かれます。以下ページを参考に先に作成しましょう。

ロールを作成し終えたら、ステップ 3: CodeDeploy でアプリケーションを作成する に沿ってアプリケーションとデプロイグループを作成してください。

ステップ 4: CodePipeline で最初のパイプラインを作成する

CodePipelineの用語説明

CodePipelineについても最初に用語を把握しておきましょう。 まず最初に以下の図をご覧ください。

パイプライン

CodePipelineの最上位概念です。ビルド、テスト、デプロイなど、リリース作業に必要な一連のプロセスをまとめたものです。

ステージ

パイプラインの「一連のプロセス」の各プロセスを指します。ビルド、テスト、デプロイといったものがこれにあたります。

アクション

全てのステージには少なくとも一つのアクションが含まれます。具体的なタスクを表します。 S3にソースコードが置かれるだとか、CodeDeployでデプロイメントグループにデプロイするとかですね。

トランジション

前段のステージから次のステージに処理が移ることです。

アーティファクト

中間生成物。各ステージは、入力値となる入力アーティファクトを必要としたり、処理結果を格納した出力アーティファクトを出力したりします。出力アーティファクトが、トランジション先の次のステージで入力アーティファクトとして使われたりします。

アーティファクトバケット

上記アーティファクトを格納するためのS3バケット。

コンソールでパイプラインを作成

[ステップ 4: CodePipeline で最初のパイプラインを作成する](ステップ 4: CodePipeline で最初のパイプラインを作成する)に沿って作成していきます。

  • 「5.[アーティファクトの場所]」は「デフォルトのロケーション」にしました。
  • また上記「アーティファクトの場所」のすぐ下に「暗号化キー」欄があります。こちらはデフォルトのまま「デフォルトの AWS マネージド型キー」にしました。
  • 「8.[Step 4: Add deploy stage (ステップ 4: デプロイステージを追加する)] 」で選択するCodeDeplyのアプリケーション名が「CodePipelineDemoApplication」となっていますが、これは事前に作成したCodeDeployのアプリケーション名なので、「MyDemoApplication」を選択します。

パイプラインが作成されました。

また同時に、S3バケットも作成されました。

これは「アーティファクトの場所」で「デフォルトのロケーション」を選んだため、アーティファクトバケットが自動で作成されたということです。 また、このバケットの中にパイプラインと同じ名前の「MyFirstPipeline」というフォルダが作成されています。MyFirstPipelineに関するアーティファクトはこのフォルダ下に作成されます。 他のパイプラインを作成しその際にも「デフォルトのロケーション」を選んだ場合、MyFirstPipelineと同様パイプラインと同じ名前のフォルダが新規作成され、その配下にアーティファクトが作成されます。

CloudWatch Eventルールも作成されています。 「6.[Step 2: Add source stage (ステップ 2: ソースステージの追加)]」でS3をソースプロバイダーに設定したので、該当S3バケットにファイルが置かれた際に発火するようになっています。

パイプライン実行結果確認

チュートリアルに書かれている通りにEC2インスタンスのパブリック DNS の値をブラウザにコピペしてページをリクエストします。 うまくいきました!もう一台のインスタンスでも成功していました。

ステップ 5: 別のステージをパイプラインに追加する

2番目のデプロイグループを CodeDeploy に作成

CodePipelineのパイプラインの他のステージとしてデプロイグループを追加

  • ステージにCodeDeployデプロイグループをアクションとして追加する際、入力アーティファクトを「MyApp」とするとありますが、「SourceArtifact」しか選択肢がありませんでしたのでこちらにしました。
  • ステージが作成できました。
  • 「変更のリリース」押下でリリースし、Productionステージが失敗しました。

ステップ 6: CodePipeline のステージ間の移行を有効化または無効化する

無効化後にS3バケットに再度ファイルをアップロードし、パイプラインを開始させます。

Productionへのトランジションは発生していません。(Source: Amazon S3 version idが異なる)

Productionステージにある「再試行する」ボタンでステージ再試行しました。当然ですがまたエラーになります。

エラーを解消する

この 3 番目のステージを成功させるには、遷移を有効にする前に CodePipelineProductionFleet デプロイグループを編集し、アプリケーションをデプロイする別の Amazon EC2 インスタンスを指定します。

チュートリアルにこう書かれていますのでやってみます。

EC2インスタンスをもう一台作成します。インスタンスのメニューから「同様のものを作成」で設定をショートカットします。

作成ウィザードを抜けた後に、Nameタグ値を変更します。

※「同様のものを作成」でなくいちから作成する場合、CodeDeployエージェントをインストールすることを忘れないようにしましょう。(私は忘れました(・・*)ゞ)

次にCodeDeployのコンソールにて、先ほど作成したCodePipelineProductionFleetの設定を変更します。

先ほど変更したName値(MyCodePipelineDemo-prod)を指定します。

Productionステージにある「再試行する」ボタンでステージ再試行です。

デプロイ成功しました!

ステップ 7: リソースをクリーンアップする

特に特記事項はないので、チュートリアル通りに実施いただければと思います。

参考情報