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 .circlecivi .circleci/config.ymlversion: '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: mastermkdir 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に更新されたことを確認出来ました。
