ArgoCD란?
ArgoCD는 CD 도구 중 하나로, GitOps 방식의 배포를 도와주는 오픈소스이다.
현재 프로젝트에서 CI 환경은 Jenkins ci를 통해 구현되어 있으며,
ArgoCD를 통해 완전히 자동화된 CI / CD 환경을 구축하게 되었다.
GitOps란?
DevOps 방법론 중에 하나로, 명령형 방식이 아닌 선언형 방식으로 애플리케이션을 배포하는 방식이다.
이전에 Jenkins CI 환경을 구축하면서 Jenkinsfile을 사용했다.
pipeline {
agent any
stages {
stage('build') {
steps {
echo 'building app'
}
}
stage('test') {
steps {
echo 'testing app'
}
}
stage('deploy') {
steps {
echo 'deploying app'
}
}
}
}
Jenkinsfile은 build, test, deploy 라는 stage로 나뉘어져 있고, 이들간에는 작업 순서가 존재한다.
이런 명령형 방식과는 다르게, GitOps를 이용하면 선언형 방식으로 애플리케이션을 배포할 수 있다.
예를 들어 쿠버네티스 클러스터에 어떤 리소스를 만들어 배포한다고 해보자.
아래와 같은 방법을 떠올릴 수 있다.
- kubectl create 명령어를 이용해 클러스터에 바로 생성
- kubectl apply 명령어를 이용해 YAML 파일을 기준으로 생성
이와 같은 방식은 애플리케이션의 크기가 작으면 상관 없지만,
크기가 증가함에 따라 파일이 여러개 생기므로 관리의 복잡성이 늘어난다는 단점이 있다.
GitOps는 이러한 불편함을 해결하기 위해 등장했다.
GitOps는 애플리케이션에 필요한 리소스와 설정들을 Git 하나로만 관리하겠다는 뜻이다.
즉, 배포의 기준이 되는 리소스가 단일 지점인 Git 하나뿐이니
모든 이들이 배포가 어떤 형태로 된 것이라는걸 동일하게 확인할 수 있다.
여러 개의 Manifest를 찾아가면서 현재 쿠버네티스 클러스터의 상태와 비교하여 apply 됐는지 일일이 확인할 필요없이,
Manifest들을 Git에 몰아넣고, 쿠버네티스 클러스터가 해당 Repo를 기준으로만 배포하게 만드는게 핵심이다.
이때 해당 Repo를 기준으로 현재 애플리케이션의 Sync를 맞춰주는 도구가 바로 ArgoCD이다.
ArgoCD 설치 with Helm
ArgoCD도 Jenkins와 마찬가지로 Helm을 통해 클러스터에 배포하였다.
https://github.com/argoproj/argo-helm/blob/main/charts/argo-cd/values.yaml
values yaml 파일은 위에 있는것을 가져와 프로젝트 상황에 맞게 변경하였다.
아래 명령어는 repo에 등록된 Chart의 value 파일을 values.yaml 파일로 redirect 하는 명령어이다.
helm show values argo/argo-cd > values.yaml
처음 values yaml 파일을 보았을 때, 무려 3000줄이 넘어가서 무엇을 건드려야 할지 잘 감이 오지 않았다.
공식문서와 레퍼런스를 참고하면서 건드려보았다.
아, 참고로 ArgoCD에서 공식적으로 제공하는 Helm Chart의 value 파일은
argocd라는 네임스페이스를 기준으로 작성되어 있기 때문에 사전에 argocd 네임스페이스를 만들어주어야 했다.
values 파일 수정하기
- config.params.server.rootpath
# -- Value for base href in index.html. Used if Argo CD is running behind reverse proxy under subpath different from /
server.basehref: /
# -- Used if Argo CD is running behind reverse proxy under subpath different from /
# server.rootpath: '' -> 'argocd'
server.rootpath: 'argocd'
# -- Directory path that contains additional static assets
server.staticassets: /shared/app
# -- Disable Argo CD RBAC for user authentication
Jenkins는 {admin 서브 도메인}/jenkins,
ArgoCD는 {admin 서브 도메인}/argocd
이런식으로 관리하고 싶었기에 rootpath를 '/' 이 아닌 'argocd'로 바꾸었다
이외에도 Slack과의 연동을 위해 추가한 부분이 있지만 아래에서 다시 설명하겠다.
ALB Ingress Rule 등록하기
argocd-server Service의 유형이 ClusterIP 이기에, 외부에 노출하기 위해서는 Ingress가 필요했다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-2:712744100487:certificate/xxxx-yyyy-zzzz
alb.ingress.kubernetes.io/ssl-redirect: '443'
alb.ingress.kubernetes.io/group.name: admin-alb
alb.ingress.kubernetes.io/group.order: '1'
namespace: argocd
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /argocd
pathType: Prefix
backend:
service:
name: argocd-server
port:
number: 80
위와 같이 Ingress Rule을 작성하고, 클러스터에 배포하면
기존에 Jenkins Ingress에 의해 프로비저닝됐던 ALB에 자동으로 Rule이 추가된다.
그런다음 브라우저에서 {admin 서브 도메인}/argocd 로 접속하면, 다음과 같은 로그인 화면이 나온다.
초기 아이디는 admin이며, password는 다음과 같은 명령어로 확인할 수 있다.
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
지금은 ArgoCD를 통해 배포하고 있기 때문에 애플리케이션이 보이지만, 원래는 아무것도 없을것이다.
ArgoCD의 동작 방식
설치는 이제 성공적으로 끝냈다. 다시 돌아와서,
ArgoCD의 동작 방식에 대해 좀 더 생각해볼 필요가 있었다.
우선, GitOps를 위해서는 Manifest 파일들을 모아놓은 Repo가 필요했다.
그래야 ArgoCD는 해당 Repo를 보고 현재 쿠버네티스 클러스터의 상태와 비교한 다음, 배포를 할지 말지 결정할 수 있다.
https://argo-cd.readthedocs.io/en/stable/
Argo CD - Declarative GitOps CD for Kubernetes
Overview What Is Argo CD? Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes. Why Argo CD? Application definitions, configurations, and environments should be declarative and version controlled. Application deployment and lifecycle ma
argo-cd.readthedocs.io
공식 문서를 참고해보면, ArgoCD가 관리할 수 있는 Manifest는
- kustomize
- helm
- plain yaml
- ...
등이 있다고 한다.
Plain Yaml
ArgoCD를 도입하기 이전까지, 수동으로 배포해야 하는 상황에서 사용해왔다.
쿠버네티스 리소스를 만드는 가장 기초적인 방법이며 직관적이지만,
운영상황에서 쓰기에는 아래와 같은 단점이 존재한다.
운영 환경 분리의 문제점
보통 프로젝트를 진행하면 dev 이외에 staging, production 등의 여러 환경별로 클러스터를 구성하게 된다.
문제는 dev 환경을 기준으로 작성한 plain yaml 파일이 다른 환경과 매우 비슷하다는 점이다.
가장 만만한 nginx deploy를 생각해보자.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-dev
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
volumeMounts:
- name: dev-secret
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: dev-secret
secret:
secretName: mysecret
아래는 prod 환경의 yaml 파일이다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-prod # 이름이 바뀌었다.
spec:
selector:
matchLabels:
app: nginx
replicas: 3 # 1 -> 3으로 증가했다.
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
volumeMounts:
- name: prod-secret # 이름이 바뀌었다.
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: prod-secret
secret:
secretName: mysecret
두 yaml 파일간의 차이점은 변수명에 지나지 않는다.
물론 이 외에도 prod 환경에서 추가되거나 삭제된 리소스 설정이 있을 순 있지만,
나머지 부분은 매우 유사한 구조를 가진다.
정리하자면, 운영환경별로 비슷한 yaml 파일을 만들어야 하므로 비효율적이다.
관리하기에 힘들고, 환경 별로 어떤 부분이 바뀌는지 쉽게 파악할 수 없다.
Kustomize
Kustomize는 이러한 문제점을 해결하기 위해 등장했다.
쿠버네티스 리소스를 보다 효율적으로 관리할 수 있게 해주는 도구이다.
k8s 1.14 버전부터 공식적으로 포함되어 kubectl 명령어를 통해 다룰 수 있다.
Kustomize의 기본 개념은, 각 운영환경별로 공통적으로 사용할 부분을 미리 정의해놓고(base)
환경 마다 다르게 처리해야할 부분을 base에 적용(patch)한다는 것이다.
patch 명령어를 적용할 yaml 파일을 각 운영 환경 별로 만들어주면, plain yaml 보다 쉽게 변경 사항을 이해할 수 있다.
Helm
Helm도 Kustomize와 동일한 역할을 하지만, 동작 방식에 있어서 차이가 있다.
Helm은 템플릿이라는 개념을 도입하여, patch가 아닌 injection 느낌으로 템플릿을 채워나간다.
언뜻 봐서는 Kustomize와 큰 차이가 없어보인다. 둘 다 하나의 타겟으로 여러 환경에 대응하고 있으니 말이다.
하지만 여러 가지 차이점이 존재한다.
Kustomize vs Helm
Kustomize는 우선 patch할 필드의 구조를 알아야 동작할 수 있다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-base
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
예를 들어 nginx-base deployment에서,
컨테이너의 이름은 spec.template.spec.containers.name[0] 과 같은 구조로 정의된다.
patch를 통해서 이름을 바꾸려면 정확히 구조를 알고있어야 한다.
하지만 Helm을 이용하면 구조를 자세히 알지 않아도 된다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-base
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: {{.Values.nginxName}}
image: nginx:1.14.2
위의 Chart는 템플릿화 되어있어 name 필드의 value를 외부에서 받아온다.
nginxName: "helm-test"
단지 value의 이름만 알고 있으면 된다.
물론 실제로 helm chart를 배포하고 운영하려면 구조를 알고있어야 하지만, 당장에 배포하는데에는 크게 문제가 없다.
이러한 이유로 Helm은 패키지 매니저의 역할도 자연스럽게 하게 된다.
우리가 패키지를 설치할 때 모든 구조를 다 알고 설치하지 않는것처럼 말이다.
우리는 그저 잘 추상화된 패키지에 value만 조정할 뿐이다.
결국은 Helm
이외에도 러닝커브, 레퍼런스등의 관점에서도 둘을 고민하다가 결국에는 Helm을 선택했다.
Helm을 선택하게 된 이유는 다음과 같다.
- Jenkins와 ArgoCD도 Helm을 이용해 배포했었다.(그나마 익숙함)
- Helm은 러닝커브가 높다고 알려져 있지만, 반대로 우리 프로젝트에는 어려운 문법이 필요하지 않았다.
- Kustomize까지 도입하게 된다면 사공이 너무 많은 느낌이었다.
Helm Chart는 Go 언어 템플릿 엔진을 사용하는데, 이 부분이 좀 낯설어 보였다.
Helm Chart Repo
ArgoCD의 동작방식에 대해 얘기하다가 여기까지 왔는데, 다시 돌아와서
우리는 ArgoCD가 관리할 Manifest를 Helm을 통해 관리하기로 했으므로,
Helm Chart 생성이 필요했다.
고민이 들었던 부분은 현재 프로젝트는 MSA 구조를 이루고 있는데,
각 서비스 마다 Chart 생성이 필요한것인지, 하나의 Chart로 관리해도 괜찮은것인지의 판단이 어려웠다
결국에는 여러 레퍼런스를 찾아보다가 구글의 MSA Helm Chart 구조를 채택했다.
https://github.com/GoogleCloudPlatform/microservices-demo
GitHub - GoogleCloudPlatform/microservices-demo: Sample cloud-first application with 10 microservices showcasing Kubernetes, Ist
Sample cloud-first application with 10 microservices showcasing Kubernetes, Istio, and gRPC. - GitHub - GoogleCloudPlatform/microservices-demo: Sample cloud-first application with 10 microservices ...
github.com
위 Repo는 MSA 애플리케이션을 배포하는 여러 가지 방법들을 소개한다.
Helm 이외에도 Kustomize, Raw Manifest 등의 방법의 가이드를 찾아볼 수 있었다.
그러나 하나의 Repo로 전체 서비스를 관리할 수 있다는 장점이 있지만, 단점도 분명 존재할 것이라 생각한다.
이는 프로젝트를 진행하면서 더 나은 방법이 있는지 찾아볼 예정이다.
이후 환경별로 사용할 values 파일을 추가한 다음 Github에 새로운 Repo를 생성했다.
https://github.com/SWM-YouQuiz/Helm
GitHub - SWM-YouQuiz/Helm: Helm charts for ArgoCD
Helm charts for ArgoCD. Contribute to SWM-YouQuiz/Helm development by creating an account on GitHub.
github.com
Repo 생성까지 끝냈으니 ArgoCD Application을 만들어보자.
다음 내용은 아래 포스트에서 이어진다.
AWS EKS ArgoCD 환경 구축하기 [2/2]
지난번 포스트에 이어 작성하겠다. AWS EKS ArgoCD 환경 구축하기 [1/2] ArgoCD란? ArgoCD는 CD 도구 중 하나로, GitOps 방식의 배포를 도와주는 오픈소스이다. 현재 프로젝트에서 CI 환경은 Jenkins ci를 통해
imsongkk.tistory.com
'Trouble Shooting' 카테고리의 다른 글
AWS EKS ArgoCD 환경 구축하기 [2/2] (0) | 2023.08.29 |
---|---|
Jenkins Webhook Multiple branch 빌드 하기 (0) | 2023.08.28 |
ALB Ingress Controller로 여러 개의 Ingress 처리하기 (0) | 2023.08.11 |
MSA 환경에서 Swagger 서버 구축하기 (0) | 2023.08.05 |
AWS EKS Jenkins 환경 구축하기 [2/2] (0) | 2023.07.31 |