CI/CD Study 6주차 ArgoCD 3/3 (2/2)
가시다님이 운영하시는 CI/CD Study 6주차 내용과 예제로 배우는 ArgoCD 책의 내용을 정리한 게시글 입니다.
1. OpenLDAP + KeyCloak + Argo CD + Jenkins
이번 실습에서는
실습 환경 구성
# kind k8s 배포
kind create cluster --name myk8s --image kindest/node:v1.32.8 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
labels:
ingress-ready: true
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
- containerPort: 30000
hostPort: 30000
EOF
# 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 -
# 인증서 생성
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
# tls 시크릿 생성
kubectl -n argocd create secret tls argocd-server-tls \
--cert=argocd.example.com.crt \
--key=argocd.example.com.key
# ArgoCD 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
# 설치 : Argo CD v3.1.9
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
# 최초 접속 암호 확인
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d ;echo
# YSqzXqNiKxCmw7lc
ARGOPW=YSqzXqNiKxCmw7lc
# argocd 서버 cli 로그인
argocd login argocd.example.com --insecure --username admin --password $ARGOPW
# admin 계정 암호 변경 : qwe12345
argocd account update-password --current-password $ARGOPW --new-password qwe12345
# Jenkins 배포를 위한 Name Space 생성
kubectl create ns jenkins
# 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
livenessProbe:
httpGet:
path: "/login"
port: 8080
initialDelaySeconds: 90
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 5
readinessProbe:
httpGet:
path: "/login"
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
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
## 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
# 9196f6fa7de641d884412a501ec038cf
# WebUI 접속 후 비밀번호 변경
wslview "http://jenkins.example.com"
# 계정명 admin 비밀번호 qwe123으로 지정 후 Save and Continue 클릭



Figure 1.1 Jenkins 초기 설정
# Keycloak 배포
kubectl create ns keycloak
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: keycloak
namespace: 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
namespace: keycloak
spec:
selector:
app: keycloak
ports:
- name: http
port: 80
targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: keycloak
namespace: keycloak
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
## C:\Windows\System32\drivers\etc\hosts 관리자모드에서 메모장에 내용 추가
127.0.0.1 keycloak.example.com
wslview "http://keycloak.example.com/admin"
# 계정명 admin 비밀번호 admin
# Manage Realms 클릭 > Create Realm 클릭 > myrealm 생성
# User miri Password miri123 생성



Figure 1.2 Keycloak 초기 설정
# Jenkins Cluster IP 확인
kubectl get svc -n jenkins
# ArgoCD Cluster IP 확인
kubectl get svc -n argocd argocd-server
# Keycloak Cluster IP 확인
kubectl get svc -n keycloak
# 내부에서 실습을 위한 도메인 호출 설정
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> jenkins.example.com
# <CLUSTER IP> argocd.example.com
# <CLUSTER IP> keycloak.example.com
# fallthrough
# }
# ...
# ...
SSO (OIDC) 설정
KeyCloak에서 SSO 연동을 위해 Keycloak CLient 설정이 필요한데, ArgoCD 연결을 위해 Client 설정을 다음과 같이 설정합니다.
ArgoCD Client 설정도 다음과 같이 설정합니다.



이때 생성한 Credentials 정보를 기억해 놔야합니다.
Figure 1.3 KeyCloak ArgoCD Client 설정
동일하게 Jenkins에서도 Client 설정을 합니다.




Figure 1.4 KeyCloak Jenkins Client 설정
생성한 Client를 이용하여 ArgoCD와 Jenkins를 OIDC 연동해보겠습니다.
# ArgoCD 연동
# 생성된 client 에서 → Credentials 값(메모)를 붙여넣어서 실행
kubectl -n argocd patch secret argocd-secret --patch='{"stringData": { "oidc.keycloak.clientSecret": "z2n67ZOZNKdJX2E14sPtr1DNmFVVCYwv" }}'
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: z2n67ZOZNKdJX2E14sPtr1DNmFVVCYwv
requestedScopes: ["openid", "profile", "email"]
'
# argocd-server 재시작
kubectl rollout restart deploy argocd-server -n argocd
Jenkins 연동 시에는 OpenID Connect Authentication 설치가 필요합니다.
설치 후 Manage Jenkins → Security : Security Realm 설정을 다음과 같이 지정합니다.


Figure 1.5 Jenkins OIDC 설정
OpenLDAP 설정
LDAP 이란 간단하게 말하면 회사 내 조직정보를 뜻하며 자세한 내용은 해당 링크를 참고하시면 됩니다.
실습을 하기 위해 Keycloak에 등록했던 user(miri)를 삭제하고 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
# 기본 LDAP 정보 : 아래 Bind DN과 PW로 로그인
## Base DN: dc=example,dc=org
## Bind DN: cn=admin,dc=example,dc=org
## Password: admin
wslview http://127.0.0.1:30000
# OpenLDAP 조직도 구성
kubectl -n openldap exec -it deploy/openldap -c openldap -- bash
# ldapadd로 ou 추가 (organizationalUnit)
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
# ldapadd로 users 추가 (inetOrgPerson) : alice , bob
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
# ldapadd로 groups 추가 (groupOfNames) : devs, admins
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
# 빠져나오기
exit

KeyCloak LDAP 설정
User Federation을 이용하여 LDAP과 연동하여 사용자 정보를 동기화 합니다.



Figure 1.6 KeyCLoak LDAP 설정
RBAC With Groups
OpenLDAP 그룹 정보를 Keycloak 동기화 설정을 하여 LDAP 사용자들이 ArgoCD CRD를 확인할 수 있도록 해보겠습니다.






Figure 1.7 KeyCLoak <-> ArgoCD 동기화 설정
kubectl edit cm -n argocd argocd-cm
# groups 추가
# ...
# requestedScopes: ["openid", "profile", "email" , "groups"]
# ...
kubectl edit cm argocd-rbac-cm -n argocd
# policy.csv 변경
# ...
# policy.csv: |
# g, devs, role:admin
# ...