시리즈 소개
이 시리즈에서는 DigitalOcean Kubernetes(DOKS)에서 GitOps 환경을 구축하는 전체 과정을 다룹니다.
시리즈 구성
- 왜 GitOps인가?
- Kubernetes 클러스터와 Traefik (현재 글)
- ExternalDNS - 자동 DNS 레코드 관리
- SOPS + age - 시크릿 암호화
- ArgoCD - GitOps 배포 자동화
DigitalOcean Kubernetes 클러스터 생성
클러스터 생성 (Console)
- DigitalOcean Console에 로그인
- Kubernetes 메뉴 선택 → Create Cluster
- 설정 입력:
- Region: Singapore (sgp1) - 한국에서 가까움
- Version: 최신 stable (예: 1.31.x)
- Node Pool: Basic nodes, $12/month (1 vCPU, 2GB RAM) x 2~3개
- Name: 클러스터 이름
DigitalOcean K8s는 Control Plane이 무료입니다. Worker Node 비용만 지불하면 됩니다.
kubeconfig 설정
# doctl CLI 설치 (macOS)
brew install doctl
# DigitalOcean 인증
doctl auth init
# kubeconfig 저장
doctl kubernetes cluster kubeconfig save <cluster-name>
# 연결 확인
kubectl get nodesTraefik 설치
Traefik이란?
Traefik은 클라우드 네이티브 환경에 최적화된 Edge Router입니다. Kubernetes Ingress Controller로 사용하면 자동 서비스 디스커버리, Let’s Encrypt 인증서 자동 발급 등의 기능을 제공합니다.
클러스터 트래픽 플로우
외부에서 클러스터 내부 서비스로 요청이 전달되는 전체 흐름을 살펴보겠습니다.
각 단계 설명:
| 단계 | 구간 | 설명 |
|---|---|---|
| ① | Internet → LB | 사용자가 도메인으로 요청. DNS는 LB의 External IP를 가리킴 |
| ② | LB → Traefik | DO Load Balancer가 Traefik Service(NodePort)로 트래픽 전달 |
| ③ | Traefik → Service | IngressRoute 규칙에 따라 적절한 백엔드 Service 선택 |
| ④ | Service → Pod | kube-proxy가 Service의 Endpoint 중 하나의 Pod로 로드밸런싱 |
Traefik Service 타입
Traefik을 설치하면 type: LoadBalancer인 Service가 생성됩니다.
$ kubectl get svc -n traefik
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
traefik LoadBalancer 10.245.x.x 143.xxx.xxx.xxx 80:30080/TCP,443:30443/TCPDigitalOcean에서는 이 Service를 감지하고 자동으로 Cloud Load Balancer를 프로비저닝합니다. EXTERNAL-IP가 바로 외부에서 접근 가능한 진입점입니다.
왜 Traefik인가? (vs Istio)
Ingress Controller를 선택할 때 Istio도 고려했지만, 다음 이유로 Traefik을 선택했습니다.
| 항목 | Traefik | Istio |
|---|---|---|
| 리소스 사용량 | 낮음 (~50MB) | 높음 (sidecar당 ~100MB+) |
| 복잡도 | 단순 | Service Mesh 전체 스택 |
| 학습 곡선 | 완만 | 가파름 |
| 기능 범위 | Ingress/Routing 특화 | Full Service Mesh |
Istio를 선택하지 않은 이유:
- 리소스 비용: Istio는 각 Pod에 Envoy sidecar를 주입하여 메모리 사용량이 크게 증가합니다. 작은 클러스터에서는 부담이 됩니다.
- 과한 기능: mTLS, 트래픽 미러링 등 Service Mesh 기능이 필요하지 않다면 오버스펙입니다.
- 운영 복잡도: Control Plane(istiod) 관리, sidecar injection 등 신경 쓸 부분이 많습니다.
단순히 Ingress + TLS 자동화 + 라우팅만 필요하다면 Traefik이 훨씬 경제적입니다.
Helmfile을 통한 설치
Helmfile을 사용하면 여러 Helm 차트를 선언적으로 관리할 수 있습니다.
# helmfile.yaml
repositories:
- name: traefik
url: https://helm.traefik.io/traefik
releases:
- name: traefik
namespace: traefik
createNamespace: true
chart: traefik/traefik
version: 35.2.0
values:
- ./values/traefik/common.yaml
- ./values/traefik/{{ .Environment.Name }}.yamltraefik-values.yaml
# values/traefik/common.yaml
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
additionalArguments:
# Let's Encrypt 인증서 저장소 위치
- "--certificatesresolvers.letsencrypt.acme.storage=/data/acme.json"
# 연락처 이메일
- "--certificatesresolvers.letsencrypt.acme.email=your-email@example.com"
# HTTP-01 챌린지 사용
- "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
- "--log.level=INFO"
service:
enabled: true
type: LoadBalancer
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 300m
memory: 256Mi
ingressRoute:
dashboard:
enabled: true
matchRule: Host(`traefik.example.com`)
entryPoints: ["traefik"]
crds:
install: true
ports:
web:
expose:
default: true
exposedPort: 80
port: 8000
protocol: TCP
websecure:
expose:
default: true
exposedPort: 443
port: 8443
protocol: TCP설치 실행
# Helmfile 설치
brew install helmfile
# 환경별 배포 (dev 환경)
helmfile -e dev sync
# 또는 특정 릴리스만 배포
helmfile -e dev -l name=traefik sync설치 확인
# Pod 상태 확인
kubectl get pods -n traefik
# Service 확인 (LoadBalancer External IP)
kubectl get svc -n traefik
# Traefik 버전 확인
kubectl logs -n traefik -l app.kubernetes.io/name=traefik | head -20Ingress 설정
Kubernetes Ingress 사용
Traefik은 표준 Kubernetes Ingress 리소스를 지원합니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
annotations:
traefik.ingress.kubernetes.io/router.tls: "true"
traefik.ingress.kubernetes.io/router.tls.certresolver: letsencrypt
external-dns.alpha.kubernetes.io/hostname: my-app.example.com
spec:
ingressClassName: traefik
tls:
- hosts:
- my-app.example.com
rules:
- host: my-app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app
port:
name: http주요 어노테이션:
| 어노테이션 | 설명 |
|---|---|
traefik.ingress.kubernetes.io/router.tls |
TLS 활성화 |
traefik.ingress.kubernetes.io/router.tls.certresolver |
Let’s Encrypt resolver 사용 |
external-dns.alpha.kubernetes.io/hostname |
ExternalDNS가 DNS 레코드 자동 생성 |
TLS/HTTPS 설정
Traefik의 Let’s Encrypt 통합으로 인증서가 자동 발급됩니다.
HTTP-01 Challenge 흐름:
- Traefik이 Let’s Encrypt에 인증서 요청
- Let’s Encrypt가
http://<domain>/.well-known/acme-challenge/<token>접근 시도 - Traefik이 올바른 응답 반환
- 인증서 발급 완료 →
/data/acme.json에 저장
인증서는 만료 30일 전에 자동 갱신됩니다.
다음 글 예고
다음 글에서는 ExternalDNS를 설정하여 Kubernetes 리소스와 DNS 레코드를 자동으로 동기화하는 방법을 다룹니다. Ingress에 어노테이션만 추가하면 Cloudflare나 DigitalOcean DNS에 자동으로 레코드가 생성됩니다.