DevOps/CICD

argoCD App of Apps 패턴을 사용한 서비스 배포

Jen'_' 2022. 3. 11. 21:09
반응형

개요

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 리스너에는 마지막으로 적용한 하나의 리스너만 등록이 되기 때문입니다.

 

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} 

 

 

app of apps
app of apps

main appclication 이 생성되고, gitops와 sync 되면 child applications 이 생성됩니다.

 

 

ALB 확인

ALB 활성화

 

443 리스너

각각 app 에 host 가 생성된 것을 확인 할 수 있습니다.

 

 

 

 

 

참고

https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#applications

https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.2/guide/ingress/annotations/#annotations

 

반응형