티스토리 뷰
안녕하세요, CICD 학습을 위해 CloudNetaStudy 스터디 모임을 통해 진행한 내용을 정리하였습니다.
[Argo CD] 6~8장(263p) - Argo CD 배포 파이프라인, 문제 해결에 대해 중점적으로 학습합니다.
Argo CD 배포 방식에 대한 팀 의견:
→ 현업에서는 App of Apps 패턴 선호도가 높음, 하지만 확장성과 동적 생성은 ApplicationSet이 더 유리함.
Argo CD 배포 방식 요약
● 유형 1. CLI / API 직접 배포
- CI/CD 파이프라인에서 kubectl, argocd CLI 직접 호출
- GitOps 아님 (변경 주도권이 CI/CD 파이프라인에 있음)
● 유형 2. App of Apps 패턴
- “Root Application”이 여러 App을 생성·관리
- Git 구조 기반으로 논리적 그룹을 구성
- 단점:
- 동적 스케일 불가 (정적 Application 목록 필요)
- Git 폴더 구조와 강하게 결합
- 멀티클러스터/테넌트 자동화 어려움
● 유형 3. ApplicationSet
- 여러 클러스터/폴더/PR 기반으로 “Application 자동 생성”
- Generator 기반(Dynamic)
- GitOps + 멀티클러스터 운영에 최적화
Cluster Management
mgmt 클러스터 + Ingress + Argo CD 설치
- sed 기반 SSL passthrough 자동 적용
- 초기 admin PW 자동 변수화
- UI 자동 오픈
#!/usr/bin/env bash
set -e
###############################################
# 1) kind 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
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
- containerPort: 30000
hostPort: 30000
protocol: TCP
EOF
###############################################
# 2) ingress-nginx 배포 (kind 전용)
###############################################
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 -
###############################################
# 3) Argo CD HTTPS용 TLS 인증서 생성
###############################################
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"
kubectl create ns argocd
kubectl -n argocd create secret tls argocd-server-tls \
--cert=argocd.example.com.crt \
--key=argocd.example.com.key
###############################################
# 4) Argo CD 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
###############################################
# 5) Argo CD 설치
###############################################
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
###############################################
# 6) /etc/hosts 등록 (macOS)
###############################################
echo "127.0.0.1 argocd.example.com" | sudo tee -a /etc/hosts
###############################################
# 7) HTTPS 접속 테스트
###############################################
curl -vk https://argocd.example.com/
###############################################
# 8) 초기 admin 비밀번호 확인
###############################################
echo "[INIT PW]"
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d ; echo
###############################################
# 9) CLI 로그인
###############################################
ARGOPW=$(kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d)
argocd login argocd.example.com --insecure \
--username admin --password "$ARGOPW"
###############################################
# 10) 기본 정보 확인
###############################################
argocd cluster list
argocd proj list
argocd account list
###############################################
# 11) admin 비밀번호 변경
###############################################
argocd account update-password \
--current-password "$ARGOPW" \
--new-password qwe12345
###############################################
# 12) 웹 브라우저 열기
###############################################
open "https://argocd.example.com"
kind dev/prd k8s 배포 & k8s 자격증명 수정
- dev/prd kind 클러스터 자동 생성
- Docker 네트워크에서 IP 자동 확인
- IP 기반 API 서버 통신 검증
- kubeconfig 자동 백업 + 자동 패치
- dev/prd 정상 접근 여부 테스트
#!/usr/bin/env bash
set -e
###############################################
# 0) 설치 전 kubeconfig context 확인
###############################################
kubectl config get-contexts
###############################################
# 1) Docker 네트워크(kind) 확인
###############################################
docker network ls
docker network inspect kind | jq || true
###############################################
# 2) kind dev / prd 클러스터 생성
###############################################
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
extraPortMappings:
- containerPort: 31000
hostPort: 31000
EOF
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
extraPortMappings:
- containerPort: 32000
hostPort: 32000
EOF
###############################################
# 3) kubeconfig context 확인
###############################################
kubectl config get-contexts
###############################################
# 4) mgmt context로 변경
###############################################
kubectl config use-context kind-mgmt
kubectl config get-contexts
###############################################
# 5) 클러스터 노드/파드 상태 확인
###############################################
kubectl get node -v=6 --context kind-mgmt
kubectl get node -v=6 --context kind-dev
kubectl get node -v=6 --context kind-prd
kubectl get pod -A --context kind-mgmt
kubectl get pod -A --context kind-dev
kubectl get pod -A --context kind-prd
###############################################
# 6) alias 설정 (선택)
###############################################
alias k8s1='kubectl --context kind-mgmt'
alias k8s2='kubectl --context kind-dev'
alias k8s3='kubectl --context kind-prd'
k8s1 get node -owide
k8s2 get node -owide
k8s3 get node -owide
###############################################
# 7) Docker 네트워크에서 IP 확인
###############################################
docker network inspect kind | grep -E 'Name|IPv4Address'
# 예)
# mgmt-control-plane → 192.168.97.2
# dev-control-plane → 192.168.97.3
# prd-control-plane → 192.168.97.4
###############################################
# 8) 클러스터 간 API Server 통신 확인
###############################################
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
###############################################
# 9) 로컬 PC에서 ping 확인
###############################################
ping -c 1 192.168.97.2 || true
ping -c 1 192.168.97.3 || true
ping -c 1 192.168.97.4 || true
###############################################
# 10) kubeconfig 백업 및 API server 주소 변경
###############################################
cp ~/.kube/config ./kube-config.bak
# 자동 패치 (localhost → docker IP)
sed -i.bak 's/https:\/\/127.0.0.1:[0-9]*/https:\/\/192.168.97.3:6443/' ~/.kube/config
sed -i.bak 's/https:\/\/127.0.0.1:[0-9]*/https:\/\/192.168.97.4:6443/' ~/.kube/config
echo "[수정한 kubeconfig 확인]"
cat ~/.kube/config
###############################################
# 11) dev/prd 접근 확인
###############################################
kubectl get node -v=6 --context kind-dev
kubectl get node -v=6 --context kind-prd
Argo CD에 다른 K8S Cluster 등록 - Docs , Cluster* , CMD , KrBlog
- Argo CD가 가진 cluster 목록 확인
- dev/prd 클러스터(ServiceAccount·RoleBinding 포함) 등록
- 등록된 클러스터의 Secret(credential) 자동 확인
- Argo CD가 관리 가능한 cluster 목록을 최종 출력
#!/usr/bin/env bash
set -e
###############################################
# 1) 기본 Cluster 상태 확인
###############################################
argocd cluster list
argocd cluster list -o json | jq
kubectl get secret -n argocd
kubectl get secret -n argocd argocd-secret -o jsonpath='{.data}' | jq
###############################################
# 2) kind-dev, kind-prd의 kube-system SA 확인
###############################################
kubectl --context kind-dev get sa -n kube-system
kubectl --context kind-prd get sa -n kube-system
###############################################
# 3) dev 클러스터 Argo CD에 등록
###############################################
argocd cluster add kind-dev --name dev-k8s --yes
kubectl --context kind-dev get sa -n kube-system argocd-manager
kubectl rolesum -n kube-system argocd-manager --context kind-dev || true
###############################################
# 4) Argo CD cluster secret 확인
###############################################
kubectl get secret -n argocd -l argocd.argoproj.io/secret-type=cluster
###############################################
# 5) Argo CD cluster 정보 출력
###############################################
argocd cluster list -o json | jq
argocd cluster list
###############################################
# 6) prd 클러스터 Argo CD에 등록
###############################################
argocd cluster add kind-prd --name prd-k8s --yes
kubectl --context kind-prd get sa -n kube-system argocd-manager
kubectl get secret -n argocd -l argocd.argoproj.io/secret-type=cluster
###############################################
# 7) 최종 클러스터 등록 상태 확인
###############################################
argocd cluster list
Argo CD로 3개의 K8S Cluster 에 각각 Nginx 배포
#!/usr/bin/env bash
set -e
###############################################
# 1) kind 네트워크에서 클러스터 IP 확인
###############################################
docker network inspect kind | grep -E 'Name|IPv4Address'
# 수동 변수 설정 (필요 시 docker inspect 결과 기반 자동 파싱 가능)
DEVK8SIP=192.168.97.3
PRDK8SIP=192.168.97.4
echo "[DEV IP:$DEVK8SIP] [PRD IP:$PRDK8SIP]"
###############################################
# 2) Argo CD Application - mgmt 환경 배포
###############################################
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
###############################################
# 3) Argo CD Application - dev 환경 배포
###############################################
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://$DEVK8SIP:6443
EOF
############################################
App of Apps 패턴 개요
Argo CD에서 부모 Application( root app ) 하나가 여러 자식 Application을 선언적으로 생성·관리하는 패턴.
장점
- 여러 Application을 하나의 그룹처럼 묶어 관리
- 부모 Application 한 번으로 모든 자식 Application 배포 가능
- 그룹 전체 Sync/Health 확인 가능
사용 예시
Helm 템플릿으로 Applications YAML을 반복 생성:
{{- range .Values.applications }}
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: example.{{ .name }}
namespace: argocd
spec:
destination:
namespace: {{ .namespace }}
server: {{ $.Values.config.spec.destination.server }}
source:
repoURL: {{ $.Values.config.spec.source.repoURL }}
targetRevision: {{ $.Values.config.spec.source.targetRevision }}
path: {{ .path }}
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
---
{{- end }}
App of Apps 패턴의 한계
App of Apps는 정적(Static) 구조라서 확장이 어려움.
주요 단점
- 동적 확장 불가
- 애플리케이션 수가 늘면 YAML에 수동 추가해야 함
- 고객 100명 = Application 100개 직접 추가
- Git 폴더 구조에 종속
- Git 디렉토리 변경 시 Root App 수정 필요
- 다중 클러스터 확장 어려움
- 클러스터 5개 → Application 5개 수동 생성
- 대규모 멀티 테넌트에서 비효율적
- Root App YAML이 거대해짐
- Conflict 빈번
- 동적 자동 생성 미지원
- label 기반 자동 배포 불가
- region/tenant 구조 자동화 불가
→ 그래서 Argo CD 팀이 ApplicationSet 컨트롤러를 개발함
ApplicationSet Controller 개요
Argo CD가 사용하는 Application 리소스를 대량·자동 생성/관리하기 위한 전용 컨트롤러.
기능
- 여러 클러스터에 동시 배포
- 여러 Git Repo에서 Application 자동 생성
- Multi-tenant 지원
- 대규모 배포 자동화
- 동적 generator 기반 Application 생성
목적
ApplicationSet은 정의한 규칙에 따라 Application들을 자동 생성·갱신·삭제하여 상태를 일관되게 유지하는 컨트롤러
ApplicationSet Generators (핵심)
ApplicationSet은 “제너레이터”가 Application을 자동 생성함.
주요 Generator 종류
| List | 정해진 요소 목록 기반으로 Application 생성 |
| Cluster | Argo CD에 등록된 클러스터 목록 기반 자동 생성 |
| Git | Git 디렉토리 구조 기반 App 생성 |
| Matrix | 두 개의 generator 조합 |
| Merge | generator 병합 |
| SCM Provider | GitHub/GitLab repo 자동 검색 |
| Pull Request | PR 자동 검색 후 App 생성 |
| Cluster Decision Resource | 사용자 정의 CR 기반 클러스터 대상 생성 |
| Plugin | 외부 HTTP RPC로 값 생성 |
ApplicationSet 실습
(1) List Generator 실습
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
namespace: argocd
spec:
goTemplate: true
generators:
- list:
elements:
- cluster: dev-k8s
url: https://192.168.97.3:6443
- cluster: prd-k8s
url: https://192.168.97.4:6443
template:
metadata:
name: '{{.cluster}}-guestbook'
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
→ 자동으로 아래 Application이 생성됨
- dev-k8s-guestbook
- prd-k8s-guestbook
(2) Cluster Generator 실습 (모든 클러스터 자동 대상화)
generators:
- clusters: {}
→ Argo CD에 등록된 모든 클러스터를 자동 대상으로 삼음.
(3) Cluster Generator + Label selector (특정 클러스터만)
generators:
- clusters:
selector:
matchLabels:
env: "stg"
→ 라벨 붙인 클러스터만 배포됨.
예:
kubectl label secret cluster-192.168.97.3-xxxx -n argocd env=stg
kubectl get applicationsets -n argocd
argocd appset list
argocd app list -l managed-by=applicationset
kubectl get applications -n argocd --show-labels
argocd app sync -l managed-by=applicationset
삭제:
argocd appset delete guestbook --yes
✔ App of Apps = “정적 구조, 작은 규모에 적합”
✔ ApplicationSet = “동적 생성 + 멀티클러스터 + 멀티테넌트 + 자동화에 특화”
규모가 커지거나 동적 배포가 필요하면 ApplicationSet이 필수
OpenLDAP + Keycloak + Argo CD + Jenkins 구성

| OpenLDAP | 인증 데이터 저장소 |
| Keycloak | LDAP 연동 + OIDC Provider (Auth Server) |
| Argo CD | Keycloak OIDC 로그인 사용 |
| Jenkins | Keycloak OIDC 로그인 사용 |
| CoreDNS hosts Plugin | 내부 도메인 → ClusterIP 매핑 |
이 구조를 통해:
- 외부/내부 모두 동일한 도메인으로 Keycloak 접근
- ArgoCD/Jenkins SSO (OAuth2/OIDC) 연동 가능
1. Keycloak 설치 및 기본 설정
Keycloak 배포
- Deployment + Service + Ingress 구성
- keycloak.example.com 도메인으로 접근
- /etc/hosts 에 127.0.0.1 매핑
- admin / admin 로그인 후 realm 생성
#
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: keycloak
labels:
app: keycloak
spec:
replicas: 1
selector:
matchLabels:
app: keycloak
template:
metadata:
labels:
app: keycloak
spec:
containers:
- name: keycloak
image: quay.io/keycloak/keycloak:26.4.0
args: ["start-dev"] # dev mode 실행
env:
- name: KEYCLOAK_ADMIN
value: admin
- name: KEYCLOAK_ADMIN_PASSWORD
value: admin
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: keycloak
spec:
selector:
app: keycloak
ports:
- name: http
port: 80
targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: keycloak
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
ingressClassName: nginx
rules:
- host: keycloak.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: keycloak
port:
number: 8080
EOF
# 확인
kubectl get deploy,svc,ep keycloak
kubectl get ingress keycloak
NAME CLASS HOSTS ADDRESS PORTS AGE
keycloak nginx keycloak.example.com localhost 80 91s
#
curl -s -H "Host: keycloak.example.com" http://127.0.0.1 -I
HTTP/1.1 302 Found
Location: http://keycloak.example.com/admin/
# 도메인 설정
## macOS의 /etc/hosts 파일 수정
echo "127.0.0.1 keycloak.example.com" | sudo tee -a /etc/hosts
cat /etc/hosts
## C:\Windows\System32\drivers\etc\hosts 관리자모드에서 메모장에 내용 추가
127.0.0.1 keycloak.example.com
# keycloak 웹 접속 : admin / admin
curl -s http://keycloak.example.com -I
open "http://keycloak.example.com/admin"
2. 클러스터 내부에서 Keycloak·Argo CD·Jenkins 도메인 접근 설정
Pod 내부에서 keycloak.example.com 이 resolve 되지 않아 접근 불가 문제 발생 → CoreDNS hosts 플러그인으로 해결.
# 경량의 curl 테스트용 파드 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: curl
namespace: default
spec:
containers:
- name: curl
image: curlimages/curl:latest
command: ["sleep", "infinity"]
EOF
#
kubectl get pod -l app=keycloak -owide
kubectl get pod -l app=keycloak -o jsonpath='{.items[0].status.podIP}'
KEYCLOAKIP=$(kubectl get pod -l app=keycloak -o jsonpath='{.items[0].status.podIP}')
echo $KEYCLOAKIP
# 기본 통신 및 정보 확인 : ClusterIP 메모!
kubectl get svc keycloak
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
keycloak ClusterIP 10.96.58.66 <none> 80/TCP 25m
kubectl get svc -n argocd argocd-server
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
argocd-server ClusterIP 10.96.156.196 <none> 80/TCP,443/TCP 134m
kubectl exec -it curl -- ping -c 1 $KEYCLOAKIP
kubectl exec -it curl -- curl -s http://keycloak.default.svc.cluster.local/realms/myrealm/.well-known/openid-configuration | jq
# 왜 호출이 되지 않을까?
kubectl exec -it curl -- curl -s http://keycloak.example.com -I
kubectl exec -it curl -- nslookup -debug keycloak.example.com
kubectl exec -it curl -- nslookup keycloak.example.com
# 해결해보자 : coredns 에 hosts 플러그인 활용
KUBE_EDITOR="nano" kubectl edit cm -n kube-system coredns
.:53 {
...
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
hosts {
<CLUSTER IP> keycloak.example.com
<CLUSTER IP> argocd.example.com
fallthrough
}
reload # cm 설정 변경 시 자동으로 reload 적용됨
...
# cm 설정 변경 시 자동으로 reload 적용 로그 확인
kubectl logs -n kube-system -l k8s-app=kube-dns --timestamps
# 도메인 질의 시, ClusterIP로 변경 확인 : 파드 내에 dns 쿼리 캐시는 없는 걸까요???
kubectl exec -it curl -- nslookup -debug keycloak.example.com
kubectl exec -it curl -- nslookup keycloak.example.com
3. Keycloak에 Argo CD OIDC Client 생성
Argo CD용 Keycloak client 설정

Argo CD OIDC 설정(ConfigMap)
#
kubectl -n argocd patch secret argocd-secret --patch='{"stringData": { "oidc.keycloak.clientSecret": "<REPLACE_WITH_CLIENT_SECRET>" }}'
kubectl -n argocd patch secret argocd-secret --patch='{"stringData": { "oidc.keycloak.clientSecret": "mV3IZO3nmHoZr3BBC37UpdrMSMkF9Umt" }}'
# 확인
kubectl get secret -n argocd argocd-secret -o jsonpath='{.data}' | jq
...
"oidc.keycloak.clientSecret": "bVYzSVpPM25tSG9acjNCQkMzN1VwZHJNU01rRjlVbXQ=",
# 설정 추가
kubectl patch cm argocd-cm -n argocd --type merge -p '
data:
oidc.config: |
name: Keycloak
issuer: http://keycloak.example.com/realms/myrealm
clientID: argocd
clientSecret: mV3IZO3nmHoZr3BBC37UpdrMSMkF9Umt
requestedScopes: ["openid", "profile", "email"]
'
# 확인
kubectl get cm -n argocd argocd-cm -o yaml | grep oidc.config: -A5
- alice로 로그인 → 정상 인증
- Keycloak 콘솔에서 해당 세션 조회 가능
5. Jenkins 배포 및 OIDC 연동
#
kubectl create ns jenkins
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jenkins-pvc
namespace: jenkins
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: jenkins
namespace: jenkins
spec:
replicas: 1
selector:
matchLabels:
app: jenkins
template:
metadata:
labels:
app: jenkins
spec:
securityContext:
fsGroup: 1000
containers:
- name: jenkins
image: jenkins/jenkins:lts
ports:
- name: http
containerPort: 8080
- name: agent
containerPort: 50000
volumeMounts:
- name: jenkins-home
mountPath: /var/jenkins_home
volumes:
- name: jenkins-home
persistentVolumeClaim:
claimName: jenkins-pvc
---
apiVersion: v1
kind: Service
metadata:
name: jenkins-svc
namespace: jenkins
spec:
type: ClusterIP
selector:
app: jenkins
ports:
- port: 8080
targetPort: http
protocol: TCP
name: http
- port: 50000
targetPort: agent
protocol: TCP
name: agent
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: jenkins-ingress
namespace: jenkins
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
spec:
ingressClassName: nginx
rules:
- host: jenkins.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: jenkins-svc
port:
number: 8080
EOF
# 확인
kubectl get deploy,svc,ep,pvc -n jenkins
kubectl get ingress -n jenkins jenkins-ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
jenkins-ingress nginx jenkins.example.com localhost 80 60s
# 도메인 설정
## macOS의 /etc/hosts 파일 수정
echo "127.0.0.1 jenkins.example.com" | sudo tee -a /etc/hosts
cat /etc/hosts
## C:\Windows\System32\drivers\etc\hosts 관리자모드에서 메모장에 내용 추가
127.0.0.1 jenkins.example.com
# 초기 암호 확인
kubectl exec -it -n jenkins deploy/jenkins -- cat /var/jenkins_home/secrets/initialAdminPassword
7521bc306a4049a6a0fd75391ae4b235
# 웹 접속 : 기본 설정 진행
curl -s http://jenkins.example.com -I
open "http://jenkins.example.com"
Jenkins OIDC 설정
- Keycloak client ID: jenkins
- Redirect URL:
- OIDC Discovery endpoint:
- Scopes:
- openid email profile
alice/bob으로 Keycloak 인증 로그인 가능.
6. OpenLDAP 설치 및 사용자/그룹 생성
OpenLDAP + phpLDAPadmin 분석
- Base DN: dc=example,dc=org
- 관리자 DN: cn=admin,dc=example,dc=org
LDAP 엔트리 구성
dc=example,dc=org # Base DN(Root DN)
├── ou=people
│ ├── uid=alice
│ └── uid=bob
└── ou=groups
├── cn=devs
└── cn=admins
User/Group 생성 및 검색
- ldapadd로 people, groups, users(bob/alice), group entries 생성
- ldapsearch, ldapwhoami로 검증
7. Keycloak ↔ LDAP 연동
Keycloak User Federation(LDAP) 설정
- LDAP URL: ldap://openldap.openldap.svc:389
- Bind DN: cn=admin,dc=example,dc=org
- Users DN: ou=people,dc=example,dc=org
- Edit Mode: WRITABLE
- Search scope: Subtree
User Sync
- Keycloak → "Sync all users"
→ LDAP의 alice, bob이 Keycloak user로 등록됨
8. LDAP Group → Keycloak Group 동기화
Keycloak Mapper 생성:
- Mapper type: group-ldap-mapper
- LDAP Groups DN: ou=groups,dc=example,dc=org
- LDAP attribute:
- name: cn
- member attribute: member
- Mode: READ_ONLY
→ Keycloak Groups에 admins, devs 자동 생성
→ 각 그룹에 alice/bob 자동 연결됨
9. Group 정보를 Token으로 전달 (ArgoCD/Jenkins RBAC)
Keycloak Client Scope 생성
- Scope name: groups
- Mapper: Group Membership
- Token Claim Name: groups
Keycloak → argocd, jenkins Client에 scope 추가(Default)
Argo CD requestedScopes에 groups 추가
Jenkins에도 groups scope 추가
→ bob 로그인 시 devs 그룹 씌워진 것 확인
10. Argo CD RBAC 설정
devs 그룹에 ArgoCD admin 권한 부여
argocd-rbac-cm 설정:
→ bob(devs 그룹) 로그인 시 ArgoCD 관리자 권한 획득
11. Applicationset 배포 테스트
- Argo CD ApplicationSet 샘플 guestbook 배포
- bob 로그인 시 RBAC에 따라 접근 권한이 달라짐
#
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
# sync
argocd app sync -l managed-by=applicationset
# 생성된 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
12. 최종 결과
OpenLDAP 사용자/그룹 → Keycloak 자동 동기화
Keycloak → Argo CD · Jenkins OIDC SSO
CoreDNS로 Kubernetes 내부에서도 동일 도메인 접근 가능
RBAC을 그룹 기반으로 통합 관리
bob(devs) / alice(admins) 의 권한이 ArgoCD/Jenkins 모두에 일관 적용
'IT > Devops' 카테고리의 다른 글
| [cicd] 5주차 - Argo CD (0) | 2025.11.16 |
|---|---|
| [cicd] 4주차 - Argo CD (0) | 2025.11.09 |
| [cicd] 3주차 - Jenkins + ArgoCD (0) | 2025.11.02 |
| [cicd] 2주차 - Helm, Tekton (0) | 2025.10.25 |
| [cicd] 1주차 - Image Build (0) | 2025.10.19 |
- Total
- Today
- Yesterday
- AI
- cloud
- OS
- CICD
- ai 엔지니어링
- terraform
- EKS
- handson
- 혼공챌린지
- security
- k8s calico
- GKE
- k8s cni
- IaC
- NFT
- GCP
- 혼공단
- S3
- 파이썬
- 혼공파
- k8s
- NW
- cni
- PYTHON
- SDWAN
- 도서
- operator
- autoscaling
- AWS
- VPN
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
