ArgoCD로 GitOps 구축할 때 막히는 5가지 지점: 홈랩 + GitLab Self-Managed 실습

안녕하세요. 인포그랩 DevOps 엔지니어 Toma입니다. GitOps를 도입할 때 배포보다 준비 단계에 시간을 많이 쓰고 계시지는 않나요?
대표 도구인 ArgoCD를 설치하고 나면 웹 UI 접속부터 막힙니다. 포트 포워딩을 걸어도 다른 장비의 브라우저는 연결하지 못하고, 브라우저로 접속하면 인증서 경고를 넘겨야 UI가 열리죠. 저장소를 연동할 때는 액세스 토큰이 유효한데도 인증 오류가 나고, Application을 만들 때 무심코 건드린 항목 하나가 나중에 Kustomize 전환을 막습니다.
GitOps를 구축할 때 이러한 증상을 먼저 경험하면 원인을 역추적하는 데 시간이 꽤 걸립니다. GitOps를 본격적으로 운영하기보다 운영할 준비를 갖추는 데 시간을 길게 쓰게 되죠.
저 역시 홈랩 Kubernetes 클러스터에 GitOps 환경을 구축하며 운영 준비 과정에서 시행착오를 많이 겪었습니다. 그러나 이 구간만 지나면 deployment.yaml의 replicas를 1에서 2로 바꿔 커밋하고 동기화하는 것만으로 클러스터에 Pod가 하나 더 뜹니다. 배포 담당자가 다루는 대상이 클러스터에서 Git으로 옮겨 가면서 본격적인 GitOps 운영이 시작되는 셈이죠.
이 글에서는 홈랩 Kubernetes 클러스터에서 ArgoCD 접속 환경을 구성하고, GitLab Self-Managed 저장소를 연동하는 준비 과정을 거쳐 nginx를 배포하고 Kustomize로 매니페스트를 정리하는 전 과정을 실습으로 다룹니다. 앞서 언급한 내용을 포함해 GitOps 운영 준비 과정에서 발목을 잡았던 다섯 가지 상황을 증상, 원인, 해결 순으로 정리했습니다. 여러분이 저와 같은 문제로 시간을 버리지 않고 GitOps 본론으로 진입하는 데 이 글이 도움이 되면 좋겠습니다.
GitOps와 ArgoCD 이해하기
실습에 들어가기 전에 개념부터 먼저 짚겠습니다. GitOps가 어떤 원리로 동작하는지, ArgoCD가 그 안에서 무슨 일을 하는지 알고 나면 뒤에서 다룰 설정 하나하나가 왜 필요한지 이해하는 데 도움이 됩니다.
GitOps란
GitOps는 시스템의 원하는 상태를 Git 저장소에 선언적으로 기록하고, 실제 운영 환경이 그 상태와 일치하도록 유지하는 운영 방식입니다. 여기서 선언적이라는 말은 "Pod를 두 개 띄워라"처럼 절차를 지시하는 대신 "Pod가 두 개인 상태여야 한다"고 결과를 기술한다는 뜻입니다. 배포 담당자가 클러스터에 직접 명령을 내리는 대신 Git에 변경 사항을 커밋하면, 컨트롤러가 이를 탐지해 실제 상태를 저장소에 기록된 상태에 맞춰 갑니다.
이 방식의 핵심은 조정이 한 번으로 끝나지 않는다는 점입니다. 컨트롤러는 저장소와 클러스터를 주기적으로 대조하고, 두 상태가 어긋나면 이를 탐지해 표시합니다. 누군가 kubectl edit으로 클러스터를 직접 수정해도 저장소에 적힌 내용과 다르다는 사실이 드러나죠. 배포 시점에만 개입하는 방식에서는 이런 차이가 다음 배포 때까지 드러나지 않는 것과 대조적입니다.
또 한 가지 주목할 점은 배포 방향입니다. 기존 CI 파이프라인이 클러스터에 직접 kubectl apply를 수행하는 push 방식이라면, GitOps는 클러스터 내부의 컨트롤러가 저장소를 읽어 오는 pull 방식입니다. CI 시스템에 클러스터 자격 증명을 보관하지 않아도 된다는 점에서 보안 요구 수준이 높은 환경에 특히 적합합니다.
ArgoCD의 역할
ArgoCD는 Kubernetes에서 GitOps를 구현하는 대표적인 컨트롤러입니다. 클러스터 안에 상주하면서 지정한 Git 저장소를 주기적으로 들여다보고, 저장소에 적힌 매니페스트와 클러스터의 현재 상태를 대조합니다. 두 상태가 다르면 OutOfSync로 표시하고, 동기화를 실행하면 저장소 내용을 클러스터에 반영합니다.
같은 역할을 하는 도구로 Flux도 있습니다. 둘 다 CNCF Graduated 프로젝트이고 pull 방식으로 동작하지만 접근 방식이 다릅니다. Flux는 명령줄과 매니페스트로 다루도록 설계돼 자동화 파이프라인에 통합하기 좋습니다. 반면에 ArgoCD는 웹 UI를 기본으로 제공해 배포 상태를 눈으로 확인하며 다루도록 설계돼 있습니다.
이 글에서 ArgoCD를 택한 이유도 여기에 있습니다. GitOps를 처음 접할 때는 "Git에 커밋한 내용이 클러스터에 어떻게 반영되는지"를 직접 보는 것이 개념을 빠르게 이해하는 데 도움이 되기 때문입니다. 여러 팀이 함께 쓰는 환경에서 배포 현황을 공유하기 쉽다는 점도 장점입니다.
실습 준비
이 글은 Kubernetes 클러스터에 ArgoCD를 설치하고 kubectl을 사용할 수 있는 상태를 가정합니다. 다음 환경에서 진행했습니다.
| 구분 | 내용 |
|---|---|
| Kubernetes | 홈랩 클러스터 (컨트롤 플레인 VM) |
| ArgoCD | v3.4.1 기준 |
| Git 저장소 | GitLab Self-Managed |
| 배포 대상 | nginx (데모용) |
전체 흐름은 다음과 같습니다. ArgoCD가 GitLab 저장소를 주기적으로 확인하고, 저장소 내용과 클러스터 상태가 다르면 OutOfSync로 표시합니다. 동기화를 실행하면 매니페스트가 클러스터에 반영됩니다.

ArgoCD 접속 설정
ArgoCD를 설치했다면 웹 UI에 접속할 수 있도록 설정하고, 초기 관리자 계정의 비밀번호를 확인해야 합니다. 이 섹션의 명령은 클러스터에 접근할 수 있는 터미널에서 실행합니다.
포트 포워딩으로 접속하기
먼저 포트 포워딩으로 웹 UI에 접속하세요. ArgoCD를 설치하면 argocd-server 서비스가 ClusterIP 타입으로 생성돼 클러스터 내부에서만 접근할 수 있는데 포트 포워딩이 가장 간단한 우회 방법입니다.
kubectl -n argocd port-forward svc/argocd-server 8445:443
kubectl port-forward는 기본적으로 로컬 주소에만 바인딩됩니다. 명령을 실행한 장비에서만 접속할 수 있다는 뜻입니다. 컨트롤 플레인이 VM이나 원격 서버에 있고 다른 장비의 브라우저로 접속한다면, 해당 장비 안에서 curl은 성공하지만 외부에서는 연결이 거부됩니다.
이때는 --address 옵션으로 바인딩 주소를 지정해 실행하세요. 0.0.0.0은 명령을 실행한 장비의 모든 네트워크 인터페이스에 UI를 여는 설정입니다. 장비에 인터페이스가 여러 개라면 --address 192.168.0.10처럼 접속에 쓸 인터페이스만 지정해 노출 범위를 좁힐 수 있습니다. 이때 넣는 IP는 명령을 실행하는 장비 자신의 주소입니다.
kubectl -n argocd port-forward --address 0.0.0.0 svc/argocd-server 8445:443
명령을 실행한 뒤 브라우저에서 https://<IP>:8445로 접속합니다.
argocd-server는 기본 설정에서 TLS를 직접 처리하며, 설치 시 자체 서명 인증서를 생성합니다. 주소창에 <IP>:8445만 입력하면 HTTP로 요청이 전송되고 서버가 HTTPS로 리다이렉트하는데 이때 인증서 경고가 표시됩니다. https://를 직접 입력해도 같은 경고가 떠서 경고를 수락하고 진행해야 UI에 접속할 수 있습니다.
NodePort로 전환하기
계속 사용할 예정이라면 NodePort로 전환하세요. 포트 포워딩은 명령을 실행한 터미널이 종료되면 함께 중단되기 때문입니다.
전환은 두 단계로 진행합니다. 먼저 server.insecure를 적용해 ArgoCD가 HTTP로 동작하도록 바꿉니다. NodePort로 노출한 뒤 자체 서명 인증서 경고를 매번 넘기지 않아도 되도록 하는 설정입니다.
kubectl -n argocd patch configmap argocd-cmd-params-cm \
--type merge -p '{"data":{"server.insecure":"true"}}'
kubectl -n argocd rollout restart deploy argocd-server
설정이 반영되면 서비스 타입을 NodePort로 바꾸고 포트를 고정합니다.
kubectl -n argocd patch svc argocd-server --patch-file=/dev/stdin <<'EOF'
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 8080
nodePort: 30080
- name: https
port: 443
targetPort: 8080
nodePort: 30443
EOF
server.insecure는 나중에 도메인을 붙일 때도 유용합니다ArgoCD 앞에 Ingress나 리버스 프록시를 두면 프록시에서 한 번, ArgoCD에서 또 한 번 TLS 종료가 일어나면서 구성이 복잡해지고 backend 통신 프로토콜을 별도로 지정해야 합니다. server.insecure를 켜면 ArgoCD는 HTTP로만 동작하고 TLS 처리는 앞단에 맡겨 설정이 단순해집니다.
다만 이 설정은 ArgoCD 앞에 TLS를 처리해 줄 무언가가 있다는 것을 전제로 합니다. 이 글처럼 홈랩 내부에서만 접근하는 환경이라면 문제없지만, 외부에 노출하는 구성이라면 반드시 프록시나 Ingress를 함께 둬야 합니다.
초기 비밀번호 확인하기
UI에 접속하려면 초기 관리자 계정의 비밀번호를 확인해야 합니다. 계정 이름은 admin이고, 비밀번호는 설치 시 자동 생성되는 argocd-initial-admin-secret 시크릿에 저장돼 있습니다.
다음 명령으로 비밀번호를 확인하세요.
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d; echo
server.insecure를 적용해 HTTPS에서 HTTP로 전환하면, 로그인 버튼을 눌러도 로그인 화면으로 되돌아오는 현상이 발생할 수 있습니다. 서버 로그를 확인하면 원인이 드러납니다.
kubectl -n argocd logs deploy/argocd-server --tail=30
SessionService/Create는 OK로 끝나는데 직후 요청이 Unauthenticated desc = no session information으로 실패한다면, 인증 자체는 성공한 것입니다. 이전 HTTPS 접속 때 발급된 세션 쿠키에 Secure 속성이 설정돼 있어 HTTP 요청에서는 브라우저가 쿠키를 전송하지 않아 발생하는 문제입니다. 해당 사이트의 쿠키를 삭제하면 해결됩니다.
로그인한 뒤에는 User Info → UPDATE PASSWORD에서 비밀번호를 변경하세요. 변경을 마쳤다면 초기 시크릿을 삭제합니다. 이 시크릿은 처음 생성된 값을 평문으로 담고 있어 비밀번호를 바꾼 뒤에는 남겨 둘 이유가 없습니다.
kubectl -n argocd delete secret argocd-initial-admin-secret
GitLab 저장소 연동
접속 환경을 갖췄으니 이제 ArgoCD가 매니페스트를 읽어 올 저장소를 연결합니다. GitLab에서 액세스 토큰을 발급한 뒤, ArgoCD에 저장소를 등록하는 순서로 진행합니다.
액세스 토큰 발급
GitLab에서 User Settings → Personal access tokens로 이동해 Add new token을 누르고, 토큰 이름과 만료일을 지정합니다. 이 글에서 다루는 저장소 연동에는 read_repository 스코프 하나면 충분합니다. ArgoCD는 저장소의 내용을 읽기만 하기 때문입니다.

발급된 토큰은 화면을 벗어나면 다시 볼 수 없습니다. 이어지는 저장소 등록에 사용할 수 있도록 복사해 두세요.
저장소 등록
ArgoCD에서 Settings → Repositories → CONNECT REPO로 이동해 VIA HTTP/HTTPS를 선택하고 다음 항목을 입력합니다.
| 항목 | 값 |
|---|---|
| Type | git |
| Project | default |
| Repository URL | https://<GitLab 도메인>/<그룹>/<프로젝트>.git |
| Username | oauth2 |
| Password | 발급받은 액세스 토큰 |
Project는 ArgoCD의 접근 제어 단위인 AppProject를 가리킵니다. 설치 시 기본으로 생성되는 default를 그대로 사용하면 됩니다.
Username에는 비어 있지 않은 아무 값이나 넣으면 됩니다. GitLab은 개인 액세스 토큰으로 인증할 때 이 값을 검증하지 않기 때문입니다. 다만 oauth2가 관례로 널리 쓰여 여기서도 그대로 사용했습니다.
CONNECT를 누르면 목록에 저장소가 추가되고, CONNECTION STATUS가 Successful로 표시됩니다.


Application을 생성할 때 저장소 URL을 직접 입력할 수도 있지만, 인증 정보는 Application이 아니라 저장소 단위로 관리됩니다. 저장소를 등록하지 않은 상태에서 Application을 생성하면 다음과 같은 오류가 발생합니다.
InvalidSpecError: repository not accessible:
... authentication required: HTTP Basic: Access denied.
토큰이 유효하더라도 등록 과정을 건너뛰면 동일한 오류가 발생합니다. 저장소 등록을 먼저 진행해 주세요.
애플리케이션 배포
저장소를 연결했으니 이제 배포할 매니페스트를 작성하고, ArgoCD에 Application을 만들어 클러스터에 반영합니다.
매니페스트 작성
저장소에 다음 구조로 매니페스트를 작성하세요.
homelab-manifest/
└── apps/
└── demo/
├── deployment.yaml
└── service.yaml
파일 두 개를 배포하는 데 굳이 apps/demo/처럼 두 단계를 둘 필요는 없습니다. 저장소 루트에 놓아도 동작하죠. 그럼에도 이 구조를 택한 이유는 디렉터리 하나가 애플리케이션 하나에 대응한다는 규칙을 처음부터 지켜 두면 나중에 구조를 갈아엎지 않아도 되기 때문입니다.
디렉터리 구조는 ApplicationSet 확장을 염두에 둔 것입니다.
애플리케이션이 하나둘 늘어나면 매번 ArgoCD UI에서 Application을 직접 만들어 줘야 합니다. 이 작업은 ApplicationSet으로 자동화할 수 있습니다. ApplicationSet의 Git generator는 지정한 경로 아래 디렉터리를 훑어 각각에 대응하는 Application을 자동으로 생성합니다. apps/* 형태로 패턴을 지정해 두면 새 디렉터리를 추가하고 커밋하는 것만으로 배포 대상이 등록되는 셈입니다.
-
Deployment 작성
배포 대상은 nginx 컨테이너 하나입니다.
apps/demo/deployment.yaml을 다음과 같이 작성합니다.apiVersion: apps/v1 kind: Deployment metadata: name: demo spec: replicas: 1 selector: matchLabels: app: demo template: metadata: labels: app: demo spec: containers: - name: nginx image: nginx:1.27-alpine ports: - containerPort: 80replicas: 1은 Pod를 하나만 띄운다는 뜻입니다. 뒤에서 이 값을 2로 바꿔 GitOps 동작을 확인할 예정이니 위치를 기억하세요.selector.matchLabels와template.metadata.labels는 짝을 이뤄야 합니다. Deployment가 자신이 관리할 Pod를 이 라벨로 찾기 때문입니다. -
Service 작성
apps/demo/service.yaml을 작성합니다.apiVersion: v1 kind: Service metadata: name: demo spec: selector: app: demo ports: - port: 80 targetPort: 80Service의
selector는 Deployment에서 지정한 라벨과 같은 값이어야 합니다. 이 값이 일치해야 Service가 Pod로 트래픽을 보냅니다. -
저장소에 반영
작성한 파일을 커밋하고 푸시합니다. ArgoCD는 저장소에 올라간 내용만 읽어서 로컬에만 있으면 다음 단계에서 인식되지 않습니다.
Application 생성
ArgoCD UI의 Applications 화면에서 NEW APP을 누르고 다음 항목을 입력합니다.
-
기본 정보 입력
항목 값 Application Name demoProject Name defaultSync Policy Manual Sync Options AUTO-CREATE NAMESPACE 체크 Repository URL 등록한 저장소 Revision HEADPath apps/demoCluster URL https://kubernetes.default.svcNamespace demo- Sync Options: Namespace에
demo를 넣었는데 클러스터에는 아직 이 네임스페이스가 없습니다. AUTO-CREATE NAMESPACE를 체크하면 동기화할 때 ArgoCD가 자동으로 만들어 줍니다. - Cluster URL:
https://kubernetes.default.svc는 ArgoCD가 설치된 클러스터 자신을 가리킵니다. 생성 후 화면에는in-cluster로 표시됩니다.
Project Name은 애플리케이션 이름이 아닙니다
애플리케이션 이름을 한 번 더 적는 칸으로 보이지만, 실제로는 ArgoCD의 접근 제어 단위인 AppProject를 가리킵니다. AppProject는 다음을 묶어서 정의합니다.
- 어떤 저장소를 소스로 쓸 수 있는지
- 어떤 클러스터와 네임스페이스에 배포할 수 있는지
- 누가 이 애플리케이션을 다룰 수 있는지
ArgoCD를 설치하면 아무런 제약이 없는
default프로젝트가 기본으로 생성됩니다. 별도로 AppProject를 만들지 않았다면default를 입력하세요. 존재하지 않는 이름을 넣으면 Application 생성 자체가 실패합니다.여러 팀이 하나의 ArgoCD를 공유한다면 팀별로 AppProject를 나누는 방식이 유용하지만, 이 글에서는
default를 그대로 사용하겠습니다. - Sync Options: Namespace에
-
DIRECTORY 섹션 확인
화면 하단에는 DIRECTORY 섹션이 있습니다. 별도 설정이 필요하지 않다면 값을 입력하거나 항목을 추가하지 마세요.
DIRECTORY 섹션을 건드리면 Kustomize 전환이 막힙니다
이 영역에 값을 입력하면
spec.source.directory가 명시적으로 저장되어 소스 타입이 고정됩니다. 그러면 나중에kustomization.yaml을 추가해도 Kustomize로 전환되지 않습니다. -
생성 및 동기화
CREATE를 누르면 Application이 생성되고, 초기 상태는
OutOfSync로 표시됩니다. SYNC를 실행하면 실제 배포가 진행됩니다. 동기화가 완료된 Application 카드에 Healthy, Synced 상태가 표시된 화면
배포 결과 확인
-
리소스 확인
배포가 끝났다면 클러스터에 리소스가 실제로 생성됐는지 확인합니다.
kubectl -n demo get allDeployment, ReplicaSet, Pod, Service가 모두 조회되면 정상입니다. ArgoCD UI에서도 같은 내용을 리소스 트리로 볼 수 있습니다. Application에서 Service와 Deployment가 갈라지고, Deployment 아래로 ReplicaSet과 Pod가 이어지는 구조입니다.
-
GitOps 동작 확인
Git에 변경 사항을 커밋했을 때 실제로 클러스터가 따라오는지 확인하세요.
deployment.yaml의replicas를 1에서 2로 바꿔 커밋합니다. 잠시 후(기본 3분 주기) ArgoCD가 저장소를 확인하고 나면 애플리케이션 상태가OutOfSync로 바뀝니다. 저장소에는 2로 적혀 있는데 클러스터에는 1개만 떠 있으니 두 상태가 어긋났다는 뜻입니다. SYNC를 실행하면 Pod가 두 개로 늘어나고 다시Synced상태가 됩니다.클러스터에 직접 명령을 내리지 않았는데도 변경이 반영된다는 점이 GitOps의 핵심입니다. 배포 담당자가 다루는 것은 Git 저장소이고, 클러스터에 적용하는 일은 ArgoCD가 맡습니다.
이 글에서는 동기화 정책을 Manual로 설정했기 때문에 SYNC 버튼을 눌러야 반영됩니다. 애플리케이션 상세 화면의 Sync Policy에서 자동 동기화를 활성화하면 이 과정도 생략돼 커밋만으로 배포가 완료됩니다.
Kustomize 적용
배포까지 마쳤으니 이제 매니페스트를 정리할 차례입니다. Kustomize가 왜 필요한지부터 짚고 적용에 들어가겠습니다.
Kustomize를 사용하는 이유
지금 상태에서는 Kustomize가 없어도 아무 문제가 없습니다. 파일이 두 개뿐이고, ArgoCD가 디렉터리 안의 YAML을 그대로 적용해 주니까요. 그럼에도 이 단계에서 Kustomize를 적용하는 이유는 두 가지입니다.
첫째, 환경별 구성이 갈라지는 시점에 필요해집니다. 개발 환경과 운영 환경은 대부분의 설정을 공유하면서 replica 수나 리소스 할당량 정도만 다른 경우가 많습니다. YAML 파일을 통째로 복사해 두 벌 관리하면 공통 부분을 고칠 때마다 양쪽을 손대야 하죠. Kustomize는 공통 설정을 base에 두고 차이나는 부분만 overlays에 선언하는 방식으로 이 문제를 해결합니다.
둘째, CI에서 이미지 태그를 갱신할 때 유용합니다. 파이프라인이 이미지를 빌드한 뒤 매니페스트의 태그를 새 값으로 바꿔 커밋해야 하는데 kustomize edit set image 명령을 쓰면 이 작업을 한 줄로 처리할 수 있습니다. sed로 YAML을 직접 치환하는 방식보다 안전하고, 파일 구조가 바뀌어도 깨지지 않습니다.
ArgoCD에는 Kustomize가 내장돼 있어 별도로 설치할 것은 없습니다.
kustomization.yaml 작성
apps/demo/kustomization.yaml을 추가하세요.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
images:
- name: nginx
newTag: 1.27-alpine
ArgoCD는 대상 경로의 파일을 보고 소스 타입을 판정합니다. Chart.yaml이 있으면 Helm, kustomization.yaml이 있으면 Kustomize, 둘 다 없으면 일반 디렉터리로 처리합니다.
커밋한 뒤 Application 상세 화면을 열어 보세요. KUSTOMIZE 섹션이 나타나면 소스 타입이 정상적으로 전환된 것입니다.

IMAGES 항목에는 kustomization.yaml에 지정한 이미지가 표시됩니다. 여기서는 deployment.yaml과 같은 태그를 넣었기에 결과는 같지만, CI에서 kustomize edit set image로 태그를 갱신하면 이 값이 바뀝니다.
kustomization.yaml에 commonLabels를 추가하면 Deployment의 spec.selector.matchLabels에도 라벨이 함께 적용됩니다. 그런데 selector는 변경할 수 없는(immutable) 필드이기에 이미 배포된 Deployment에는 적용되지 않고 다음 오류가 발생합니다.
Deployment.apps "demo" is invalid: spec.selector: field is immutable
commonLabels는 Kustomize v5부터 deprecated 상태이며, 실행하면 labels를 쓰라는 경고가 표시됩니다. selector에 영향을 주지 않으려면 labels와 includeSelectors: false를 사용하거나, 라벨 정책을 배포 이전에 확정하는 것이 좋습니다.
소스 타입이 전환되지 않을 때
KUSTOMIZE 섹션이 나타나지 않고 다음과 같은 오류가 표시될 수 있습니다.
Resource not found in cluster:
kustomize.config.k8s.io/v1beta1/Kustomization:undefined
이는 ArgoCD가 kustomization.yaml을 설정 파일이 아니라 배포 대상 리소스로 취급하고 있다는 의미입니다. Application 생성 시 DIRECTORY 섹션을 건드려 spec.source.directory가 저장된 경우 발생합니다.
-
현재 설정 확인
Application의 소스 설정을 조회해
directory키가 있는지 확인하세요.kubectl -n argocd get app demo -o json | jq '.spec.source' -
directory 키 제거
directory키가 존재한다면 제거합니다.kubectl -n argocd patch app demo --type json \ -p '[{"op":"remove","path":"/spec/source/directory"}]' -
하드 리프레시
캐시된 매니페스트를 버리고 저장소를 다시 읽도록 하드 리프레시를 수행합니다. 설정만 지우면 ArgoCD가 이전에 판정한 소스 타입을 그대로 쓸 수 있기 때문입니다.
kubectl -n argocd patch app demo --type merge \ -p '{"metadata":{"annotations":{"argocd.argoproj.io/refresh":"hard"}}}'
맺음말
지금까지 홈랩 Kubernetes 클러스터에 ArgoCD를 구성하고, GitLab Self-Managed 저장소와 연동해 nginx를 배포하는 과정을 살펴봤습니다. 접속 환경을 구성하고, 저장소를 등록하고, Application을 만들어 동기화한 뒤, Kustomize로 매니페스트를 정리하는 순서였습니다.
구축 과정에서 자주 마주치는 지점을 다시 정리하면 다음과 같습니다.
- 포트 포워딩은 기본적으로 로컬 주소에만 바인딩되므로, 다른 장비에서 접속하려면
--address 0.0.0.0이 필요합니다. argocd-server는 기본 설정에서 TLS를 직접 처리하고 자체 서명 인증서를 사용하므로,server.insecure를 적용하기 전에는 브라우저에서 인증서 경고를 수락해야 UI에 접속할 수 있습니다.- 저장소 인증 정보는 Application이 아니라 저장소 단위로 관리되므로, Repositories에 먼저 등록해야 합니다.
- HTTPS에서 HTTP로 전환하면 이전에 발급된 세션 쿠키가 전송되지 않아 로그인이 반복될 수 있습니다.
- Application 생성 시 DIRECTORY 섹션을 건드리면 소스 타입이 고정돼 이후
kustomization.yaml을 추가해도 Kustomize로 전환되지 않습니다.
이 글에서 만든 구조는 시작점에 가깝습니다. 애플리케이션이 늘어나면 Application 생성을 자동화하는 방법을 고민하게 되고, 환경이 여러 개로 갈라지면 Kustomize의 base와 overlays 구조가 본격적으로 필요해집니다. 그때마다 다시 정리해 볼 생각입니다.
한 가지 덧붙이자면, 이런 것들을 처음 익히기에 홈랩만 한 환경이 없습니다. 설정을 잘못 넣어 서비스가 멈춰도 곤란해질 사람이 없고, 무엇이 잘못됐는지 끝까지 파고들 시간도 있습니다. 이 글에서 다룬 다섯 가지 지점도 모두 그렇게 알게 된 것들입니다. 관심 있는 도구가 있다면 클러스터 하나를 띄우고 직접 붙여 보시길 권합니다.
구축은 끝났는데 운영은 시작도 못 했습니다
홈랩에서 통하던 설정이 운영 클러스터에서는 그대로 쓰이지 않습니다. 인포그랩은 GitOps 도입 단계에서 접근 제어와 멀티 클러스터 구조를 함께 설계하고, 조직에 맞는 배포 파이프라인까지 구축합니다.
참고 자료
- "Getting Started", Argo CD Documentation, https://argo-cd.readthedocs.io/en/stable/getting_started/
- "Ingress Configuration", Argo CD Documentation, https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/
- "Private Repositories", Argo CD Documentation, https://argo-cd.readthedocs.io/en/stable/user-guide/private-repositories/
- "Tool Detection", Argo CD Documentation, https://argo-cd.readthedocs.io/en/stable/user-guide/tool_detection/
- "Kustomize", Argo CD Documentation, https://argo-cd.readthedocs.io/en/stable/user-guide/kustomize/
- "Projects", Argo CD Documentation, https://argo-cd.readthedocs.io/en/stable/user-guide/projects/
- "Sync Options", Argo CD Documentation, https://argo-cd.readthedocs.io/en/stable/user-guide/sync-options/
- "Git Webhook Configuration", Argo CD Documentation, https://argo-cd.readthedocs.io/en/stable/operator-manual/webhook/
- "Generators - Git", Argo CD ApplicationSet Documentation, https://argo-cd.readthedocs.io/en/stable/operator-manual/applicationset/Generators-Git/
- "kubectl port-forward", Kubernetes Documentation, https://kubernetes.io/docs/reference/kubectl/generated/kubectl_port-forward/
- "JSONPath Support", Kubernetes Documentation, https://kubernetes.io/docs/reference/kubectl/jsonpath/
- "Personal access tokens", GitLab Docs, https://docs.gitlab.com/user/profile/personal_access_tokens/
- "Labels and Annotations", Kustomize Documentation, https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/labels/
Toma
DevOps Engineer
서버 오퍼레이터를 시작으로 시스템 어드민, 클라우드 엔지니어를 거쳐 DevOps 엔지니어로 성장해왔습니다. Kubernetes와 CI/CD 파이프라인에 관심이 많고, 홈 랩에서 직접 인프라를 구성하고 실험하며 기술을 익혀왔습니다. 현장에서 부딪히고 홈 랩에서 검증하며 얻은 것들을 기록으로 남기는 걸 좋아합니다.
이 저자의 글 모두 보기 →이 글이 도움이 되셨나요?
인포그랩 전문가가 맞춤 상담을 도와드립니다.
관련 글

Kubernetes 제대로 아는 DevOps 엔지니어를 구분하는 8가지 질문과 답변
DevOps 엔지니어는 단순 개발을 넘어 운영·확장·자동화까지 포괄하는 Kubernetes 역량을 갖춰야 합니다. 면접, 자격증(CKA·CKAD·CKS) 시험, 고객 대응 상황에서 K8s 개념을 제대로 설명하면, DevOps 엔지니어로서 전문성을 입증할 수 있습니다. 이 글은 면접과 실무에서 자주 등장하는 K8s 핵심 질문 8가지와 모범 답변을 정리했습니다.

K9s로 더 빠르게, 효율적으로 Kubernetes 관리하기
K9s는 터미널 기반의 Kubernetes 클러스터 관리 도구입니다. 이 도구는 복잡한 CLI 작업을 단축키로 간편하게 처리합니다. 에어갭 환경에서도 강력한 기능을 제공하며, 실시간 모니터링과 Pod 로그 확인, 리소스 조회 등을 빠르게 수행할 수 있습니다. 이 글은 K9s 개요와 설치 방법, 주요 기능과 고급 기능 활용법을 다뤘습니다.

2025년 GitOps 현실 진단 4가지
이 글은 2025년 GitOps 트렌드 4가지를 다뤘습니다. GitOps 도입 양극화와 확산, 기본 단계에 머문 구현 수준, 애플리케이션 구성 중심 활용, 도구 선택 1위인 ArgoCD가 그 내용입니다. 각 트렌드의 상세 현황과 등장 배경, 유의 사항을 소개합니다.