티스토리 뷰

AEWS study

8주차 - K8S CI/CD - #2

haru224 2025. 3. 29. 23:11

CloudNet@ 가시다님이 진행하는 AWS EKS Hands-on Study 내용 참고.

 

3. Argo CD + K8S(Kind)


☞ Argo CD 소개 : Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes

  • 애플리케이션 정의, 구성, 환경은 선언적(declarative)이어야 하며 버전 관리되어야 합니다.
  • 애플리케이션의 배포 및 수명 주기 관리는 자동화되고, 감사 가능하며, 이해하기 쉬워야 합니다.
  • 작동 방식: Argo CD는 Git 리포지토리를 원하는 애플리케이션 상태(desired state)를 정의하는 소스 오브 트루스(source of truth)로 사용하는 GitOps 패턴을 따릅니다. Kubernetes 매니페스트는 여러 가지 방식으로 지정할 수 있습니다:
    • kustomize applications
    • helm charts
    • jsonnet files
    • Plain directory of YAML/json manifests
    • Any custom config management tool configured as a config management plugin
  • Architecture : Git → (DESIRED) ArgoCD (LIVE) ⇒ K8S - Docs

출처: https://argo-cd.readthedocs.io/en/stable/

 

 

  • API Server: Web UI 대시보드, k8s API처럼 API 서버 역할
    • API 서버는 Web UI, CLI, CI/CD 시스템에서 사용하는 API를 노출하는 gRPC/REST 서버입니다. 다음과 같은 역할을 담당합니다:
    • 애플리케이션 관리 및 상태 보고
    • 애플리케이션 작업 실행 (예: 동기화, 롤백, 사용자 정의 작업)
    • 리포지토리 및 클러스터 자격 증명 관리 (Kubernetes 시크릿으로 저장)
    • 외부 인증 제공자에 대한 인증 및 인증 위임
    • RBAC(역할 기반 접근 제어) 적용
    • Git 웹훅 이벤트 수신 및 전달 역할
  • Repository Server : Git 연결 및 배포할 yaml 생성
    • 리포지토리 서버는 애플리케이션 매니페스트를 포함하고 있는 Git 리포지토리의 로컬 캐시를 유지하는 내부 서비스입니다. 다음 입력을 받아 Kubernetes 매니페스트를 생성하고 반환하는 역할을 합니다:
    • 리포지토리 URL
    • 리비전 (커밋, 태그, 브랜치)
    • 애플리케이션 경로
    • 템플릿별 설정: 파라미터, Helm values.yaml
  • Application Controller : k8s 리소스 모니터링, Git과 비교 
    • 애플리케이션 컨트롤러는 실행 중인 애플리케이션을 지속적으로 모니터링하고 현재 상태와 리포지토리에 정의된 원하는 목표 상태를 비교하는 Kubernetes 컨트롤러입니다.
    • OutOfSync 상태를 감지하고, 필요 시 자동으로 수정 작업을 수행합니다.
    • 수명 주기 이벤트(PreSync, Sync, PostSync)에 대해 사용자 정의 훅을 호출하는 역할도 수행합니다.
  • Redis: Kubernetes API 및 Git 요청을 줄이기 위한 캐시 역할
  • Notification: 이벤트 알림 및 트리거 처리
  • Dex: 외부 인증 관리
  • ApplicationSet 컨트롤러: 멀티 클러스터를 위한 애플리케이션 패키징 관리

 

출처: https://argo-cd.readthedocs.io/en/stable/developer-guide/architecture/components/

 

  • 기능
    • 지정된 대상 환경에 애플리케이션을 자동 배포
    • 다양한 구성 관리/템플릿 도구 지원 (Kustomize, Helm, Jsonnet, plain-YAML)
    • 여러 클러스터에 대한 관리 및 배포 가능
    • SSO 통합 지원 (OIDC, OAuth2, LDAP, SAML 2.0, GitHub, GitLab, Microsoft, LinkedIn)
    • 멀티 테넌시 및 권한 부여를 위한 RBAC 정책
    • Git 리포지토리에 커밋된 모든 애플리케이션 구성으로 롤백/어디서든 롤
    • 애플리케이션 리소스의 상태 분석 기능
    • 구성 드리프트(불일치) 자동 감지 및 시각화
    • 애플리케이션을 원하는 상태로 자동 또는 수동 동기화
    • 실시간 애플리케이션 활동을 보여주는 Web UI
    • 자동화 및 CI 통합을 위한 CLI
    • 웹훅 통합 (GitHub, BitBucket, GitLab)
    • 자동화를 위한 액세스 토큰 지원
    • 복잡한 애플리케이션 롤아웃(예: 블루/그린, 카나리 업그레이드)을 위한 PreSync, Sync, PostSync 훅
    • 애플리케이션 이벤트 및 API 호출에 대한 감사 로그 제공
    • Prometheus 메트릭 제공
    • Git에 정의된 Helm 파라미터를 재정의하는 파라미터 오버라이드 기능
  • 핵심 개념 – Docs
    • Application : 매니페스트에 의해 정의된 Kubernetes 리소스들의 그룹. Custom Resource Definition(CRD).
    • Application source type : 애플리케이션 생성을 위해 사용하는 도구.
    • Target state : Git 리포지토리에 정의된 애플리케이션의 원하는 상태.
    • Live state : 현재 클러스터에 배포되어 있는 애플리케이션의 실제 상태 (실행 중인 파드 등).
    • Sync status : 실행 상태가 목표 상태와 일치하는지 여부. 실제 배포된 애플리케이션이 Git에 정의된 것과 동일한가?
    • Sync : 애플리케이션을 목표 상태로 이동시키는 과정. 예: Kubernetes 클러스터에 변경사항 적용.
    • Sync operation status : 동기화가 성공했는지 여부.
    • Refresh : Git의 최신 코드와 현재 실행 상태를 비교하여 차이점을 확인.
    • Health : 애플리케이션이 정상적으로 실행 중인지 여부. 요청을 처리할 수 있는 상태인지?
    • Tool : 디렉토리 내 파일들로부터 매니페스트를 생성하는 도구. 예: Kustomize. → Application Source Type 참고.
    • Configuration management tool : 위의 Tool과 동일.
    • Configuration management plugin : 사용자 정의 도구.

 

☞  Argo CD 설치 및 기본 설정 - helm_chart

  • Argo CD 설치
# 네임스페이스 생성 및 파라미터 파일 작성
cd cicd-labs

kubectl create ns argocd
cat <<EOF > argocd-values.yaml
dex:
  enabled: false

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 7.8.13 -f argocd-values.yaml --namespace argocd # 7.7.10

# 확인
kubectl get pod,svc,ep,secret,cm -n argocd
kubectl get crd | grep argo
applications.argoproj.io      2025-03-29T13:34:19Z
applicationsets.argoproj.io   2025-03-29T13:34:19Z
appprojects.argoproj.io       2025-03-29T13:34:19Z

kubectl get appproject -n argocd -o yaml

# configmap
kubectl get cm -n argocd argocd-cm -o yaml
kubectl get cm -n argocd argocd-rbac-cm -o yaml
...
data:
  policy.csv: ""
  policy.default: ""
  policy.matchMode: glob
  scopes: '[groups]'


# 최초 접속 암호 확인
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d ;echo
CMIVNYQxCQsNpcmq

# Argo CD 웹 접속 주소 확인 : 초기 암호 입력 (admin 계정)
# open "http://127.0.0.1:30002" # macOS
Windows OS경우 직접 웹 브라우저에서 http://127.0.0.1:30002 접속

 

  • Argo CD 웹 접속 확인
    • User info → UPDATE PASSWORD 로 admin 계정 암호 변경 (qwe12345)

  • 기본 정보 확인 (Settings) : Clusters, Projects, Accounts

 

  • ops-deploy Repo 등록 : Settings → Repositories → CONNECT REPO 클릭
    • connection method : VIA HTTPS
    • Type : git
    • Project : default
    • Repo URL : http://<자신의 집 IP>:3000/devops/ops-deploy http://172.24.254.126:3000/devops/ops-deploy
      • Windows (WSL2) 사용자는 자신의 WSL2 Ubuntu eth0 IP
    • Username : devops
    • Password : <Gogs 토큰>
    ⇒ 입력 후 CONNECT 클릭

 

☞ (기초) helm chart 를 통한 배포 실습

#
cd cicd-labs
mkdir nginx-chart
cd nginx-chart

mkdir templates

cat > templates/configmap.yaml <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}
data:
  index.html: |
{{ .Values.indexHtml | indent 4 }}
EOF

cat > templates/deployment.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app: {{ .Release.Name }}
    spec:
      containers:
      - name: nginx
        image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
        ports:
        - containerPort: 80
        volumeMounts:
        - name: index-html
          mountPath: /usr/share/nginx/html/index.html
          subPath: index.html
      volumes:
      - name: index-html
        configMap:
          name: {{ .Release.Name }}
EOF

cat > templates/service.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
  name: {{ .Release.Name }}
spec:
  selector:
    app: {{ .Release.Name }}
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30000
  type: NodePort
EOF

cat > values.yaml <<EOF
indexHtml: |
  <!DOCTYPE html>
  <html>
  <head>
    <title>Welcome to Nginx!</title>
  </head>
  <body>
    <h1>Hello, Kubernetes!</h1>
    <p>Nginx version 1.26.1</p>
  </body>
  </html>

image:
  repository: nginx
  tag: 1.26.1

replicaCount: 1
EOF

cat > Chart.yaml <<EOF
apiVersion: v2
name: nginx-chart
description: A Helm chart for deploying Nginx with custom index.html
type: application
version: 1.0.0
appVersion: "1.26.1"
EOF

# 이전 timeserver/service(nodeport) 삭제
kubectl delete deploy,svc --all

# 직접 배포 해보기
helm template dev-nginx . -f values.yaml
helm install dev-nginx . -f values.yaml
helm list
kubectl get deploy,svc,ep,cm dev-nginx -owide

#
curl http://127.0.0.1:30000
curl -s http://127.0.0.1:30000 | grep version
open http://127.0.0.1:30000


# value 값 변경 후 적용 해보기 : version/tag, replicaCount
cat > values.yaml <<EOF
indexHtml: |
  <!DOCTYPE html>
  <html>
  <head>
    <title>Welcome to Nginx!</title>
  </head>
  <body>
    <h1>Hello, Kubernetes!</h1>
    <p>Nginx version 1.26.2</p>
  </body>
  </html>

image:
  repository: nginx
  tag: 1.26.2

replicaCount: 2
EOF

sed -i "s|1.26.1|1.26.2|g" Chart.yaml


# helm chart 업그레이드 적용
helm template dev-nginx . -f values.yaml # 적용 전 렌더링 확인 Render chart templates locally and display the output.
helm upgrade dev-nginx . -f values.yaml

# 확인
helm list
kubectl get deploy,svc,ep,cm dev-nginx -owide
curl http://127.0.0.1:30000
curl -s http://127.0.0.1:30000 | grep version
open http://127.0.0.1:30000

# 확인 후 삭제
helm uninstall dev-nginx

 

☞ Repo(ops-deploy) 에 nginx helm chart 를 Argo CD를 통한 배포 1

  • git 작업
#
cd cicd-labs

TOKEN=<>
git clone http://devops:$TOKEN@$MyIP:3000/devops/ops-deploy.git
cd ops-deploy

#
git --no-pager config --local --list
git config --local user.name "devops"
git config --local user.email "a@a.com"
git config --local init.defaultBranch main
git config --local credential.helper store
git --no-pager config --local --list
cat .git/config

#
git --no-pager branch
git remote -v

#
VERSION=1.26.1
mkdir nginx-chart
mkdir nginx-chart/templates

cat > nginx-chart/VERSION <<EOF
$VERSION
EOF

cat > nginx-chart/templates/configmap.yaml <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}
data:
  index.html: |
{{ .Values.indexHtml | indent 4 }}
EOF

cat > nginx-chart/templates/deployment.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app: {{ .Release.Name }}
    spec:
      containers:
      - name: nginx
        image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
        ports:
        - containerPort: 80
        volumeMounts:
        - name: index-html
          mountPath: /usr/share/nginx/html/index.html
          subPath: index.html
      volumes:
      - name: index-html
        configMap:
          name: {{ .Release.Name }}
EOF

cat > nginx-chart/templates/service.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
  name: {{ .Release.Name }}
spec:
  selector:
    app: {{ .Release.Name }}
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30000
  type: NodePort
EOF

cat > nginx-chart/values-dev.yaml <<EOF
indexHtml: |
  <!DOCTYPE html>
  <html>
  <head>
    <title>Welcome to Nginx!</title>
  </head>
  <body>
    <h1>Hello, Kubernetes!</h1>
    <p>DEV : Nginx version $VERSION</p>
  </body>
  </html>

image:
  repository: nginx
  tag: $VERSION

replicaCount: 1
EOF

cat > nginx-chart/values-prd.yaml <<EOF
indexHtml: |
  <!DOCTYPE html>
  <html>
  <head>
    <title>Welcome to Nginx!</title>
  </head>
  <body>
    <h1>Hello, Kubernetes!</h1>
    <p>PRD : Nginx version $VERSION</p>
  </body>
  </html>

image:
  repository: nginx
  tag: $VERSION

replicaCount: 2
EOF

cat > nginx-chart/Chart.yaml <<EOF
apiVersion: v2
name: nginx-chart
description: A Helm chart for deploying Nginx with custom index.html
type: application
version: 1.0.0
appVersion: "$VERSION"
EOF


tree nginx-chart
nginx-chart
├── Chart.yaml
├── VERSION
├── templates
│   ├── configmap.yaml
│   ├── deployment.yaml
│   └── service.yaml
├── values-dev.yaml
└── values-prd.yaml

# 
helm template dev-nginx nginx-chart -f nginx-chart/values-dev.yaml
helm template prd-nginx nginx-chart -f nginx-chart/values-prd.yaml
DEVNGINX=$(helm template dev-nginx nginx-chart -f nginx-chart/values-dev.yaml | sed 's/---//g')
PRDNGINX=$(helm template prd-nginx nginx-chart -f nginx-chart/values-prd.yaml | sed 's/---//g')
diff <(echo "$DEVNGINX") <(echo "$PRDNGINX")

#
git add . && git commit -m "Add nginx helm chart" && git push -u origin main

 

  • Argo CD에 App 등록 : ApplicationNEW APP
    • GENERAL
      • App Name : dev-nginx
      • Project Name : default
      • SYNC POLICY : Manual
        • AUTO-CREATE NAMESPACE : 클러스터에 네임스페이스가 없을 시 argocd에 입력한 이름으로 자동 생성
        • APPLY OUT OF SYNC ONLY : 현재 동기화 상태가 아닌 리소스만 배포
      • SYNC OPTIONS : AUTO-CREATE NAMESPACE(Check)
      • PRUNE PROPAGATION POLICY
        • foreground : 부모(소유자, ex. deployment) 자원을 먼저 삭제함
        • background : 자식(종속자, ex. pod) 자원을 먼저 삭제함
        • orphan : 고아(소유자는 삭제됐지만, 종속자가 삭제되지 않은 경우) 자원을 삭제함
    • Source
      • Repo URL : 설정되어 있는 것 선택
      • Revision : HEAD
      • PATH : nginx-chart
    • DESTINATION
      • Cluster URL : <기본값>
      • NAMESPACE : dev-nginx
    • HELM
      • Values files : values-dev.yaml
    ⇒ 작성 후 상단 CREATE 클릭
    • PRUNE : GIt에서 자원 삭제 후 배포시 K8S에서는 삭제되지 않으나, 해당 옵션을 선택하면 삭제시킴
    • FORCE : --force 옵션으로 리소스 삭제
    • APPLY ONLY : ArgoCD의 Pre/Post Hook은 사용 안함 (리소스만 배포)
    • DRY RUN : 테스트 배포 (배포에 에러가 있는지 한번 확인해 볼때 사용)

  • dev-nginx App 클릭 후 상세 정보 확인 → DIFF 클릭 확인

#
kubectl get applications -n argocd
NAME        SYNC STATUS   HEALTH STATUS
dev-nginx   OutOfSync     Missing

kubectl describe applications -n argocd dev-nginx

# 상태 모니터링
kubectl get applications -n argocd -w

# 반복 접속 시도
while true; do curl -s --connect-timeout 1 http://127.0.0.1:30000 ; date ; echo "------------" ; sleep 1 ; done

  • SYNC 클릭 으로 K8S(Live) 반영 확인 : 생성될 리소스 확인

# 아래 처럼 yaml 로 APP 생성 가능
kubectl get applications -n argocd
kubectl get applications -n argocd -o yaml | kubectl neat

# 배포 확인
kubectl get all -n dev-nginx -o wide

 

☞ GitOps 방식(?)을 무시하고 K8S(Live)를 수정 시도해보기!

  • 동작 확인을 위해서 반복 접속
while true; do curl -s --connect-timeout 1 http://127.0.0.1:30000 ; date ; echo "------------" ; sleep 1 ; done
  • configmap (dev-nginx) 클릭

  • LIVE MANIFEST 에 EDIT 클릭 후 index.html 내용 추가 → SAVE

  • K8S(Live) 상태 확인
#
kubectl get cm -n dev-nginx dev-nginx -o yaml
apiVersion: v1
data:
  index.html: |
    <!DOCTYPE html>
    <html>
    <head>
      <title>Welcome to Nginx!</title>
    </head>
    <body>
      <h1>Hello, Kubernetes!</h1>
      <p>DEV testtest : Nginx version 1.26.1</p>
    </body>
    </html>
...
  labels:
    argocd.argoproj.io/instance: dev-nginx
    myname: tester
...

# (추가) kubectl 로 직접 k8s 추가 시 >> 이후 ArgoCD LIVE 에서 확인!
kubectl get cm -n dev-nginx dev-nginx --show-labels
kubectl label cm dev-nginx -n dev-nginx study=aews
kubectl get cm -n dev-nginx dev-nginx --show-labels

# 변경된 CM 적용을 위해서 롤아웃
kubectl rollout restart deployment -n dev-nginx dev-nginx

#
while true; do curl -s --connect-timeout 1 http://127.0.0.1:30000 ; date ; echo "------------" ; sleep 1 ; done

 

  • ArgoCD 에서 Git(원본) 과 LIVE간 차이점 DIFF 발견

 

  • 하지만 Git에 없던 정보는 DIFF 차이점 발견이 되지 않는다!

 

  • ArgoCD 에서 SYNC 클릭 후 확인
# 변경된 CM 적용을 위해서 롤아웃
kubectl rollout restart deployment -n dev-nginx dev-nginx
  • 하지만 Git에 없던 정보는 DIFF 차이점은 여전히 발견이 되지 않는다!

⇒ GitOps를 위해서는, 반드시 단일 진실 공급원(Single Source Of Trush, SSOT)를 통해서 관리를 할 것!

  • 1.26.2 로 업데이트(코드 수정) 후 반영 확인
#
VERSION=1.26.2

cat > nginx-chart/VERSION <<EOF
$VERSION
EOF

cat > nginx-chart/values-dev.yaml <<EOF
indexHtml: |
  <!DOCTYPE html>
  <html>
  <head>
    <title>Welcome to Nginx!</title>
  </head>
  <body>
    <h1>Hello, Kubernetes!</h1>
    <p>DEV : Nginx version $VERSION</p>
  </body>
  </html>

image:
  repository: nginx
  tag: $VERSION

replicaCount: 2
EOF

cat > nginx-chart/values-prd.yaml <<EOF
indexHtml: |
  <!DOCTYPE html>
  <html>
  <head>
    <title>Welcome to Nginx!</title>
  </head>
  <body>
    <h1>Hello, Kubernetes!</h1>
    <p>PRD : Nginx version $VERSION</p>
  </body>
  </html>

image:
  repository: nginx
  tag: $VERSION

replicaCount: 2
EOF

cat > nginx-chart/Chart.yaml <<EOF
apiVersion: v2
name: nginx-chart
description: A Helm chart for deploying Nginx with custom index.html
type: application
version: 1.0.0
appVersion: "$VERSION"
EOF

#
git add . && git commit -m "Update nginx version $(cat nginx-chart/VERSION)" && git push -u origin main

 

  • Argo CD 웹 확인 → REFRESH 클릭 - Interval

Argo CD는 Git 또는 Helm 저장소의 변경 사항을 얼마나 자주 확인하나요?
기본 폴링 간격은 3분(180초)입니다. 이 설정은 argocd-cm 설정 맵(ConfigMap)의 timeout.reconciliation 값을 변경하여 수정할 수 있습니다.
kubectl get cm -n argocd argocd-cm -o yaml | grep timeout
  timeout.hard.reconciliation: 0s
  timeout.reconciliation: 180s

 

SYNC 클릭 → SYNCHRONIZE 클릭

# 배포 확인
kubectl get all -n dev-nginx -o wide

 

  • Argo CD 웹에서 App 삭제
watch -d kubectl get all -n dev-nginx -o wide

 

 

 

☞ Repo(ops-deploy) 에 nginx helm chart 를 Argo CD를 통한 배포 2 : ArgoCD Declarative Setup

  • ArgoCD Declarative Setup - Project, applications(ArgoCD App 자체를 yaml로 생성), ArgoCD Settings - Docs

 

  • (참고) K8S FinalizersArgo Finalizers 동작 - Docs , Blog

출처: https://kubernetes.io/blog/2021/05/14/using-finalizers-to-control-deletion/

 

  • Kubernetes에서 finalizers는 리소스의 metadata.finalizers 필드에 정의된 이름 목록으로, 리소스가 삭제 요청을 받았을 때(즉, kubectl delete나 API 호출로 삭제가 시작될 때) 바로 제거되지 않고, 지정된 작업이 완료될 때까지 "종료 중"(Terminating) 상태로 유지되게 합니다.
  • ArgoCD는 이 메커니즘을 활용해 애플리케이션 삭제 시 관리 대상 리소스의 정리(cleanup)를 제어합니다.
  • ArgoCD에서 가장 흔히 사용되는 finalizer는 resources-finalizer.argocd.argoproj.io입니다. 이 finalizer는 애플리케이션이 삭제될 때 해당 애플리케이션이 관리하는 모든 리소스(예: Pod, Service, ConfigMap 등)를 함께 삭제하도록 보장합니다.
  • ArgoCD Finalizers의 목적
    1. 리소스 정리 보장: 애플리케이션 삭제 시 관련 리소스가 남지 않도록 보장합니다. 이는 GitOps 워크플로우에서 선언적 상태를 유지하는 데 중요합니다.
    2. 의도치 않은 삭제 방지: finalizer가 없으면 실수로 Argo App을 삭제해도 K8S 리소스가 남아 혼란이 생길 수 있습니다. finalizer는 이를 방지합니다.
    3. App of Apps 패턴 지원: 여러 애플리케이션을 계층적으로 관리할 때, 상위 애플리케이션 삭제 시 하위 리소스까지 정리되도록 합니다.
  • dev-nginx App 생성 및 Auto SYNC
#
echo $MyIP

cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: dev-nginx
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    helm:
      valueFiles:
      - values-dev.yaml
    path: nginx-chart
    repoURL: http://$MyIP:3000/devops/ops-deploy
    targetRevision: HEAD
  syncPolicy:
    automated:
      prune: true
    syncOptions:
    - CreateNamespace=true
  destination:
    namespace: dev-nginx
    server: https://kubernetes.default.svc
EOF


#
kubectl get applications -n argocd dev-nginx
kubectl get applications -n argocd dev-nginx -o yaml | kubectl neat
kubectl describe applications -n argocd dev-nginx
kubectl get pod,svc,ep,cm -n dev-nginx

#
curl http://127.0.0.1:30000
open http://127.0.0.1:30000

# Argo CD App 삭제
kubectl delete applications -n argocd dev-nginx

 

  • prd-nginx App 생성 및 Auto SYNC
#
cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: prd-nginx
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  destination:
    namespace: prd-nginx
    server: https://kubernetes.default.svc
  project: default
  source:
    helm:
      valueFiles:
      - values-prd.yaml
    path: nginx-chart
    repoURL: http://$MyIP:3000/devops/ops-deploy
    targetRevision: HEAD
  syncPolicy:
    automated:
      prune: true
    syncOptions:
    - CreateNamespace=true
EOF

#
kubectl get applications -n argocd prd-nginx
kubectl describe applications -n argocd prd-nginx
kubectl get pod,svc,ep,cm -n prd-nginx

#
curl http://127.0.0.1:30000
open http://127.0.0.1:30000

# Argo CD App 삭제
kubectl delete applications -n argocd prd-nginx

 

 

 

☞ Repo(ops-deploy) 에 Webhook 를 통해 Argo CD 에 즉시 반영 trigger하여 k8s 배포 할 수 있게 설정 - Docs

  • Repo(ops-deploy) 에 webhooks 설정 : Gogs 선택
    • Payload URL : http://192.168.254.127:30002/api/webhook
      • Windows (WSL2) 사용자는 자신의 WSL2 Ubuntu eth0 IP
    • 나머지 항목 ‘기본값’ ⇒ Add webhook
    • 이후 생성된 webhook 클릭 후 Test Delivery 클릭 후 정상 응답 확인
  • dev-nginx App 생성 및 Auto SYNC
#
echo $MyIP

cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: dev-nginx
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    helm:
      valueFiles:
      - values-dev.yaml
    path: nginx-chart
    repoURL: http://$MyIP:3000/devops/ops-deploy
    targetRevision: HEAD
  syncPolicy:
    automated:
      prune: true
    syncOptions:
    - CreateNamespace=true
  destination:
    namespace: dev-nginx
    server: https://kubernetes.default.svc
EOF


#
kubectl get applications -n argocd dev-nginx
kubectl get applications -n argocd dev-nginx -o yaml | kubectl neat
kubectl describe applications -n argocd dev-nginx
kubectl get pod,svc,ep,cm -n dev-nginx

#
curl http://127.0.0.1:30000
open http://127.0.0.1:30000

  • Git(Gogs) 수정 후 ArgoCD 즉시 반영 확인
#
cd cicd-labs/ops-deploy/nginx-chart

#
sed -i -e "s|replicaCount: 2|replicaCount: 3|g" values-dev.yaml
git add values-dev.yaml && git commit -m "Modify nginx-chart : values-dev.yaml" && git push -u origin main
watch -d kubectl get all -n dev-nginx -o wide

#
sed -i -e "s|replicaCount: 3|replicaCount: 4|g" values-dev.yaml
git add values-dev.yaml && git commit -m "Modify nginx-chart : values-dev.yaml" && git push -u origin main
watch -d kubectl get all -n dev-nginx -o wide

#
sed -i -e "s|replicaCount: 4|replicaCount: 2|g" values-dev.yaml
git add values-dev.yaml && git commit -m "Modify nginx-chart : values-dev.yaml" && git push -u origin main
watch -d kubectl get all -n dev-nginx -o wide

  • Argo CD App 삭제
kubectl delete applications -n argocd dev-nginx

 

 

 

4. Jenkins CI + Argo CD + K8S(Kind) 


Full CI/CD 구성도

 

☞ Repo(ops-deploy) 기본 코드 작업

#
cd ops-deploy

#
mkdir dev-app

# 도커 계정 정보
DHUSER=<도커 허브 계정>
DHUSER=gasida

# 버전 정보 
VERSION=0.0.1

#
cat > dev-app/VERSION <<EOF
$VERSION
EOF

cat > dev-app/timeserver.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: timeserver
spec:
  replicas: 2
  selector:
    matchLabels:
      pod: timeserver-pod
  template:
    metadata:
      labels:
        pod: timeserver-pod
    spec:
      containers:
      - name: timeserver-container
        image: docker.io/$DHUSER/dev-app:$VERSION
        livenessProbe:
          initialDelaySeconds: 30
          periodSeconds: 30
          httpGet:
            path: /healthz
            port: 80
            scheme: HTTP
          timeoutSeconds: 5
          failureThreshold: 3
          successThreshold: 1
      imagePullSecrets:
      - name: dockerhub-secret
EOF

cat > dev-app/service.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
  name: timeserver
spec:
  selector:
    pod: timeserver-pod
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    nodePort: 30000
  type: NodePort
EOF

#
git add . && git commit -m "Add dev-app deployment yaml" && git push -u origin main

 

 

 

☞ Repo(ops-deploy) 를 바라보는 ArgoCD App 생성

#
echo $MyIP

cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: timeserver
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    path: dev-app
    repoURL: http://$MyIP:3000/devops/ops-deploy
    targetRevision: HEAD
  syncPolicy:
    automated:
      prune: true
    syncOptions:
    - CreateNamespace=true
  destination:
    namespace: default
    server: https://kubernetes.default.svc
EOF

#
kubectl get applications -n argocd timeserver
kubectl get applications -n argocd timeserver -o yaml | kubectl neat
kubectl describe applications -n argocd timeserver
kubectl get deploy,rs,pod
kubectl get svc,ep timeserver

#
curl http://127.0.0.1:30000
curl http://127.0.0.1:30000/healthz
open http://127.0.0.1:30000

 

☞ Repo(dev-app) 코드 작업

  • dev-app Repo에 VERSION 업데이트 시 → ops-deploy Repo 에 dev-app 에 파일에 버전 정보 업데이트 작업 추가
    1. 기존 버전 정보는 VERSION 파일 내에 정보를 가져와서 변수 지정 : OLDVER=$(cat dev-app/VERSION)
    2. 신규 버전 정보는 environment 도커 태그 정보를 가져와서 변수 지정 : NEWVER=$(echo ${DOCKER_TAG})
    3. 이후 sed 로 ops-deploy Repo 에 dev-app/VERSION, timeserver.yaml 2개 파일에 ‘기존 버전’ → ‘신규 버전’으로 값 변경
    4. 이후 ops-deploy Repo 에 git push ⇒ Argo CD App Trigger 후 AutoSync 로 신규 버전 업데이트 진행

 

  • 아래는 dev-app 에 위치한 Jenkinsfile 로 젠킨스에 SCM-Pipeline(SCM:git) 으로 사용되고 있는 파일을 수정해서 실습에 사용
pipeline {
    agent any
    environment {
        DOCKER_IMAGE = '<자신의 도커 허브 계정>/dev-app' // Docker 이미지 이름
        GOGSCRD = credentials('gogs-crd')
    }
    stages {
        stage('dev-app Checkout') {
            steps {
                 git branch: 'main',
                 url: 'http://<자신의 집 IP>:3000/devops/dev-app.git',  // Git에서 코드 체크아웃
                 credentialsId: 'gogs-crd'  // Credentials ID
            }
        }
        stage('Read VERSION') {
            steps {
                script {
                    // VERSION 파일 읽기
                    def version = readFile('VERSION').trim()
                    echo "Version found: ${version}"
                    // 환경 변수 설정
                    env.DOCKER_TAG = version
                }
            }
        }
        stage('Docker Build and Push') {
            steps {
                script {
                    docker.withRegistry('https://index.docker.io/v1/', 'dockerhub-crd') {
                        // DOCKER_TAG 사용
                        def appImage = docker.build("${DOCKER_IMAGE}:${DOCKER_TAG}")
                        appImage.push()
                        appImage.push("latest")
                    }
                }
            }
        }
        stage('ops-deploy Checkout') {
            steps {
                 git branch: 'main',
                 url: 'http://<자신의 집 IP>:3000/devops/ops-deploy.git',  // Git에서 코드 체크아웃
                 credentialsId: 'gogs-crd'  // Credentials ID
            }
        }
        stage('ops-deploy version update push') {
            steps {
                sh '''
                OLDVER=$(cat dev-app/VERSION)
                NEWVER=$(echo ${DOCKER_TAG})
                sed -i '' "s/$OLDVER/$NEWVER/" dev-app/timeserver.yaml
                sed -i '' "s/$OLDVER/$NEWVER/" dev-app/VERSION
                git add ./dev-app
                git config user.name "devops"
                git config user.email "a@a.com"
                git commit -m "version update ${DOCKER_TAG}"
                git push http://${GOGSCRD_USR}:${GOGSCRD_PSW}@<자신의 집 IP>:3000/devops/ops-deploy.git
                '''
            }
        }
    }
    post {
        success {
            echo "Docker image ${DOCKER_IMAGE}:${DOCKER_TAG} has been built and pushed successfully!"
        }
        failure {
            echo "Pipeline failed. Please check the logs."
        }
    }
}
pipeline {
    agent any
    environment {
        DOCKER_IMAGE = 'sspp30578/dev-app' // Docker 이미지 이름
        GOGSCRD = credentials('gogs-crd')
    }
    stages {
        stage('dev-app Checkout') {
            steps {
                 git branch: 'main',
                 url: 'http://172.24.254.126:3000/devops/dev-app.git',  // Git에서 코드 체크아웃
                 credentialsId: 'gogs-crd'  // Credentials ID
            }
        }
        stage('Read VERSION') {
            steps {
                script {
                    // VERSION 파일 읽기
                    def version = readFile('VERSION').trim()
                    echo "Version found: ${version}"
                    // 환경 변수 설정
                    env.DOCKER_TAG = version
                }
            }
        }
        stage('Docker Build and Push') {
            steps {
                script {
                    docker.withRegistry('https://index.docker.io/v1/', 'dockerhub-crd') {
                        // DOCKER_TAG 사용
                        def appImage = docker.build("${DOCKER_IMAGE}:${DOCKER_TAG}")
                        appImage.push()
                        appImage.push("latest")
                    }
                }
            }
        }
        stage('ops-deploy Checkout') {
            steps {
                 git branch: 'main',
                 url: 'http://172.24.254.126:3000/devops/ops-deploy.git',  // Git에서 코드 체크아웃
                 credentialsId: 'gogs-crd'  // Credentials ID
            }
        }
        stage('ops-deploy version update push') {
            steps {
                sh '''
                OLDVER=$(cat dev-app/VERSION)
                NEWVER=$(echo ${DOCKER_TAG})
                sed -i -e "s/$OLDVER/$NEWVER/" dev-app/timeserver.yaml
                sed -i -e "s/$OLDVER/$NEWVER/" dev-app/VERSION
                git add ./dev-app
                git config user.name "devops"
                git config user.email "a@a.com"
                git commit -m "version update ${DOCKER_TAG}"
                git push http://${GOGSCRD_USR}:${GOGSCRD_PSW}@172.24.254.126:3000/devops/ops-deploy.git
                '''
            }
        }
    }
    post {
        success {
            echo "Docker image ${DOCKER_IMAGE}:${DOCKER_TAG} has been built and pushed successfully!"
        }
        failure {
            echo "Pipeline failed. Please check the logs."
        }
    }
}

 

  • 아래는 dev-app (Repo) 에서 git push 수행
# [터미널] 동작 확인 모니터링
while true; do curl -s --connect-timeout 1 http://127.0.0.1:30000 ; echo ; kubectl get deploy timeserver -owide; echo "------------" ; sleep 1 ; done

#
cd cicd-labs/dev-app

# VERSION 파일 수정 : 0.0.3
# server.py 파일 수정 : 0.0.3

# git push : VERSION, server.py, Jenkinsfile
git add . && git commit -m "VERSION $(cat VERSION) Changed" && git push -u origin main

 

 

☞ Full CI/CD 동작 확인 : Argo CD app Trigger 후 AutoSync 로 신규 버전 업데이트 진행 확인

 

  • dev-app Repo 에서 한번 더 버전 업데이트 수행
# [터미널] 동작 확인 모니터링
while true; do curl -s --connect-timeout 1 http://127.0.0.1:30000 ; echo ; kubectl get deploy timeserver -owide; echo "------------" ; sleep 1 ; done

# VERSION 파일 수정 : 0.0.4
# server.py 파일 수정 : 0.0.4

# git push : VERSION, server.py, Jenkinsfile
git add . && git commit -m "VERSION $(cat VERSION) Changed" && git push -u origin main

# VERSION 파일 수정 : 0.0.5
# server.py 파일 수정 : 0.0.5

# git push : VERSION, server.py, Jenkinsfile
git add . && git commit -m "VERSION $(cat VERSION) Changed" && git push -u origin main

 

 

 

즉, 개발팀 dev-app Repo 에서만 코드 업데이트 작업 시, jenkins pipeline 에서 ops-deploy Repo 에 버전 정보 업데이트를 하고, 이후 Argo CD가 자동으로 신규 버전 정보로 배포를 하게 된다.

 

 

5. Argo Image Updater


동작 - Docs , Blog

  • ArgoCD 기존 방식

출처: https://kmaster.tistory.com/85
출처: https://kmaster.tistory.com/85
[출처] 책 GitOps Cookbook - https://product.kyobobook.co.kr/detail/S000214781090

☞ KrBlog

  • argo CD Image Updater - Blog*
  • ArgoCD 빠르게 레벨업 하기 - Blog*
  • [CD] ArgoCD Image Updater를 활용한 Continuous Delivery w/AWS ECR - Blog
  • K8s Argocd Image Updater - Blog
  • 제목은 안정적인 AI 서빙 시스템으로 하겠습니다. 근데 이제 자동화를 곁들인… - Blog
  • [AWS] ArgoCD Image Updater로 이미지 자동 배포 with ECR - Blog

 

6. Argo CD App-of-apps


☞  App-of-apps (배포를 배포) 동작 - Docs & [악분일상] Blog* , Youtube / Blog1 , Blog2

 

기존 방식

출처: https://beer1.tistory.com/68

 

App of apps : Root Application, Child Application

출처: https://beer1.tistory.com/68

 

출처: https://malwareanalysis.tistory.com/478

 

출처: https://argo-cd.readthedocs.io/en/stable/operator-manual/cluster-bootstrapping/

 

☞  [ArgoCD Docs] Cluster Boostrapping : app of apps pattern - Docs , Github

  • apps 생성

#
cd cicd-labs
git clone https://github.com/argoproj/argocd-example-apps.git

#
tree argocd-example-apps/apps
argocd-example-apps/apps
├── Chart.yaml
├── templates
│   ├── helm-guestbook.yaml
│   ├── helm-hooks.yaml
│   ├── kustomize-guestbook.yaml
│   ├── namespaces.yaml
│   └── sync-waves.yaml
└── values.yaml

#
helm template -f argocd-example-apps/apps/values.yaml argocd-example-apps/apps


# you need to create and sync your parent app
cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: apps
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    path: apps
    repoURL: https://github.com/argoproj/argocd-example-apps.git
    targetRevision: HEAD
  destination:
    namespace: argocd
    server: https://kubernetes.default.svc
  syncPolicy:
    automated:
      prune: true
EOF

#
kubectl get applications -n argocd --show-labels 
NAME                  SYNC STATUS   HEALTH STATUS   LABELS
apps                  Synced        Healthy         <none>
helm-guestbook        OutOfSync     Missing         argocd.argoproj.io/instance=apps
helm-hooks            OutOfSync     Missing         argocd.argoproj.io/instance=apps
kustomize-guestbook   OutOfSync     Missing         argocd.argoproj.io/instance=apps
sync-waves            OutOfSync     Missing         argocd.argoproj.io/instance=apps

# 상태 모니터링
kubectl get applications -n argocd -w

  • You can either sync via the UI, firstly filter by the correct label:

  • Then select the "out of sync" apps and sync:

  • 확인
# 확인
kubectl get pod -n helm-guestbook -l app=helm-guestbook
NAME                              READY   STATUS    RESTARTS     AGE
helm-guestbook-57c97698c4-pmdmd   1/1     Running   0          2m8s

kubectl describe pod -n helm-guestbook -l app=helm-guestbook
Containers:
  helm-guestbook:
    Container ID:   containerd://eef3cc33978303e22680cea7f258524edc8635069122dd8e7e3c18ed0e779a32
    Image:          gcr.io/heptio-images/ks-guestbook-demo:0.1
    Image ID:       gcr.io/heptio-images/ks-guestbook-demo@sha256:fe18e00a6aeece16b5b2f77a32ee60929e8a60e27c71df8df66bf804f5677f47
    Port:           80/TCP
  ...
  Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  2m32s  default-scheduler  Successfully assigned helm-guestbook/helm-guestbook-57c97698c4-pmdmd to myk8s-worker2
  Normal  Pulling    2m32s  kubelet            Pulling image "gcr.io/heptio-images/ks-guestbook-demo:0.1"
  Normal  Pulled     112s   kubelet            Successfully pulled image "gcr.io/heptio-images/ks-guestbook-demo:0.1" in 38.078s (38.079s including waiting). Image size: 193410335 bytes.
  Normal  Created    112s   kubelet            Created container: helm-guestbook
  Normal  Started    112s   kubelet            Started container helm-guestbook
  
#
for i in worker worker2; do echo ">> node $i <<"; docker exec -it myk8s-$i ctr -n k8s.io image list --quiet | grep -i guestbook; echo; done

#
docker pull gcr.io/heptio-images/ks-guestbook-demo:0.1
gcr.io/heptio-images/ks-guestbook-demo:0.1
gcr.io/heptio-images/ks-guestbook-demo@sha256:fe18e00a6aeece16b5b2f77a32ee60929e8a60e27c71df8df66bf804f5677f47

#
docker pull gcr.io/heptio-images/ks-guestbook-demo:0.1
docker images
docker inspect gcr.io/heptio-images/ks-guestbook-demo:0.1 | grep -i arch
"Architecture": "amd64",

 

  • 삭제 : Cascading deletion - app of app application과 모든 application이 삭제  - Docs
kubectl delete applications -n argocd apps

 

 

☞  Non cascade를 선택하면 app of app application만 삭제되고 다른 application은 유지 Ignoring differences in child applications

 

# you need to create and sync your parent app
cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: apps
  namespace: argocd
spec:
  project: default
  source:
    path: apps
    repoURL: https://github.com/argoproj/argocd-example-apps.git
    targetRevision: HEAD
  destination:
    namespace: argocd
    server: https://kubernetes.default.svc
  syncPolicy:
    automated:
      prune: true
EOF

 

☞ [CNKCD2024] 선언형으로 만드는 멀티 클러스터 - Cluster API 와 App of Apps 패턴 (문지현) , PDF

 

 

7. Argo Rollout


☞ Argo Rollouts 소개 : k8s 고급 배포 도구, Kubernetes Progressive Delivery Controller - Docs

  • Argo Rollouts : Argo Rollouts is a Kubernetes controller and set of CRDs which provide advanced deployment capabilities such as blue-green, canary, canary analysis, experimentation, and progressive delivery features to Kubernetes.
    • Argo RolloutsIngress Controller 및 Service Meshes와 통합되어 트래픽 형성 기능을 활용하여 업데이트 중에 트래픽을 점진적으로 새 버전으로 전환합니다. 또한 Rollouts는 다양한 공급업체의 메트릭을 쿼리하고 해석하여 주요 KPI를 검증하고 업데이트 중에 자동화된 프로모션 또는 롤백을 실행할 수 있습니다.
  • Why Argo Rollouts? : 롤링업데이트만으로는 부족한 기능
    • The native Kubernetes Deployment Object supports the RollingUpdate strategy which provides a basic set of safety guarantees (readiness probes) during an update. However the rolling update strategy faces many limitations:
      • 출시 속도에 대한 몇 가지 제어 기능 Few controls over the speed of the rollout
      • 새 버전으로의 트래픽 흐름**(카나리)을 제어할 수 없음** Inability to control traffic flow to the new version
      • Readiness probes 는 ‘복잡하고, 스트레스 또는 일회성 점검’에 적합하지 않습니다 Readiness probes are unsuitable for deeper, stress, or one-time checks
      • 업데이트를 확인하기 위해 외부 메트릭을 쿼리할 수 없습니다 No ability to query external metrics to verify an update
      • 진행을 중지할 수는 있지만 업데이트를 자동으로 중단하고 롤백할 수는 없습니다 Can halt the progression, but unable to automatically abort and rollback the update
  • Controller Features
    • Blue-Green update strategy

출처: https://argoproj.github.io/argo-rollouts/concepts/

  • Canary update strategy

출처: https://argoproj.github.io/argo-rollouts/concepts/

  • 세분하고 가중치를 통한 점진전 트래픽 전환 Fine-grained, weighted traffic shifting
  • 자동 롤백 및 프로모션 Automated rollbacks and promotions
  • 수동 적용 Manual judgement
  • 사용자 지정 가능한 메트릭 쿼리와 분석 Customizable metric queries and analysis of business KPIs
  • 입력 컨트롤러 통합 Ingress controller integration: NGINX, ALB, Apache APISIX
  • 서비스 메시 통합 Service Mesh integration: Istio, Linkerd, SMI
  • 여러 제공업체의 동시 사용 Simultaneous usage of multiple providers: SMI + NGINX, Istio + ALB, etc.
  • 메트릭 제공업체 통합 Metric provider integration: Prometheus, Wavefront, Kayenta, Web, Kubernetes Jobs, Datadog, New Relic, Graphite, InfluxDB

 

  • 아키텍처 - Docs

출처: https://argoproj.github.io/argo-rollouts/architecture/

  • Argo Rollouts controller :
  • Rollout resource :
  • Replica sets for old and new version :
  • Ingress/Service :
  • AnalysisTemplate and AnalysisRun :
  • Metric providers :
  • CLI and UI :

☞  Argo Rollouts 설치 및 Sample 테스트 - Docs

  • Argo Rollouts 설치
# 네임스페이스 생성 및 파라미터 파일 작성
cd cicd-labs

kubectl create ns argo-rollouts
cat <<EOT > argorollouts-values.yaml
dashboard:
  enabled: true
  service:
    type: NodePort
    nodePort: 30003
EOT

# 설치: 2.35.1
helm install argo-rollouts argo/argo-rollouts --version 2.39.2 -f argorollouts-values.yaml --namespace argo-rollouts

# 확인
kubectl get all -n argo-rollouts
kubectl get crds

# Argo rollouts 대시보드 접속 주소 확인
echo "http://127.0.0.1:30003"
open "http://127.0.0.1:30003"

  • Deploying a Rollout
    • 먼저, 롤아웃 리소스와 해당 롤아웃을 타겟으로 하는 Kubernetes 서비스를 배포합니다.
    • 이 가이드의 예제 롤아웃은 카나리아 업데이트 전략을 사용하여 트래픽의 20%를 카나리아로 보내고, 이어서 수동 프로모션을 실시하며, 마지막으로 업그레이드의 나머지 기간 동안 점진적으로 자동 트래픽이 증가합니다.
    • 이 동작은 롤아웃 사양의 다음 부분에서 설명됩니다:
spec:
  replicas: 5
  strategy:
    canary:
      steps:
      - setWeight: 20
      - pause: {}
      - setWeight: 40
      - pause: {duration: 10}
      - setWeight: 60
      - pause: {duration: 10}
      - setWeight: 80
      - pause: {duration: 10}
# 다음 명령을 실행하여 초기 롤아웃 및 서비스를 배포합니다:
kubectl apply -f https://raw.githubusercontent.com/argoproj/argo-rollouts/master/docs/getting-started/basic/rollout.yaml
kubectl apply -f https://raw.githubusercontent.com/argoproj/argo-rollouts/master/docs/getting-started/basic/service.yaml

# 확인
kubectl get rollout --watch
kubectl get rollout
kubectl describe rollout

kubectl get pod -l app=rollouts-demo
kubectl get svc,ep rollouts-demo
kubectl get rollouts rollouts-demo -o json | grep rollouts-demo
...
   "image": "argoproj/rollouts-demo:blue"
...

 

  • 모든 롤아웃의 초기 생성물은 업그레이드가 발생하지 않았기 때문에 즉시 복제본을 100%로 확장합니다(카나리 업그레이드 단계, 분석 등 생략).
  • Argo 롤아웃 쿠벡틀 플러그인을 사용하면 롤아웃 및 관련 리소스(ReplicaSets, Pods, AnalysisRuns)를 시각화할 수 있으며, 발생하는 실시간 상태 변경 사항을 표시할 수 있습니다. 롤아웃이 배포되는 동안 롤아웃을 확인하려면 플러그인에서 get rollout --watch 명령을 실행하세요:
  • Updating a Rollout
    • 다음은 업데이트를 수행할 시간입니다. 배포와 마찬가지로 Pod 템플릿 필드(spec.template)를 변경하면 새로운 버전(즉, ReplicaSet)이 배포됩니다.
    • 롤아웃 업데이트에는 롤아웃 사양을 수정하고 일반적으로 컨테이너 이미지 필드를 새 버전으로 변경한 다음 새로운 매니페스트에 대해 kubectl 적용을 실행하는 작업이 포함됩니다.
    • 편의상 롤아웃 플러그인은 실시간 롤아웃 객체에 대해 다음 단계를 수행하는 설정 이미지 명령을 제공합니다. 다음 명령을 실행하여 롤아웃 데모 롤아웃을 컨테이너의 "yellow" 버전으로 업데이트합니다:
# Run the following command to update the rollouts-demo Rollout with the "yellow" version of the container:
KUBE_EDITOR="nano" kubectl edit rollouts rollouts-demo
..
     - image: argoproj/rollouts-demo:yellow
...

#
kubectl get rollout --watch

# 파드 label 정보 확인
watch -d kubectl get pod -l app=rollouts-demo -owide --show-labels

  • 롤아웃 업데이트 중에 컨트롤러는 롤아웃의 업데이트 전략에 정의된 단계를 진행합니다.
  • 예제 롤아웃은 카나리아의 트래픽 가중치를 20%로 설정하고, 롤아웃을 일시 중지/촉진하기 위한 사용자 조치가 취해질 때까지 롤아웃을 무기한 일시 중지합니다. 이미지를 업데이트한 후 일시 중지 상태에 도달할 때까지 롤아웃을 확인하세요.
  • 데모 롤아웃이 두 번째 단계에 도달하면 플러그인을 통해 롤아웃이 일시 중지된 상태이며, 이제 5개의 복제본 중 1개가 포드 템플릿의 새 버전을 실행하고 있고, 5개의 복제본 중 4개가 이전 버전을 실행하고 있음을 알 수 있습니다. 이는 set Weight: 20로 정의된 20%에 해당합니다.

 

  • Promoting a Rollout
    • 이제 롤아웃이 일시 중지된 상태입니다. 롤아웃이 지속 시간 없이 일시 중지 단계에 도달하면 재개/추진될 때까지 무기한 일시 중지된 상태로 유지됩니다. 롤아웃을 다음 단계로 수동으로 승격하려면 플러그인의 promote 명령을 실행합니다:

# 아래 입력 혹은 UI에서 Promote Yes 클릭
# kubectl argo rollouts promote rollouts-demo

# 정보 확인
kubectl get rollouts rollouts-demo -o json | grep rollouts-demo
watch -d kubectl get pod -l app=rollouts-demo -owide --show-labels
  • 프로모션 후 롤아웃은 나머지 단계를 실행합니다. 예제의 남은 롤아웃 단계는 완전히 자동화되어 있으므로 롤아웃은 새 버전으로 완전히 전환될 때까지 단계를 완료합니다. 모든 단계가 완료될 때까지 롤아웃을 확인하세요
  • 모든 단계가 성공적으로 완료되면 새로운 ReplicaSet은 "안정적인" ReplicaSet으로 표시됩니다. 업데이트 중에 실패한 카나리아 분석을 통해 자동으로 또는 사용자가 수동으로 롤아웃을 중단하면 롤아웃은 다시 "안정적인" 버전으로 돌아갑니다.

  • 요약
    • 이 기본 예제의 롤아웃은 트래픽을 라우팅하기 위해 입력 컨트롤러나 서비스 메시 제공자를 사용하지 않았습니다. 대신, 일반적인 Kubernetes 서비스 네트워킹(즉, kube-proxy)을 사용하여 새로운 복제본 수와 이전 복제본 수의 가장 가까운 비율을 기준으로 대략적인 카나리아 가중치를 달성했습니다. 그 결과, 이 롤아웃은 새로운 버전을 실행하기 위해 5개의 포드 중 1개를 확장함으로써 최소 카나리아 가중치를 20%까지만 달성할 수 있다는 한계가 있었습니다. 훨씬 더 세밀한 카나리아를 달성하기 위해서는 입력 컨트롤러나 서비스 메시가 필요합니다.
    • 트래픽 라우팅 가이드 중 하나를 따라가면 Argo Rollouts가 네트워킹 제공업체를 어떻게 활용하여 보다 발전된 트래픽 형성을 달성할 수 있는지 확인할 수 있습니다.

 

 

(참고) 모든 실습 환경 삭제 : 

docker compose down --volumes --remove-orphans && kind delete cluster --name myk8s

 

 

8. GitOps Bridge


GitOps Bridge : Kubernetes 클러스터를 만드는 과정부터 GitOps를 통해 모든 것을 관리 - Github

출처: https://github.com/gitops-bridge-dev/gitops-bridge

  • Kubernetes 클러스터를 만드는 과정부터 GitOps를 통해 모든 것을 관리하는 과정까지 연결하는 모범 사례와 패턴을 선보이는 커뮤니티 프로젝트

'AEWS study' 카테고리의 다른 글

10주차 - K8s 시크릿 관리 Update  (0) 2025.04.09
9주차 - EKS Upgrade  (0) 2025.03.30
8주차 - K8S CI/CD - #1  (0) 2025.03.28
7주차 - EKS Mode/Nodes - #2  (0) 2025.03.22
7주차 - EKS Mode/Nodes - #1  (0) 2025.03.20
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함