Argo CD Image Updater 사용하기 (with. AWS EKS) (완)

이준석·2022년 3월 19일
1

Infra

목록 보기
3/5
post-thumbnail

서론

Argo CD 관련한 포스팅은 해당 내용을 마지막으로 마무리가 될 꺼 같다. 이외의 다른 설정값이나 사용 방법들은 구글링을 통해 충분히 찾아서 해결할 수 있을 것으로 생각이 됩니다.

이번 포스팅에서는 Pull 방식으로 도커 이미지 태그를 업데이트 하고 AWS EKS 에 자동으로 배포할 수 있도록 Argo CD 에서 개발하고 있는 Argo CD Image Updater 설정 방법에 대해서 알아보도록 하겠습니다.

본론

그럼 pull 방식이 있으면 push 방식도 있냐고 물어볼 수 있는데, 대표적으로 pull, push 두가지 방식이 존재합니다. 해당 포스팅은 GitOps 에 대한 내용을 다루는 부분이 아님으로 간략하게만 짚고 넘어가면 다음과 같습니다. (AWS 기준으로 설명을 작성하겠습니다.)

PUSH 방식의 GitOps

해당 이미지는 AWS CDK 활용법에서 제안한 AWS GitOps 인프라입니다.

하나의 프로젝트에 자신이 개발하는 애플리케이션 레포지토리와 CDK용 레포지토리 2개가 존재합니다.

위와 같이 사용자가 이미지를 배포를 하기 위해서 push 를 하게되면 트리거에 따라서 배포 프로세스가 실행되는 방식을 push 방식이라고 합니다.

PULL 방식의 GitOps

반면에 Pull 방식은 이미지를 배포할 때 배포 파이프라인을 가동시키는 것이 아닌 배포 파이프라인을 대신하는 툴(Argo CD, Flux CD 등)이 자동으로 변경점을 인식해서 쿠버네티스에 배포하는 방식을 말합니다. (위의 이미지는 Argo CD Tutorial 영상에서 발췌했습니다.)

그럼 둘 중에 뭐가 더 좋은 방식이라고 할 수 있냐? 무조건적인 답은 아니지만 GitOps 개념을 만든 Weavework 에서 권장하는 방식은 Pull 방식이라고 합니다. 자세한 내용은 삼성 SDS에서 설명한 자료를 한번 읽어보시면 이해가 좀 더 쉽게 되실꺼라고 생각됩니다.

Argo CD Image Updater 다운로드 받기

❗️ 주의 ❗️

들어가기에 앞서 Argo CD Image Updater 플러그인을 사용하려면 쿠버네티스 리소스를 Helm chart 혹은 Kustomize 형식으로 배포를 해주셔야지만 사용이 가능합니다!!

이제 진짜 본격적으로 자동으로 이미지 태그를 업데이트 하기 위한 절차를 밟아보도록 하자! 먼저 공식 사이트가 존재는 하는데 뭔가 설정들이 파편화 되어있어서 보는데 애좀 먹었다.

각설하고 공식 문서에 따르면 Argo CD Image Updater 플러그인은 Argo CD가 설치되어있는 클러스터에 설치해서 사용하는 것을 권장하고 있습니다. (강요는 아니라고 나와있지만 하라는대로 합시다!)

그럼 Argo CD Image Updater 설치를 위해 Argo CD 가 설치되어있는 클러스터에 터미널을 이용해서 접속합니다. 그리고 다음 명령을 입력해서 설치해줍니다. (argocd 네임스페이스가 아닌 다른 곳에 설치했다면 -n <argocd가 설치된 네임스페이스> 로 변경해줍니다.)

kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-image-updater/stable/manifests/install.yaml

조금의 시간이 흐르면 Argo CD Image Updater 파드가 실행이 될 것이고 정상적으로 실행이 된다면 다운로드가 완료된 것 입니다.

로그 레벨 설정하기

이 부분은 Argo CD Image Updater 의 로그 레벨을 설정할 수 있는 부분인데 필요 없다면 그냥 넘어가도 무방하다.

로그 레벨 설정 방법은 다음과 같다. 아래의 명령으로 argocd-image-updater-config 설정 파일을 엽니다.

kubectl edit configmap argocd-image-updater-config -n argocd

그리고 내용을 다음과 같이 수정합니다.

apiVersion: v1
kind: ConfigMap
data:
  # log.level can be one of trace, debug, info, warn or error
  log.level: debug

# 생략

그리고 :wq! 로 저장하고 나오면 로그 레벨 설정이 완료된 것입니다.

로컬 계정 설정하기

그 다음으로 해줘야할 부분이 Argo CDAPI 를 사용하기 위해서 API 용 계정을 하나 생성해주어야 한다. (현재는 Argo CD 홈페이지 로그인 계정 하나만 존재할 것이다.)

생성하기 위해서 argocd-cm configMap 파일을 열 수 있도록 한다.

kubectl edit configmap argocd-cm -n argocd

그 다음 아래의 내용을 적을 수 있도록 한다.

apiVersion: v1
kind: ConfigMap
data:
  # api 접근 용도로만 사용할꺼기 때문에 apiKey 만 적어준다
  accounts.image-updater: apiKey 

#생략

이렇게하고 저장하면 image-updater 라는 이름으로 계정이 생성된 모습을 볼 수 있다.

$ argocd account list

NAME           ENABLED  CAPABILITIES
admin          true     login
image-updater  true     apiKey

만약 FATA[0000] rpc error: code = Unauthenticated desc = invalid session: token is expired by <토큰> 에러가 뜨면 argocd 로그인을 다시 진행해주고 계정 조회를 할 수 있도록 하자!

$ argocd login <argocd 주소>

WARN[0000] Failed to invoke grpc call. Use flag --grpc-web in grpc calls. To avoid this warning message, use flag --grpc-web.
Username: admin
Password:
'admin:login' logged in successfully
Context <argocd 주소> updated

계정 권한 설정하기

그 다음 방금 생성한 계정에 RBAC 권한을 설정해주어야지만 정상적으로 Argo CD API 사용이 가능해진다. 필수로 추가해야하는 권한은 GETUPDATE 이다.

계정 권한 설정을 위해 argocd-rbac-cm configMap 파일을 열고 다음 정보를 기입한다.

kubectl edit configmap argocd-rbac-cm -n argocd
apiVersion: v1
kind: ConfigMap
data:
  policy.csv: |
    p, role:image-updater, applications, get, */*, allow
    p, role:image-updater, applications, update, */*, allow
    g, image-updater, role:image-updater
  policy.default: role.readonly

# 생략

Argo CD Endpoint 설정하기

이제 계정이 준비가 다 되었으면 Argo CD 를 이용해서 도커 이미지 파일을 다운로드할 레포지토리를 등록해주어야 한다. 저는 AWS ECR 을 이용해서 도커 이미지 파일을 관리하고 있기 때문에 AWS ECR 로 등록해주겠습니다.

등록하기 위해 argocd-image-updater-config configMap 파일을 열고 다음과 같이 수정해줍니다. (공식 문서에서는 argocd-image-updater-cm 에서 설정을 변경하라고 나와있는데 해당 configMap 파일은 없어서 가장 유사한 argocd-image-updater-config 에 설정을 해주었더니 되었습니다. 참고하시면 될 것 같습니다.)

kubectl edit configmap argocd-image-updater-config -n argocd
apiVersion: v1
data:
  applications_api: argocd
  argocd.grpc_web: "true"
  argocd.insecure: "false"
  argocd.plaintext: "false"
  argocd.server_addr: <argocd 접속 주소>
kind: ConfigMap

설정 값에 따른 간략한 설명은 다음과 같습니다.

  • applications_api : argocd로 고정
  • argocd.grpc_web : HTTP/2를 통해 GRPC 대신 GRPC_WEB 프로토콜을 사용할지 여부
  • argocd.insecure : Argo CD API endpoint의 잘못된 TLS 인증서를 무시할지 여부
  • argocd.plaintext : TLS (https) 대신 일반 텍스트 연결(http)을 사용할지 여부

위에서 credentials 에 적힌 secret 생성 방법은 다음과 같습니다.

  • pullsecret:<네임스페이스>/<secret 이름>
  • aws configure 설정을 필히 해주신 다음에 생성해주셔야 합니다.
kubectl create secret docker-registry aws-ecr-creds \
--docker-server=<AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com/<ECR REPO 이름> \
--docker-username=AWS \
--docker-password=$(aws ecr get-login-password) \
-n argocd

Argo CD Access Token Secret 생성하기

이제 Argo CD API 에 사용될 Access Token 을 쿠버네티스 리소스인 secret 으로 생성을 해주도록 하겠습니다.

먼저 아까 image-updater 계정에 대한 토큰을 발행해줍니다.

  1. 주의할 점으로 토큰은 한번 발급하면 새로 발급하지 않는 이상 조회할 수 없습니다. 필요한 경우 복사해서 다른 곳에 보관하시기 바랍니다.
  2. 토큰은 기본적으로 만료일이 없는 No Expired 설정이 디폴트입니다. 따라서 Expired 값을 주고 싶은 경우에는 -e 혹은 --expires-in 옵션값을 주고 0s 와 같은 식으로 작성해주시면 됩니다.

image-updater 토큰 발행은 다음 명령으로 합니다.

argocd account generate-token --account image-updater --id image-updater

명령으로 나오는 토큰을 복사해두고 Access Token secret $YOUT_TOKEN 에다가 생성해 넣을 수 있도록 합니다.

kubectl create secret generic argocd-image-updater-secret \
  --from-literal argocd.token=$YOUR_TOKEN --dry-run -o yaml |
  kubectl -n argocd apply -f -

그 동안 만든 secret 을 조회하기 위해서는 다음 명령을 통해 조회할 수 있습니다.

kubectl get secrets -n argocd

AWS ECR 연동 추가하기

기본적으로 Argo CD Image UpdaterAWS ECR 을 공식 지원하지 않습니다. 하지만 인증 정보를 잘 설정해주면 사용할 수 있는 것으로 알고 있고 적용이 되었습니다.

먼저 컨테이너 레파지토리 정보를 설정해주어야 합니다. 설정은 아래와 같이 할 수 있습니다.

kubectl edit configmap argocd-image-updater-config -n argocd
apiVersion: v1
kind: ConfigMap
data:
  applications_api: argocd
  argocd.grpc_web: "true"
  argocd.insecure: "false"
  argocd.plaintext: "false"
  argocd.server_addr: <argocd 주소>
  registries.conf: |  <-- 추가
    registries:
      - name: AWS ECR HUB
        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
        tagsortmode: latest-last

# 생략

간략한 설정 값 설명은 다음과 같습니다.

  • api_url : suffix 없이 순수한(?) AWS ECR 주소
  • prefix : https:// 제외한 api_url 주소 (해당 부분을 명시하지 않으면 prefix 오류 발생)
  • ping : ping 요청을 보낼지에 대한 여부
  • credentials : ECR 이미지 엑세스 권한을 넣어준다.
  • tagsortmode : 태그 이미지 소트 방식에 대해서 적어준다. (latest-first, latest-last 중 하나)

여기서 핵심이 credentials 부분인데 쿠버네티스 secret 리소스로 하드코딩 방식으로 토큰값을 넣게 되면 하루가 지날 경우 만료돼서 매번 다시 생성해줘야 한다. 따라서 요청시마다 토큰값을 생성해주는 명령을 쳐서 인증할 수 있도록 구성할 예정이다.

AWS ECR 인증 파일 ecr.sh 생성 후 적용하기

  1. 먼저 argocd-image-updater 컨테이너 내부로 접속합니다.
kubectl -n argocd exec --stdin --tty pod/argocd-image-updater-8687d55bb-mxdn2 -- /bin/sh
  1. app 폴더 밑에 sh 파일을 생성하고 다음 내용을 적습니다. (credentials 에서 경로만 잘 맞춰면 돼서 경로는 자유롭게 하시면 됩니다. 저의 경우 ext:/app/aws/ecr.sh 라고 적었기 때문에 app 폴더 밑에 aws 폴더 생성하고 그 곳에 ecr.sh 파일을 생성할 예정입니다.)
$ cd /app
$ mkdir aws
$ cd aws
$ vi ecr.sh
#!/bin/sh
aws ecr --region ap-northeast-2 get-authorization-token --output text --query 'authorizationData[].authorizationToken' | base64 -d

컨테이너에 접속해서 명령어만 치면 권한이 없다고 뜰텐데 권한 설정을 잘 못해서 유일하게 권한이 있는 app 폴더에서 작업하였습니다.

  1. 해당 컨테이너 내부에 aws configure 설정을 해줍니다.
$ aws configure
AWS Access Key ID: <AWS_ACCESS_KEY_ID>
AWS Secret Access Key: <AWS_SECRET_KEY_ID>
Default region name: <AWS_REGION>
Default output format:
  1. 설정이 정상적으로 되었는지 연결을 테스트 해봅니다.
$ argocd-image-updater test \
<AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com/<ECR_REPO_NAME> \
--registries-conf ./app/config/registries.conf

INFO[0000] getting image                                 image_name=<ECR_REPO_NAME> registry=<AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com
DEBU[0000] rate limiting is disabled                     prefix=<AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com registry="https://<AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com"
INFO[0000] Loaded 1 registry configurations from ./app/config/registries.conf
INFO[0000] /app/aws/ecr.sh                               dir= execID=hE99c
INFO[0003] Fetching available tags and metadata from registry  image_name=<IMAGE_NAME>
INFO[0003] Found 2 tags in registry                      image_name=<ECR_REPO_NAME>
DEBU[0003] found 2 from 2 tags eligible for consideration  image=<AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com/<ECR_REPO_NAME>
INFO[0003] latest image according to constraint is <AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com/<ECR_REPO_NAME>:<IMAGE_TAG>

위와 같이 로그가 나오면 성공한 것이고 실패했을 경우 실패 로그를 보고 원인을 파악해야 하는데 저의 경우에는 스무스하게 잘 되었던걸로 기억이 돼서 registries.conf 파일 경로나 ecr.sh 파일에 오타만 없으면 잘 될 것으로 생각됩니다.

Argo CD Application annotations 설정

마지막으로 Argo CD Image Updater 의 기능을 적용하기 위해서 Argo CD Applicationannotations 부분에 몇개의 설정 값들을 적어주어야 합니다. 해당 annotation 을 작성하지 않으면 트리거가 일어나지 않습니다.

  1. 우선 생성한 Argo CD Application 을 선택합니다.

  2. APP DETAILS > SUMMARY > EDIT > ANNOTATIONS 에서 + 버튼 을 눌러서 다음을 채워넣습니다.

  • argocd-image-updater.argoproj.io/image-list : org/app=<AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com/<ECR_REPO_NAME>
  • argocd-image-updater.argoproj.io/org_app.pull-secret : ext:/app/aws/ecr.sh
  • argocd-image-updater.argoproj.io/write-back-method : argocd (git or argocd 택 1, 디폴트는 argocd)
  • argocd-image-updater.argoproj.io/org_app.update-strategy : latest
  • argocd-image-updater.argoproj.io/org_app.allow-tags : regexp :^[0-9a-f]{7}$
    (Git commit SHA로 커밋되는 이미지 태그도 포함시켜서 업데이트 되도록 해준다.)
  1. 저장을 누르고 CI 를 통해 AWS ECR 에 이미지를 업로드하면 다음과 같이 PARAMETERSimage.tag 가 업데이트 된다.

💡 위의 이미지를 보시면 image.name, image.tag 라는 변수가 보일 것이다. image.name, image.tag변수는 argocd-image-updater 가 생성하고 관리하는 변수명이고 해당 변수와 동일하게 Helm Chart 를 구성해야지만 자동 업데이트 기능을 사용할 수 있게 된다.
예를 들어, ecr.image.name, ecr.image.tag 와 같이 Argo CD Image Updater 가 모르는 태그로 이미지를 관리한다면 업데이트가 되어도 적용이 안된다.

  1. 마지막으로 Argo CD Image Updater가 실행되는 로그를 보려면 다음과 같이 명령을 치면 된다.
$ kubectl logs pod/argocd-image-updater-8687d55bb-mxdn2 -n argocd

time="2022-03-14T07:06:57Z" level=info msg="Starting image update cycle, considering 1 annotated application(s) for update"
time="2022-03-14T07:06:57Z" level=info msg="Setting new image to <AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com/<ECR_REPO_NAME>:<IMAGE_TAG>" alias=org/app application=<Argo CD app name> image_name=<ECR_REPO_NAME> image_tag=<NOW_IMAGE_TAG> registry=<AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com 
time="2022-03-14T07:06:57Z" level=info msg="Successfully updated image '<AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com/<ECR_REPO_NAME>:<NOW_IMAGE_TAG>' to '<AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com/<ECR_REPO_NAME>:<NEW_IMAGE_TAG>', but pending spec update (dry run=false)" alias=org/app application=<Argo CD app Name> image_name=<IMAGE_TAG> image_tag=<NOW_IMAGE_TAG> registry=<AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com
time="2022-03-14T07:06:57Z" level=info msg="Committing 1 parameter update(s) for application <Argo CD app Name>" application=<Argo CD app Name>
time="2022-03-14T07:07:01Z" level=info msg="Successfully updated the live application spec" application=<Argo CD app Name>
time="2022-03-14T07:07:01Z" level=info msg="Processing results: applications=1 images_considered=1 images_skipped=0 images_updated=1 errors=0"

이 부분에서 가장 많이 뜬 오류는 단연코 인증 관련 문제였다. 만약 권한이 없다는 오류가 발생하면 ecr.sh 가 정상적으로 작동하지 않는다는 것이다. 따라서 다시 그 부분을 설정해보고 시도할 수 있도록 한다.

Argo CD Image Updater 는 약 2분 간격으로 실행된다.

결론

이렇게해서 Argo CD 를 회사에 적용하면서 파편화 되어있던 정보들을 한 곳에 모으고자 작성했던 내용이었는데 적으면서 한번 더 리마인드가 된 계기가 되었다. 근데 또 다음에 하려고 한다면 헤매지 않을까 걱정되지만 그래도 한번 해봤기 때문에 해결에 있어서는 조금 수월할 것으로 생각이 된다.

뭔가 두서도 없고 비약된 내용이 있을지도 모른다고 생각이 되지만 결론은 공식 문서에서 찾아서 한 부분이라 제 글에서 부족한 부분이라고 판단되는 부분은 공식 문서에서 찾아보시면 저보다 더 빠르게 해결할 수 있을 것으로 생각이 됩니다.

잘못된 부분이나 기타 다른 피드백 등 해주시면 빠르게 답변하도록 하겠습니다.

감사합니다.

profile
호주 워홀중

4개의 댓글

comment-user-thumbnail
2022년 5월 25일

안녕하세요. 좋은 글 잘 보고 있습니다. 궁금한 게 있어 댓글 남겨 봅니다. 현재 테스트를 ECR이 아닌 Harbor를 사용하려 하는데 위 과정에서 Harbor 기준으로 변경해야 할 부분을 알려주실 수 있을까요? 샘플도 좋을 거 같습니다. ^^

1개의 답글
comment-user-thumbnail
2023년 3월 12일

안녕하세요! 좋은 글 감사합니다
한 가지 궁금한 부분이 생겨서 댓글 남겨요

CI를 통해서 AWS ECR에 새로운 이미지를 푸시해도 Argocd 파라미터 image.tag가 업데이트 되지 않습니다.

helm 차트 작성 시, image.tag를 어떤 식을 작성해야하는지 알 수 있을까요?

argocd-image-updater test 명령어에서는 새롭게 푸시된 이미지를 잘 인식합니다.

$argocd-image-updater test xxx.dkr.ecr.ap-northeast-2.amazonaws.com/monster-was --registries-conf-path /app/config/registries.conf

INFO[0000] latest image according to constraint is xxx.dkr.ecr.ap-northeast-2.amazonaws.com/xxx:2.0.0  application=test image_alias= image_name=xxx.ecr.ap-northeast-2.amazon
aws.com/monster-was registry_url=xxx.dkr.ecr.ap-northeast-2.amazonaws.com

답변 부탁드립니다!

1개의 답글