こんにちは。アプリケーションサービス部の兼安です。
以前AWS CodePipelineを使ってCI/CDを構築した時に、CodeDeployで結構つまずいたため、押さえるべきポイントをまとめてみました。
- はじめに
- 本記事の対象者
- [前提知識] AWSで構築するCI/CDパイプラインの基礎知識
- CI/CDパイプラインとは
- AWSで構築するCI/CDパイプラインの基本構成
- サーバーにビルド済みファイルをデプロイするAWS CodeDeploy
- AWS CodeDeployでEC2にデプロイする時のポイント
- 最後に
はじめに
本記事ではAWS CodeDeployを用いてEC2にデプロイする場合を想定しています。
他のサービスへのデプロイや、AWS CodePipelineそのものやビルドに関する内容は今回の対象外としています。
また、デプロイ対象のEC2は、Linuxを想定しています。
CI/CDパイプラインの考え方については、こちらをご覧ください。
blog.serverworks.co.jp
本記事の対象者
CI/CDパイプラインの初心者を想定しています。
概念は知っているが、構築は初めてという方のヒントになれば幸いです。
[前提知識] AWSで構築するCI/CDパイプラインの基礎知識
CI/CDパイプラインとは
CI/CDパイプラインとは、Continuous Integration(継続的インテグレーション)とContinuous Deployment(継続的デプロイメント)の略で、ソフトウェア開発プロセスを自動化するための手法です。
一般的には、Gitのリポジトリにコードをプッシュすると、自動的にビルド、テスト、デプロイが行われる仕組みのことを指します。
AWSで構築するCI/CDパイプラインの基本構成
AWSでCI/CDパイプラインを構築する場合、AWS CodePipelineというサービスを使うことが一般的です。
AWS CodePipelineは、何をトリガーにして起動し、ビルド、デプロイをどのように行うかを定義することができます。
ビルド、デプロイは、AWS CodeBuild、AWS CodeDeployという専用サービスが存在します。
トリガーは、AWS CodeCommit、外部リポジトリ(GitHub、Bitbucketなど)、Amazon S3、Amazon SNS、Amazon CloudWatch Eventsなどが利用できます。
例えば、AWS CodeCommitへのプッシュをトリガーにしてビルド、デプロイを行うとしたら、図のような三段階になります。
各段階はステージと呼ばれます。
図中にS3があるのは、ステージ間でソースコードやビルド済みファイルのやり取りにS3を使用するためです。
各ステージで生成されたファイルはアーティファクト(Artifact)と呼ばれ、アーティファクトをS3に保存することで、次のステージに引き継ぎます。
サーバーにビルド済みファイルをデプロイするAWS CodeDeploy
AWS CodeDeployは、EC2やLambdaなどにファイルをデプロイするためのサービスです。
一般的にAWS CodeDeployでデプロイするのはビルド済ファイルです。
ビルド済ファイルというのは、コンパイル・ビルドした実行可能ファイル、スクリプト言語ならソースコードそのもの、あとはライブラリや静的ファイルなどです。
ビルド済ファイルもAWS CodePipelineおよびAWS CodeDeploy上ではアーティファクトと表現されます。
AWS CodeDeployはビルド済ファイルをアーティファクトとして引き継ぎ、これらをサーバー上の適切な場所に配置、場合によってはパーミッションの設定などを行います。
AWS CodeDeployでEC2にデプロイする時のポイント
1. EC2側にCodeDeployエージェントのインストールが必要
AWS CodeDeployでEC2にデプロイする場合、まずEC2側にCodeDeployエージェントをインストールする必要があります。
AWS CodeDeployによるEC2へのデプロイは、ファイルを送るイメージではなく、EC2上のCodeDeployエージェントが動いてファイルを取りに行くイメージです。
デプロイ対象となるEC2は、AWS CloudFormationテンプレートなどを用いて、事前にCodeDeployエージェントをインストールしておくと良いと思います。
AWS CloudFormationテンプレートなら、EC2のUserDataで起動時にCodeDeployエージェントをインストールすることができます。
このようなイメージです。
UserData: Fn::Base64: !Sub | #cloud-config package_update: true package_upgrade: true packages: - wget runcmd: - echo "Starting CodeDeploy agent installation" - cd - dnf update -y - dnf install -y ruby - wget https://aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/latest/install - chmod +x ./install - ./install auto - systemctl enable codedeploy-agent - systemctl start codedeploy-agent
2. EC2側にS3へのアクセス権限が必要
CodeDeployエージェントがS3からビルト済ファイル=アーティファクトを取得するには、EC2にS3へのアクセス権限が必要です。
アーティファクトが格納されているS3バケットに対してGetObject権限を付与しておく必要があります。
3. デプロイスクリプトはEC2の台数分実行される
CodeDeployエージェントは、S3からアーティファクトを取得し、中のデプロイスクリプトに従ってデプロイを行います。
このデプロイスクリプトを、AppSpec ファイルと呼びます。
ソースディレクトリの直下にappspec.yml
というファイルを配置すると、CodeDeployエージェントがAppSpec ファイル=デプロイスクリプトとして認識します。
(パスは変更可能です。 )
AppSpec ファイルによるデプロイ処理は、EC2の台数分実行されます。
したがって、S3のような外部ストレージやデータベースサーバーに対する処理をAppSpecファイルに記述する場合、複数回実行されることによる矛盾を考慮する必要があります。
SQLの実行などは、冪等性(何度実行しても問題ない作り)を検討してください。
4. AppSpec ファイルのフック処理とユーザー
こちらは、AppSpec ファイルのサンプルです。
詳細は省かせていただきますが、PHPのアプリケーションをApacheで動かす場合の例です。
version: 0.0 os: linux files: - source: /httpd_example.conf destination: /etc/httpd/conf.d/ - source: / destination: /var/www/html hooks: BeforeInstall: - location: deploy_scripts/before_install.sh timeout: 300 runas: root AfterInstall: - location: deploy_scripts/after_install.sh timeout: 300 runas: root ApplicationStart: - location: deploy_scripts/application_start.sh timeout: 300 runas: root
files
がどのファイルをどこに配置するかを指定します。
この例の場合、/httpd_example.conf
を/etc/httpd/conf.d/
に、/
を/var/www/html
に配置します。
sourceの/
はビルド済ファイルの全体を指します。
したがって、全ファイルを/var/www/html
という意味になります。
hooks
は、デプロイの各段階で実行するスクリプトを指定します。
スクリプトは別途用意して、そのパスを指定します。
ここに直接スクリプトを書くことはできないようです。
この例の場合、BeforeInstall
、AfterInstall
、ApplicationStart
の3つの段階でそれぞれスクリプトを実行します。
AppSpec ファイルにおけるInstallとは、ファイルを配置することを指します。
従って、BeforeInstall
、AfterInstall
は、ファイルを配置する前後に実行されるスクリプトを指定することになります。
そして、runas
は、スクリプトを実行するユーザーを指定します(Linux限定です)。
従って、各スクリプト内で、sudoなどを書く必要は必ずしもありません。
runas
でユーザーを指定するのか、スクリプト内でsudoを使うのか、どちらかを統一しておかないと矛盾が生じる可能性があるので注意してください。
hooks
の更なる詳細は、こちらを参照してください。
5. CodeDeployエージェントのログ
CodeDeployエージェントは、AppSpec ファイルに従ってデプロイを行います。
デプロイ中にエラーが発生した場合、デプロイが失敗しますが、AWS CodePipelineやAWS CodeDeployの画面上にはあまり詳細なエラーメッセージが表示されません。
EC2の中にCodeDeployエージェントのログが出ているので、こちらを見るのがオススメです。
場所はこちらです。
セッションマネージャーでEC2に入って見ると良いと思います。
/var/log/aws/codedeploy-agent/codedeploy-agent.log
また、CodeDeployエージェントがS3から読み込んだファイルは、こちらにあります。
ここを見ることで、デプロイに正しくファイルが渡ってきているかを確認できます。
なお、ファイルはZip圧縮されているため解凍する必要があります。
/opt/codedeploy-agent/deployment-root/
最後に
本記事が皆様のお役に立てれば幸いです。
他のサービスへのデプロイや、AWS CodePipelineそのものやビルドに関する内容は、別の機会にまとめたいと思います。
サーバーワークスはDevOpsを支援するサービスを提供しています。
兼安 聡(執筆記事の一覧)
アプリケーションサービス部 DS3課所属
2024 Japan AWS Top Engineers (Database)
2024 Japan AWS All Certifications Engineers
認定スクラムマスター
広島在住です。今日も明日も修行中です。