CI/CD Study 5주차 ArgoCD 2/3
가시다님이 운영하시는 CI/CD Study 5주차 내용과 예제로 배우는 ArgoCD 책의 내용을 정리한 게시글 입니다.
1. 실습 환경 구성
이번 실습에서는 kind와 Ingress-nginx를 사용하여 실습환 경을 구성합니다.
Kind로 실습 환경 구성 시 80, 443포트를 Port Mapping을 하게 되면 Ingress-nginx에서 kind로 설치 시 자동으로 매핑해주기 때문에 80, 443 포트를 매핑해줍니다.
Kind 및 Ingress-nginx 설정
# 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
- containerPort: 30001
hostPort: 30001
- containerPort: 30002
hostPort: 30002
- containerPort: 30003
hostPort: 30003
EOF
# NGINX ingress 배포
# node Selector를 사용하여 배포되는 Node 지정 ingress-ready: "true"
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
# NGINX ingress pod IP 확인
k get po -n ingress-nginx -o=wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ingress-nginx-controller-8676d56f78-7bd6g 1/1 Running 0 2m25s 10.244.0.7 myk8s-control-plane <none> <none>
# Conrol-plane 노드에 iptables의 규칙 확인
docker exec -it myk8s-control-plane bash
iptables -t nat -L -n -v | grep '10.244.0.7'
# ...
# 0 0 DNAT 6 -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:10.244.0.7:80
# 0 0 DNAT 6 -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 to:10.244.0.7:443
# ...
# SSL Passthrough flag 활성화 설정을 하여 Too many Redirction 문제를 해결
kubectl edit -n ingress-nginx deployments/ingress-nginx-controller
# spec.container.args에 해당 내용 추가
# - --enable-ssl-passthrough
Helm을 이용한 ArgoCD 설치
이번 시간에는 https를 사용하기 때문에, 인증서 발급 과정까지 수행하여 실습을 진행합니다.
# 1. TLS 키·인증서 생성 : 공통 이름이 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"
# 2. Argo CD가 자신의 TLS를 쓰도록 argocd 네임스페이스에 tls 타입 시크릿 생성
kubectl create ns argocd
kubectl -n argocd create secret tls argocd-server-tls \
--cert=argocd.example.com.crt \
--key=argocd.example.com.key
# Helm Value에 certificate.enabled value는 cert-manager가 존재할때만 적용 (유형욱님 확인 )
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 Repo 추가 및 install
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.
# admin 비밀번호 확인
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
# iSpYt8BNtY6w2WkR
# C:\Windows\System32\drivers\etc\hosts 관리자모드에서 메모장에 내용 추가
127.0.0.1 argocd.example.com
# 접속 확인
wslview "https://argocd.example.com"
# argocd 서버 cli 로그인
argocd login argocd.example.com --insecure
# Username: admin
# Password: iSpYt8BNtY6w2WkR
# 'admin:login' logged in successfully
# Context 'argocd.example.com' updated

Figure 1.1 ArgoCD HTTPS 접속 확인
유저와 Nginx-IngressController 까지는 HTTPS로 통신을 하고 IngressController에서 ArgoCD까지는 HTTP 통신을 할 경우에는 다음과 같은 helm value를 사용하여 적용하면 됩니다.
server:
ingress:
enabled: true
ingressClassName: nginx
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
2. 접근제어
ArgoCD에서 계정들에 대해 RBAC을 적용하는 방법에 대해서 알아보겠습니다.
선언적 사용자
기본적으로 ArgoCD를 설치하는 경우 관리자 admin 계정이 최초로 생성이됩니다.
argoCD CLI나 UI에서 비밀번호가 변경 가능하며, 비밀번호 분실 시 bcrypt hash를 이용하여 비빌번호를 초기화 수 있습니다.
# 일반적인 비밀변호 변경
argocd account update-password
# init - password 입력 iSpYt8BNtY6w2WkR
*** Enter password of currently logged in user (admin):
# 변경 비밀번호 입력 qwe12345
*** Enter new password for user admin:
# 변경 비밀번호 입력 qwe12345
*** Confirm new password for user admin:
# 비밀번호 초기화
argocd account bcrypt --password foobar
# $2a$10$iL2hr1jUzA5HIwGsy6bxJueKEnFrt.paNkWs28FAfaXLIHM2svKlC(
# bcrypt hash값으로 초기화된 값으로 patch수행
kubectl -n argocd patch secret argocd-secret \
-p '{"stringData": {
"admin.password": "$2a$10$iL2hr1jUzA5HIwGsy6bxJueKEnFrt.paNkWs28FAfaXLIHM2svKlC(",
"admin.passwordMtime": "'$(date +%FT%T%Z)'"
}}'
보안 상 admin 계정은 초기 구성시 시에만 사용하는 것을 권하며, 이후에는 local 사용자 계정으로 전환하거나 SSO를 이용하여 관리자 계정을 비활성화 하는 것을 권장합니다.
kubectl edit cm -n argocd argocd-cm
# 추가
# admin.enabled: "false"
일상적인 작업을 수행하는 최소 권한을 가진 local 사용자(alice)를 생성해보겠습니다.
kubectl edit cm -n argocd argocd-cm
# accounts.alice: apiKey, login 맨 윗줄에 추가
# 사용자 확인
argocd account list
# NAME ENABLED CAPABILITIES
# admin true login
# alice true apiKey, login
# alice 계정 비밀번호 변경
argocd account update-password \
--account alice \
--current-password foobar \
--new-password alice12345
# Password updated

Figure 2.1 Settings > Accounts 메뉴에서 계정 확인
실습을 위해 샘플 Application을 배포 후 admin 계정과 alice 계정으로 UI로 접속을 해보면 Application CR이 admin 계정에서만 확인되는 것을 알 수 있습니다.
이 문제를 해결하기위해 alice 계정에 RBAC설정이 필요합니다.
cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: guestbook
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
helm:
valueFiles:
- values.yaml
path: helm-guestbook
repoURL: https://github.com/argoproj/argocd-example-apps
targetRevision: HEAD
syncPolicy:
automated:
enabled: true
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
destination:
namespace: guestbook
server: https://kubernetes.default.svc
EOF


Figure 2.2 admin 계정과 alice 계정 차이 확인
admin 계정은 슈퍼유저기 때문에 시스템에 대한 모든 권한을 가지고 있지만 alice 계정은 그렇지 않습니다. 이 문제를 해결하기 위해 사용자에게 권한을 부여하거나 기본적으로 적용되는 정책을 수정하는 방법이 있습니다.
alice 계정에 application CR을 확인 하기 위해서는 argocd-rbac-cm의 configMap에서 policy.default: role:readonly 부분을 추가하여 alice 계정에 UI에서 application CR을 확인할 수 있도록 합니다.
kubectl edit cm -n argocd argocd-rbac-cm
# policy.default 값 변경
# policy.default: role:readonly

Figure 2.3 Service Account 변경으로 통한 alice계정으로 Application 확인
Service Account
Service Account란 시스템 인증 시 필요한 사용한 계정이며, 사용자와 연결되어있지 않는 것을 기본적으로 필요한 권한만 부여하는 것이 원칙입니다.
ArgoCD에서는 Service Account를 사용할 때 login 기능을 제거하고 API Key만 사용하는 로컬 사용자를 만들어서 사용하거나, 프로젝트 역할을 사용하여 역핧을 할당하는 방식으로 Token을 사용하는 방식입니다.
첫번째 방식(로컬 Service Account RBAC)을 실습해 보겠습니다.
:ㅂ!kubectl edit cm -n argocd argocd-cm
# data 필드에 해당 항목 추가
# accounts.gitops-ci: apiKey
# 토큰 생성
argocd account generate-token -a gitops-ci
# {"level":"fatal","msg":"rpc error: code = Unauthenticated desc = Account admin is disabled","time":"2025-11-16T03:57:47+09:00"}
admin 계정은 비활성화 되어잇기때문에 Alice 계정에 Token생성 권한을 부여하여 사용자에게 역할을 할당합니다.
kubectl edit cm -n argocd argocd-rbac-cm
# configMap에 해당 Data 추가
# policy.csv: |
# p, role:user-update, accounts, update, *, allow
# p, role:user-update, accounts, get, *, allow
# g, alice, role:user-update
# 토큰 생성
argocd account generate-token -a gitops-ci
# eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhcmdvY2QiLCJzdWIiOiJnaXRvcHMtY2k6YXBpS2V5IiwibmJmIjoxNzYzMjMzNTk3LCJpYXQiOjE3NjMyMzM1OTcsImp0aSI6IjkzOTAyYzY0LWI5YjUtNDM2Zi05ZWVmLTRjNDQwMzdiZWYyYSJ9.xt8t4jEqc098h8cQrCr_2_r5nJzEcY-9qUVdbxN5sD0
# 토큰 정보 확인
argocd account get-user-info --auth-token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhcmdvY2QiLCJzdWIiOiJnaXRvcHMtY2k6YXBpS2V5IiwibmJmIjoxNzYzMjMzNTk3LCJpYXQiOjE3NjMyMzM1OTcsImp0aSI6IjkzOTAyYzY0LWI5YjUtNDM2Zi05ZWVmLTRjNDQwMzdiZWYyYSJ9.xt8t4jEqc098h8cQrCr_2_r5nJzEcY-9qUVdbxN5sD0
# Logged In: true
# Username: gitops-ci
# Issuer: argocd
# Groups:
기본적으로 생성된 Token은 읽기권한만 있어 추가 작업이 필요한 경우 Application 생성 및 동기화, 새 클러스터 등록과 같은 작업을 수행 가능하게 권한을 부여해야합니다.
두번째 방식(Project 역할과 Token 부여)을 실습해 보겠습니다.
AppProject는 역할을 통해 Application 정의 시 일부 제약 조건을 적용하는 방식입니다.
저장소, 배포대상 클러스터, 네임스페이스와, 설치 가능한 리소스 유형같은 정보를 통제할 수 있습니다.
기본적으로 default라는 기본 프로젝트가 있지만, 해당 프로젝트에 대해 제한 사항이 걸려있지 않습니다.
kubectl get appprojects.argoproj.io -n argocd default -o yaml
# apiVersion: argoproj.io/v1alpha1
# kind: AppProject
# metadata:
# creationTimestamp: "2025-11-15T12:49:42Z"
# generation: 1
# name: default
# namespace: argocd
# resourceVersion: "2057"
# uid: 1e952c94-1c49-4b35-b6ee-0f643f8528a7
# spec:
# clusterResourceWhitelist:
# - group: '*'
# kind: '*'
# destinations:
# - namespace: '*'
# server: '*'
# sourceRepos:
# - '*'
sample-apps라는 신규 프로젝트를 생성하여 실습을 진행해보겠습니다.
cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: sample-apps
namespace: argocd
spec:
roles:
- name: read-sync
description: read and sync privileges
policies:
- p, proj:sample-apps:read-sync, applications, get, sample-apps/*, allow
- p, proj:sample-apps:read-sync, applications, sync, sample-apps/*, allow
clusterResourceWhitelist:
- group: '*'
kind: '*'
description: Project to configure argocd self-manage application
destinations:
- namespace: test
server: https://kubernetes.default.svc
sourceRepos:
- https://github.com/argoproj/argocd-example-apps.git
EOF
# 애플리케이션 생성
cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: pre-post-sync
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: sample-apps
source:
path: pre-post-sync
repoURL: https://github.com/argoproj/argocd-example-apps
targetRevision: master
destination:
namespace: test
server: https://kubernetes.default.svc
syncPolicy:
automated:
enabled: false
syncOptions:
- CreateNamespace=true
EOF
# 동기화 실행 시 실패
argocd app sync argocd/pre-post-sync
# {"level":"fatal","msg":"rpc error: code = PermissionDenied desc = permission denied: applications, sync, sample-apps/pre-post-sync, sub: alice, iat: 2025-11-15T19:04:41Z","time":"2025-11-16T04:20:28+09:00"}
# RBAC 수정해 필요한 권한 추가
kubectl edit cm -n argocd argocd-rbac-cm
# data.plicy.csv에 해당 항목 추가
# p, role:user-update, projects, update, sample-apps, allow
# 역할에 대한 토큰 생성
argocd proj role create-token sample-apps read-sync
# Create token succeeded for proj:sample-apps:read-sync.
# ID: cc783f56-a4b9-471b-a464-ec12a7421576
# Issued At: 2025-11-16T04:24:25+09:00
# Expires At: Never
# Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhcmdvY2QiLCJzdWIiOiJwcm9qOnNhbXBsZS1hcHBzOnJlYWQtc3luYyIsIm5iZiI6MTc2MzIzNDY2NSwiaWF0IjoxNzYzMjM0NjY1LCJqdGkiOiJjYzc4M2Y1Ni1hNGI5LTQ3MWItYTQ2NC1lYzEyYTc0MjE1NzYifQ.Bfc1nkxhG9babHmoZfZl_IWg9FuPAw6MTUEmm3hRvUM
TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhcmdvY2QiLCJzdWIiOiJwcm9qOnNhbXBsZS1hcHBzOnJlYWQtc3luYyIsIm5iZiI6MTc2MzIzNDY2NSwiaWF0IjoxNzYzMjM0NjY1LCJqdGkiOiJjYzc4M2Y1Ni1hNGI5LTQ3MWItYTQ2NC1lYzEyYTc0MjE1NzYifQ.Bfc1nkxhG9babHmoZfZl_IWg9FuPAw6MTUEmm3hRvUM
argocd app sync argocd/pre-post-sync --auth-token $TOKEN
SSO
SSO란 분산된 여러 시스템의 인증 절차를 중앙에서 통합 관리하는 방식이며, ArgoCD에서도 SSO를 지원합니다.
Dex OIDC 공급자를 사용하거나, 다른 OIDC 공급자를 사용하여 ArgoCD를 연동하여 사용하는 방식이 있습니다.
SSO를 활성화한 상태에서 로그인 할수 있는 로컬 계정이 없고 관리자가 비활성화된 경우, 사용자/비밀번호 입력 양식이 UI에서 자동으로 제거되고 SSO를 통한 로그인 버튼만 남습니다.
이번에는 KeyCloak을 이용하여 SSO 실습을 진행해보겠습니다.
# admin 계정 활성화
kubectl edit cm -n argocd argocd-cm
# admin.enabled: "false" - > admin.enabled: "true로 변경"
argocd login argocd.example.com --username admin --password foobar --insecure
# 'admin:login' logged in successfully
# Context 'argocd.example.com' updated
# 도커에서 컨테이너로 Keycloak 실행
# 기본 관리자 계정이 제공되지 않아, 환경 변수로 초기 관리자 계정 생성
docker run -d -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin -p 8080:8080 --net kind --name dev-keycloak quay.io/keycloak/keycloak:22.0.0 start-dev
# admin 웹 콘솔 접속 : admin / admin
wslview http://localhost:8080/admin
# KeyCloak에서 bob/bob123 계정 생성




Figure 2.1 BOB계정 생성 및 비밀번호 지정
KeyCloak 생성 후 KeyCloak과 ArgoCD를 연결 하기 위해 Client를 생성해보겠습니다.





Figure 2.2 Keycloak Clients 생성 과정
Client 생성 시 같이 생성된 Secret값을 복사해둔 후 argoCD와 KeyCloak이 연결하기 위해 작업을 하겠습니다.
kubectl -n argocd patch secret argocd-secret --patch='{"stringData": { "oidc.keycloak.clientSecret": "UiGlMDoG0vMMRw3vU2Fl77JTBpP16MpN" }}'
# IP주소 확인
ifconfig eth0
# eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
# inet 172.20.159.236 netmask 255.255.240.0 broadcast 172.20.159.255
kubectl edit cm -n argocd argocd-cm
# data.url 밑에 해당 항목 추가
# oidc.config: |
# name: Keycloak
# issuer: http://172.20.159.236:8080/realms/master
# clientID: argocd
# clientSecret: UiGlMDoG0vMMRw3vU2Fl77JTBpP16MpN
# requestedScopes: ["openid", "profile", "email"]
kubectl rollout restart deploy argocd-server -n argocd


Figure 2.3 Keycloak 버튼 생성 및 로그인 확인
3. Argo Rollout
✅ Argo Rollout 이란
Kubernetes에서 Canary, Blue‑Green 같은 고급 배포 전략을 구현하기 위해 만든 커스텀 컨트롤러이자 CRD(Custom Resource) 세트입니다.
ArgoRollout에서는 기본적으로 kuberntes에서 지원하지 않는 Canary 배포를 지원하며, 지표를 이용하여 자동 배포 및 자동 롤백을 수행할 수 있습니다.
Deployment 객체와 동일하게 Argo Rollouts Controller는 ReplicaSets를 관리하며, Deploymnet와 동일한 Pod Template를 사용합니다.

Figure 3.1 Argo Rollout Architecture
Argo Rollouts 설치
kubectl create ns argo-rollouts
cat <<EOT > argorollouts-values.yaml
dashboard:
enabled: true
service:
type: NodePort
nodePort: 30003
EOT
# 설치
helm install argo-rollouts argo/argo-rollouts --version 2.40.5 -f argorollouts-values.yaml --namespace argo-rollouts
# ArgoCD와 Argo Rollouts 연동
cat <<EOF > argocd-values.yaml
global:
domain: argocd.example.com
certificate:
enabled: true
server:
ingress:
enabled: true
ingressClassName: nginx
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
tls: true
extensions:
enabled: true
extensionList:
- name: rollout-extension
env:
- name: EXTENSION_URL
value: https://github.com/argoproj-labs/rollout-extension/releases/download/v0.3.7/extension.tar
EOF
helm upgrade -i argocd argo/argo-cd --version 9.0.5 -f argocd-values.yaml --namespace argocd
wslview "http://127.0.0.1:30003"
연동 플러그인을 설치 후 Sample Application을 배포 및 등록 해보겠습니다.
임의의 Repository를 사용할 예정이며, Repository 등록 시에는 반드시 admin 계정으로 등록해야합니다.

Figure 3.2 Repository 등록
git clone https://github.com/ymir0804/dev-app -b dev
cd dev-app && mkdir argo-rollouts && cd argo-rollouts
wget https://raw.githubusercontent.com/argoproj/argo-rollouts/master/docs/getting-started/basic/rollout.yaml
wget https://raw.githubusercontent.com/argoproj/argo-rollouts/master/docs/getting-started/basic/service.yaml
git add . && git commit -m "Add sample yaml" && git push
cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: rollout-test
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: 'https://github.com/ymir0804/dev-app.git'
path: argo-rollouts
targetRevision: dev
destination:
server: https://kubernetes.default.svc
namespace: test
syncPolicy:
syncOptions:
- CreateNamespace=true
EOF

Figure 3.3 Application 배포 후 Rollout plugin 확인
'DevOps > Study' 카테고리의 다른 글
| CI/CD Study 7주차 Vault (1/2) (0) | 2025.11.29 |
|---|---|
| CI/CD Study 6주차 ArgoCD 3/3 (1/2) (0) | 2025.11.23 |
| CI/CD Study 4주차 ArgoCD 1/3 (2) (0) | 2025.11.08 |
| CI/CD Study 4주차 ArgoCD 1/3 (1) (0) | 2025.11.08 |
| CI/CD Study 3주차 Jenkins, ArgoCD (0) | 2025.11.02 |