之前有寫過一篇 一條龍佈署 CI/CD 從 Travis 到 CodeDeploy 的 On-Premises (IAM Role/STS) 的作法,對於 On-Premises 來說集中控管便於管理,而 AWS CodeDeploy 的另一個方式 IAM User 讓每一個 On-Premises Server 都擁有不同的 IAM User key 來訪問,這個作法我覺得有好有壞,
好在於你的 Key 要是不小心掉了,可以快速知道是哪一台發生問題,且不會所有 On-Premises 都淪陷
壞在於你的 IAM User 會多到爆炸 ..
關係架構圖:
與使用 IAM Role/STS 不同的地方在於直接用 IAM User 訪問,而不再需要用 STS 交換 token 後用再 Assume Role 了
環境
- Region(東京) = ap-northeast-1
- 產品名稱 = project
在進行 CodeDeploy On-Premises 之前必須先確認你的網路環境允許連上以下 AWS 服務
- S3 (每一個 S3 bucket 都是全球唯一的位址)
- ${bucketname}.s3-${region}.amazonaws.com
- CodeDeploy Server
- codedeploy.${region}.amazonaws.com
- AWSCLI 安裝
- s3.amazonaws.com
- CodeDeploy Agent 安裝
- aws-codedeploy-us-east-1.s3.amazonaws.com (非 EC2 的 fail-safe mode 安裝位置)
- aws-codedeploy-${region}.s3.amazonaws.com
- codedeploy-commands.${region}.amazonaws.com
必要條件
用來建立以下服務的 IAM User 必須擁有以下權限
Attach
AWSCodeDeployFullAccess
lnline
iam:CreateAccessKey,
iam:CreateUser,
iam:DeleteAccessKey,
iam:DeleteUser,
iam:DeleteUserPolicy,
iam:ListAccessKeys,
iam:ListUserPolicies,
iam:PutUserPolicy,
iam:GetUser
此安裝將會建立以下 AWS 服務
- 一個 S3 bucket
- 一個 IAM User 給 Travis CI 使用 CodeDeploy, S3
- 一個 IAM User 給 On-Premises 使用 CodeDeploy, S3 服務使用
- 一個 IAM Role 給 CodeDeploy 服務使用
- 一個 CodeDeploy Application 與 deployment_group
- 在 CodeDeploy 註冊 On-Premises (register-on-premises-instance)
全程將使用 AWS command line 建立,將不會有 Web cosole 的執行過程
開始建立 CodeDeploy On-Premises (IAM User)
或者你可以用 shazi7804/codedeploy-permissions-onpremises 進行自動佈署。
Step 1: 建立 S3 bucket
$ aws s3api create-bucket --bucket codedeploy-project --region ap-northeast-1 --create-bucket-configuration LocationConstraint=ap-northeast-1
強者同事補充:根據 AWS-CLI 的 Help 指出,要在 eu-west-1 之外的 region 建 bucket,需要加上 LocationConstraint 參數。
確認可以訪問
$ aws s3 ls project
Step 2: 建立 IAM User for Travis CI
建立 IAM User
$ aws iam create-user --user-name travisci-project
Attach Policy – AWSCodeDeployDeployerAccess
$ aws iam attach-user-policy --user-name travisci-project --policy-arn arn:aws:iam::aws:policy/AWSCodeDeployDeployerAccess
lnline Policy – 授與 bucket name 為 codedeploy-project 有權限
$ tee travisci-project-lnline.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1487528506000",
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::codedeploy-project/*"
]
}
]
}
EOF
$ aws iam put-user-policy --user-name travis-project --policy-name s3-travisci-project --policy-document file://travisci-project-lnline.json
$ rm travisci-project-lnline.json
Step 3: 建立 IAM User for On-Premises
每一個 On-Premises 皆使用獨立的 IAM User,這邊示範建立 dev
$ aws iam create-user --user-name codedeploy-onpremises-project-dev
lnline IamPolicyfile.json
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::codedeploy-project/*"
}
]
}
$ aws iam put-user-policy --user-name codedeploy-onpremises-project-dev --policy-name iam-codedeploy-project-onpremises --policy-document file://IamPolicyfile.json.json
$ rm IamPolicyfile.json
Step 4: 建立 IAM Role for CodeDeploy
給 CodeDeploy Server 的 IAM Role 一個 AWS account 僅需要一個。
$ tee role-codedeploy-trust.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "codedeploy.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
$ aws iam create-role --role-name Role-CodeDeploy --assume-role-policy-document file://role-codedeploy-trust.json
$ rm role-codedeploy-trust.json
Attach policy
$ aws iam attach-role-policy --role-name Role-CodeDeploy --policy-arn arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole
Create Profile
$ aws iam create-instance-profile --instance-profile-name Role_CodeDeploy-Profile
把 Role 和 Profile 關聯起來
$ aws iam add-role-to-instance-profile --role-name Role-CodeDeploy --instance-profile-name Role_CodeDeploy-Profile
Step 5: 建立 CodeDeploy
Create application
$ aws deploy create-application --application-name project --region ap-northeast-1
Create deployment_group (prod)
$ aws deploy create-deployment-group \
--application-name project \
--deployment-config-name CodeDeployDefault.AllAtOnce \
--deployment-group-name prod \
--service-role-arn arn:aws:iam::0123456789:role/Role-CodeDeploy \
--region ap-northeast-1
Step 6: 註冊 CodeDeploy On-Premises
註冊 On-Premises instance
$ aws deploy register-on-premises-instance --instance-name project-dev --iam-user-arn arn:aws:iam::0123456789:user/codedeploy-onpremises-project-dev
替註冊的 On-Premises instance 加入 tags:Key=Name,Values=project-dev
$ aws deploy add-tags-to-on-premises-instances --instance-names project-dev --tags Key=Name,Values=project-dev
在 On-Premises Server 安裝 CodeDeploy
Step 1: 設定 Proxy
如果你的 On-Premises 不允許直接訪問外部網路,需要另外設定 Proxy,因為安裝 CodeDeploy 必須對外訪問。
建議先把他寫到 /etc/environment,否則在接下來的 sudo 會無法使用 export 環境變數
Step 2: 安裝 aws cli
$ sudo apt-get install -y wget unzip $ cd /tmp $ wget https://s3.amazonaws.com/aws-cli/awscli-bundle.zip $ unzip awscli-bundle.zip $ cd awscli-bundle $ sudo chmod +x install $ sudo ./install -i /usr/local/aws -b /usr/local/bin/aws
確認版本為最新的 aws cli
$ aws --version
在 On-Premises 必須取得 #Step 3: “建立 IAM User for On-Premises” 的 Access Key/ Secret Access Key,並且登記在 On-Premises Server 的 aws cli
$ aws configure
Step 3: 安裝 CodeDeploy agent
$ sudo apt-get install -y ruby $ wget https://aws-codedeploy-ap-northeast-1.s3.amazonaws.com/latest/install $ sudo chmod +x install $ sudo ./install auto
install 有支援 proxy 參數,可以用 –proxy 解決
Step 4: 設定檔 codedeploy.onpremises.yml & codedeployagent.yml
建立 CodeDeploy On-Premises 需要使用的設定檔
$ sudo tee /etc/codedeploy-agent/conf/codedeploy.onpremises.yml <<EOF --- aws_access_key_id: OnPremises IAM User 的 access key aws_secret_access_key: OnPremises IAM User 的 secret key iam_user_arn: arn:aws:iam::0123456789:user/codedeploy-project-onpremises-dev region: ap-northeast-1 EOF
- iam_session_arn 是在 #Step 6: “建立 CodeDeploy” 中建立的 sts session arn
- aws_credentials_file 是要用來放 sts session 的 token and access key
- region 為你 codedeploy 的所在地區
在 codedeployagent.yml 把 proxy 參數加入,讓 codedeploy agent 可以用 proxy 去更新
:proxy_uri: http://proxy.com:3128
重新啟動 CodeDeploy agent 把 proxy 的設定參數吃進去
$ sudo service codedeploy-agent restart
在 CodeDeploy 中決定 deploy 的 On-Premises instance tags
CodeDeploy 中的 deployment_group tags 必須和 On-Premises instance tags 符合才會進行 CodeDeploy。
你可以透過 Web cosole 在 CodeDeploy/Application/deployment_group/Search by tags 進行設定 tags,tags type 必須是 On-premises-instance
或是使用 awscli “更新” tags,此設定會直接覆蓋現有 tags,若有多筆 tags 可以用 json 或是多個 –on-premises-instance-tag-filters 來指定 tag
$ aws deploy update-deployment-group \
--application-name project \
--current-deployment-group-name master \
--on-premises-instance-tag-filters Key=Name,Value=project-dev,Type=KEY_AND_VALUE
或是用 json 更新 tags
$ tee multi_tags.json <<EOF
[
{
"Key": "project",
"Value": "dev",
"Type": "KEY_AND_VALUE"
},
{
"Key": "project",
"Value": "staging",
"Type": "KEY_AND_VALUE"
}
]
EOF
$ aws deploy update-deployment-group \
--application-name project \
--current-deployment-group-name master \
--on-premises-instance-tag-filters file://multi_tags.json
驗證
驗證服務正在使用
$ ps ax | grep codedeploy codedeploy-agent: master 19248 codedeploy-agent: InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller of master 19248
正常運作時 access codedeploy 的 log。
$ less /var/log/aws/codedeploy-agent/codedeploy-agent.log 2017-03-06 00:03:13 INFO [codedeploy-agent(19252)]: Version file found in /opt/codedeploy-agent/.version. 2017-03-06 00:04:14 INFO [codedeploy-agent(19252)]: [Aws::CodeDeployCommand::Client 200 61.019261 0 retries] poll_host_command(host_identifier:"arn:aws:sts::0123456789:assumed-role/Role-onpremises/project-session-server01")
收到 codedeploy 的 access log 狀態為 200
[codedeploy-agent(...)]: [Aws::CodeDeployCommand::Client 200 ....
Note
- 已 register 的 On-Premises,如果要 deregister 必須等待 24H 後才會消除,一樣的 instance name 無法重複申請
- CodeDeploy 的 On-Premises 方式不支援 Auto Scaling。
- CodeDeploy 的 deploy tags 方式不支援 * 等字符,必須完整輸入 tag name。
Reference
