[CI/CD Study 6주차] ArgoCD 실전 활용 - App of Apps, ApplicationSet, 인증 통합
- -
CoudNet@ 팀의 가시다님께서 리딩하시는 CI/CD Study 6주차 스터디 내용 정리
이번 글에서는 CI/CD 스터디에서 ArgoCD 를 다루는 마지막 주차인 만큼 멀티 클러스터 배포, 다수의 Application 배포 방법, 인증 통합 등에 대해서 학습했습니다.
1. 실습 환경 구성
실습은 멀티 클러스터 환경을 위해서 총 3대의 쿠버네티스 클러스터를 구성할 예정입니다.
ArgoCD 가 배포되는 Management 클러스터 + DEV 클러스터 + PRD 클러스터 로 구성되며,
DEV 와 PRD 의 배포는 MGMT ArgoCD 가 담당하게 됩니다.
1.1. Management K8S 배포
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
EOF
# Ingress Nginx 배포
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
# SSL Passthrough 패치
kubectl patch deployment ingress-nginx-controller -n ingress-nginx --type='json' \
-p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--enable-ssl-passthrough"}]'
# ArgoCD https 를 위한 TLS/SSL 키 생성
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"
# ArgoCD https 를 위한 시크릿 등록
kubectl create ns argocd
kubectl -n argocd create secret tls argocd-server-tls \
--cert=argocd.example.com.crt \
--key=argocd.example.com.key
# ArgoCD value 작성
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
# ArgoCD 배포
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
# ArgoCD 접속을 위한 host 파일 변경 - MAC
echo "127.0.0.1 argocd.example.com" | sudo tee -a /etc/hosts
# ArgoCD 암호 확인
ARGOPW=$(kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d ;echo)
# ArgoCD CLI 를 통한 로그인 후 암호 변경
argocd login argocd.example.com --insecure --username admin --password $ARGOPW
argocd account update-password --current-password $ARGOPW --new-password qwe12345
1.2. DEV / PRD K8S 배포
DEV , PRD 클러스터도 마찬가지로 Kind 를 통해서 배포합니다.
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
1.3. Alias 지정
이후 k8s 리소스 호출을 편리하게 하기 위해 별칭을 지정합니다.
# alias 설정
alias k8s1='kubectl --context kind-mgmt'
alias k8s2='kubectl --context kind-dev'
alias k8s3='kubectl --context kind-prd'
이후 클러스터 간 통신을 위해서 kube config 를 수정합니다.
# 각 클러스터 IP 확인
docker network inspect kind | grep -E 'Name|IPv4Address'
"Name": "kind",
"Name": "dev-control-plane",
"IPv4Address": "172.18.0.3/16",
"Name": "mgmt-control-plane",
"IPv4Address": "172.18.0.2/16",
"Name": "prd-control-plane",
"IPv4Address": "172.18.0.4/16",
# kube config 수정
vi ~/.kube/config
# kind-dev 및 kind-prd 클러스터 Server IP 변경
clusters:
- cluster:
server: https://172.18.0.3:6443
name: kind-dev
- cluster:
server: https://172.18.0.4:6443
name: kind-prd
# 호출 테스트
kubectl get node -v=6 --context kind-dev
kubectl get node -v=6 --context kind-prd

2. ArgoCD 활용
2.1. Multi Cluster 등록
ArgoCD CLI 를 통해서 간단하게 다른 클러스터를 관리 대상으로 등록할 수 있습니다.
# DEV / PRD 클러스터 등록
argocd cluster add kind-dev --name dev-k8s --yes
argocd cluster add kind-prd --name prd-k8s --yes


ArgoCD 인증은 Kubernetes Secret 과 Service Account 리소스를 통해서 진행하기 때문에 해당 리소스 관계를 잘 이해하는 것도 중요합니다.
2.2. Multi Cluster 배포 테스트
ArgoCD 배포를 위한 Helm Chart 는 Gasida 님의 Github Repo 를 Fork 하여 사용했습니다.
GitHub - gasida/cicd-study
Contribute to gasida/cicd-study development by creating an account on GitHub.
github.com
해당 어플리케이션은 Nginx Helm Chart 를 배포하는 단순한 리소스지만 mgmt, dev, prd 클러스터에 각각 배포됩니다.
# 변수 등록
DEVK8SIP=172.18.0.3
PRDK8SIP=172.18.0.4
GITREPO="https://github.com/AlarmKimKB/cicd-study"
echo $DEVK8SIP $PRDK8SIP $GITREPO
# 어플리케이션 배포
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: $GITREPO
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: $GITREPO
targetRevision: HEAD
syncPolicy:
automated:
prune: true
syncOptions:
- CreateNamespace=true
destination:
namespace: dev-nginx
server: https://$DEVK8SIP:6443
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: $GITREPO
targetRevision: HEAD
syncPolicy:
automated:
prune: true
syncOptions:
- CreateNamespace=true
destination:
namespace: prd-nginx
server: https://$PRDK8SIP:6443
EOF

2.3. App of Apps 패턴
여러 개의 ArgoCD Application 을 하나의 상위 Application 으로 관리하는 패턴
App of Apps 패턴의 핵심 개념은 부모 애플리케이션과 자식 애플리케이션입니다.
하나의 부모 애플리케이션에 여러 자식 애플리케이션이 묶여 있다는 것입니다.
부모 애플리케이션만 배포하면 자동으로 해당 부모 애플리케이션 휘하의 자식 애플리케이션들이 배포되는 형태입니다.
App of Apps 패턴 파일은 마치 Helm 을 작성하는 것처럼 구성 됩니다.
Application 을 템플릿화해놓은 상태로 Values.yaml 에서 Application Name 만 변경해서 배포하는 형식입니다.
App of Apps Application.yaml
{{- range .Values.applications }}
{{- $config := $.Values.config -}}
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: {{ printf "example.%s" .name | quote }}
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
destination:
namespace: {{ .namespace | default .name | quote }}
server: {{ $config.spec.destination.server | quote }}
project: default
source:
path: {{ .path | default .name | quote }}
repoURL: {{ $config.spec.source.repoURL }}
targetRevision: {{ $config.spec.source.targetRevision }}
{{- with .tool }}
{{- . | toYaml | nindent 4 }}
{{- end }}
syncPolicy:
syncOptions:
- CreateNamespace=true
automated:
prune: true
selfHeal: true
---
{{ end -}}
App of Apps values.yaml
config:
spec:
destination:
server: https://kubernetes.default.svc
source:
repoURL: https://github.com/AlarmKimKB/cicd-study
targetRevision: main
applications:
- name: helm-guestbook
tool:
helm:
releaseName: helm-guestbook
- name: kustomize-guestbook
- name: sync-waves
App of Apps 배포
argocd app create apps \
--dest-namespace argocd \
--dest-server https://kubernetes.default.svc \
--repo https://github.com/AlarmKimKB/cicd-study.git \
--path apps
argocd app sync apps


2.4. ApplicationSet
ArgoCD Application 을 자동으로 생성 / 관리하는 컨트롤러
여러개의 Application 을 한번에 관리하는 것은 App of Apps 패턴과 동일하나,
정적으로만 생성할 수 있는 App of Apps 와는 다르게 ApplicationSet 은 동적으로도 생성이 가능합니다.

동적으로 생성된다는 말은 자동화가 된다는 말입니다.
예를 들어, 모니터링이나 로깅 서비스는 ArgoCD 에 연결된 모든 클러스터에 동일하게 배포되어야 합니다.
이 때, ApplicationSet 의 Cluster Generator 를 사용하게 되면 ArgoCD 에 신규 클러스터가 등록될 때마다 자동으로 해당 클러스터에 서비스를 배포하게 됩니다.
Generator
- ApplicationSet이 어떤 조건으로 Application을 생성할지 정의하는 규칙
Generator 종류
1. List : 수동으로 정의한 리스트
2. Cluster : ArgoCD에 등록된 클러스터 자동 감지, 클러스터 추가되면 자동 생성
3. Git : 깃 리포지터리 내에서 혹은 깃 리포지터리의 디렉터리 구조를 기반으로 하는 애플리케이션 생성
4. Matrix : 2개의 서로 다른 제너레이터에 대한 매개변수 결합
5. Merge : 2개의 다른 제너레이터에 대한 매개변수 병합
6. SCM Provider : GitHub/GitLab Organization의 모든 레포지토리 자동 감지.
7.Pull Request : PR 마다 임시 환경 자동 생성
8. Cluster Decision Resource : 사용자 지정 리소스별 논리를 사용하여 배포할 Argo CD 클러스터 목록을 생성
9. Plugin : 커스텀 로직으로 데이터를 생성할 수 있는 확장 가능한 Generator
ApplicationSet List Generator 실습
List Generator 에 들어있는 요소를 확인하여 해당 요소에 Application 을 배포하는 실습입니다.
여기서는 cluster 를 List 로 지정했기 때문에, 각 cluster 에 Application 이 배포됩니다.
docker network inspect kind | grep -E 'Name|IPv4Address'
DEVK8SIP=172.18.0.3
PRDK8SIP=172.18.0.4
GITREPO=https://github.com/AlarmKimKB/cicd-study.git
echo $DEVK8SIP $PRDK8SIP $GITREPO
# argocd app 배포
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://$DEVK8SIP:6443
- cluster: prd-k8s
url: https://$PRDK8SIP:6443
template:
metadata:
name: '{{.cluster}}-guestbook'
labels:
environment: '{{.cluster}}'
managed-by: applicationset
spec:
project: default
source:
repoURL: $GITREPO
targetRevision: HEAD
path: appset/list/{{.cluster}}
destination:
server: '{{.url}}'
namespace: guestbook
syncPolicy:
syncOptions:
- CreateNamespace=true
EOF

ApplicationSet Cluster Generator 실습
cluster generator 에 포함된 클러스터를 확인해서 해당 클러스터에 배포하는 실습입니다.
cluster 에 아무 내용이 없을 경우, 기본적으로 ArgoCD 에 등록된 모든 클러스터에 배포됩니다.
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/AlarmKimKB/cicd-study
targetRevision: HEAD
path: guestbook
destination:
server: '{{.server}}'
namespace: guestbook
syncPolicy:
syncOptions:
- CreateNamespace=true
EOF

3. OpenLDAP + KeyCloak + Argo CD + Jenkins
이번에는 OpenLDAP, KeyCloak, ArgoCD, Jenkins 를 모두 사용해보는 인증 통합 실습을 진행해보겠습니다.
3.1. KeyCloak
먼저 키클락을 쿠버네티스에 배포하겠습니다.
키클락 개념에 대해서는 이전 주차에서 다뤘기 때문에 생략하겠습니다.
KeyCloak 배포
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
# Keycloak host 파일 등록
echo "127.0.0.1 keycloak.example.com" | sudo tee -a /etc/hosts
Keycloak 의 초기 접속 정보는 admin / admin 입니다.

실습 편의성을 위해서 Realm 을 하나 생성합니다. (myrealm)
그 후 실습 User 도 생성합니다. (alice / alice123)
3.2. MGMT 파드 내부에서 ArgoCD, KeyCloak 도메인 호출을 위한 CoreDNS 설정
MGMT 파드에서 ArgoCD, KeyCloak 도메인 호출을 위해서는 CoreDNS 에 host 플러그인 활용이 필요합니다.
# KeyCloack, ArgoCD 의 ClusterIP 확인
kubectl get svc -n argocd argocd-server
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
argocd-server ClusterIP 10.96.152.75 <none> 80/TCP,443/TCP 3h42m
kubectl get svc keycloak
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
keycloak ClusterIP 10.96.37.138 <none> 80/TCP 10m
# CoreDNS ConfigMap 편집
kubectl edit cm -n kube-system coredns

3.3. ArgoCD - KeyCloak 연동
KeyCloak 까지 준비되었으면 ArgoCD 와 연동을 진행해보겠습니다.
연동 과정은 저번 글에서 작성된 것과 동일합니다.



그 후 Credential 을 확인하여 ArgoCD 에 등록해줍니다.
# 시크릿 업데이트
kubectl -n argocd patch secret argocd-secret --patch='{"stringData": { "oidc.keycloak.clientSecret": "<키클락_클라이언트 크레덴셜>" }}'
# 컨피그맵 업데이트
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: <키클락_클라이언트 크레덴셜>
requestedScopes: ["openid", "profile", "email"]
'
# ArgoCD 재시작
kubectl rollout restart deploy argocd-server -n argocd
ArgoCD 를 KeyCloak 의 alice 사용자로 로그인하면 유저 정보에 아래와 같이 나타나게 됩니다.

3.4. Jenkins 배포
젠킨스도 쿠버네티스로 배포를 하겠습니다.
젠킨스도 배포 과정은 앞의 키클락과 거의 동일합니다.
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
# Jenkins host 등록
echo "127.0.0.1 jenkins.example.com" | sudo tee -a /etc/hosts
# Jenkins 초기 암호 확인
kubectl exec -it -n jenkins deploy/jenkins -- cat /var/jenkins_home/secrets/initialAdminPassword
Jenkins 도메인 호출을 위한 CoreDNS 편집
젠킨스도 마찬가지로 mgmt 클러스터 내부에서 도메인을 호출할 수 있도록 CoreDNS 를 편집합니다.
# cluster IP 확인
kubectl get svc -n jenkins
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
jenkins-svc ClusterIP 10.96.198.166 <none> 8080/TCP,50000/TCP 12m
kubectl edit cm -n kube-system coredns

3.5. Jenkins - KeyCloak 연동
ArgoCD 와 KeyCloak 을 연동했던 과정을 Jenkins 로 변경했다고 생각하시면 됩니다.
과정은 동일합니다.
KeyCloak 에서 Jenkins Client 생성



Jenkins OpenID Connect Authentication 플러그인 설치

- Client id : jenkins
- Client secret : KeyCloak 의 Jenkins Client Credential
- Well-know configuration endpoint: http://keycloak.example.com/realms/myrealm/.well-known/openid-configuration
- Override scopes : openid email profile


KeyCloak 연동 후 Jenkins 에 로그인하고 ArgoCD 를 들어가보면 KeyCloak 을 통해서 접속했기 때문에 로그인 세션이 유지되고 있는 것을 알 수 있습니다.

3.6. OpenLDAP 배포
디렉터리 서비스에 접근하기 위한 표준 프로토콜로 “조직 내 사용자, 그룹, 권한 등의 정보를 트리 구조로 저장하고 조회하는 시스템” 입니다.
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: openldap
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: openldap
namespace: openldap
spec:
replicas: 1
selector:
matchLabels:
app: openldap
template:
metadata:
labels:
app: openldap
spec:
containers:
- name: openldap
image: osixia/openldap:1.5.0
ports:
- containerPort: 389
name: ldap
- containerPort: 636
name: ldaps
env:
- name: LDAP_ORGANISATION # 기관명, LDAP 기본 정보 생성 시 사용
value: "Example Org"
- name: LDAP_DOMAIN # LDAP 기본 Base DN 을 자동 생성
value: "example.org"
- name: LDAP_ADMIN_PASSWORD # LDAP 관리자 패스워드
value: "admin"
- name: LDAP_CONFIG_PASSWORD
value: "admin"
- name: phpldapadmin
image: osixia/phpldapadmin:0.9.0
ports:
- containerPort: 80
name: phpldapadmin
env:
- name: PHPLDAPADMIN_HTTPS
value: "false"
- name: PHPLDAPADMIN_LDAP_HOSTS
value: "openldap" # LDAP hostname inside cluster
---
apiVersion: v1
kind: Service
metadata:
name: openldap
namespace: openldap
spec:
selector:
app: openldap
ports:
- name: phpldapadmin
port: 80
targetPort: 80
nodePort: 30000
- name: ldap
port: 389
targetPort: 389
- name: ldaps
port: 636
targetPort: 636
type: NodePort
EOF
# OpenLDAP 접속
open http://127.0.0.1:30000
초기 접속 정보는 다음과 같습니다.
- Login DN: cn=admin,dc=example,dc=org
- Password: admin

3.7. OpenLDAP 구성 설정
OpenLDAP 을 구성하기 위해 파드 안에서 작업을 진행합니다.
작업 후에는 다음과 같은 조직 구성이 준비될 예정입니다.
최종 LDAP 구성도
dc=example,dc=org
├── ou=people
│ ├── uid=alice
│ │ ├── cn: Alice
│ │ ├── sn: Kim
│ │ ├── uid: alice
│ │ └── mail: alice@example.org
│ └── uid=bob
│ ├── cn: Bob
│ ├── sn: Lee
│ ├── uid: bob
│ └── mail: bob@example.org
└── ou=groups
├── cn=devs
│ └── member: uid=bob,ou=people,dc=example,dc=org
└── cn=admins
└── member: uid=alice,ou=people,dc=example,dc=org

# OpenLDAP 파드 접속
kubectl -n openldap exec -it deploy/openldap -c openldap -- bash
# OU 추가
cat <<EOF | ldapadd -x -D "cn=admin,dc=example,dc=org" -w admin
dn: ou=people,dc=example,dc=org
objectClass: organizationalUnit
ou: people
dn: ou=groups,dc=example,dc=org
objectClass: organizationalUnit
ou: groups
EOF
# 유저 추가
cat <<EOF | ldapadd -x -D "cn=admin,dc=example,dc=org" -w admin
dn: uid=alice,ou=people,dc=example,dc=org
objectClass: inetOrgPerson
cn: Alice
sn: Kim
uid: alice
mail: alice@example.org
userPassword: alice123
dn: uid=bob,ou=people,dc=example,dc=org
objectClass: inetOrgPerson
cn: Bob
sn: Lee
uid: bob
mail: bob@example.org
userPassword: bob123
EOF
# 그룹 추가
cat <<EOF | ldapadd -x -D "cn=admin,dc=example,dc=org" -w admin
dn: cn=devs,ou=groups,dc=example,dc=org
objectClass: groupOfNames
cn: devs
member: uid=bob,ou=people,dc=example,dc=org
dn: cn=admins,ou=groups,dc=example,dc=org
objectClass: groupOfNames
cn: admins
member: uid=alice,ou=people,dc=example,dc=org
EOF
3.8. OpenLDAP - KeyCloak 사용자 연동
OpenLDAP 이 연동 완료되었으니, KeyCloak 과 연동해보겠습니다.
OpenLDAP 에서는 AD 역할을 통한 계정 관리, KeyCloak 은 SSO 를 통한 세션 관리를 해주는 역할로 구분될 것 같습니다.
KeyCloak LDAP provider 설정




그 후 세이브를 누르게 되면, LDAP 구성이 완료됩니다.

User 동기화
OpenLDAP 에 구성된 사용자들을 KeyCloak 으로 가져와야합니다.
다음 과정으로 동기화를 시켜줄 수 있습니다.


ArgoCD 에 BoB 유저로 로그인
OpenLDAP 에만 등록된 bob 유저로 ArgoCD 를 접속해봅니다.

다만, 해당 사용자는 아직 아무 권한이 없기 때문에 어떠한 정보도 보이지 않습니다.

3.9. OpenLDAP - KeyCloak 그룹 연동
이번엔 OpenLDAP 에 설정된 그룹을 KeyCloak 으로 가져오고, 해당 그룹에 권한을 부여해주겠습니다.
KeyCloak Group Mapper 설정
User Federation -> LDAP -> Mapper -> Create Mapper



Mapper 생성이 끝났다면, 생성된 Mapper 에서 Sync 를 눌러줍니다.

그 후 KeyCloak 그룹에서 OpenLDAP 의 그룹이 보이고, 그룹에 속한 사용자도 확인할 수 있게 됩니다.

KeyCloak Client Scope 설정
이제 그룹은 연결했으니, 권한 설정을 진행해보겠습니다.


Client Scope 생성 후 해당 Scope 에 Mapper 를 생성합니다.

ArgoCD Client 에서 Group Scope 추가


이후 ArgoCD 에서 bob 유저에 대해 dev 그룹이 부여된 것을 알 수 있습니다.

그리고 ArgoCD Configmap 에서도 group scope 에 대한 추가를 진행합니다.
kubectl edit cm -n argocd argocd-cm

kubectl edit cm argocd-rbac-cm -n argocd
# ArgoCD 권한 부여
policy.csv: |
g, devs, role:admin

모든 것이 다 설정 완료되면 Bob 유저는 ArgoCD 에서 Application 을 확인할 수 있게 됩니다.

Jenkins Group Scope 설정
ArgoCD 에 설정했던 것처럼 Jenkins 도 Group Scope 를 추가해주겠습니다.

Jenkins 에서도 설정이 필요합니다.


그 후 젠킨스를 재로그인 하면 그룹 설정이 보이게 됩니다.

'CICD' 카테고리의 다른 글
| [CI/CD Study 7주차] Vault 개요 - Vault Agent, Transit 엔진 (1) | 2025.11.30 |
|---|---|
| [CI/CD Study 5주차] Argo Rollout (0) | 2025.11.16 |
| [CI/CD Study 5주차] ArgoCD SSO - Keycloak (0) | 2025.11.16 |
| [CI/CD Study 5주차] ArgoCD 접근 제어 (0) | 2025.11.16 |
| [CI/CD Study 4주차] ArgoCD HA, 모니터링, 백업 (0) | 2025.11.09 |