3
4

More than 3 years have passed since last update.

超ミニマムなチュートリアルを通してCodeDeployを理解する。

Last updated at Posted at 2019-12-17

CodeDeployチュートリアルに失敗した記事のリベンジです。

wordpressとかdbとか余計なものをいれる過程でエラーして本質が見えなくなるのが嫌だったので内容を削ぎ落として超ミニマムなチュートリアルを勝手に作りました。
apacheが動いてるEC2にindex.htmlをデプロイするという簡単な進行でCodeDeployを理解していきます。

そもそもの理解。

image.png

上図、クラメソさんを参考にパクりました(本家参考:CodeDeployによるバージョン管理とステージング

CodeDeployはデプロイ対象のデータをS3等に置いておき、手動/自動のタイミングでEC2へ流すというものです。その過程で、シェルを動かしたりなど細かな設定をS3に同時に格納するappspec.ymlに書くことで実現できます。(ここでEC2にS3への適切なアクセス権が必要。)
CodeDeployではアプリケーションという一番大きな単位がありその中にデプロイメントグループ、デプロイメントという粒度で構成されています。

デプロイメント
デプロイメントというのが、1回1回のデプロイに当たります。それぞれに結果や処理時間、エラーなどが見れます。

デプロイメントグループ
デプロイメントグループとは、どこにデプロイするのか(EC2)、どこにデータはあるのか(S3=リビジョン)、デプロイ方式は何かなどを設定しておき、これをもとにデプロイメントを行います。(デプロイメントの設計図のようなものかな?)

リビジョン
デプロイするデータがどこに置かれているかを指し示すものです。S3上に、デプロイするデータをバージョン管理していき、リビジョンでそれらの最新版を指定することで新しい物をデプロイすることができます。

アプリケーション
これらのデプロイ作業を機能単位などで分けるためにある?と思います。

まずはやってみる。ミニマムなチュートリアル。

IAMユーザを作成する。

アクセスキー/シークレットキーを設定しAWS CLIからAWSへアクセスできるユーザを1つ作成する必要あり。このユーザには少なくとも以下のポリシーを割り振ってください。

  • AWSCodeCommitFullAccess (多分不要かも)
  • AWSCodeDeployFullAccess
  • AWSS3FullAccess
  • AWSIAMFullAccess

EC2インスタンスを用意する。

Amazon Linuxを用いてインスタンスを作成。

AMI: Amazon Linux
インスタンスタイプ:任意のものでOK
IAMロール:`S3FullAccess`を含むロールを当てること。
EBS:デフォルトのままでOK
タグ:のちのち必要になるのでのでインスタンスには名前をつけてあげましょう。今回は`codedeploy`と命名。
セキュリティ:SSHとHTTP(S)が必要になります。以下を参考に。

SSH → マイIP(xx.xxx.xxx.xxx/32)
HTTP、HTTPS → 任意(0.0.0.0/0)

pemファイルはssh接続時に必要です。

EC2にApacheを入れる。

sshで侵入します。

$ ssh -i Download/xxx.pem ec2-user@xx.xxx.xxx.xxx
Warning: Permanently added 'xx,xxx,xxx,xxx' (ECDSA) to the list of known hosts.
       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/
13 package(s) needed for security, out of 26 available
Run "sudo yum update" to apply all updates.
$ sudo yum update -y
$ sudo yum install httpd -y
$ sudo service httpd start
Starting httpd:                                            [  OK  ]

IPv4 パブリックIPにアクセスするとApatchのデフォルトのページが出迎えてくれることを確認します。

EC2にCodeDeploy用のAgentを入れる。

前回ここがうまくいかないポイントの一つだったのですが、公式にちゃんとAmazon Linux用のセットアップ方法がありました。(参考:https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/codedeploy-agent-operations-install-linux.html)

なお、下記は東京リージョンでのケースなので、他のリージョンを使う場合には、install元のURIを適切なものに変える必要があります。(→一覧

$ sudo yum install ruby
$ sudo yum install wget
$ cd /home/ec2-user
$ wget https://aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/latest/install
$ chmod +x ./install
$ sudo ./install auto
$ sudo service codedeploy-agent status
The AWS CodeDeploy agent is running as PID 14515

EC2の準備はOKです。

デプロイするファイルを準備する。

ローカルでやることは3つです。

  • AWS CLIを入れるorアップデートする。
  • デプロイ対象のindex.htmlを作成する。
  • CodeDeployのデプロイ設定を記述したappspec.ymlを作成する。

AWS CLIを入れるorアップデートする。

まだ入れていない場合は、以下公式参照。
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-install.html

アップデート
$ sudo pip install --upgrade awscli

index.html/appspec.ymlを作成する。

$ mkdir testCodeDeploy
$ cd testCodeDeploy
$ touch index.html
$ vi index.html    ←"Hello World!"とでも書いて保存。
$ touch appspec.yml
$ vi appspec.yml   ←中身は下記。
appspec.yml
version: 0.0
os: linux
files:
  - source: /
    destination: /var/www/html

今回は超ミニマムな内容なので、デプロイのみです。本当はhooksでインストール前後や要所要所のタイミングを指定して任意のシェルを実行したりする設定も可能です。→この辺は今後やります。

  • sourceはリビジョン(=S3バケット)の中のデプロイするファイルの位置を示します。
  • destinationにはデプロイ先を指定します。

S3バケットの準備

デプロイ対象を上げるS3バケットを作成します。

  • バケット名はここではtestcodedeployとします。
  • パブリックアクセスはすべてブロック。(=デフォルトの設定)

バケットポリシーを以下のように設定します。
アクセス元を示すPrincipalにはローカル環境のAWS CLI configureに設定したアクセスキー/シークレットキーのIAMユーザのARNを書くこと。後々、AccessDeniedで悲しい気持ちになります。
なお、IAMユーザのARNはIAMコンソール画面からコピペできます。

バケットポリシー
{
    "Version": "2012-10-17",
    "Id": "ExamplePolicy01",
    "Statement": [
        {
            "Sid": "testcodedeploy",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::xxxxxxxxxxxx:user/xxx",
                    "arn:aws:iam::xxxxxxxxxxxx:user/xxx"
                ]
            },
            "Action": [
                "s3:GetObject",
                "s3:GetBucketLocation",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::testcodedeploy/*",
                "arn:aws:s3:::testcodedeploy"
            ]
        }
    ]
}

デプロイ

現在、testCodeDeployディレクトリの中身は以下のようになっているはずです。

$ ls
appspec.yml index.html

まずは、アプリケーションを作成します。ここではTestとします。

$ aws deploy create-application --application-name Test
{
    "applicationId": "f33128d3-81bd-49f7-9b97-28f635995xxx"
}

デプロイ対象をzip化して、まるごと先ほど作成したS3バケットへ放り込みます。(1つのコマンドでできる。)
ここではファイル名をtestCodeDeploy.zipとします。

$ aws deploy push \
--application-name Test \
--s3-location s3://testcodedeploy/testCodeDeploy.zip \
--ignore-hidden-files
To deploy with this revision, run:
aws deploy create-deployment --application-name Test --s3-location bucket=testcodedeploy,key=testCodeDeploy.zip,bundleType=zip,eTag=2dbc9aab3836f21317a9eed7a36f1xxx --deployment-group-name <deployment-group-name> --deployment-config-name <deployment-config-name> --description <description>

なお、この処理は以下のことをやっているのと同じです。(参考:CodeDeploy pushコマンドは裏で何をやっている?

上記のコマンドと一緒
$ zip -r testCodeDeploy.zip .
$ aws s3api put-object --bucket testcodedeploy --key testCodeDeploy.zip --body testCodeDeploy.zip
$ aws deploy register-application-revision \
  --application-name Test \
  --s3-location bucket=testcodedeploy,key=testCodeDeploy.zip,bundleType=zip

デプロイメントグループの作成です。ここではTestGroupという命名をします。

$ aws deploy create-deployment-group \
--application-name Test \
--deployment-group-name TestGroup \
--deployment-config-name CodeDeployDefault.OneAtATime \
--ec2-tag-filters Key=Name,Value=codedeploy,Type=KEY_AND_VALUE \
--service-role-arn arn:aws:iam::xxxxxxxxxxxx:role/CodeDeployServiceRole
{
    "deploymentGroupId": "d4b9e016-b175-49eb-af9f-6ee6c0c55xxx"
}

deployment-config-nameではデプロイ方式を選択しています。
service-role-arnには、AWSがデフォルトで提供しているロールCodeDeployServiceRoleを使用。

いよいよデプロイです。

aws deploy create-deployment --application-name Test \
--deployment-config-name CodeDeployDefault.OneAtATime \
--deployment-group-name TestGroup \
--s3-location bucket=testcodedeploy,bundleType=zip,key=testCodeDeploy.zip
{
    "deploymentId": "d-18TVA1BXD"
}

これで実際に対象のEC2の/var/www/html下にindex.htmlが置かれているはずです。
先ほどアクセスしたEC2のIPアドレスにブラウザからアクセスしてみましょう。Hello World!が表示されれば成功です。

実際にCodeDeployコンソールからデプロイメントを見てみると成功となっているでしょう。

おしまい

今後は、AutoScalingグループやlambdaへの応用、appspec.ymlの探索をやっていこうと思います。

追記

続編書きました。

トラブルシューティング

1) create-applicationで失敗する。

$ aws deploy create-application --application-name Test
ModuleNotFoundError: No module named 'yaml'

$ pip install pyyamlしろと書かれているページを発見。実行するも効果なし。
結局AWS CLIをアップデートしたところ解消しました。

2) deploy pushでAccessDeniedとなる。

$ aws deploy push \
--application-name Test \
--s3-location s3://testcodedeploy/testCodeDeploy.zip \
--ignore-hidden-files
Failed to upload '.' to 's3://testcodedeploy/testCodeDeploy.zip': An error occurred (AccessDenied) when calling the PutObject operation: Access Denied

AccessDeniedに弾き倒される。S3のバケットポリシーの設定なので、自身のAWS CLIのconfigureとそのIAMユーザがS3へアクエスできるバケットポリシー設定になっているかを確認してください。

3) デプロイされない!(deploymentIdは返されている。)

CodeDeployコンソールからデプロイメントを見て失敗していないか確認します。失敗の場合、エラー原因が出ているのでそれを修正します。
→ もしくは、EC2上からログを辿っても見られます。特にunknown errorなどであればここを見てもいいかも。

$ tail -f -n 200  /var/log/aws/codedeploy-agent/codedeploy-agent.log

2019-12-17 13:30:46 ERROR [codedeploy-agent(14520)]: InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller: Error during perform: Aws::S3::Errors::AccessDenied - Access Denied 

こんな感じでエラーの理由がわかります。なお、上記は、EC2からS3へのアクセス許可がないためにでたエラーでした。EC2のロールにS3FullAccessをアタッチして再実行すると解決しました。

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4