git pushでkubernetesのpodのイメージ更新まで自動化出来たので手順を残します。
How To Automate Deployments to DigitalOcean Kubernetes with CircleCI
githubに公開しました。
https://github.com/a5ro5a/k8s-deploy-with-circleci-ecr
- 実現したいこと
- git push したタイミングでcircleciでテスト、問題なければkubernetes上で稼働しているpodのイメージを更新させる
environment
- kubernetes
- v1.28.2
- namespace
- doks-wp
- container registry
- ECR private
- 既にdigitalocean上のkubernetesにて運用中である
- deploy
- kubernetesへはyamlファイルの管理はしない
- podのイメージの更新のみとする
SSH 鍵の作成
非対称型暗号化のSSH鍵のペアをローカル環境で作成
- 秘密鍵はcircleciのプロジェクトに
- 公開鍵はgithubのアカウントに
空のgitレポジトリを作成しておく
- レポジトリの作成
- SSHの公開鍵の登録
circle ciにてプロジェクトを作成する
https://circleci.com/docs/ja/create-project/
-
github.comを選択
-
SSH秘密鍵を登録
-
Faster: Commit a starter CI pipeline to a new branch オプションを選択します。これにより、プロジェクト用の新しい circleci-project-setup ブランチが作成されます。
circle ciからkubernetesを操作するアカウントの作成
circle ciプロジェクト設定
Projects > プロジェクト選択 > 右側歯車 Project Settings
Environment Variables
環境変数の追加
Name | Value |
---|---|
AWS_ACCESS_KEY_ID | AWS API ID |
AWS_ACCOUNT_ID | AWS Account ID |
AWS_DEFAULT_REGION | ECRコンテナレジストリリージョン |
AWS_SECRET_ACCESS_KEY | AWS API キー |
DEPLOYMENT_NAME | kubernetesのdeployementの名前 |
ECR_IMAGE_NAME | ECRコンテナレポジトリ名 |
KUBERNETES_TOKEN | 先に$TOKENとして取得したもの |
KUBERNETES_SERVER | 先に$KUBERNETES_SERVERとして取得したもの(~/.kube/config に記載されているserver: の値) |
KUBERNETES_CLUSTER_CERTIFICATE | ~/.kube/config に記載されているcertificate-authority-data: の値 |
circleciのmanifest作成
cd ~/work/$_PROJECTNAME
mkdir .circleci
vi .circleci/config.yml
version: '2.1'
orbs:
aws-cli: circleci/[email protected]
jobs:
build:
working_directory: ~/app
docker:
- image: cimg/python:3.9
steps:
- checkout
- setup_remote_docker
- aws-cli/install
- aws-cli/setup
- run:
name: docker build
command: |
source ~/app/.env
docker build -t ${ECR_IMAGE_NAME}:${_VERSION} ~/app/docker
status=$(echo "$?")
if [ "${status}" != "0" ]; then
exit 1
else
RESISTRY_URL=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com
REPOSITORY_URL=${RESISTRY_URL}/${ECR_IMAGE_NAME}
aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | docker login --username AWS --password-stdin $RESISTRY_URL
#docker tag ${ECR_IMAGE_NAME}:${_VERSION} ${REPOSITORY_URL}:${_VERSION}
docker tag docker.io/library/${ECR_IMAGE_NAME}:${_VERSION} ${REPOSITORY_URL}:${_VERSION}
docker push ${REPOSITORY_URL}:${_VERSION}
fi
exit 0
deploy:
docker:
#- image: circleci/buildpack-deps:bullseye
- image: cimg/python:3.9
working_directory: ~/app
steps:
- checkout
- run:
name: Install envsubst
command: |
sudo apt-get update && sudo apt-get -y install gettext-base
- run:
name: Install awscli
command: |
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
- run:
name: Install kubectl
command: |
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
chmod u+x ./kubectl
- run:
name: Deploy Code
command: ./scripts/ci-deploy.sh
workflows:
version: 2
build-deploy-master:
jobs:
- build:
filters:
branches:
only: master
- deploy:
requires:
- build
filters:
branches:
only: master
mkdir scripts
vi scripts/ci-deploy.sh
chmod +x scripts/ci-deploy.sh
#! /bin/bash -x
# exit script when any command ran here returns with non-zero exit code
set -e
#COMMIT_SHA1=$CIRCLE_SHA1
source ~/app/.env
# Export it so it's available for envsubst
#export COMMIT_SHA1=$COMMIT_SHA1
# Since the only way for envsubst to work on files is using input/output redirection,
# it's not possible to do in-place substitution, so you will save the output to another file
# and overwrite the original with that one.
#envsubst <./kube/do-sample-deployment.yml >./kube/do-sample-deployment.yml.out
#mv ./kube/do-sample-deployment.yml.out ./kube/do-sample-deployment.yml
echo "$KUBERNETES_CLUSTER_CERTIFICATE" | base64 --decode > cert.crt
RESISTRY_URL=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com
REPOSITORY_URL=${RESISTRY_URL}/${ECR_IMAGE_NAME}
aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | docker login --username AWS --password-stdin $RESISTRY_URL
./kubectl \
--kubeconfig=/dev/null \
--server=$KUBERNETES_SERVER \
--certificate-authority=cert.crt \
--token=$KUBERNETES_TOKEN \
set image deployment/${DEPLOYMENT_NAME} -n ${ECR_IMAGE_NAME} ${ECR_IMAGE_NAME}=${REPOSITORY_URL}:${_VERSION}
chmod +x scripts/ci-deploy.sh
説明
- buildジョブ
- タグ名が$CIRCLE_SHA1 となり長くてわかりずらい為、自分で指定できるように変更(.envファイル)
- ../.envファイルを読み込み_VERSION情報を取得します(イメージのタグ名)
- buildして問題なければECRへ認証し、タグ付けし、PUSHします。
- タグ付けの際に、"docker.io/library/"が無いとPUSHがタイムアウトで失敗します。
- タグ名が$CIRCLE_SHA1 となり長くてわかりずらい為、自分で指定できるように変更(.envファイル)
- deployジョブ
- buildが成功したときのみ実行
- masterブランチへのpush時のみ実行
- kubectlでdeploymentへset imageするだけです
- yamlファイルを用意してkubectl apply -f でも利用可能
gitへpush
含まれるもの
- .circleci/config.yml
- scripts/ci-deploy.sh
- .envファイル
- docker/Dockerfile
- その他docker buildに必要なもの
確認
Circle CI
ECR
kubernetes
ocarina@ab350-pro4:~/work/doks-wp$ kubectl get pods -n doks-wp
NAME READY STATUS RESTARTS AGE
doks-wp-dev-web-776d445c4c-sdfkx 1/1 Running 0 55m
doks-wp-prod-web-55dc67dc98-75584 1/1 Running 0 54s
doks-wp-prod-web-55dc67dc98-xx5pd 1/1 Running 0 51s
ocarina@ab350-pro4:~/work/doks-wp$ kubectl describe pods/doks-wp-prod-web-55dc67dc98-xx5pd -n doks-wp | grep Image\:
Image: 123456789012.dkr.ecr.ap-southeast-1.amazonaws.com/doks-wp:0.0.13
ocarina@ab350-pro4:~/work/doks-wp$
0.0.13に更新されたことを確認出来ました。