이 예제에서는 스테이징(staging)과 프로덕션(production) 두 개의 클러스터 환경을 가정합니다. Flux와 Kustomize를 활용해 중복 선언을 최소화하면서 클러스터를 관리하는 것이 핵심 목표입니다.
Flux는 HelmRepository와 HelmRelease CRD(Custom Resource Definition)를 사용하여 데모 애플리케이션 설치, 테스트, 업그레이드를 수행합니다. Flux는 Helm 저장소를 모니터링하고 semver 범위에 따라 최신 차트 버전으로 자동 업그레이드합니다.
사전 준비
프로젝트 저장소:
쿠버네티스 클러스터(v1.16+)와 kubectl(v1.18+)이 필요합니다. 로컬 테스트에는 Kubernetes Kind를 사용할 수 있습니다.
GitHub 계정과 저장소 생성 권한이 있는 Personal Access Token이 필요합니다.
Flux CLI 설치 (macOS/Linux):
brew install fluxcd/tap/flux
또는:
curl -s https://fluxcd.io/install.sh | sudo bash
프로젝트 구조
저장소 디렉토리 구성:
├── 애플리케이션
│ ├── 베이스
│ ├── 프로덕션
│ └── 스테이징
├── 인프라
│ ├── nginx
│ ├── redis
│ └── 소스
└── 클러스터
├── 프로덕션
└── 스테이징
애플리케이션 구성:
./애플리케이션/
├── 베이스
│ └── 앱데모
│ ├── kustomization.yaml
│ ├── 네임스페이스.yaml
│ └── 릴리즈.yaml
├── 프로덕션
│ ├── kustomization.yaml
│ └── 앱데모-패치.yaml
└── 스테이징
├── kustomization.yaml
└── 앱데모-패치.yaml
공통 HelmRelease (apps/base/app-demo/release.yaml):
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: app-demo
namespace: app-demo
spec:
chart:
spec:
chart: app-demo
sourceRef:
kind: HelmRepository
name: app-demo
namespace: flux-system
interval: 5m
values:
cache: redis-master.redis:6379
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: nginx
스테이징 전용 패치 (apps/staging/app-demo-patch.yaml):
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: app-demo
spec:
chart:
spec:
version: ">=1.0.0-alpha"
test:
enable: true
values:
ingress:
hosts:
- app-demo.staging
프로덕션 전용 패치 (apps/production/app-demo-patch.yaml):
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: app-demo
spec:
chart:
spec:
version: ">=1.0.0"
values:
ingress:
hosts:
- app-demo.production
인프라 구성:
./인프라/
├── nginx
│ ├── kustomization.yaml
│ ├── 네임스페이스.yaml
│ └── 릴리즈.yaml
├── redis
│ ├── kustomization.yaml
│ ├── 네임스페이스.yaml
│ └── 릴리즈.yaml
└── 소스
├── bitnami.yaml
├── kustomization.yaml
└── 앱데모.yaml
Helm 저장소 정의 (infrastructure/sources/app-demo.yaml):
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: HelmRepository
metadata:
name: app-demo
spec:
interval: 5m
url: https://stefanprodan.github.io/podinfo
클러스터 부트스트랩
클러스터 디렉토리 구성:
./클러스터/
├── 프로덕션
│ ├── 앱.yaml
│ └── 인프라.yaml
└── 스테이징
├── 앱.yaml
└── 인프라.yaml
스테이징 Kustomization (clusters/staging/apps.yaml):
apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
kind: Kustomization
metadata:
name: apps
namespace: flux-system
spec:
interval: 10m
dependsOn:
- name: infrastructure
sourceRef:
kind: GitRepository
name: flux-system
path: ./apps/staging
prune: true
환경 변수 설정:
export GITHUB_TOKEN=<토큰>
export GITHUB_USER=<사용자명>
export GITHUB_REPO=<저장소명>
사전 조건 확인:
flux check --pre
스테이징 클러스터 부트스트랩:
flux bootstrap github \
--context=staging \
--owner=${GITHUB_USER} \
--repository=${GITHUB_REPO} \
--branch=main \
--path=clusters/staging
배포 상태 확인:
watch flux get helmreleases --all-namespaces
애플리케이션 접근 테스트:
kubectl -n nginx port-forward svc/nginx-ingress-controller 8080:80 &
curl -H "Host: app-demo.staging" http://localhost:8080
프로덕션 클러스터 부트스트랩:
flux bootstrap github \
--context=production \
--owner=${GITHUB_USER} \
--repository=${GITHUB_REPO} \
--branch=main \
--path=clusters/production
시크릿 암호화
SOPS 설치:
brew install gnupg sops
GPG 키 생성:
gpg --full-generate-key
gpg --list-secret-keys fluxcdbot@users.noreply.github.com
시크릿 생성:
kubectl -n redis create secret generic redis-auth \
--from-literal=password=change-me \
--dry-run=client \
-o yaml > infrastructure/redis/redis-auth.yaml
sops --encrypt \
--pgp=<키ID> \
--encrypted-regex '^(data|stringData)$' \
--in-place infrastructure/redis/redis-auth.yaml
복호화 설정 (infrastructure.yaml):
spec:
decryption:
provider: sops
secretRef:
name: sops-gpg
클러스터 추가
신규 개발 클러스터 디렉토리 생성:
mkdir -p clusters/dev
cp clusters/staging/infrastructure.yaml clusters/dev
cp clusters/staging/apps.yaml clusters/dev
Flux 부트스트랩:
flux bootstrap github \
--context=dev \
--owner=${GITHUB_USER} \
--repository=${GITHUB_REPO} \
--branch=main \
--path=clusters/dev
환경 복제
프로덕션 복제 클러스터 부트스트랩:
flux bootstrap github \
--context=production-clone \
--owner=${GITHUB_USER} \
--repository=${GITHUB_REPO} \
--branch=main \
--path=clusters/production-clone
Kustomization 설정 (clusters/production-clone/kustomization.yaml):
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- flux-system
- ../production/infrastructure.yaml
- ../production/apps.yaml
배포 동기화:
flux reconcile kustomization flux-system \
--context=production-clone \
--with-source