CI를 어느정도 구체화시켰으니 이제 CD를 구체화할 시간이다. CD의 Continuous Deployment는 GUI를 활용해 관리 용이성을 높이고 history rollback을 쉽게 수행하기 위해서 ArgoCD를 활용하기로 결정했다.
ArgoCD를 선택하면서 처음에는 여러 환경을 나눠서 사용하지 않아서 Kustomize 없이 아래와 같이 CD 레포를 구성했다.
.
├── README.md
└── backend
├── deployment.yaml
├── hpa.yaml
├── ingress.yaml
└── service.yaml
그리고 ArgoCD에서 해당 레포를 추적하게 설정했다.
하지만 여기서 고려해봐야할 사항이 생겼다.
ArgoCD는 GitHub Repo를 바라보게 설정해서 직접 클러스터와 싱크를 맞춰 CD를 수행하고 Jenkins는 CI 과정을 수행한다. 그렇다면 이 중간을 이을 Continuous Delivery는 어떻게 수행할 것인가?
이 과정에서 ECR에 이미지가 올라가고 나면 쿠버네티스 매니페스트를 담고있는 레포에 이미지 태그 업데이트가 필요했다.
가장 먼저 생각했던 부분은 Jenkins 파이프라인으로 직접 GitHub을 업데이트하는 것이었다.
하지만 이 부분은 지난 프로젝트에서 직접 수행했을 때 ssh를 통해 GitHub에 커밋을 푸시하는 것이 꽤나 번거롭다고 느꼈다. 더하여 ArgoCD의 편리함과 가시성이라는 장점을 살리지 못한다고 생각했다.
FluxCD도 고려했는데 CLI로만 설정할 수 있다는 점에서 ArgoCD 서버가 제공하는 GUI보다 같이 클라우드를 하는 팀원이 이해하기 몇배로 어려울 것 같다고 생각해서 ArgoCD를 사용하게 되었다. 트러블슈팅 자료도 ArgoCD가 더 풍부하고 리소스를 아끼고 싶지만 ArgoCD를 활용해도 큰 문제는 없을 정도라는 것에 대한 확인은 이미 Continuous Deployment를 선정할 때 고려했던 부분이었다.
이렇게 이미지 태그를 업데이트하는 방법을 탐색하는 과정에서 ArgoCD Image Updater를 발견했다. 이미 Deployment에 ArgoCD를 쓰고 있으니 금방 적용이 가능하다고 생각했고 전반적인 CD를 ArgoCD에 맡기는 것도 좋아보였다.
A tool to automatically update the container images of Kubernetes workloads that are managed by Argo CD.
말 그대로 컨테이너 이미지를 자동으로 업데이트 해주는 ArgoCD 도구이다.
한 가지 주의할 점은 아직 개발 중인 서비스이므로 중요한 환경에서 적용하는 것은 추천하지 않는다는 점이다. 아직 v1이 릴리즈되지 않고 최신 버전이 v0.15.1이다.
Argo CD Image Updater is under active development.
You are welcome to test it out on non-critical environments, and of course to contribute by many means.
There will be (probably a lot of) breaking changes from release to release as development progresses until version 1.0. We will do our best to indicate any breaking change and how to un-break it in the respective release notes.
Argo CD Image Updater is not currently compatible with Argo CD Applications in any namespace.
ArgoCD Image Updater의 기능은 다음과 같다.
- Updates images of apps that are managed by Argo CD and are either generated from Helm or Kustomize tooling
- Update app images according to different update strategies
- semver: update to highest allowed version according to given image constraint,
- latest/newest-build: update to the most recently created image tag,
- name/alphabetical: update to the last tag in an alphabetically sorted list
- digest: update to the most recent pushed version of a mutable tag
- Support for widely used container registries
- Support for private container registries via configuration
- Can write changes back to Git
- Ability to filter list of tags returned by a registry using matcher functions
- Support for custom, per-image pull secrets (using generic K8s secrets, K8s pull secrets, environment variables or external scripts)
- Runs in a Kubernetes cluster or can be used stand-alone from the command line
- Ability to perform parallel update of applications
볼드체로 표시한 부분이 Continuous Delivery 방식을 고민하면서 가장 필요했던 부분이었고 이번 프로젝트에서는 ArgoCD Image Updater로 다음과 같은 기능을 수행했다.
이전까지 Kustomize를 활용하지 않았는데 ArgoCD Image Updater에서는 Helm이나 Kustomize로 관리되는 애플리케이션의 앱의 이미지 업데이트만 지원한다.
Updates images of apps that are managed by Argo CD and are either generated from Helm or Kustomize tooling
그래서 다음과 같이 폴더 구조를 바꾸어 Kustomize를 적용하고 backend/overlays/dev
를 클러스터와 ArgoCD에 적용했다.
.
├── README.md
└── backend
├── base
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── kustomization.yaml
│ └── service.yaml
└── overlays
└── dev
└── kustomization.yaml
다른 분께서 이미 해두신 블로그 글 Argo CD Image Updater 사용하기 (with. AWS EKS) (완)과 공식 문서를 참고하며 설정했다.
먼저 Installation에서 Method 1을 골라 YAML로 설치했다. 설치하면 아래와 같은 리소스들이 설치된다.
serviceaccount/argocd-image-updater created
role.rbac.authorization.k8s.io/argocd-image-updater created
clusterrole.rbac.authorization.k8s.io/argocd-image-updater created
rolebinding.rbac.authorization.k8s.io/argocd-image-updater created
clusterrolebinding.rbac.authorization.k8s.io/argocd-image-updater created
configmap/argocd-image-updater-config created
configmap/argocd-image-updater-ssh-config created
secret/argocd-image-updater-secret created
deployment.apps/argocd-image-updater created
그리고 기타 설정을 직접 변경하였다.
가장 먼저 argocd-image-updater-config ConfigMap에 다음과 같은 설정을 추가했다.
data:
log.level: debug # default: info
registries.conf: |
registries:
- name: AWS ECR
api_url: https://<AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com
prefix: <AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com
ping: yes
credentials: ext:/app/aws/ecr.sh
credsexpire: 12h # ECR Token은 12시간이 지나면 만료됨
tagsortmode: latest-last
log.level은 자세히 로그를 찍기 위함이고 registries.conf는 ECR 레포에 연결하기 위함이다. ECR 레포에 연결하기 위해서는 추가로 Secret를 설정하고 위에 보이는 /app/aws/ecr.sh
를 마운트해야한다.
ECR Token은 12시간이 지나면 만료되므로 credsexpire를 추가해야 한다!
ECR 이외에 다른 레지스트리를 활용한다면 예제를 참고하길 바란다.
ECR에 접근하기 위해서 ECR 패스워드를 가져올 수 있는 크레덴셜과 커맨드 실행이 필요하다.
# config
[default]
region = ap-northeast-2
# credentials
[default]
aws_access_key_id = ...
aws_secret_access_key = ...
# ecr.sh
#!/bin/sh
aws ecr --region ap-northeast-2 get-authorization-token --output text --query 'authorizationData[].authorizationToken' | base64 -d
# k create secret generic aws-config --from-file=config -n argocd
# k create secret generic aws-cred --from-file=credentials -n argocd
# k create configmap ecr-pwd --from-file=ecr.sh -n argocd
그리고 argocd-image-updater
deployment를 수정하여 각각의 Secret과 ConfigMap을 마운트한다.
...
- containers:
...
- volumeMounts:
- mountPath: /app/.aws/config
name: aws-config
subPath: config
- mountPath: /app/.aws/credentials
name: aws-credentials
subPath: credentials
- mountPath: /app/aws
name: script-volume
- volumes:
...
- name: aws-config
secret:
defaultMode: 420
secretName: aws-config
- name: aws-credentials
secret:
defaultMode: 420
secretName: aws-cred
- configMap:
defaultMode: 511
name: ecr-pwd
name: script-volume
그리고 ArgoCD와 ArgoCD Image Updater가 서로 연결될 수 있도록 설정해야한다. 같은 클러스터의 네임스페이스에서 실행되고 있다면 별도의 argocd endpoint 설정은 필요하지 않다.
중요한 점은 ArgoCD에 등록한 Application에 Annotation을 설정해야한다는 점이다.
ArgoCD 설정 전에 푸시가 가능한 GitHub Token을 argocd 네임스페이스에 설정했다. repo 전체 권한을 가진 Token을 생성 후 secret을 생성했다.
k create secret generic git-cred -n argocd \
--from-literal=username=... \
--from-literal=password=<TOKEN>
argocd-image-updater-secret에 넣어줘도 괜찮고 별도로 secret을 생성해도 괜찮다. 무엇으로 생성했는지 기억해서 ArgoCD에 제대로 넣어주기만 하면 된다.
기존에 만들어둔 Application > Details > Summary
에서 Annotation을 추가한다.
argocd-image-updater.argoproj.io/image-list: <AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com/<ECR_REPO>
argocd-image-updater.argoproj.io/org_app.allow-tags: regexp :^v\d+\.\d+\.\d+$ # vN.N.N 형식 태그
argocd-image-updater.argoproj.io/org_app.pull-secret: ext:/app/aws/ecr.sh
argocd-image-updater.argoproj.io/org_app.update-strategy: latest # latest/newest-build
argocd-image-updater.argoproj.io/write-back-method: git:secret:argocd/git-cred # GitHub Secret
여기까지 하면 ECR 레포에 업데이트 사항이 생기면 GitHub 레포에 자동으로 태그를 업데이트하는 설정 끝이다!
먼저 v0.0.24
Image Tag를 확인한다. 뒤의 24는 Jenkins Build 순서를 가리킨다.
다음은 v0.0.25
차례이고 25번째 파이프라인을 실행시킨다.
위 파이프라인 실행이 종료되면 ECR 레포에 이미지 업데이트가 완료된 것을 확인할 수 있다.
기본 설정으로 ArgoCD Iamge Updater는 2분에 한 번씩 등록된 레포를 추적하여 변경 사항을 확인한다. 타이밍이 좋아 바로 Image Updater를 확인했을 때 다음과 같은 로그와 함께 GitHub에 태그 변경 사항이 반영된 것을 확인할 수 있었다.
GitHub에서도 ./backend/overlays/dev
에 변경사항이 반영되고 ArgoCD에서도 OutOfSync로 변경 사항을 잘 추적한 것을 확인할 수 있다.
여기서 Sync를 눌러 이미지를 업데이트하면 설정한대로 RollingUpdate가 수행되고 이미지가 교체된 것을 확인할 수 있다.
아직 v1이 아닌 게 아쉽고 얼른 출시되면 ArgoCD 만으로 안정적인 CD를 수행할 수 있을 것 같다! 오픈소스 기여를 해보고 싶고 개발 환경이라서 ArgoCD Image Updater를 써볼 수 있어서 좋은 기회였다.
작은 도움이 되었으면 좋겠습니다. 읽어주셔서 감사합니당 🙇🏻♀️