본문으로 건너뛰기
Kreath Archive
TechProjectsBooksAbout
TechProjectsBooksAbout
TechProjectsBooksAbout
© 2026 Kreath. All rights reserved.
홈TechProjectsBooksAbout
//
  1. 홈
  2. 테크
  3. 10장: 실전 프로젝트 - GitOps 기반 Kubernetes 플랫폼 구축
2026년 6월 6일·인프라·

10장: 실전 프로젝트 - GitOps 기반 Kubernetes 플랫폼 구축

ArgoCD, Karpenter, Crossplane, Kyverno를 통합한 GitOps 기반 Kubernetes 플랫폼을 구축합니다. app-of-apps 패턴, 환경 프로모션, 모니터링, Day-2 운영 체크리스트를 다룹니다.

14분1,125자10개 섹션
kubernetesci-cdinfrastructureautomationobservability
공유
kubernetes-gitops10 / 10
12345678910
이전9장: 보안 강화와 정책 관리

시리즈의 마지막 장입니다. 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/

1단계: ArgoCD 부트스트랩

ArgoCD 설치

argocd-install.sh
bash
# 관리 클러스터에 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 staging

App-of-Apps 패턴

App-of-Apps 패턴은 ArgoCD의 핵심 관리 패턴입니다. 하나의 루트 Application이 다른 Application들을 관리하여, 전체 플랫폼을 하나의 진입점에서 제어합니다.

bootstrap/argocd/app-of-apps.yaml
yaml
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: true
platform/apps/kustomization.yaml
yaml
apiVersion: 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으로 정의합니다.

platform/apps/karpenter.yaml
yaml
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=true
Info

App-of-Apps 패턴에서 sync-wave 어노테이션을 활용하여 배포 순서를 제어합니다. 예를 들어, Kyverno(wave: 0)를 먼저 설치하고, 정책(wave: 1)을 적용한 후, 애플리케이션(wave: 2)을 배포하는 순서를 보장합니다.

2단계: Karpenter 설정

6장에서 다룬 NodePool과 EC2NodeClass를 프로덕션 환경에 맞게 구성합니다.

platform/base/karpenter/nodepool-general.yaml
yaml
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: 9h

3단계: 환경 프로모션 (Dev -> Staging -> Production)

ApplicationSet으로 멀티환경 배포

platform/apps/app-applicationset.yaml
yaml
apiVersion: 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

프로모션 워크플로우

Warning

프로덕션 배포는 반드시 수동 승인을 거쳐야 합니다. ApplicationSet에서 프로덕션 클러스터의 autoSync를 비활성화하고, ArgoCD RBAC으로 프로덕션 동기화 권한을 SRE/플랫폼 팀에만 부여하십시오.

4단계: Crossplane으로 클라우드 리소스 관리

8장에서 다룬 Crossplane으로 데이터베이스와 캐시를 프로비저닝합니다.

claims/production/database.yaml
yaml
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"

5단계: Kyverno 정책 적용

9장에서 다룬 Kyverno 정책을 플랫폼 수준에서 적용합니다.

platform/base/kyverno/policies/kustomization.yaml
yaml
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.yaml
platform/base/kyverno/policies/restrict-image-registries.yaml
yaml
apiVersion: 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/*"

6단계: 모니터링과 알림

Prometheus + Grafana 스택

platform/base/monitoring/helm-release.yaml
yaml
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: monitoring

핵심 알림 규칙

platform/base/monitoring/alerts.yaml
yaml
apiVersion: 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 운영 체크리스트

플랫폼 구축 후 안정적인 운영을 위해 정기적으로 수행해야 할 항목들입니다.

일간 점검

  • ArgoCD 대시보드에서 모든 Application의 Sync 상태 확인
  • Kyverno 정책 위반 로그 확인
  • 알림 채널에서 미처리 경고 검토

주간 점검

  • Goldilocks/VPA 권장값과 현재 리소스 설정 비교
  • Karpenter 노드 통합 현황 및 비용 리포트 확인
  • Crossplane Managed Resource 상태 확인 (드리프트 여부)
  • 미사용 리소스(PV, LoadBalancer, EIP) 정리

월간 점검

  • Kubernetes 버전 업데이트 검토
  • ArgoCD, Karpenter, Crossplane, Kyverno 버전 업데이트
  • RBAC 권한 감사 (불필요한 권한 회수)
  • 재해 복구(DR) 테스트 수행
  • 비용 트렌드 분석 및 최적화 계획 수립

분기 점검

  • 보안 감사 수행 (펜테스트, 취약점 스캔)
  • SLA/SLO 달성률 리뷰
  • 플랫폼 로드맵 업데이트
  • 사용자(개발팀) 만족도 조사
Tip

Day-2 운영 체크리스트를 Git 저장소에 이슈 템플릿으로 관리하면, 매 점검 주기마다 이슈를 생성하고 담당자를 지정하여 체계적으로 운영할 수 있습니다. 자동화할 수 있는 항목(비용 리포트, 드리프트 감지 등)은 CronJob이나 GitHub Actions로 자동화하십시오.

최종 아키텍처 요약

이 시리즈에서 구축한 GitOps 기반 Kubernetes 플랫폼의 핵심 구성 요소를 정리합니다.

영역도구역할시리즈 장
GitOpsArgoCD선언적 배포, App-of-Apps2장
노드 관리Karpenter자동 노드 프로비저닝, 비용 최적화6장
인프라 관리Crossplane클라우드 리소스 셀프서비스8장
정책 관리Kyverno보안 정책, 이미지 검증9장
비용 관리OpenCost + Goldilocks비용 가시성, 리소스 최적화7장
모니터링Prometheus + Grafana메트릭, 알림, 대시보드본 장
시크릿External Secrets Operator외부 시크릿 동기화9장
인증서cert-managerTLS 자동 발급본 장

시리즈 마무리

1장의 GitOps 기본 개념부터 시작하여, ArgoCD와 Flux의 심층 분석, 멀티클러스터 관리, 컨트롤러 패턴의 이해, Karpenter를 활용한 노드 관리, 비용 최적화, Crossplane을 통한 인프라 관리, 보안 정책, 그리고 이 모든 것을 통합한 실전 프로젝트까지 다루었습니다.

GitOps는 단순히 Git에서 배포하는 것이 아닙니다. 선언적 인프라 관리, 자동화된 조정 루프, 감사 가능한 변경 이력, 협업 기반의 운영 문화를 아우르는 종합적인 운영 패러다임입니다. 이 시리즈가 여러분의 Kubernetes 운영 수준을 한 단계 끌어올리는 데 도움이 되었기를 바랍니다.

Info

이 시리즈에서 다룬 모든 YAML 매니페스트와 설정은 참조용입니다. 실제 프로덕션 환경에 적용할 때는 조직의 보안 요구사항, 클라우드 환경, 팀 구조에 맞게 조정해야 합니다. 특히 RBAC 설정, 네트워크 정책, 리소스 제한은 환경에 따라 크게 달라질 수 있습니다.

이 글이 도움이 되셨나요?

관련 글

인프라

9장: 보안 강화와 정책 관리

OPA/Gatekeeper, Kyverno, Pod Security Standards, RBAC 모범 사례, External Secrets Operator, 공급망 보안(SLSA, Sigstore), 이미지 서명을 다룹니다.

2026년 6월 3일·11분
인프라

8장: Crossplane - 인프라를 코드로 관리하기

Crossplane의 아키텍처, Provider와 Managed Resource, XRD와 Composition을 활용한 인프라 추상화, GitOps 통합, Terraform과의 비교를 다룹니다.

2026년 5월 30일·12분
인프라

7장: 비용 최적화와 리소스 관리

Kubernetes 리소스 requests/limits 모범 사례, VPA/HPA 전략, Goldilocks, Kubecost/OpenCost, 스팟 인스턴스, 네임스페이스 쿼터, FinOps 실천법을 다룹니다.

2026년 5월 27일·14분
이전 글9장: 보안 강화와 정책 관리

댓글

목차

약 14분 남음
  • 프로젝트 아키텍처
    • 전체 구성도
    • 저장소 구조
  • 1단계: ArgoCD 부트스트랩
    • ArgoCD 설치
    • App-of-Apps 패턴
  • 2단계: Karpenter 설정
  • 3단계: 환경 프로모션 (Dev -> Staging -> Production)
    • ApplicationSet으로 멀티환경 배포
    • 프로모션 워크플로우
  • 4단계: Crossplane으로 클라우드 리소스 관리
  • 5단계: Kyverno 정책 적용
  • 6단계: 모니터링과 알림
    • Prometheus + Grafana 스택
    • 핵심 알림 규칙
  • Day-2 운영 체크리스트
    • 일간 점검
    • 주간 점검
    • 월간 점검
    • 분기 점검
  • 최종 아키텍처 요약
  • 시리즈 마무리