sehyun.dev
k8s스터디

WSL2 + k3s로 쿠버네티스 연습 환경 구성하기 (feat. 두번째!)

2026년 2월 7일

개요

Ingress-NGINX까지 구성한 이후, kubectl apply로 직접 배포하는 방식에서 벗어나 Git을 사용하는 GitOps 흐름을 연습해보기로 했다.

이번 단계의 목표는 “ArgoCD를 붙이기 전, GitOps를 위한 Git 서버(Gitea)를 클러스터 내부에 구성하고,

Kubernetes 매니페스트를 Git으로 관리할 수 있는 상태를 만드는 것”이다.

즉, 이 시점에서는 빌드(Jenkins)자동 배포(ArgoCD) 가 목적이 아니라

Git에 ‘배포 정의’를 안전하게 보관하는 기반을 만드는 단계

전체 흐름 요약

(Local 작업)
k3s giteat 관련 yaml 작성 후 apply

Git commit/ push

Gitea (GitOps repo) 확인

이후 단계에서 ArgoCD가 이 Git 저장소를 감시하게 된다.

1. 쿠버네티스 운영 중 GitOps를 위해 Git이 필요한 이유

GitOps의 본질은 Kubernetes 클러스터의 상태를 사람이 직접 조작하지 않고, Git에 정의된 상태와 항상 일치하도록 유지하는 것에 있다.

실제로 사내에서 Kubernetes 기반 CI/CD를 운영할 때, 로컬 환경에서 YAML을 작성한 뒤 kubectl apply를 통해 클러스터 상태를 변경하는전통적인 방식을 경험했습니다.

위 방식은 초기에는 단순하고 빠르지만, 시간이 지날수록 여러 한계를 맞이 했습니다.

  • 누가, 언제, 어떤 설정을 변경했는지 추적하기 어렵고
  • 각자의 로컬 환경에 서로 다른 YAML 파일이 존재하게 되며
  • 결국 클러스터의 실제 상태가 코드가 아닌 사람의 기억이나 로컬 파일에 의존하게 됩니다.

이로 인해 설정 변경 이력을 다시 정리하거나, 문제가 발생했을 때 정확한 상태로 되돌리기 위해 YAML을 새로 작성하거나 수작업으로 복구해야 하는 상황이 반복됩니다.

GitOps에서는 이러한 문제를 해결하기 위해 Git을 단순한 저장소가 아닌 ‘클러스터 상태의 기준점’으로 사용한다.

Git에 정의된 매니페스트는 언제든지 되돌릴 수 있는 상태의 스냅샷이 되고 모든 변경 사항은 명확한 변경 이력과 의도로 기록이 가능하게 됩니다.

즉, Kubernetes 운영에서 Git은 단순히 YAML을 보관하는 공간이 아니라, “지금 클러스터가 어떤 상태여야 하는지”를 정의하는 기준이 됩니다.

이러한 전제가 있어야만, 이후 ArgoCD와 같은 도구를 통해 사람의 개입 없이도 안정적인 배포와 상태 동기화가 가능합니다.

2. Gitea를 k3s 안에 Pod로 구성

Gitea는 다음 리소스로 구성했다.

  • Namespace: gitea
  • Deployment: Gitea 서버
  • PVC: /data 디렉토리를 통한 데이터 영구 저장
  • Service: 내부 접근용
  • Ingress: gitea.local 도메인으로 접근

이 구성의 특징은 다음과 같다.

  • Pod가 재시작되어도 Git 데이터가 유지
  • Ingress-NGINX를 통해 클러스터 외부에서 접근 가능
  • 이후 ArgoCD, Jenkins와 같은 컴포넌트와 동일한 네트워크 레벨에서 연동 가능
apiVersion: v1
kind: Namespace
metadata:
  name: gitea
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: gitea-data
  namespace: gitea
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gitea
  namespace: gitea
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gitea
  template:
    metadata:
      labels:
        app: gitea
    spec:
      containers:
        - name: gitea
          image: gitea/gitea:1.22
          ports:
            - containerPort: 3000
          env:
            - name: USER_UID
              value: "1000"
            - name: USER_GID
              value: "1000"
          volumeMounts:
            - name: gitea-data
              mountPath: /data
      volumes:
        - name: gitea-data
          persistentVolumeClaim:
            claimName: gitea-data
---
apiVersion: v1
kind: Service
metadata:
  name: gitea-svc
  namespace: gitea
spec:
  selector:
    app: gitea
  ports:
    - name: http
      port: 3000
      targetPort: 3000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: gitea-ing
  namespace: gitea
spec:
  ingressClassName: nginx
  rules:
    - host: gitea.local
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: gitea-svc
                port:
                  number: 3000

image.png

3. 로컬에서 GitOps repo 구성 및 Push

로컬(WSL)에서 GitOps 전용 작업 디렉토리를 만들고, 기존에 작성했던 hello 예제 매니페스트를 다음 구조로 정리했다.

gitops-repo/
└── apps/
    └── hello/
        ├── deployment.yaml
        ├── service.yaml
        ├── ingress.yaml
        ├──admin-deployment.yaml
        ├──admin-service.yaml
        ├── api-deployment.yaml
        └── api-service.yaml

이후 Git 저장소를 초기화하고, Gitea remote를 연결한 뒤 첫 커밋을 생성했다.

이 과정에서 Git user.name, user.email이 설정되지 않아 커밋이 실패했는데,

이는 Git 초기 환경에서 흔히 발생하는 이슈로 글로벌 설정을 통해 해결했다.

image.png

image.png

마무리

이번 단계에서는 Kubernetes 배포를 자동화하는 데 집중하기보다, 자동화가 가능해지기 위한 전제 조건을 먼저 정리하는 데 초점을 맞췄다.

Ingress-NGINX까지 구성한 상태에서, 더 이상 kubectl apply로 클러스터를 직접 조작하지 않고, “클러스터가 어떤 상태여야 하는지”를 Git에 명확히 기록하는 구조를 만드는 것이 핵심이었다.

이를 위해 Gitea를 k3s 클러스터 내부에 구성하고, Kubernetes 매니페스트를 GitOps 전용 저장소로 분리해 관리함으로써, 배포 정의가 로컬 환경이 아닌 Git에 고정되고 변경 이력과 의도가 커밋 단위로 추적 가능해지며 이후 ArgoCD와 같은 도구가 개입할 수 있는 기준점을 마련했다

아직 이 단계에서는 실제로 자동 배포가 이루어지지는 않는다.

하지만 배포의 책임은 사람에서 도구로 자연스럽게 이동할 준비를 마친 셈이다.

다음 단계에서는 이 GitOps 저장소를 ArgoCD에 연결해, Git 변경 사항이 어떻게 Kubernetes 클러스터에 자동으로 반영되는지 직접 확인해볼 예정이다.