카테고리 없음

CI/CD Study 6주차 ArgoCD 3/3 (2/2)

juyeon22 2025. 11. 23. 06:24

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
# ...