LESSON 30分

「GitOps は単なるデプロイ手法じゃない。Git を唯一の真実の源として、インフラとアプリケーションの全ての状態を宣言的に管理する思想だ」と佐藤CTOが力を込めた。

推定読了時間: 30分


GitOps の4つの原則

原則説明
宣言的 (Declarative)システムの望ましい状態をコードで宣言する
バージョン管理 (Versioned)全ての変更は Git に記録される
自動適用 (Automated)承認された変更は自動的にシステムに適用される
継続的リコンサイル (Reconciled)実際の状態が宣言された状態と一致するよう継続監視
graph LR
    Dev([Developer])
    Git[(Git Repo)]
    Cluster{{Cluster}}
    Recon{Reconciliation Loop<br/>desired == actual?}

    Dev -- PR --> Git
    Git -- sync --> Cluster
    Cluster --> Recon
    Recon -. review .-> Git

    classDef devStyle fill:#4F46E5,stroke:#3730A3,color:#FFFFFF
    classDef gitStyle fill:#059669,stroke:#047857,color:#FFFFFF
    classDef clusterStyle fill:#D97706,stroke:#B45309,color:#FFFFFF
    classDef reconStyle fill:#DC2626,stroke:#B91C1C,color:#FFFFFF

    class Dev devStyle
    class Git gitStyle
    class Cluster clusterStyle
    class Recon reconStyle

Push 型 vs Pull 型

Push 型(従来の CI/CD)

graph LR
    CI([CI Pipeline])
    K8s{{Cluster}}

    CI -- "kubectl apply" --> K8s

    classDef ciStyle fill:#7C3AED,stroke:#6D28D9,color:#FFFFFF
    classDef k8sStyle fill:#D97706,stroke:#B45309,color:#FFFFFF

    class CI ciStyle
    class K8s k8sStyle
  • CI パイプラインがクラスタの認証情報を持つ
  • セキュリティリスクが高い
  • 外部からの変更を検知できない

Pull 型(GitOps)

graph LR
    Git[(Git Repo)]
    Agent([GitOps Agent])
    K8s{{Cluster}}

    Agent -- poll --> Git
    Agent -- apply --> K8s

    classDef gitStyle fill:#059669,stroke:#047857,color:#FFFFFF
    classDef agentStyle fill:#2563EB,stroke:#1D4ED8,color:#FFFFFF
    classDef k8sStyle fill:#D97706,stroke:#B45309,color:#FFFFFF

    class Git gitStyle
    class Agent agentStyle
    class K8s k8sStyle
  • エージェントがクラスタ内で動作
  • CI は Git リポジトリへの push のみ
  • ドリフト検出と自動修復

「Pull 型の最大のメリットは、クラスタの認証情報を外部に持ち出さなくて済むことだ」


ArgoCD

インストールと基本設定

# argocd-install.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: argocd
---
# Helm でインストール
# helm repo add argo https://argoproj.github.io/argo-helm
# helm install argocd argo/argo-cd -n argocd

Application マニフェスト

# argocd/applications/api-server.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: api-server
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/k8s-manifests.git
    targetRevision: main
    path: apps/api-server/overlays/production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true       # Gitから削除されたリソースを削除
      selfHeal: true     # 手動変更を自動修復
      allowEmpty: false
    syncOptions:
      - CreateNamespace=true
      - PrunePropagationPolicy=foreground
    retry:
      limit: 3
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

ApplicationSet(マルチクラスタ)

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: api-server-multi-cluster
  namespace: argocd
spec:
  generators:
    - clusters:
        selector:
          matchLabels:
            env: production
  template:
    metadata:
      name: "api-server-{{name}}"
    spec:
      project: default
      source:
        repoURL: https://github.com/myorg/k8s-manifests.git
        targetRevision: main
        path: "apps/api-server/overlays/{{metadata.labels.region}}"
      destination:
        server: "{{server}}"
        namespace: production
      syncPolicy:
        automated:
          prune: true
          selfHeal: true

Flux

GitRepository と Kustomization

# flux-system/sources/git-repo.yaml
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: app-manifests
  namespace: flux-system
spec:
  interval: 1m
  url: https://github.com/myorg/k8s-manifests.git
  ref:
    branch: main
  secretRef:
    name: git-credentials
---
# flux-system/kustomizations/api-server.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: api-server
  namespace: flux-system
spec:
  interval: 5m
  path: ./apps/api-server/overlays/production
  prune: true
  sourceRef:
    kind: GitRepository
    name: app-manifests
  healthChecks:
    - apiVersion: apps/v1
      kind: Deployment
      name: api-server
      namespace: production
  timeout: 3m
  retryInterval: 30s

HelmRelease

apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: ingress-nginx
  namespace: ingress-system
spec:
  interval: 10m
  chart:
    spec:
      chart: ingress-nginx
      version: "4.9.x"
      sourceRef:
        kind: HelmRepository
        name: ingress-nginx
        namespace: flux-system
  values:
    controller:
      replicaCount: 3
      resources:
        requests:
          cpu: 100m
          memory: 128Mi

リポジトリ構成パターン

Mono-repo パターン

graph TD
    Root["k8s-manifests/"]
    Apps["apps/"]
    Infra["infrastructure/"]
    Clusters["clusters/"]

    API["api-server/"]
    Web["web-frontend/"]

    APIBase["base/<br/>deployment.yaml<br/>service.yaml<br/>kustomization.yaml"]
    APIOverlays["overlays/<br/>development/<br/>staging/<br/>production/"]

    WebBase["base/"]
    WebOverlays["overlays/"]

    Ingress["ingress/"]
    Monitoring["monitoring/"]
    CertMgr["cert-manager/"]

    DevCluster["dev-cluster/"]
    StagingCluster["staging-cluster/"]
    ProdCluster["prod-cluster/"]

    Root --> Apps
    Root --> Infra
    Root --> Clusters

    Apps --> API
    Apps --> Web
    API --> APIBase
    API --> APIOverlays
    Web --> WebBase
    Web --> WebOverlays

    Infra --> Ingress
    Infra --> Monitoring
    Infra --> CertMgr

    Clusters --> DevCluster
    Clusters --> StagingCluster
    Clusters --> ProdCluster

    classDef rootStyle fill:#1E293B,stroke:#0F172A,color:#FFFFFF
    classDef dirStyle fill:#2563EB,stroke:#1D4ED8,color:#FFFFFF
    classDef subDirStyle fill:#7C3AED,stroke:#6D28D9,color:#FFFFFF
    classDef leafStyle fill:#059669,stroke:#047857,color:#FFFFFF

    class Root rootStyle
    class Apps,Infra,Clusters dirStyle
    class API,Web,Ingress,Monitoring,CertMgr subDirStyle
    class APIBase,APIOverlays,WebBase,WebOverlays,DevCluster,StagingCluster,ProdCluster leafStyle

Environment Promotion

# Kustomize overlay による環境差分管理
# apps/api-server/overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: production
resources:
  - ../../base
patches:
  - target:
      kind: Deployment
      name: api-server
    patch: |
      - op: replace
        path: /spec/replicas
        value: 4
      - op: replace
        path: /spec/template/spec/containers/0/resources/requests/memory
        value: "512Mi"
images:
  - name: my-registry/api-server
    newTag: v1.2.3

ドリフト検出と自動修復

graph TD
    subgraph ReconciliationLoop["Reconciliation Loop"]
        GitState([Git Desired State])
        Diff{"Diff<br/>Engine"}
        Heal([Auto-Heal<br/>selfHeal])
        Actual[(Actual Cluster State)]

        GitState --> Diff
        Diff --> Heal
        Actual --> Diff
    end

    classDef gitStyle fill:#059669,stroke:#047857,color:#FFFFFF
    classDef diffStyle fill:#D97706,stroke:#B45309,color:#FFFFFF
    classDef healStyle fill:#2563EB,stroke:#1D4ED8,color:#FFFFFF
    classDef actualStyle fill:#7C3AED,stroke:#6D28D9,color:#FFFFFF
    classDef subgraphStyle fill:#F1F5F9,stroke:#64748B,color:#1E293B

    class GitState gitStyle
    class Diff diffStyle
    class Heal healStyle
    class Actual actualStyle
    class ReconciliationLoop subgraphStyle
// ArgoCD のドリフト検出をSlackに通知
// argocd-notifications の設定
const notification = {
  trigger: "on-sync-status-unknown",
  template: {
    message: `
Application {{.app.metadata.name}} has drifted from desired state.
Details: {{.app.status.sync.status}}
Revision: {{.app.status.sync.revision}}
    `,
  },
  destination: {
    service: "slack",
    channel: "#infrastructure-alerts",
  },
};
ArgoCD Notifications 設定例
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
  namespace: argocd
data:
  service.slack: |
    token: $slack-token
  trigger.on-deployed: |
    - when: app.status.operationState.phase in ['Succeeded']
      send: [app-deployed]
  trigger.on-health-degraded: |
    - when: app.status.health.status == 'Degraded'
      send: [app-health-degraded]
  template.app-deployed: |
    slack:
      attachments: |
        [{
          "color": "#18be52",
          "title": "{{.app.metadata.name}} deployed",
          "text": "Revision: {{.app.status.sync.revision}}"
        }]
  template.app-health-degraded: |
    slack:
      attachments: |
        [{
          "color": "#E96D76",
          "title": "{{.app.metadata.name}} health degraded",
          "text": "{{.app.status.health.message}}"
        }]

ArgoCD vs Flux 比較

機能ArgoCDFlux
UIリッチなWeb UICLI中心
マルチクラスタApplicationSetKustomization
Helm サポートありHelmRelease CRD
通知argocd-notificationsAlert/Provider CRD
イメージ自動更新argocd-image-updaterImagePolicy/ImageRepository
RBACProject ベースKubernetes RBAC
学習コスト低~中

まとめ

概念説明
GitOpsGit を唯一の真実の源とする運用モデル
Pull 型デプロイエージェントが Git を監視して適用
宣言的管理望ましい状態をコードで定義
ドリフト検出実際の状態との乖離を自動検出
自動修復selfHeal で手動変更を自動で元に戻す
環境プロモーションKustomize overlay で環境差分を管理

チェックリスト

  • インフラの状態が Git リポジトリで管理されている
  • GitOps エージェント(ArgoCD/Flux)が導入されている
  • selfHeal が有効でドリフトが自動修復される
  • 環境ごとの差分は Kustomize overlay で管理されている
  • デプロイの承認フローが PR ベースで行われている
  • 通知が設定されデプロイ状況が可視化されている

次のステップへ

Step 1 の原則を理解したところで、演習とクイズで知識を定着させましょう。