CICD STUDY-4주차

dev_suha·2025년 11월 8일
0

Argo CD

애플리케이션 개발은 테스트, 스테이징, 프로덕션 환경으로 구분이 된다.

이러한 환경은 구성은 하나의 클러스터 안에서 네임스페이스로 구분

네임스페이스로 구성하고 필요한 모드 환경을 추가한다.

시간이 지남에 따라 인프라 자원들이 서로 다른 상태가 되는 현상 발생

Argo CD 사용 사례

  • 배포 자동화
    • git commit 또는 CI 파이프라인이 동작하고 수동 동기화를 트리거한 후에 argo CD 컨트롤러는 자동으로 클러스터를 git repository에 의도한 상태로 push
  • 관찰 가능성
    • Argo CD는 애플리케이션 상태가 깃에서 의도한 상태와 동기화돼 있는지 식별할 수 있는 UI 및 CLI를 제공하고 Argo CD Notifications 엔진을 제공
  • 멀티 테넌시
    • 인증을 위한 RBAC 정책을 사용해 여러 클러스터를 관리하고 배포하는 기능

용어

용어설명
application쿠버네티스 리소스 그룹은 매니페스트에 의해 규정된다.
Argo CD에서는 CRD에서 규정한다.
application source typehelm, kustomize, jsonnet 과 같이 애플리케이션을 구축하는 데 사용하는 도구
target state애플리케이션의 의도한 상태를 이야기하며 원천 소스인 git repository를 의미한다.
live state애플리케이션의 현재 상태로 k8s 클러스터에 배포된 상태를 의미한다.
sync state현재 상태와 target 상태가 일치하는지 확인한다.
synck8s cluster에 변화를 적용해 애플리케이션을 target 상태로 변경
sync operation status동기화 단계에서 작업이 실패인지 성공인지 여부를 보여준다.
refresh깃 리포지터리의 최신 코드와 현재 상태의 차이점을 비교한다.
health status애플리케이션이 요청을 받을 수 있고 운영 중인 상태인지를 말해준다.

argoCD 아키텍처

핵심 구성요소는 쿠버네티스 컨트롤러로 구성

쿠버네티스 컨트롤러 : 클러스터의 상태를 관찰한 다음 필요한 경우 변경 사항을 적용하거나 요청한다.

핵심 구성요소

  • API 서버
    • 애플리키에션 관리 및 상태 보고
    • 애플리케이션 trigger 작업
    • git repository와 k8s cluster 관리
    • 인증과 SSO 지원
    • RBAC 정책 강화
  • repository server
    • git repository cache 유지
    • git repository 서버에 매니페스트 가져오기 위한 매개변수
      • repository URL
      • git version
      • application path
      • 템플릿 세부설정
  • application controller
    • 리소스를 수정했는데 상태가 동기화되지 않은 경우, 컨트롤러가 상태를 동기화하려고 하며, 현재 상태를 의도한 상태와 맞추려고 한다.
    • 사용자가 생성한 hook 을 생명 주기 동안 실행

argoCD 핵심 오브젝트와 리소스

CRD : Argo CD 애플리케이션, 프로젝트, 리포지터리, 클러스터의 자격 증명과 설정 값들은 쿠버네티스 매니페스트를 이용해 선언적으로 정의

  • 애플리케이션
    • 실제 k8s 클러스터에 배포하려는 애플리케이션의 인스턴스를 application 이라는 CRD로 구현
  • 앱 프로젝트
    • 태그 지정과 같이 관련 있는 애플리케이션을 논리적으로 그룹화
  • 리포지터리 자격 증명
    • 실제에서는 private repository를 사용하기에 argo CD가 해당 repository에 접근하기 위해서는 접근 가능한 자격 증명이 필요하다.
    • argo CD는 이것을 k8s secrets과 configmap을 사용해 해결한다.
  • 클러스터 자격 증명
    • argoCD가 여러 클러스터를 관리하고 argo CD가 실행 중인 클러스터에 포함되지 않은 경우 다른 K8S 클러스터에 대한 액세스 권한을 얻어야 한다

Argo CD 설치 by Helm

kind k8s 배포

kind create cluster --name myk8s --image kindest/node:v1.32.8 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: **control-plane**
  extraPortMappings:
  - containerPort: 30000
    hostPort: 30000
  - containerPort: 30001
    hostPort: 30001
  - containerPort: 30002
    hostPort: 30002
  - containerPort: 30003
    hostPort: 30003
EOF

kube-ops-view

# kube-ops-view
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set service.main.type=**NodePort**,service.main.ports.http.nodePort=**30001** --set env.TZ="Asia/Seoul" --namespace kube-system

# kube-ops-view 접속 URL 확인 (1.5 , 2 배율)
open "http://127.0.0.1:30001/#scale=1.5"
open "http://127.0.0.1:30001/#scale=2"
kubectl create ns **argocd**
cat <<EOF > argocd-values.yaml
server:
  service:
    type: NodePort
    nodePortHttps: 30002
  extraArgs:
    - --insecure  # HTTPS 대신 HTTP 사용
EOF

helm repo add argo https://argoproj.github.io/argo-helm
helm install **argocd** argo/argo-cd --version 9.0.5 -f argocd-values.yaml --namespace argocd
  • -f argocd-values.yaml : 사용자 정의 values 파일 적용

접속 확인

kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d ;echo

xjcDxnMUJ82QrnqL

open "http://localhost:30002"

첫 애플리케이션 실행

cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: **guestbook
  namespace: argocd**
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  **source:**
    helm:
      valueFiles:
      - **values.yaml**
    path: **helm-guestbook**
    repoURL: **https://github.com/argoproj/argocd-example-apps**
    targetRevision: HEAD
  **syncPolicy**:
    automated:
      enabled: true
      prune: true
      **selfHeal: true**
    syncOptions:
    - CreateNamespace=true
  **destination:**
    namespace: guestbook
    server: https://kubernetes.default.svc
EOF

(|kind-myk8s:N/A) root@DESKTOP-8S932ET:/# kubectl get svc -n guestbook
NAME                       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
guestbook-helm-guestbook   ClusterIP   10.96.80.229   <none>        80/TCP    2m43s

# nodeport 변경 
kubectl patch svc -n guestbook guestbook-helm-guestbook -p '{"spec":{"type":"NodePort","ports":[{"port":80,"targetPort":80,"nodePort":30003}]}}'

안바뀌어지는 경우 
self heal disabled

(|kind-myk8s:N/A) root@DESKTOP-8S932ET:/# kubectl patch svc -n guestbook guestbook-helm-guestbook -p '{"spec":{"type":"NodePort","ports":[{"port":80,"targetPort":80,"nodePort":30003}]}}'
service/guestbook-helm-guestbook patched

(|kind-myk8s:N/A) root@DESKTOP-8S932ET:/# kubectl get svc -n guestbook
NAME                       TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
guestbook-helm-guestbook   NodePort   10.96.80.229   <none>        80:30003/TCP   4m44s

## nodeport로 변경 확인 

(|kind-myk8s:N/A) root@DESKTOP-8S932ET:/# curl http://localhost:30003
<html ng-app="redis">
  <head>
    <title>Guestbook</title>
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.min.js"></script>
    <script src="controllers.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.6/ui-bootstrap-tpls.js"></script>
  </head>
  <body ng-controller="RedisCtrl">
    <div style="width: 50%; margin-left: 20px">
      <h2>Guestbook</h2>
    <form>
    <fieldset>
    <input ng-model="msg" placeholder="Messages" class="form-control" type="text" name="input"><br>
    <button type="button" class="btn btn-primary" ng-click="controller.onRedis()">Submit</button>
    </fieldset>
    </form>
    <div>
      <div ng-repeat="msg in messages track by $index">
        {{msg}}
      </div>
    </div>
    </div>
  </body>
</html>
# 삭제 
(|kind-myk8s:N/A) root@DESKTOP-8S932ET:/# kubectl delete applications -n argocd guestbook

kind k8s 에 ingress-nginx 설치 후, ingress(도메인)을 통해 argocd 접근 설정 해보기

ingress nginx 설치

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx --create-namespace \
  --set controller.publishService.enabled=true

https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/#kubernetesingress-nginx

(|kind-myk8s:N/A) root@DESKTOP-8S932ET:/# cat <<'EOF' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-ingress
  namespace: argocd
  annotations:
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
spec:
  ingressClassName: nginx
  rules:
  - host: argocd.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: https
EOF

/etc/hosts 추가

127.0.0.1 argocd.example.com

port-forward

kubectl -n ingress-nginx port-forward svc/ingress-nginx-controller 443:443
  • 클러스터 내부에서만 접근 가능한 자원을 내 PC에서 직접 접근할 수 있게 터널을 여는 것

(|kind-myk8s:N/A) root@DESKTOP-8S932ET:~# argocd account list
NAME   ENABLED  CAPABILITIES
admin  true     login
(|kind-myk8s:N/A) root@DESKTOP-8S932ET:~# argocd proj list
NAME     DESCRIPTION  DESTINATIONS  SOURCES  CLUSTER-RESOURCE-WHITELIST  NAMESPACE-RESOURCE-BLACKLIST  SIGNATURE-KEYS  ORPHANED-RESOURCES  DESTINATION-SERVICE-ACCOUNTS
default               *,*           *        */*                         <none>                        <none>          disabled            <none>
(⎈|kind-myk8s:N/A) root@DESKTOP-8S932ET:~# argocd repo list
TYPE  NAME  REPO  INSECURE  OCI  LFS  CREDS  STATUS  MESSAGE  PROJECT
(⎈|kind-myk8s:N/A) root@DESKTOP-8S932ET:~# argocd cluster list
SERVER                          NAME        VERSION  STATUS   MESSAGE                                                  PROJECT
https://kubernetes.default.svc  in-cluster           Unknown  Cluster has no applications and is not being monitored.
(⎈|kind-myk8s:N/A) root@DESKTOP-8S932ET:~# argocd app list
NAME  CLUSTER  NAMESPACE  PROJECT  STATUS  HEALTH  SYNCPOLICY  CONDITIONS  REPO  PATH  TARGET

argocd cli

(|kind-myk8s:N/A) root@DESKTOP-8S932ET:~# argocd login 127.0.0.1:30002 --plaintext
Username: admin
Password:
'admin:login' logged in successfully
Context '127.0.0.1:30002' updated
(|kind-myk8s:N/A) root@DESKTOP-8S932ET:~# argocd account list
NAME   ENABLED  CAPABILITIES
admin  true     login
(|kind-myk8s:N/A) root@DESKTOP-8S932ET:~# argocd proj list
NAME     DESCRIPTION  DESTINATIONS  SOURCES  CLUSTER-RESOURCE-WHITELIST  NAMESPACE-RESOURCE-BLACKLIST  SIGNATURE-KEYS  ORPHANED-RESOURCES  DESTINATION-SERVICE-ACCOUNTS
default               *,*           *        */*                         <none>                        <none>          disabled            <none>
(⎈|kind-myk8s:N/A) root@DESKTOP-8S932ET:~# argocd repo list
TYPE  NAME  REPO  INSECURE  OCI  LFS  CREDS  STATUS  MESSAGE  PROJECT
(⎈|kind-myk8s:N/A) root@DESKTOP-8S932ET:~# argocd cluster list
SERVER                          NAME        VERSION  STATUS   MESSAGE                                                  PROJECT
https://kubernetes.default.svc  in-cluster           Unknown  Cluster has no applications and is not being monitored.
(⎈|kind-myk8s:N/A) root@DESKTOP-8S932ET:~# argocd app list
NAME  CLUSTER  NAMESPACE  PROJECT  STATUS  HEALTH  SYNCPOLICY  CONDITIONS  REPO  PATH  TARGET

argo cd 공식 app 을 배포해보고, app 별 특징을 정리

https://github.com/argoproj/argocd-example-apps

ArgoCD 10편 - App of Apps 패턴

Blue Green

  • Argo Rollouts controller 설치
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml

Argo Rollouts는 Kubernetes 환경에서 블루-그린(Blue-Green), 카나리(Canary), 실시간 트래픽 조정, 자동 롤백 같은 고급 배포 전략을 구현할 수 있게 해주는 배포 컨트롤러(Deployment Controller)입니다.

블루-그린 전략은 Kubernetes의 기본 Deployment에서는 지원되지 않지만, 서드파티 Kubernetes 컨트롤러를 통해 사용할 수 있습니다. 이 예제는 Argo Rollouts를 통해 블루-그린 배포를 구현하는 방법을 보여줍니다:

  1. Argo Rollouts 컨트롤러를 설치합니다: https://github.com/argoproj/argo-rollouts#installation
  2. 샘플 애플리케이션을 생성하고 동기화합니다.
argocd app create --name blue-green --repo https://github.com/argoproj/argocd-example-apps --dest-server https://kubernetes.default.svc --dest-namespace default --path blue-green && argocd app sync blue-green

애플리케이션이 동기화되면 blue-green-helm-guestbook 서비스를 통해 접근할 수 있습니다.

  1. 블루-그린 배포 프로세스를 시작하기 위해 이미지 버전 파라미터를 변경합니다:
argocd app set blue-green -p image.tag=0.2 && argocd app sync blue-gree

이제 애플리케이션은 ks-guestbook-demo:0.1ks-guestbook-demo:0.2 이미지를 동시에 실행합니다. ks-guestbook-demo:0.2는 아직 blue 상태로 간주되며, 프리뷰 서비스 blue-green-helm-guestbook-preview를 통해서만 접근 가능합니다.

  1. Rollout 리소스를 패치하여 ks-guestbook-demo:0.2green으로 승격시킵니다:
argocd app patch-resource blue-green --kind Rollout --resource-name blue-green-helm-guestbook --patch '{ "status": { "verifyingPreview": false } }' --patch-type 'application/merge-patch+json'

이렇게 하면 ks-guestbook-demo:0.2green 상태로 승격되고, Rolloutks-guestbook-demo:0.1을 실행하는 이전 레플리카를 삭제합니다.

guestbook

 argocd app create guestbook   --repo https://github.com/argoproj/argocd-example-apps.git   --path helm-guestbook   --dest-server https://kubernetes.default.svc   --dest-namespace default
  • 순수 Kubernetes 매니페스트(Deployment, Service, ConfigMap 등 직접 기술)

helm-guestbook

argocd app create helm-guestbook   --repo https://github.com/argoproj/argocd-example
-apps.git   --path helm-guestbook   --dest-server https://kubernetes.default.svc   --dest-namespace default
  • Helm Chart 구조(Chart.yaml, values.yaml, templates/)

helm-dependency

argocd app create helm-dependency   --repo https://github.com/argoproj/argocd-exampl
e-apps.git   --path helm-dependency   --dest-server https://kubernetes.default.svc   --dest-namespace default

kustomization-guestbook

argocd app create kustomize-guestbook   --repo https://github.com/argoproj/argocd-ex
ample-apps.git   --path kustomize-guestbook   --dest-server https://kubernetes.default.svc   --dest-namespace default
  • Kustomize는 YAML 템플릿 없이 base + overlay 구조로 Kubernetes 리소스를 재사용* 변형하는 도구
namePrefix: kustomize-

resources:
- guestbook-ui-deployment.yaml
- guestbook-ui-svc.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

argo-cd autopilot

Argo-CD Autopilot

git 저장소에 code를 push 해도 argocd application이 자동으로 생성되지 않는다.

사용자가 수동으로 argocd application을 만들어야 한다.

Argo-CD Autopilot 제공 기능

  • gitops를 사용해 bootstrap argo cd 애플리케이션을 생성하고 관리
  • github repository를 짜여진 구조로 셋팅하여 새로운 서비스를 추가하고 argo cd의 수명 주기에 적용

Argo-CD Autopilot 아키텍처

  • Autopilot이 ArgoCD 자체를 GitOps 방식으로 “스스로 설치하고 관리”하게 만드는 초기 설정(bootstrap) 과정
  1. Autopilot이 ArgoCD 매니페스트를 K8s 클러스터에 적용하고
  2. 동시에 Git 저장소에 그 설정 내용을 커밋함으로써
  3. ArgoCD가 자기 자신(ArgoCD 설치) 을 Git으로부터 관리하게 만듭니다.
구분기존 설치 방식Autopilot 방식
설치 주체사용자가 kubectl applyAutopilot CLI
ArgoCD 자기 관리 여부❌ 없음 (사람이 직접 관리)✅ 있음 (자기 자신을 GitOps로 관리)
Git 연동 시점설치 후 수동 설정설치 중 자동 연결
재현성환경마다 매번 수동 작업 필요Git 저장소만 있으면 자동 재설치 가능
관리 패턴수동 DevOps완전한 GitOps

argocd-autopilot CLI 설치

# install : Linux and WSL (using curl)
VERSION=$(curl --silent "https://api.github.com/repos/argoproj-labs/argocd-autopilot/releases/latest" | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')
curl -L --output - https://github.com/argoproj-labs/argocd-autopilot/releases/download/"$VERSION"/argocd-autopilot-linux-amd64.tar.gz | tar zx
mv ./argocd-autopilot-* /usr/local/bin/argocd-autopilot
argocd-autopilot version

Git 레포지토리 생성 : Private & token


get start (argocd-autopilot repo bootstrap)

  • argocd-autopilot repo bootstrap : 매니페스트를 푸시하고 깃 리포지터리 안에 필요한 구조를 생성
(|kind-myk8s:N/A) root@DESKTOP-8S932ET:~# export GIT_TOKEN=ghp_ojW4KoKV6BGnXlNUqJl
(|kind-myk8s:N/A) root@DESKTOP-8S932ET:~# export GIT_REPO=https://github.com/hp0724/autopilot.git
# Bootstrap Argo-CD
**argocd-autopilot repo bootstrap**

INFO pushing bootstrap manifests to repo
Resolving deltas: 100% (1/1), done.
INFO applying argo-cd bootstrap application
I1104 23:32:21.663669   29305 warnings.go:110] "Warning: metadata.finalizers: \"resources-finalizer.argocd.argoproj.io\": prefer a domain-qualified finalizer name including a path (/) to avoid accidental conflicts with other finalizer writers"
application.argoproj.io/autopilot-bootstrap created
INFO running argocd login to initialize argocd config
'admin:login' logged in successfully
Context 'autopilot' updated

INFO argocd initialized. password: ZNpw3JoGiyxut7tF
INFO run:

    kubectl port-forward -n argocd svc/argocd-server 8080:80

  • port forwording 통해서 Argo CD UI 접근 가능

  • bootstrap은 GitOps용 리포지토리를 초기화합니다.
폴더역할
bootstrap/Argo CD 및 클러스터 초기 부트스트랩 구성
apps/실제 배포 애플리케이션 정의 (GitOps 대상)
projects/애플리케이션 그룹화 및 정책 설정
.autopilot/Autopilot 내부 상태 관리용

App of Apps 패턴

argoCD는 원래 하나의 Application이 하나의 git 경로를 바라보고, 그 안에 있는 매니페스트를 클러스터에 배포하는 구조

ArgoCD application을 모아서 관리하는 패턴을 app of apps패턴

ArgoCD Application이 또 다른 ArgoCD Application들을 만들어주는 구조

“앱들의 앱” → App of Apps

새롭게 구축한 쿠버네티스 클러스터에 필요한 쿠버네티스 리소스를 빠르게 배포하는 것을 cluster bootstrapping

동일한 app of apps패턴을 여러 클러스터에 배포하면 동일한 쿠버네티스 인프라가 구축

동작 흐름

  1. Root Application(또는 Parent Application)을 하나 만듭니다.
  2. 이 Root App이 Git 저장소의 특정 디렉터리를 봅니다. (예: apps/)
  3. 그 디렉터리 안에는 ArgoCD Application 매니페스트들이 여러 개 들어 있습니다.
  4. Root App을 Sync하면,
    • Root App이 먼저 적용되고
    • 그 안에 정의된 여러 하위 Application들이 ArgoCD에 “등록”됩니다.
  5. 등록된 하위 Application들이 자기들이 바라보는 Git 경로를 다시 배포합니다.

장점

  1. 구조화
    • 환경별(dev/stage/prod)로 루트 앱만 다르게 두면 됨
    • 팀별(apps/team-a, apps/team-b)로도 나눌 수 있음
  2. 확장성
    • 새로운 서비스 생기면 Git에 Application 하나 추가 → root-app sync → 자동 등록
  3. GitOps 일원화
    • ArgoCD UI에서 일일이 앱 만들 필요 없이 Git만 관리
  4. 권한 분리하기 좋음
    • 최상위(Platform 팀)만 root-app을 관리
    • 각 서비스 팀은 자기 Application 디렉터리만 PR로 추가

Project 생성, Application 추가

export GIT_TOKEN=*<자신의 Git Token>*
export GIT_REPO=*<자신의 Repo>*
**argocd-autopilot project create dev
argocd-autopilot project create prd**

(|kind-myk8s:N/A) root@DESKTOP-8S932ET:~# kubectl get appprojects.argoproj.io -n argocd
NAME      AGE
default   47h
dev       2m55s
prd       2m55s


  • Application 추가
(|kind-myk8s:N/A) root@DESKTOP-8S932ET:~# argocd-autopilot app create hello-world1 --app github.com/argoproj-labs/argocd-autopilot/examples/demo-app/ -p dev --type kustomize
INFO cloning git repository: https://github.com/hp0724/autopilot.git
Enumerating objects: 19, done.
Counting objects: 100% (19/19), done.
Compressing objects: 100% (16/16), done.
Total 19 (delta 3), reused 17 (delta 1), pack-reused 0 (from 0)
INFO using revision: "", installation path: "/"
INFO committing changes to gitops repo...
INFO installed application: hello-world1
(|kind-myk8s:N/A) root@DESKTOP-8S932ET:~# argocd-autopilot app create hello-world2 --app github.com/argoproj-labs/argocd-autopilot/examples/demo-app/ -p prd --type kustomize
INFO cloning git repository: https://github.com/hp0724/autopilot.git
Enumerating objects: 26, done.
Counting objects: 100% (26/26), done.
Compressing objects: 100% (22/22), done.
Total 26 (delta 4), reused 23 (delta 1), pack-reused 0 (from 0)
INFO using revision: "", installation path: "/"
INFO committing changes to gitops repo...
INFO installed application: hello-world2
(|kind-myk8s:N/A) root@DESKTOP-8S932ET:~# argocd-autopilot app delete hello-world2 -p prd
INFO cloning git repository: https://github.com/hp0724/autopilot.git
Enumerating objects: 30, done.
Counting objects: 100% (30/30), done.
Compressing objects: 100% (25/25), done.
Total 30 (delta 5), reused 26 (delta 1), pack-reused 0 (from 0)
INFO using revision: "", installation path: "/"
INFO committing changes to gitops repo...
(|kind-myk8s:N/A) root@DESKTOP-8S932ET:~# kubectl get applications.argoproj.io -n argocd -owide
NAME                           SYNC STATUS   HEALTH STATUS   REVISION                                   PROJECT
argo-cd                        Synced        Healthy         6319514589a7780dcd9a23e67e8a87c036bdaa61   default
autopilot-bootstrap            Synced        Healthy         c247b6c5390725392e794824ba20d941843cbc8a   default
cluster-resources-in-cluster   Synced        Healthy         6319514589a7780dcd9a23e67e8a87c036bdaa61   default
dev-hello-world1               Synced        Healthy         6319514589a7780dcd9a23e67e8a87c036bdaa61   dev
root                           Synced        Healthy         6319514589a7780dcd9a23e67e8a87c036bdaa61   default

동기화 원리

k8s 클러스터에 변경 내용을 적용해 애플리케이션을 target 상태로 만드는 단계

phase

Phase실행 시점주요 역할예시 Hook
PreSync리소스를 실제로 적용하기 직전사전 작업 수행 (예: 백업, 점검, 알림 등)Job, ConfigMap, Script
SyncGit의 선언된 상태를 클러스터에 반영하는 단계Deployment, Service 등 리소스를 생성/업데이트실제 Kubernetes 리소스 적용
PostSync리소스 적용이 끝난 직후검증, 테스트, 후처리 등 수행Job, Pod, Script

resource hook

  • sync 단계 전, 중, 후에 다른 작업을 실행할 수 있는 권한 제공
  • 리소스 훅은 논리적인 순서나 사용 사례에 맞게 매니페스트 동기화 순서를 배치하는 데 유리하다.
단계(Phase)조건(Trigger)설명결과
PreSyncSync 시작 전리소스를 실제로 적용하기 전에 실행되는 단계. 주로 백업, 점검, 준비 작업 등에 사용됨.성공 시 → Sync 단계로 진행
SyncPreSync 성공 후Git에 정의된 쿠버네티스 리소스를 실제 클러스터에 적용하는 핵심 단계.성공 시 → PostSync로 진행실패 시 → SyncFail로 이동
PostSyncSync 성공 후리소스 배포가 완료된 후 실행되는 후처리 단계. 테스트, 알림, 정리 작업 등에 사용됨.완료 시 Sync 종료
SyncFailSync 실패 시Sync 과정 중 오류가 발생했을 때 실행되는 복구/알림 단계.오류 처리 및 로그 기록 수행
  • 리소스 hook은 k8s 매니페스트에 적용된다.

  • 리소스 hook은 k8s 매니페스트에 적용된다.

apiVersion: batch/v1
kind: Job
metadata:
  name: db-migrate
  annotations:
    **argocd.argoproj.io/hook: PreSync**

resource hook 실습

argocd-example-apps/pre-post-sync at master · argoproj/argocd-example-apps

apiVersion: batch/v1
kind: Job
metadata:
  name: before
  annotations:
    argocd.argoproj.io/hook: PreSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      containers:
      - name: sleep
        image: alpine:latest
        command: ["sleep", "10"]
      restartPolicy: Never
  backoffLimit: 0
  • argocd.argoproj.io/hook: PreSync → Argo CD가 앱을 sync하기 전에 이 Job을 실행합니다. (즉, 리소스 배포 전에 미리 실행되는 작업)
  • argocd.argoproj.io/hook-delete-policy: HookSucceeded → Job이 성공하면 자동으로 삭제됩니다. 실패 시엔 로그를 남기기 위해 남습니다.
  • Sync 전에 10초 대기하는 역할을 하는 “사전 훅(PreSync)”
apiVersion: batch/v1
kind: Job
metadata:
  name: after
  annotations:
    argocd.argoproj.io/hook: PostSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      containers:
      - name: sleep
        image: alpine:latest
        command: ["sleep", "10"]
      restartPolicy: Never
  backoffLimit: 0
  • PostSync → Argo CD가 앱의 모든 리소스를 성공적으로 배포한 이후 실행됩니다.
  • HookSucceeded로 지정했으므로 Job이 성공하면 자동 삭제됩니다.
  • 내부 spec은 PreSync Job과 동일하게 10초 대기.
namePrefix: pre-post-sync-

bases:
- ../kustomize-guestbook

resources:
- pre-sync-job.yaml
- post-sync-job.yaml
  • 원래 guestbook 배포 흐름에 PreSync/ PostSync 훅 Job을 삽입하는 Kustomize 오버레이

동기화 웨이브

  • 매니페스트 실행 순서를 재배치

Argo CD는 다음 순서에 따라 리소스를 변경

  1. 어노테이션 확인
  2. 웨이브 어노테이션
  3. k8s 리소스 종류
  4. 이름 (오름차순)

sync-waves/manifests.yaml

---
apiVersion: batch/v1
kind: Job
metadata:
  generateName: upgrade-sql-schema
  annotations:
    argocd.argoproj.io/hook: PreSync
spec:
  template:
    spec:
      containers:
        - name: upgrade-sql-schema
          image: alpine:latest
          command: ["sleep", "5"]
      restartPolicy: Never
---
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      tier: backend
  template:
    metadata:
      labels:
        tier: backend
    spec:
      containers:
        - name: main
          image: nginx:latest
---
apiVersion: v1
kind: Service
metadata:
  name: backend
spec:
  selector:
    tier: backend
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
---
apiVersion: batch/v1
kind: Job
metadata:
  name: maint-page-up
  annotations:
    argocd.argoproj.io/hook: Sync
    argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
    argocd.argoproj.io/sync-wave: "1"
spec:
  template:
    spec:
      containers:
        - name: page-up
          image: alpine:latest
          command: ["sleep", "2"]
      restartPolicy: Never
  backoffLimit: 0
---
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
  annotations:
    argocd.argoproj.io/sync-wave: "2"
spec:
  replicas: 1
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
        - name: main
          image: nginx:latest
---
apiVersion: v1
kind: Service
metadata:
  name: frontend
  annotations:
    argocd.argoproj.io/sync-wave: "2"
spec:
  selector:
    tier: frontend
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
---
apiVersion: batch/v1
kind: Job
metadata:
  name: maint-page-down
  annotations:
    argocd.argoproj.io/hook: Sync
    argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
    argocd.argoproj.io/sync-wave: "3"
spec:
  template:
    spec:
      containers:
        - name: page-down
          image: alpine:latest
          command: ["sleep", "2"]
      restartPolicy: Never
  • 순서에 따라서 배포되는것을 확인

동기화 windows

  • 언제 애플리케이션을 동기화할 수 있는지를 제한하는 기능
apiVersion: argoproj.io/v1alpha1
kind: **AppProject**
metadata:
  name: default
spec:
  syncWindows:
  - kind: **allow # 허용**
    schedule: '10 1 * * *' # cron 형식 지원
    duration: 1h # 얼마동안
    applications: # application or namespace or cluster
    - '*-prod'   # 이름이 -prod로 끝나는 모든 애플리케이션
    manualSync: true
  - kind: **deny # 차단**
    schedule: '0 22 * * *'
    timeZone: "Europe/Amsterdam"
    duration: 1h
    namespaces:
    - default
  - kind: allow
    schedule: '0 23 * * *'
    duration: 1h
    clusters:
    - in-cluster
    - cluster1
필드설명
kindallow 또는 deny (해당 시간대에 배포를 허용할지, 금지할지)
schedulecron-like 표현식으로 요일/시간 지정 가능 (Mon-Fri 09:00-18:00 등)
duration윈도우 지속 시간 (예: 2h, 24h)
applications해당 규칙을 적용할 Application 목록 (*이면 전체)

리소스 삭제

kind delete cluster --name myk8s

argocd 운영

Kind k8s 배포

# kind k8s 배포
kind create cluster --name myk8s --image kindest/node:v1.32.8 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30000
    hostPort: 30000
  - containerPort: 30001
    hostPort: 30001
  - containerPort: 30002
    hostPort: 30002
  - containerPort: 30003
    hostPort: 30003
- role: worker
- role: worker
- role: worker
EOF

# kube-ops-view
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set service.main.type=NodePort,service.main.ports.http.nodePort=30001 --set env.TZ="Asia/Seoul" --namespace kube-system

# kube-ops-view 접속 URL 확인 (1.5 , 2 배율)
open "http://127.0.0.1:30001/#scale=1.5"
open "http://127.0.0.1:30001/#scale=2"
  • worker 3대 구성
mkdir resources

# 매니페스트 파일 작성 및 배포
cat << EOF > resources/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: argocd
EOF

**kubectl apply -f resources/namespace.yaml**
cd resources
wget https://raw.githubusercontent.com/argoproj/argo-cd/refs/heads/master/manifests/**ha**/install.yaml

**kubectl apply -f resources/install.yaml -n argocd**

# 확인
watch -d kubectl get pod -n argocd
kubectl port-forward svc/argocd-server -n argocd 8080:80

#
kubectl get secret -n argocd argocd-initial-admin-secret -o jsonpath='{.data.password}' | base64 -d ; echo
*UOn2CEkg0c4RCfQU*
open https://127.0.0.1:8080 # 프로덕션의 경우 TLS인증서가 적용된 로드밸랜서 서비스로 오픈하자

# 원격 리포지터리에 커밋하고 푸시한다.
git add . && git commit -m "Deploy Argo CD " && git push -u origin main
****
(|kind-myk8s:N/A) root@DESKTOP-8S932ET:~/resources# kubectl get pods -n argocd
NAME                                                READY   STATUS     RESTARTS   AGE
argocd-application-controller-0                     1/1     Running    0          2m6s
argocd-applicationset-controller-694b4774cd-pg4h9   1/1     Running    0          2m7s
argocd-dex-server-66585dc685-rnqsc                  1/1     Running    0          2m7s
argocd-notifications-controller-7c584f65cc-x827l    1/1     Running    0          2m7s
argocd-redis-ha-haproxy-7487b954d9-8g6td            1/1     Running    0          2m7s
argocd-redis-ha-haproxy-7487b954d9-jc5bm            1/1     Running    0          2m7s
argocd-redis-ha-haproxy-7487b954d9-pxcg8            1/1     Running    0          2m7s
argocd-redis-ha-server-0                            0/3     Init:0/1   0          2m6s
argocd-repo-server-74b54f7cb-46829                  1/1     Running    0          2m7s
argocd-repo-server-74b54f7cb-jcd25                  1/1     Running    0          2m7s
argocd-server-8b767f58c-gb4kf                       1/1     Running    0          2m7s
argocd-server-8b767f58c-lld6w                       1/1     Running    0          2m6s

# svc 연결 
kubectl port-forward svc/argocd-server -n argocd 8080:80

#
kubectl get secret -n argocd argocd-initial-admin-secret -o jsonpath='{.data.password}' | base64 -d ; echo
*UOn2CEkg0c4RCfQU*
open https://127.0.0.1:8080 # 프로덕션의 경우 TLS인증서가 적용된 로드밸랜서 서비스로 오픈하자

# 원격 리포지터리에 커밋하고 푸시한다.
git add . && git commit -m "Deploy Argo CD " && git push -u origin main

network policy 삭제

  • install.yaml 에서 network policy 삭제
 git add . && git commit -m "Delete Network Policy Resource" && git push -u origin main

HA 운영

argocd는 기본적으로 무상태 구조

중요한 데이터는 k8s object로 저장되고, etcd가 있으니깐 pod 하나가 죽어도 전체 설정이 날아가지는 않는다.

그럼에도 HA를 통해서 여러 개의 pod를 띄우면 장애나 배포 시에도 끊기지 않고 서비스 유지가 가능

컴포넌트 어떤거 늘려야 하나 ?

  1. argocd-repo-server
  2. argocd-application-controller
  3. argocd-server
  4. dex, redis

argocd-repo-server

git clone하고, helm, kustomize, plugin으로 매니페스트를 만들어주는 친구

  • 해당 서버는 매니페스트 생성 시 동시에 너무 많이 돌면 메모리/스레드 한계로 죽을 수 있음 → --parallelismlimit로 동시 작업 수를 제한하라.
  • /tmp에 클론하기 때문에 디스크 부족 나면 PVC 붙여라.

argocd-application-controller

Git에서 만들어진 매니페스트와 실제 클러스터 상태를 비교해서 “이 앱을 동기화해야 하나?”를 결정하는 핵심 컨트롤러.

  • 상태 확인큐
    • —status-processors
  • 실제 동기화 큐
    • —operation-processors

컨트롤러는 Kubernetes 리소스를 watch해서 자체 캐시를 유지하므로, 규모가 커질수록 이 부분 튜닝이 중요하다

argocd-server

사용자가 접속하는 서버라 여러 개 띄우면 좋습니다

dex, redis

  • dex는 메모리 DB라 2개 이상 띄우면 데이터가 안 맞을 수 있으니 주의
  • Redis는 HA 모드로 돌리도록 매니페스트가 준비돼 있고, 총 3개(redis+sentinel) 구성으로 가정합니다.

관찰 가능성

구분모니터링 (Monitoring)관측 가능성 (Observability)
목적상태 감시, 이상 탐지문제 원인 분석, 내부 이해
질문 예시“문제가 생겼는가?”“왜 문제가 생겼는가?”
데이터 형태Metrics 중심Logs + Metrics + Traces
도구 예시Prometheus, GrafanaELK Stack, Jaeger, OpenTelemetry
접근 방식사전 정의된 지표 관찰시스템 내부 상태를 추론 가능하게 설계
요소설명
Logs시스템 내 세부 이벤트 기록 (예: 에러 메시지, 요청 처리 로그)
Metrics성능 지표 (예: CPU 사용률, 응답 시간, 에러율)
Traces요청이 여러 서비스 간을 이동할 때 전체 경로 추적

push, pull 장단점

방식장점단점
Push- 대상 시스템의 제어 가능- 빠른 데이터 전송- 비동기적 수집- 네트워크 부하 증가- 시스템 과부하 가능성- 수집 실패 위험
Pull- 중앙 집중식 관리- 대규모 시스템에 적합- 누락된 데이터 처리 용이- 모니터링 시스템의 부하 증가- 응답 지연 발생- 비효율적인 네트워크 사용

0개의 댓글