개요
GitOps로 app 을 일괄적으로 관리하고 new app 이 추가되어도 구조가 바뀌지 않도록 하기 위한 방법을 생각해봤습니다. 그래서 하나의 폴더에 child application 을 생성하도록 하는 App of Apps 패턴을 사용하게 되었습니다. 이를 사용하면 배포 및 구성할 수 있는 apps 들을 선언적으로 관리 할 수 있습니다.
https://argo-cd.readthedocs.io/en/stable/operator-manual/cluster-bootstrapping/
디렉터리(GitOps) 구조
├── application.yaml
├── apps
│ ├── app-apache.yaml
│ ├── app-kustomize-guestbook.yaml
│ └── app-helm-nginx.yaml
├── charts
│ ├── apache
│ │ └── manifestfile.yaml
│ ├── helm-nginx
│ │ ├── Chart.lock
│ │ ├── Chart.yaml
│ │ ├── charts
│ │ │ └── common
│ │ │ ├── Chart.yaml
│ │ │ ├── templates
│ │ │ │ └── …
│ │ │ └── values.yaml
│ │ ├── templates
│ │ │ └── …
│ │ ├── values.schema.json
│ │ └── values.yaml
│ └── kustomize-guestbook
│ ├── guestbook-ui-deployment.yaml
│ ├── guestbook-ui-svc.yaml
│ └── kustomization.yaml
└── install
├── ingress.yaml
└── values.yaml
깃헙 소스코드 참고
https://github.com/Jena98/argocd-env.git
Main Application File
./application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: argocd
namespace: argocd
# Add a this finalizer ONLY if you want these to cascade delete.
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: apps
source:
repoURL: https://github.com/Jena98/argocd-env.git
targetRevision: HEAD
path: apps
destination:
server: https://kubernetes.default.svc
# The namespace will only be set for namespace-scoped resources that have not set a value for .metadata.namespace
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
# Namespace Auto-Creation ensures that namespace specified as the application destination exists in the destination cluster.
syncOptions:
- CreateNamespace=true
Application CRD는 환경에 배포된 애플리케이션 인스턴스를 나타내는 Kubernetes 리소스 개체입니다.
main application crd 은 child application crd 들을 찾는 방법을 argoCD에 알려줍니다. spec.source.path 를 apps 로 지정하고 있습니다. 해당 깃헙 주소의 apps 폴더 에는 child application crd 가 있으며, 이들은 자신들의 어플리케이션(manifest/charts/kustomize)을 가리킵니다.
참고
spec.destination.namespace 에 이름을 설정하고 syncPolicy.syncOptions.CreateNamespace 을 true 로 설정했다면, 가리키고 있는 app manifestfile 에 namespace 가 지정이 안되어 있으면 spec.destination.namespace 으로 자동 지정됩니다.
Child Application File
apps/app-apache.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: apache
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: apps
source:
repoURL: https://github.com/Jena98/argocd-env.git
targetRevision: HEAD
path: charts/apache
destination:
server: https://kubernetes.default.svc
namespace: my-apps
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
apps/app-kustomize-guestbook.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: kustomize-guestbook
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: apps
source:
repoURL: https://github.com/Jena98/argocd-env.git
targetRevision: HEAD
path: charts/kustomize-guestbook
destination:
server: https://kubernetes.default.svc
namespace: my-apps
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
apps/app-helm-nginx
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: helm-nginx
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: apps
source:
repoURL: https://github.com/Jena98/argocd-env.git
targetRevision: HEAD
path: charts/helm-nginx
destination:
server: https://kubernetes.default.svc
namespace: my-apps
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
application crd 들은 자신들의 어플리케이션(manifest/charts/kustomize)을 가리키고 있습니다. spec.source.path 를 보면 해당 어플리케이션의 위치를 알 수 있습니다. 어플리케이션 명세를 보기 전에 argocd ingress.yaml 을 살펴보겠습니다.
install/ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: argocd-ingress
namespace: argocd
annotations:
kubernetes.io/ingress.class: alb
# 다른 app들과 같은 alb를 공유하기 위해 추가
alb.ingress.kubernetes.io/group.name: my-alb
alb.ingress.kubernetes.io/group.order: '1'
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/certificate-arn: "AWS_ACM_CERT"
alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-2016-08
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80,"HTTPS": 443}]'
alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
labels:
app: argocd-ingress
spec:
rules:
- http:
paths:
- backend:
serviceName: ssl-redirect
servicePort: use-annotation
- host: "ARGOCD_HOSTNAME"
http:
paths:
- backend:
serviceName: argocd-server
servicePort: 443
argocd 를 포함한 모든 app 들이 리소스 비용을 절약하고자 하나의 alb 를 사용하기 위해 annotations 를 추가했습니다. (alb-ingress-controller, external-dns 배포 되어있습니다)
ingress 를 생성할 때 주의할 점이 있는데 metadata.name 을 서로 다르게 해야합니다. name이 같으면 같은 ingress 설정이라고 판단하고 설정을 덮어쓰게 되어 alb 리스너에는 마지막으로 적용한 하나의 리스너만 등록이 되기 때문입니다.
- alb.ingress.kubernetes.io/group.name : 모든 ingress의 그룹명을 동일하게 지정하여 하나의 alb 에 리스너 등록을 하도록 합니다.
- alb.ingress.kubernetes.io/group.order: 1~1000 사이의 수를 문자열의 형태로 입력하여 ingress 가 생성되는 순서를 지정합니다.
- https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.2/guide/ingress/annotations/#ingressgroup
Applications
charts/apache/manifestfile.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: apache-deployment
namespace: argocd
labels:
app: apache
spec:
replicas: 2
selector:
matchLabels:
app: apache
template:
metadata:
labels:
app: apache
spec:
containers:
- name: apache
image: httpd
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: apache-svc
namespace: argocd
spec:
selector:
app: apache
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30010
type: NodePort
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: apache-ingress
namespace: argocd
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/group.name: my-alb
alb.ingress.kubernetes.io/group.order: '2'
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS": 443}]'
labels:
app: argocd-ingress
spec:
rules:
- host: "apache.example.com"
http:
paths:
- backend:
serviceName: apache-svc
servicePort: 80
apache app 을 manifestfile 을 사용하여 생성하였습니다.
charts/kustomize-guestbook/guestbook-ui-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: guestbook-ui
spec:
ports:
- port: 80
targetPort: 80
selector:
app: guestbook-ui
type: NodePort
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: kguestbook-ingress
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/group.name: my-alb
alb.ingress.kubernetes.io/group.order: '3'
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS": 443}]'
labels:
app: argocd-ingress
spec:
rules:
- host: "kguestbook-ingress.example.com"
http:
paths:
- backend:
serviceName: kustomize-guestbook-ui
servicePort: 80
guestbook app 은 kustomize 를 사용하여 생성하였습니다. svc, ingress 부분만 살펴보겠습니다.
charts/helm-nginx
https://github.com/bitnami/charts/tree/master/bitnami/nginx
nginx helm chart 를 사용했습니다.
kustomize-guestbook, helm-nginx은 metadata.namespace 가 없으니 spec.destination.namespace 에서 지정한 my-apps 로 자동 생성되었겠군요. 확인해봅시다.
배포 자동화
이제 application.yaml 만 배포하면 자동적으로 하위 apps 들이 배포가 될 것입니다.
$ kubectl apply -f application.yaml
$ kubectl apply -f https://raw.githubusercontent.com/Jena98/argocd-env/master/application.yaml
※ 깃허브를 데이터 저장소로 활용하는 방법
https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{file_path}
main appclication 이 생성되고, gitops와 sync 되면 child applications 이 생성됩니다.
ALB 확인
각각 app 에 host 가 생성된 것을 확인 할 수 있습니다.
참고
https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#applications
'DevOps > CICD' 카테고리의 다른 글
GitOps, ArgoCD Overview (0) | 2023.10.11 |
---|---|
Argocd를 사용하여 helm chart 배포 및 주의사항 (1) | 2022.04.25 |
Github, Jenkins, argoCD를 사용하여 CI/CD 구축 (0) | 2022.01.24 |
Jenkins Pipeline Github Private Token 사용하여 연동 (0) | 2022.01.03 |
Jenkins, Codedeploy 사용하여 CICD 환경 구축 (0) | 2021.10.10 |