Edited at

CodeDeploy オンプレミスをためしてみました

More than 3 years have passed since last update.

CodeDeploy オンプレミスをためしてみました。


結論

配布元に github を指定したときは、S3 へのアクセスは不要です。

codedeploy-agent が対応している配布元が、S3 か Github.com なので、そのままだと配布元データの場所はインターネット上になりますが、少しエージェントを手直しすれば、オンプレミスのリポジトリからデプロイできました。


サポートするOS

The AWS CodeDeploy agent has been tested


  • Amazon Linux 2014.09.1, 2015.03, 2016.03.0, 2016.03.1

  • Ubuntu Server 14.04 LTS

  • Windows Server 2008 R2 and Windows Server 2012 R2

  • Red Hat Enterprise Linux (RHEL) 7.x

今回は、Ubuntu 16.04.1 LTS で実験したため、リストにはありません。


The AWS CodeDeploy agent is available as open source for you to adapt to

your needs
. It can be used with other on-premises instance operating

systems. For more information, go to the AWS CodeDeploy Agent repository in GitHub.


自分で直してね、ということで。


Ubuntu 16.04.1 LTS

Ruby2.0 が動作すればなんとかなりそうです。

rubyパッケージは2.3なので、PPAから ruby2.0

をインストールして直接エージェントをインストールします。

$ sudo apt-add-repository ppa:brightbox/ruby-ng

$ sudo apt-get update
$ sudo apt-get install ruby2.0 libruby2.0

エージェントを手動でインストールします。

$ wget https://aws-codedeploy-ap-northeast-1.s3.amazonaws.com/latest/install

$ wget https://aws-codedeploy-ap-northeast-1.s3.amazonaws.com/latest/VERSION
$ cat VERSION
{"rpm":"releases/codedeploy-agent-1.0-1.1037.noarch.rpm","deb":"releases/codedeploy-agent_1.0-1.1037_all.deb","msi":"releases/codedeploy-agent-1.0.1.998.msi"}
$ wget https://aws-codedeploy-ap-northeast-1.s3.amazonaws.com/releases/codedeploy-agent_1.0-1.1037_all.deb
$ sudo dpkg -i codedeploy-agent_1.0-1.1037_all.deb

dpkg -L codedeploy-agent するとインストールされたファイル一覧が表示されます。

一覧の中に設定ファイルがありました。

/etc/codedeploy-agent/conf/codedeployagent.yml

---

:log_aws_wire: false
:log_dir: '/var/log/aws/codedeploy-agent/'
:pid_dir: '/opt/codedeploy-agent/state/.pid/'
:program_name: codedeploy-agent
:root_dir: '/opt/codedeploy-agent/deployment-root'
:verbose: false
:wait_between_runs: 1
:proxy_uri:
:max_revisions: 5


セットアップ

$ export AWS_REGION=us-east-1

$ NAME=Ubuntu-16
$ IAM_USER_ARN=arn:aws:iam::XXXXXXXXXXXX:user/XXXXXXXXXX

ここで使用する IAM ユーザには、つぎの内容のポリシーをアタッチして作成してあります。

ポリシー > CodeDeply-On-Premises

{

"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"codedeploy:*",
"iam:CreateAccessKey",
"iam:CreateUser",
"iam:DeleteAccessKey",
"iam:DeleteUser",
"iam:DeleteUserPolicy",
"iam:ListAccessKeys",
"iam:ListUserPolicies",
"iam:PutUserPolicy",
"iam:GetUser",
"tag:GetTags",
"tag:GetResources"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": [
"arn:aws:s3:::aws-codedeploy-us-east-1/*",
"arn:aws:s3:::aws-codedeploy-us-east-2/*",
"arn:aws:s3:::aws-codedeploy-us-west-1/*",
"arn:aws:s3:::aws-codedeploy-us-west-2/*",
"arn:aws:s3:::aws-codedeploy-ap-northeast-1/*",
"arn:aws:s3:::aws-codedeploy-ap-northeast-2/*",
"arn:aws:s3:::aws-codedeploy-ap-south-1/*",
"arn:aws:s3:::aws-codedeploy-ap-southeast-1/*",
"arn:aws:s3:::aws-codedeploy-ap-southeast-2/*",
"arn:aws:s3:::aws-codedeploy-eu-central-1/*",
"arn:aws:s3:::aws-codedeploy-eu-west-1/*",
"arn:aws:s3:::aws-codedeploy-sa-east-1/*"
]
}
]
}

オンプレミスインスタンスの登録

$ aws deploy register-on-premises-instance --instance-name $NAME --iam-user-arn $IAM_USER_ARN --region $AWS_REGION

$ aws deploy add-tags-to-on-premises-instances
--instance-name $NAME --tags Key=Name,Value=CodeDeploy-OnPremises

あるいは、一行でまとめて実行できます。

$ aws deploy register --instance-name $NAME --iam-user-arn $IAM_USER_ARN --region $AWS_REGION --tags Key=Name,Value=CodeDeploy-OnPremises

エージェントのインストール

$ sudo aws deploy install --override-config --config-file codedeploy.onpremises.yml

codedeploy.onpremises.yml:

---

aws_access_key_id: XXXXXXXXXXXXXXXXXXXX
aws_secret_access_key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
iam_user_arn: arn:aws:iam::XXXXXXXXXXXX:user/XXXXXXXXXX
region: us-east-1


デプロイのセットアップ

アプリケーションを作成します。

aws deploy create-application --application-name MyApp --region $AWS_REGION

ロールを作成します。

aws iam create-role --role-name CodeDeploy-OnPremises --assume-role-policy-document file://CodeDeploy-Trust.json

CodeDeploy-Trust.json:

{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": [ "codedeploy.us-east-1.amazonaws.com" ] }, "Action":

"sts:AssumeRole" } ] }

$ SERVICE_ROLE_ARN=arn:aws:iam::XXXXXXXXXXXX:role/CodeDeploy-OnPremises

オンプレミスインスタンスが使用するIAMユーザにロールをアタッチします。

aws iam attach-role-policy --role-name CodeDeployServiceRole --policy-arn $SERVICE_ROLE_ARN

デプロイメントグループを作成します。

aws deploy create-deployment-group \

--region $AWS_REGION --application-name MyApp \
--deployment-group-name MyDepGroup \
--deployment-config-name CodeDeployDefault.OneAtATime \
--on-premises-instance-tag-filters Key=Name,Value=Ubuntu-16,Type=KEY_AND_VALUE \
--service-role-arn $SERVICE_ROLE_ARN


デプロイ

デプロイしてみます。

appspec.yml:

version: 0.0

os: linux
files:
  - source: subtree
    destination: /opt/codedeploy-on-premises
  - source: README.md
    destination: /opt/codedeploy-on-premises
  - source: LICENSE
    destination: /opt/codedeploy-on-premises
hooks:
  ApplicationStop:
    - location: scripts/application-stop.sh
      timeout: 300
      runas: root
  BeforeInstall:
    - location: scripts/before-install.sh
      timeout: 300
      runas: root
  AfterInstall:
    - location: scripts/after-install.sh
      timeout: 300
      runas: root
  ApplicationStart:
    - location: scripts/application-start.sh
      timeout: 300
      runas: root
  ValidateService:
    - location: scripts/validate-service.sh
      timeout: 300
      runas: root

$ aws deploy create-deployment --region $AWS_REGION --application-name MyApp --deployment-config-name CodeDeployDefault.OneAtATime --deployment-group-name MyDepGroup --github-location repository=xxxxx/yyyyyy,commitId=zzzzzzzz


クレデンシャルについて


  • EC2インスタンスの場合

    インスタンスプロファイルで設定するので不要です。


  • オンプレミス

    codedeploy.onpremises.ymlで指定します。

    登録ごとに1対1でIAMユーザが必要です。


  • Github.com へのアクセス

    マネージメントコンソールで 「Githubに接続」を実行しておけば、デプロイ時にOAuthのアクセストークンがエージェントに渡ってくるようです。

    ログではマスクされて、 "GitHubAccessToken"=>"REDACTED" になります。



エージェントの動作

デプロイするファイルはここに展開されます。

/opt/codedeploy-agent/deployment-root/${DEPLOYMENT_GROUP_ID}/${DEPLOYMENT_ID}/deployment-archive

max_revisions で指定した世代分保存されています。

ポーリング対象のURL。ここからコマンドを受け取っているようです。

vendor/gems/codedeploy-commands-1.0.0/lib/aws/plugins/deploy_control_endpoint.rb:

url = "https://codedeploy-commands.#{cfg.region}.amazonaws.com"

poll_host_command(host_identifier: IAM_USER_ARN)

codedeployagent.ymlproxy_uri

の項目があるので、プロキシサーバ経由でも使えるようです。(未確認)

ログファイルの場所

/var/log/aws/codedeploy-agent/codedeploy-agent.log

/opt/codedeploy-agent/deployment-root/deployment-logs/codedeploy-agent-deployments.log


フック


  • スクリプトの実行で、終了ステータス 0 のとき成功、それ以外の時は失敗です。


  • ApplicationStop だけ実行タイミングが異なります。


  • ApplicationStopで指定されたスクリプトは、今回のデプロイではなく、後のデプロイの時に、このデプロイしたアプリケーションを停止するためにに使用されます。



Install

appspec.yml に書かれたインストール対象のファイルは、Install のステップで存在していれば良いようです。

files: に記載しておいて、BeforeInstall スクリプトで準備することもできそうです。

たとえばこのように。

DEPLOYMENT_ROOT=/opt/codedeploy-agent/deployment-root

DEPLOYMENT_DIR=$DEPLOYMENT_ROOT/${DEPLOYMENT_GROUP_ID}/${DEPLOYMENT_ID}
[ -d $DEPLOYMENT_DIR/subtree ] || mkdir $DEPLOYMENT_DIR/subtree
cd /path/to/workset
git pull
rsync -a --exclude .git . $DEPLOYMENT_DIR/subtree/.


スクリプト中で利用できる環境変数

APPLICATION_NAME=デプロイアプリケーション名

DEPLOYMENT_GROUP_NAME=デプロイグループ名
DEPLOYMENT_GROUP_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
DEPLOYMENT_ID=d-XXXXXXXXX
LIFECYCLE_EVENT=ステージ名
AWS_HOST_IDENTIFIER=codedeploy.onpremises.ymlのiam_user_arn
AWS_ACCESS_KEY=codedeploy.onpremises.ymlのaws_access_key_id
AWS_SECRET_KEY=codedeploy.onpremises.ymlのaws_secret_access_key
AWS_REGION=リージョン名
PWD=/opt/codedeploy-agent

ステージ名: (ApplicationStop|BeforeInstall|AfterInstall|ApplicationStart|ValidateService)


手元のリポジトリからデプロイしたいとき

gitbucketをセットアップして実験しました。

エージェントの lib/instance_agent/plugins/codedeploy/command_executor.rb

の中にdownload_from_s3()download_from_github()があります。

ここのURLを書き換えて、ダウンロードしてくるアーカイブのタイプも変更しました。

        private

        def download_from_github(deployment_spec, account, repo, commit,
anonymous, token)
          retries = 0
          errors = []
          if InstanceAgent::Platform.util.supported_oses.include? 'windows'
            deployment_spec.bundle_type = 'zip'
            format = 'zipball'
          else
            #deployment_spec.bundle_type = 'tar'
            #format = 'tarball'
            deployment_spec.bundle_type = 'zip'
            format = 'zip'
          end
          #uri = URI.parse("https://api.github.com/repos/#{account}/#{repo}/#{format}/#{commit}")
          #options = {:ssl_verify_mode => OpenSSL::SSL::VERIFY_PEER, :redirect => true, :ssl_ca_cert => ENV['AWS_SSL_CA_DIRECTORY']}
          uri = URI.parse("https://gitbucket.repository.local/#{account}/#{repo}/archive/#{commit}.#{format}")
          options = {:ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE, :redirect => true, :ssl_ca_cert => ENV['AWS_SSL_CA_DIRECTORY']}

 


  • ダウンロードはHTTP/HTTPSのみ対応可能です。


  • 渡せるパラメータが限られるため、自由度はありません。


  • 認証が必要な場合は、別途 BeforeInstall スクリプトで取得する方がよさそうです。



気になる点

Ruby 2.0.0系の公式サポートは2016年2月24日に終了しています。


Ruby 2.0.0系に関しては今後バグ修正や脆弱性修正のパッチがリリースされることはありません。


Ruby 2.3 に対応するのはいつになるのでしょう。