2025. 11. 22. 04:01ㆍCICD
실습 환경 구성
Kind(k8s) - mgmt 배포
kind create cluster --name mgmt --image kindest/node:v1.32.8 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
labels:
ingress-ready: true
# 1. API 서버 포트 매핑 추가 (172.30.1.39 바인딩)
extraPortMappings:
- containerPort: 6443
hostPort: 6444 # 호스트 PC에서 사용할 포트
listenAddress: "172.30.1.39" # <--- 로컬 PC IP로 고정 바인딩(필자에 경우 해당 IP)
protocol: TCP
# 기존에 있던 포트 매핑들
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
- containerPort: 30000
hostPort: 30000
protocol: TCP
# 2. kubeadm 설정을 패치하여 인증서(SANs)에 IP 추가
kubeadmConfigPatches:
- |
kind: ClusterConfiguration
apiServer:
ExtraArgs:
bind-address: 0.0.0.0 # 컨테이너 내부 API 서버는 모든 IP에 바인딩
certSANs:
- "172.30.1.39" # <--- API 서버 인증서에 호스트 IP를 추가
- "127.0.0.1" # 기본 로컬호스트 접근 유지
- "0.0.0.0" # 기본 0.0.0.0 바인딩 유지
---
EOF
Kind(k8s) - NGINX-ingress 배포 및 SSL passthrough 설정
# NGINX Ingress 배포
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
# SSL passthrough
kubectl get deployment ingress-nginx-controller -n ingress-nginx -o yaml \
| sed '/- --publish-status-address=localhost/a\
- --enable-ssl-passthrough' | kubectl apply -f -
로컬 PC - OpenSSL 개인키, 인증키 생성(argocd.example.com)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout argocd.example.com.key \
-out argocd.example.com.crt \
-subj "/CN=argocd.example.com/O=argocd"
Kind(k8s) - 시크릿 생성
# ArgoCD 네임스페이스 생성
kubectl create ns argocd
# TLS 시크릿 생성
kubectl -n argocd create secret tls argocd-server-tls \
--cert=argocd.example.com.crt \
--key=argocd.example.com.key
Helm - Values 생성
cat <<EOF > argocd-values.yaml
global:
domain: argocd.example.com
server:
ingress:
enabled: true
ingressClassName: nginx
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
tls: true
EOF
Helm - Kind(k8s)에 ArgoCD 배포
# Helm Repo 추가
helm repo add argo https://argoproj.github.io/argo-helm
# Helm ArgoCD 배포
helm install argocd argo/argo-cd --version 9.0.5 -f argocd-values.yaml --namespace argocd
로컬 PC - 설정(/etc/hosts 변경)
# /etc/hosts 도메인 변조
echo "127.0.0.1 argocd.example.com" | sudo tee -a /etc/hosts
로컬 PC - 접속 테스트(curl 통신 및 argoCLI 접속)
# curl 통신 확인
curl -vk https://argocd.example.com/
# Argo CD 암호 확인
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d ;echo
# 암호 변수 설정
ARGOPW={최초 암호}
# argo CLI 로그인
argocd login argocd.example.com --insecure --username admin --password $ARGOPW
# argo URL 접속(argocd.example.com)
open "http://argocd.example.com"




Kind(k8s) - dev 및 prd 배포
로컬 PC - docker 사전 확인
docker network ls
docker network inspect kind | jq

Kind(k8s) - dev/prd 배포
# dev k8s 배포
kind create cluster --name dev --image kindest/node:v1.32.8 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
# API 서버 포트 (6443)와 31000 포트 매핑 설정
extraPortMappings:
- containerPort: 6443
hostPort: 6445 # 6443 포트를 호스트 PC의 6445 포트에 매핑
listenAddress: "172.30.1.39" # 호스트 IP에 바인딩
protocol: TCP
- containerPort: 31000
hostPort: 31000
protocol: TCP
# kubeadm 설정을 패치하여 API 서버 인증서에 호스트 IP 추가
kubeadmConfigPatches:
- |
kind: ClusterConfiguration
apiServer:
ExtraArgs:
bind-address: 0.0.0.0
certSANs:
- "172.30.1.39" # 인증서에 호스트 IP를 추가
- "127.0.0.1"
- "0.0.0.0"
---
EOF
# prd k8s 배포
kind create cluster --name prd --image kindest/node:v1.32.8 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
# API 서버 포트 (6443)와 32000 포트 매핑 설정
extraPortMappings:
- containerPort: 6443
hostPort: 6446 # 6443 포트를 호스트 PC의 6446 포트에 매핑
listenAddress: "172.30.1.39" # 호스트 IP에 바인딩
protocol: TCP
- containerPort: 32000
hostPort: 32000
protocol: TCP
# kubeadm 설정을 패치하여 API 서버 인증서에 호스트 IP 추가
kubeadmConfigPatches:
- |
kind: ClusterConfiguration
apiServer:
ExtraArgs:
bind-address: 0.0.0.0
certSANs:
- "172.30.1.39" # 인증서에 호스트 IP를 추가
- "127.0.0.1"
- "0.0.0.0"
---
EOF
Kind(k8s) - dev/prd/mgmt 확인
kubectl config get-contexts

Kind(k8s) - k8s 자격증명 변경(kind-prd > kind-mgmt)
# mgmt k8s 자격증명 변경
kubectl config use-context kind-mgmt
kubectl config get-contexts

로컬PC - alias 설정
alias k8s1='kubectl --context kind-mgmt'
alias k8s2='kubectl --context kind-dev'
alias k8s3='kubectl --context kind-prd'

로컬PC - 도커 네트워크 및 통신 확인
docker network inspect kind | grep -E 'Name|IPv4Address'
# 도커 컨테이너 - 컨테이너 내부 도메인 통신 확인
docker ps
docker exec -it mgmt-control-plane curl -sk https://dev-control-plane:6443/version
docker exec -it mgmt-control-plane curl -sk https://prd-control-plane:6443/version
docker exec -it dev-control-plane curl -sk https://prd-control-plane:6443/version
# local > 컨테이너 Control Plane 통신 확인
kubectl get node -v=6 --context kind-mgmt
kubectl get node -v=6 --context kind-dev
kubectl get node -v=6 --context kind-prd



로컬 PC - 로컬에서 컨테이너 Ping 통신(실패)
ping -c 1 172.18.0.2
ping -c 1 172.18.0.3
ping -c 1 172.18.0.4
실습을 그대로 진행 시 계속해서 로컬 PC > 컨테이너로 Ping을 보낼 경우 실패가 발생하였다.

원인이 불명확하여 해당 건에 대해서는 추후 docker 컨테이너 네트워크 구조에 대해 학습이 필요... 결국 각 kind(mgmt,prd,dev)에 ExtraPortMappings을 사용하여 Host PC에 IP를 통해 접속할 수 있게 환경을 구성하였따.

로컬 PC - ~/.kube/config 파일 수정
# config 파일 백업
cp ~/.kube/config ./kube-config.bak
# 수정
vi ~/.kube/config
# 확인
kubectl get node -v=6 --context kind-dev
kubectl get node -v=6 --context kind-prd


ArgoCD - K8s 클러스터 등록(kind-dev, kind-prd)
# ArgoCD 현재 등록된 클러스터 확인
argocd cluster list
argocd cluster list -o json | jq
# 초기 SA 확인
k8s2 get sa -n kube-system
k8s3 get sa -n kube-system
# dev k8s 등록 및 SA(argocd-manager) 생성 확인
argocd cluster add kind-dev --name dev-k8s
k8s2 get sa -n kube-system argocd-manager
# prd k8s 등록
argocd cluster add kind-prd --name prd-k8s --yes
k8s3 get sa -n kube-system argocd-manager
# 클러스터 리스트 확인 및 조회
argocd cluster list
argocd cluster list -o json | jq






ArgoCD - 각 클러스터 NGINX 배포
# argocd app 배포
cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: mgmt-nginx
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
helm:
valueFiles:
- values.yaml
path: nginx-chart
repoURL: https://github.com/gasida/cicd-study
targetRevision: HEAD
syncPolicy:
automated:
prune: true
syncOptions:
- CreateNamespace=true
destination:
namespace: mgmt-nginx
server: https://kubernetes.default.svc
EOF
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: https://github.com/gasida/cicd-study
targetRevision: HEAD
syncPolicy:
automated:
prune: true
syncOptions:
- CreateNamespace=true
destination:
namespace: dev-nginx
server: https://172.30.1.39:6445
EOF
cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: prd-nginx
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
helm:
valueFiles:
- values-prd.yaml
path: nginx-chart
repoURL: https://github.com/gasida/cicd-study
targetRevision: HEAD
syncPolicy:
automated:
prune: true
syncOptions:
- CreateNamespace=true
destination:
namespace: prd-nginx
server: https://172.30.1.39:6446
EOF
ArgoCD - 애플리케이션 배포 확인
# 애플리케이션 조회
argocd app list
# mgmt
kubectl get pod,svc,ep,cm -n mgmt-nginx
curl -s http://127.0.0.1:30000
# dev
kubectl get pod,svc,ep,cm -n dev-nginx --context kind-dev
curl -s http://127.0.0.1:31000
# prd
kubectl get pod,svc,ep,cm -n prd-nginx --context kind-prd
curl -s http://127.0.0.1:32000




ArgoCD - 애플리케이션 삭제
kubectl delete applications -n argocd mgmt-nginx dev-nginx prd-nginx
ApplicationSet
App of apps 패턴
App of Apps 패턴은 ArgoCD 환경에서 애플리케이션을 배포하는 애플리케이션을 의미
즉, 하나의 Root ArgoCD Application 리소스가 다른 하위에 ArgoCD Application 리소스들을 정의하고 동기화하는 역할을 수행합니다.
- app of apps 패턴은 부모 애플리케이션과 자식 애플리케이션 집합을 논리적으로 그룹화할 수 있는 기능을 제공한다.
- 부모 애플리케이션을 통해 자식 애플리케이션을 만들수 있고, 함께 배포할 수 있는 애플리케이션 그룹을 선언적으로 관리할 수 있다.
- app of apps 패턴을 사용하면 여러 Argo CD 애플리케이션 CRD를 배포하는 대신 부모 애플리케이션 하나만 배포하면 된다.
- 논리적 그룹화가 되어, 그룹의 모든 애플리케이션이 배포되고 정상 상태인지 확인 할 수 있다.
최상위 애플리케이션 (Root App)
- 단일 Git 저장소를 참조
- 해당 Git 저장소에는 배포하고자 하는 모든 하위 애플리케이션의 ArgoCD Application 정의 파일만 포함되어 있다.
- 해당 Root Appdms 정의된 파일들을 읽어 Kubernetes 클러스터에 배포하고, 여러 개의 하위 ArgoCD Apllication이 생성됨
하위 애플리케이션(Child Apps)
- Root App에서 생성된 애플리케이션은 실제 워크로드를 정의하는 Helm 차트, Kustomize 구성, Kubernetes Manifest 파일이 있는 각각의 Git 저장소를 특정 경로로 참조
- 실제 Kubernetes 리소스를 클러스터(kind-dev, kind-prd)에 배포하고 관리
App of apps 패턴의 장점
- 중앙 집중식 : 모든 애플리케이션의 배포 상태 및 구성을 단일 Git 저장소 (Root App이 참조하는 곳)를 통해 중앙에서 관리 가능
- 재사용 및 일관성 : 애플리케이션이 등록된 환경(Mgmt/Dev/Prod)에 표준화된 템플릿을 적용하기 용이
ArgoCD - Sample Application Deploy
argocd app create apps \
--dest-namespace argocd \
--dest-server https://kubernetes.default.svc \
--repo https://github.com/gasida/cicd-study.git \ # gasida repo 활용
--path apps

ArgoCD - Sample Application Sync
dargocd app sync apps

ArgoCD - Sample Application 상태 확인
argocd app list
kubectl get pod -A


ArgoCD - Sample Application 삭제
argocd app delete argocd/apps --yes
ApplicationSet 컨트롤러

1. 해당 그림처럼 ApplicationSet Controller는 ArgoCD와 통신하는 목적은 애플리케이션에 생성,수정,삭제를 통해 선언적 상태를 정의된 상태로 보장 하는 것이 유일한 목표이다.
ApplicationSet은 Generator를 사용해 다른 데이터 소스를 지원하느 매개변수를 생성한다.
아래 링크는 ApplicationSet의 Generator에 대한 설명이다.
https://argo-cd.readthedocs.io/en/stable/operator-manual/applicationset/Generators/
| ApplicationSet Generator 이름 | 용도 |
| List | Argo CD 애플리케이션이 사용할 수 있는 쿠버네티스 클러스터 목록 |
| Cluster | Argo CD에서 이미 정의되고 관리되는 클러스터 기반의 동적 목록 (클러스터 추가/제거 이벤트에 자동으로 응답하는 기능 포함) |
| Git | 깃 리포지터리 내에서 혹은 깃 리포지터리의 디렉터리 구조를 기반으로 하는 애플리케이션 생성 |
| Matrix | 2개의 서로 다른 제너레이터에 대한 매개변수 결합 |
| Merge | 2개의 다른 제너레이터에 대한 매개변수 병합 |
| SCM 공급자 | 소스 코드 관리 SCM Source Code Management 공급자(예, 깃랩이나 깃허브)에서 리포지터리를 자동으로 검색 |
| Pull Request | SCMaaS 제공자(예: GitHub)의 API를 사용하여 Repo 내에서 열려 있는 풀 리퀘스트를 자동으로 검색 |
| Cluster Decision Resource | 사용자 지정 리소스별 논리를 사용하여 배포할 Argo CD 클러스터 목록을 생성 |
| Plugin | 플러그인 생성기는 매개변수를 제공하기 위해 RPC HTTP 요청 |
ApplicationSet - List Generator 실습
- kind-dev, kind-prd ApplicationSet Deploy
# argocd app 배포(dev,prd)
cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ["missingkey=error"]
generators:
- list:
elements:
- cluster: dev-k8s
url: https://172.30.1.39:6445 # ExtraPortMappings(각자 host IP)
- cluster: prd-k8s
url: https://172.30.1.39:6446 # ExtraPortMappings(각자 host IP)
template:
metadata:
name: '{{.cluster}}-guestbook'
labels:
environment: '{{.cluster}}'
managed-by: applicationset
spec:
project: default
source:
repoURL: https://github.com/gasida/cicd-study.git
targetRevision: HEAD
path: appset/list/{{.cluster}}
destination:
server: '{{.url}}'
namespace: guestbook
syncPolicy:
syncOptions:
- CreateNamespace=true
EOF

- Sync
argocd app sync -l managed-by=applicationset


ApplicationSet - Label 필터링


ApplicationSet - kind-dev, kind-prd 각 Pod 정보 확인
k8s2 get pod -n guestbook
k8s3 get pod -n guestbook

ApplicationSet - List Generator 실습 종료(삭제)
argocd appset delete guestbook --yes
ApplicationSet - Cluster Generator 실습
clusters: {}는 ArgoCD에 미리 등록된 모든 클러스터 목록을 가져오도록 지시합니다. 이 목록은 현재 ArgoCD 서버가 실행 중인 클러스터(In-Cluster, kind-mgmt)와 ArgoCD에 추가로 연결된 외부 클러스터(kind-dev,kind-prd) 모두 포함
(외부 클러스터를 가져오는건 ArgoCD에 등록된 클러스터 정보를 읽음으로 가져올 수 있음)
-ApplicationSet Deploy
cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ["missingkey=error"]
generators:
- clusters: {}
template:
metadata:
name: '{{.name}}-guestbook'
labels:
managed-by: applicationset
spec:
project: "default"
source:
repoURL: https://github.com/gasida/cicd-study
targetRevision: HEAD
path: guestbook
destination:
server: '{{.server}}'
namespace: guestbook
syncPolicy:
syncOptions:
- CreateNamespace=true
EOF
# 확인
argocd appset list

- ApplicationSet Sync
argocd app sync -l managed-by=applicationset

- ApplicationSet 및 Pod 정보 확인
# 생성된 application yaml 확인
kubectl get applications -n argocd in-cluster-guestbook -o yaml | k neat | yq
kubectl get applications -n argocd dev-k8s-guestbook -o yaml | k neat | yq
kubectl get applications -n argocd prd-k8s-guestbook -o yaml | k neat | yq
# 각 k8s 에 배포된 파드 정보 확인
k8s1 get pod -n guestbook
k8s2 get pod -n guestbook
k8s3 get pod -n guestbook





동작 순서
ArgoCD(In-Cluster) > ApplicationSet > Child Application > 하위 클러스터(Dev, Prd) 실행
- ApplicationSet 실습 종료
argocd appset delete guestbook --yes
'CICD' 카테고리의 다른 글
| CI/CD 7주차(Vault) (0) | 2025.11.24 |
|---|---|
| CI/CD 6주차(Argo CD)[3] - OpenLDAP + KeyCloak + Argo CD + Jenkins(2) (0) | 2025.11.22 |
| CI/CD 5주차(Argo CD)[2] - Argo Rollout (0) | 2025.11.15 |
| CI/CD 5주차(Argo CD) - 접근제어, SSO (0) | 2025.11.15 |
| CI/CD 4주차(Argo CD) (0) | 2025.11.09 |