ArgoCD, Karpenter, Crossplane, Kyverno를 통합한 GitOps 기반 Kubernetes 플랫폼을 구축합니다. app-of-apps 패턴, 환경 프로모션, 모니터링, Day-2 운영 체크리스트를 다룹니다.
시리즈의 마지막 장입니다. 1장부터 9장까지 다룬 ArgoCD, Flux, 멀티클러스터 관리, 컨트롤러 패턴, Karpenter, 비용 최적화, Crossplane, 보안 정책을 하나로 통합하여 실전 프로젝트를 구축합니다. 이 프로젝트는 중규모 조직에서 실제로 운영 가능한 GitOps 기반 Kubernetes 플랫폼의 레퍼런스 아키텍처입니다.
infra-manifests/
bootstrap/
argocd/
install.yaml # ArgoCD 설치
argocd-cm.yaml # ArgoCD 설정
app-of-apps.yaml # 루트 Application
platform/
base/
argocd/ # ArgoCD 설정 + RBAC
karpenter/ # NodePool + EC2NodeClass
kyverno/ # 정책 엔진 + 정책
crossplane/ # Provider + XRD + Composition
monitoring/ # Prometheus + Grafana + Alertmanager
ingress/ # Ingress Controller
cert-manager/ # TLS 인증서 관리
external-secrets/ # ESO 설정
overlays/
production/
kustomization.yaml
staging/
kustomization.yaml
claims/
production/
database.yaml # Crossplane Database Claim
cache.yaml # Crossplane Cache Claim
staging/
database.yaml
cache.yaml
app-manifests/
apps/
api-server/
base/
deployment.yaml
service.yaml
hpa.yaml
pdb.yaml
overlays/
production/
kustomization.yaml
staging/
kustomization.yaml
web-frontend/
base/
overlays/
background-workers/
base/
overlays/
# 관리 클러스터에 ArgoCD 설치
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/ha/install.yaml
# 초기 비밀번호 확인
argocd admin initial-password -n argocd
# 워크로드 클러스터 등록
argocd cluster add eks-production --name production
argocd cluster add eks-staging --name stagingApp-of-Apps 패턴은 ArgoCD의 핵심 관리 패턴입니다. 하나의 루트 Application이 다른 Application들을 관리하여, 전체 플랫폼을 하나의 진입점에서 제어합니다.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: platform-root
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://github.com/org/infra-manifests.git
targetRevision: main
path: platform/apps
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: trueapiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- karpenter.yaml
- kyverno.yaml
- crossplane.yaml
- monitoring.yaml
- ingress.yaml
- cert-manager.yaml
- external-secrets.yaml
- app-applicationset.yaml각 플랫폼 컴포넌트를 개별 Application으로 정의합니다.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: karpenter
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "1"
spec:
project: platform
source:
repoURL: https://github.com/org/infra-manifests.git
targetRevision: main
path: platform/base/karpenter
destination:
server: https://production.example.com
namespace: kube-system
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=trueApp-of-Apps 패턴에서 sync-wave 어노테이션을 활용하여 배포 순서를 제어합니다. 예를 들어, Kyverno(wave: 0)를 먼저 설치하고, 정책(wave: 1)을 적용한 후, 애플리케이션(wave: 2)을 배포하는 순서를 보장합니다.
6장에서 다룬 NodePool과 EC2NodeClass를 프로덕션 환경에 맞게 구성합니다.
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: general
spec:
template:
metadata:
labels:
workload-type: general
spec:
requirements:
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand", "spot"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r"]
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values: ["5"]
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
expireAfter: 720h
limits:
cpu: "500"
memory: 1000Gi
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1m
budgets:
- nodes: "10%"
- nodes: "0"
schedule: "0 9 * * 1-5"
duration: 9hapiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: applications
namespace: argocd
spec:
goTemplate: true
generators:
- matrix:
generators:
- list:
elements:
- cluster: staging
server: https://staging.example.com
branch: main
autoSync: "true"
- cluster: production
server: https://production.example.com
branch: release
autoSync: "false"
- git:
repoURL: https://github.com/org/app-manifests.git
revision: main
directories:
- path: 'apps/*'
template:
metadata:
name: '{{ .path.basename }}-{{ .cluster }}'
labels:
app: '{{ .path.basename }}'
env: '{{ .cluster }}'
spec:
project: applications
source:
repoURL: https://github.com/org/app-manifests.git
targetRevision: '{{ .branch }}'
path: '{{ .path.path }}/overlays/{{ .cluster }}'
destination:
server: '{{ .server }}'
namespace: '{{ .path.basename }}'
syncPolicy:
syncOptions:
- CreateNamespace=true
- PrunePropagationPolicy=foreground프로덕션 배포는 반드시 수동 승인을 거쳐야 합니다. ApplicationSet에서 프로덕션 클러스터의 autoSync를 비활성화하고, ArgoCD RBAC으로 프로덕션 동기화 권한을 SRE/플랫폼 팀에만 부여하십시오.
8장에서 다룬 Crossplane으로 데이터베이스와 캐시를 프로비저닝합니다.
apiVersion: platform.example.com/v1alpha1
kind: Database
metadata:
name: app-database
namespace: production
spec:
size: large
engine: postgres
version: "16.3"
highAvailability: true
---
apiVersion: platform.example.com/v1alpha1
kind: Cache
metadata:
name: session-cache
namespace: production
spec:
size: medium
engine: redis
version: "7.2"9장에서 다룬 Kyverno 정책을 플랫폼 수준에서 적용합니다.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- require-labels.yaml
- require-resource-limits.yaml
- restrict-image-registries.yaml
- verify-image-signatures.yaml
- add-security-context.yaml
- generate-network-policies.yaml
- restrict-host-namespaces.yamlapiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restrict-image-registries
annotations:
policies.kyverno.io/title: Restrict Image Registries
policies.kyverno.io/severity: high
spec:
validationFailureAction: Enforce
background: true
rules:
- name: allowed-registries
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Images must come from approved registries."
pattern:
spec:
containers:
- image: "ghcr.io/org/* | public.ecr.aws/org/*"
initContainers:
- image: "ghcr.io/org/* | public.ecr.aws/org/*"apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: monitoring
namespace: argocd
spec:
project: platform
source:
repoURL: https://prometheus-community.github.io/helm-charts
chart: kube-prometheus-stack
targetRevision: "61.x.x"
helm:
valuesObject:
prometheus:
prometheusSpec:
retention: 30d
storageSpec:
volumeClaimTemplate:
spec:
storageClassName: gp3
resources:
requests:
storage: 100Gi
additionalScrapeConfigs:
- job_name: argocd
metrics_path: /metrics
static_configs:
- targets: ["argocd-metrics.argocd:8082"]
- job_name: karpenter
metrics_path: /metrics
static_configs:
- targets: ["karpenter.kube-system:8000"]
alertmanager:
alertmanagerSpec:
storage:
volumeClaimTemplate:
spec:
storageClassName: gp3
resources:
requests:
storage: 10Gi
grafana:
adminPassword:
existingSecret: grafana-admin
dashboardProviders:
dashboardproviders.yaml:
apiVersion: 1
providers:
- name: custom
folder: Platform
type: file
options:
path: /var/lib/grafana/dashboards/custom
destination:
server: https://production.example.com
namespace: monitoringapiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: platform-alerts
namespace: monitoring
spec:
groups:
- name: gitops-alerts
rules:
- alert: ArgocdAppOutOfSync
expr: |
argocd_app_info{sync_status="OutOfSync"} == 1
for: 30m
labels:
severity: warning
annotations:
summary: "ArgoCD app {{ $labels.name }} is out of sync"
- alert: ArgocdAppSyncFailed
expr: |
argocd_app_info{health_status="Degraded"} == 1
for: 10m
labels:
severity: critical
annotations:
summary: "ArgoCD app {{ $labels.name }} sync failed"
- name: karpenter-alerts
rules:
- alert: KarpenterNodeNotReady
expr: |
karpenter_nodes_terminating > 5
for: 10m
labels:
severity: warning
annotations:
summary: "Multiple Karpenter nodes terminating simultaneously"
- name: cost-alerts
rules:
- alert: HighClusterCost
expr: |
sum(node_total_hourly_cost) * 24 * 30 > 10000
for: 1h
labels:
severity: warning
annotations:
summary: "Estimated monthly cluster cost exceeds $10,000"플랫폼 구축 후 안정적인 운영을 위해 정기적으로 수행해야 할 항목들입니다.
Day-2 운영 체크리스트를 Git 저장소에 이슈 템플릿으로 관리하면, 매 점검 주기마다 이슈를 생성하고 담당자를 지정하여 체계적으로 운영할 수 있습니다. 자동화할 수 있는 항목(비용 리포트, 드리프트 감지 등)은 CronJob이나 GitHub Actions로 자동화하십시오.
이 시리즈에서 구축한 GitOps 기반 Kubernetes 플랫폼의 핵심 구성 요소를 정리합니다.
| 영역 | 도구 | 역할 | 시리즈 장 |
|---|---|---|---|
| GitOps | ArgoCD | 선언적 배포, App-of-Apps | 2장 |
| 노드 관리 | Karpenter | 자동 노드 프로비저닝, 비용 최적화 | 6장 |
| 인프라 관리 | Crossplane | 클라우드 리소스 셀프서비스 | 8장 |
| 정책 관리 | Kyverno | 보안 정책, 이미지 검증 | 9장 |
| 비용 관리 | OpenCost + Goldilocks | 비용 가시성, 리소스 최적화 | 7장 |
| 모니터링 | Prometheus + Grafana | 메트릭, 알림, 대시보드 | 본 장 |
| 시크릿 | External Secrets Operator | 외부 시크릿 동기화 | 9장 |
| 인증서 | cert-manager | TLS 자동 발급 | 본 장 |
1장의 GitOps 기본 개념부터 시작하여, ArgoCD와 Flux의 심층 분석, 멀티클러스터 관리, 컨트롤러 패턴의 이해, Karpenter를 활용한 노드 관리, 비용 최적화, Crossplane을 통한 인프라 관리, 보안 정책, 그리고 이 모든 것을 통합한 실전 프로젝트까지 다루었습니다.
GitOps는 단순히 Git에서 배포하는 것이 아닙니다. 선언적 인프라 관리, 자동화된 조정 루프, 감사 가능한 변경 이력, 협업 기반의 운영 문화를 아우르는 종합적인 운영 패러다임입니다. 이 시리즈가 여러분의 Kubernetes 운영 수준을 한 단계 끌어올리는 데 도움이 되었기를 바랍니다.
이 시리즈에서 다룬 모든 YAML 매니페스트와 설정은 참조용입니다. 실제 프로덕션 환경에 적용할 때는 조직의 보안 요구사항, 클라우드 환경, 팀 구조에 맞게 조정해야 합니다. 특히 RBAC 설정, 네트워크 정책, 리소스 제한은 환경에 따라 크게 달라질 수 있습니다.
이 글이 도움이 되셨나요?
OPA/Gatekeeper, Kyverno, Pod Security Standards, RBAC 모범 사례, External Secrets Operator, 공급망 보안(SLSA, Sigstore), 이미지 서명을 다룹니다.
Crossplane의 아키텍처, Provider와 Managed Resource, XRD와 Composition을 활용한 인프라 추상화, GitOps 통합, Terraform과의 비교를 다룹니다.
Kubernetes 리소스 requests/limits 모범 사례, VPA/HPA 전략, Goldilocks, Kubecost/OpenCost, 스팟 인스턴스, 네임스페이스 쿼터, FinOps 실천법을 다룹니다.