SiamCafe.net Blog
Technology

Flux CD GitOps Event-Driven Design สร้าง GitOps Pipeline แบบ Event-Driven

flux cd gitops event driven design
Flux CD GitOps Event Driven Design | SiamCafe Blog
2025-10-12· อ. บอม — SiamCafe.net· 1,375 คำ

Flux CD ?????????????????????

Flux CD ???????????? GitOps toolkit ?????????????????? Kubernetes ????????????????????? sync ???????????????????????? cluster ??????????????????????????? configuration ??????????????????????????? Git repository ???????????? CNCF graduated project ????????????????????????????????????????????????????????? event-driven ?????????????????????????????????????????????????????????????????????????????? Git, container registries ????????? Helm repositories ???????????????????????????

Flux ?????????????????????????????? controllers ????????????????????? Source Controller ????????? manifests ????????? Git/Helm/OCI repositories, Kustomize Controller apply Kustomize overlays, Helm Controller ?????????????????? Helm releases, Notification Controller ????????? alerts ??????????????????????????? events, Image Automation Controller ?????????????????? image tags ???????????????????????????

Event-Driven Design ?????? Flux ?????????????????????????????? component ???????????????????????? reactive ??????????????? Git commit ?????????????????????????????? Source Controller ?????????????????? ???????????? trigger Kustomize/Helm Controller ????????? apply changes controller ????????????????????????????????????????????????????????? Kubernetes events ????????? conditions ??????????????? polling loop ????????????????????????????????????

????????????????????? Flux CD ?????? Kubernetes

Bootstrap Flux CD

# === Flux CD Installation ===

# 1. Install Flux CLI
curl -s https://fluxcd.io/install.sh | sudo bash

# Or via Homebrew:
brew install fluxcd/tap/flux

# Verify
flux --version
# flux version 2.3.0

# 2. Check Prerequisites
flux check --pre
# ??? Kubernetes 1.28.0 >=1.26.0-0
# ??? prerequisites checks passed

# 3. Bootstrap with GitHub
export GITHUB_TOKEN=ghp_xxxxxxxxxxxx

flux bootstrap github \
  --owner=myorg \
  --repository=fleet-infra \
  --branch=main \
  --path=clusters/production \
  --personal

# This creates:
# fleet-infra/
# ????????? clusters/
#     ????????? production/
#         ????????? flux-system/
#             ????????? gotk-components.yaml
#             ????????? gotk-sync.yaml
#             ????????? kustomization.yaml

# 4. Verify Installation
flux check
# ??? source-controller: deployment ready
# ??? kustomize-controller: deployment ready
# ??? helm-controller: deployment ready
# ??? notification-controller: deployment ready

kubectl get pods -n flux-system
# NAME                                       READY
# source-controller-xxx                      1/1
# kustomize-controller-xxx                   1/1
# helm-controller-xxx                        1/1
# notification-controller-xxx                1/1

# 5. Add Application Source
flux create source git myapp \
  --url=https://github.com/myorg/myapp \
  --branch=main \
  --interval=1m

# 6. Create Kustomization
flux create kustomization myapp \
  --source=GitRepository/myapp \
  --path="./k8s/production" \
  --prune=true \
  --interval=5m \
  --health-check="Deployment/myapp.default"

echo "Flux CD bootstrapped"

GitOps Workflow ????????? Flux

??????????????? GitOps workflow ??????????????????????????????

# === GitOps Repository Structure ===

# fleet-infra/
# ????????? clusters/
# ???   ????????? production/
# ???   ???   ????????? flux-system/
# ???   ???   ????????? infrastructure.yaml    # ??? infra sources
# ???   ???   ????????? apps.yaml              # ??? app sources
# ???   ????????? staging/
# ???       ????????? flux-system/
# ???       ????????? infrastructure.yaml
# ???       ????????? apps.yaml
# ????????? infrastructure/
# ???   ????????? controllers/
# ???   ???   ????????? cert-manager.yaml
# ???   ???   ????????? ingress-nginx.yaml
# ???   ???   ????????? monitoring.yaml
# ???   ????????? configs/
# ???       ????????? cluster-issuer.yaml
# ???       ????????? network-policies.yaml
# ????????? apps/
#     ????????? base/
#     ???   ????????? myapp/
#     ???   ???   ????????? deployment.yaml
#     ???   ???   ????????? service.yaml
#     ???   ???   ????????? hpa.yaml
#     ???   ???   ????????? kustomization.yaml
#     ???   ????????? api-gateway/
#     ????????? production/
#     ???   ????????? myapp/
#     ???       ????????? kustomization.yaml
#     ???       ????????? patch-replicas.yaml
#     ????????? staging/
#         ????????? myapp/
#             ????????? kustomization.yaml
#             ????????? patch-resources.yaml

# Infrastructure Kustomization
cat > clusters/production/infrastructure.yaml << 'EOF'
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: infrastructure-controllers
  namespace: flux-system
spec:
  interval: 1h
  retryInterval: 1m
  timeout: 5m
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./infrastructure/controllers
  prune: true
  wait: true
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: infrastructure-configs
  namespace: flux-system
spec:
  dependsOn:
    - name: infrastructure-controllers
  interval: 1h
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./infrastructure/configs
  prune: true
EOF

# Apps Kustomization
cat > clusters/production/apps.yaml << 'EOF'
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: apps
  namespace: flux-system
spec:
  dependsOn:
    - name: infrastructure-configs
  interval: 5m
  retryInterval: 2m
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./apps/production
  prune: true
  wait: true
  healthChecks:
    - apiVersion: apps/v1
      kind: Deployment
      name: myapp
      namespace: default
EOF

echo "GitOps workflow configured"

Event-Driven Architecture

Implement event-driven patterns ????????? Flux

#!/usr/bin/env python3
# event_driven_flux.py ??? Event-Driven Design Patterns
import json
import logging
from datetime import datetime
from typing import Dict, List

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("events")

class FluxEventDrivenDesign:
    def __init__(self):
        self.events = []
    
    def image_automation_flow(self):
        """Auto-update container images when new versions are pushed"""
        return {
            "flow": [
                "1. Developer pushes code ??? CI builds new image v1.2.3",
                "2. Image pushed to registry (ghcr.io/myorg/myapp:v1.2.3)",
                "3. Flux ImageRepository scans registry every 1m",
                "4. ImagePolicy selects latest semver tag",
                "5. ImageUpdateAutomation commits tag update to Git",
                "6. Source Controller detects Git change",
                "7. Kustomize Controller applies updated deployment",
                "8. Notification Controller sends Slack alert",
            ],
            "manifests": {
                "image_repository": {
                    "apiVersion": "image.toolkit.fluxcd.io/v1beta2",
                    "kind": "ImageRepository",
                    "metadata": {"name": "myapp", "namespace": "flux-system"},
                    "spec": {
                        "image": "ghcr.io/myorg/myapp",
                        "interval": "1m",
                    },
                },
                "image_policy": {
                    "apiVersion": "image.toolkit.fluxcd.io/v1beta2",
                    "kind": "ImagePolicy",
                    "metadata": {"name": "myapp", "namespace": "flux-system"},
                    "spec": {
                        "imageRepositoryRef": {"name": "myapp"},
                        "policy": {
                            "semver": {"range": ">=1.0.0"},
                        },
                    },
                },
            },
        }
    
    def webhook_receiver(self):
        """Trigger reconciliation via webhooks"""
        return {
            "receiver": {
                "apiVersion": "notification.toolkit.fluxcd.io/v1",
                "kind": "Receiver",
                "metadata": {"name": "github-webhook", "namespace": "flux-system"},
                "spec": {
                    "type": "github",
                    "events": ["ping", "push"],
                    "secretRef": {"name": "webhook-token"},
                    "resources": [
                        {"kind": "GitRepository", "name": "myapp", "namespace": "flux-system"},
                    ],
                },
            },
            "usage": "GitHub webhook ??? Flux Receiver ??? Immediate reconciliation (no polling delay)",
        }
    
    def progressive_delivery(self):
        """Canary deployment with Flagger"""
        return {
            "steps": [
                "1. New image detected by Flux",
                "2. Flagger creates canary deployment",
                "3. Route 10% traffic to canary",
                "4. Check metrics (success rate > 99%, latency < 500ms)",
                "5. Gradually increase to 20%, 50%, 80%, 100%",
                "6. Promote canary to primary",
                "7. Cleanup old version",
            ],
            "rollback_trigger": "Automatic if metrics fail threshold",
        }

design = FluxEventDrivenDesign()
flow = design.image_automation_flow()
print("Image Automation Flow:")
for step in flow["flow"]:
    print(f"  {step}")

webhook = design.webhook_receiver()
print(f"\nWebhook: {webhook['usage']}")

canary = design.progressive_delivery()
print(f"\nProgressive Delivery: {len(canary['steps'])} steps")

Notification ????????? Alerting

????????????????????? notifications ?????????????????? Flux events

# === Flux Notifications ===

# 1. Slack Provider
cat > notifications/slack-provider.yaml << 'EOF'
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Provider
metadata:
  name: slack
  namespace: flux-system
spec:
  type: slack
  channel: "#gitops-alerts"
  secretRef:
    name: slack-webhook
---
apiVersion: v1
kind: Secret
metadata:
  name: slack-webhook
  namespace: flux-system
stringData:
  address: "https://hooks.slack.com/services/xxx/yyy/zzz"
EOF

# 2. Alert for all Kustomizations
cat > notifications/alerts.yaml << 'EOF'
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Alert
metadata:
  name: on-call-alerts
  namespace: flux-system
spec:
  providerRef:
    name: slack
  eventSeverity: error
  eventSources:
    - kind: Kustomization
      name: "*"
    - kind: HelmRelease
      name: "*"
    - kind: GitRepository
      name: "*"
---
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Alert
metadata:
  name: info-alerts
  namespace: flux-system
spec:
  providerRef:
    name: slack
  eventSeverity: info
  eventSources:
    - kind: Kustomization
      name: apps
  inclusionList:
    - ".*reconciliation.*"
EOF

# 3. PagerDuty Provider for Critical
cat > notifications/pagerduty.yaml << 'EOF'
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Provider
metadata:
  name: pagerduty
  namespace: flux-system
spec:
  type: pagerduty
  channel: "ROUTING_KEY"
  secretRef:
    name: pagerduty-token
---
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Alert
metadata:
  name: critical-alerts
  namespace: flux-system
spec:
  providerRef:
    name: pagerduty
  eventSeverity: error
  eventSources:
    - kind: Kustomization
      name: "*"
      namespace: flux-system
  exclusionList:
    - ".*staging.*"
EOF

kubectl apply -f notifications/

# 4. Check Flux Events
flux events --for Kustomization/apps
flux logs --level=error

echo "Notifications configured"

Advanced Patterns ????????? Multi-Cluster

Multi-cluster GitOps patterns

#!/usr/bin/env python3
# multi_cluster.py ??? Multi-Cluster GitOps Patterns
import json
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("multicluster")

class MultiClusterGitOps:
    def __init__(self):
        self.clusters = []
    
    def architecture(self):
        return {
            "management_cluster": {
                "role": "Central management plane",
                "components": ["Flux controllers", "Secret management", "Policy engine"],
                "manages": ["staging", "production-us", "production-eu", "production-ap"],
            },
            "workload_clusters": {
                "staging": {"region": "us-east-1", "purpose": "Testing and QA"},
                "production-us": {"region": "us-west-2", "purpose": "US customers"},
                "production-eu": {"region": "eu-west-1", "purpose": "EU customers (GDPR)"},
                "production-ap": {"region": "ap-southeast-1", "purpose": "APAC customers"},
            },
            "repo_structure": {
                "fleet-infra/": {
                    "clusters/": {
                        "staging/": "Staging-specific overrides",
                        "production-us/": "US production config",
                        "production-eu/": "EU production + GDPR compliance",
                        "production-ap/": "APAC production config",
                    },
                    "infrastructure/": "Shared infra (cert-manager, nginx, monitoring)",
                    "apps/": {
                        "base/": "Base application manifests",
                        "overlays/": "Per-cluster Kustomize overlays",
                    },
                },
            },
        }
    
    def deployment_strategies(self):
        return {
            "rolling_across_clusters": {
                "description": "Deploy to staging ??? US ??? EU ??? AP sequentially",
                "mechanism": "Flux dependencies + health checks",
                "rollback": "Revert Git commit, Flux auto-rolls back",
            },
            "canary_per_cluster": {
                "description": "Each cluster runs its own canary analysis",
                "mechanism": "Flagger + Istio/Linkerd per cluster",
                "metrics": "Prometheus federated metrics",
            },
            "blue_green_global": {
                "description": "DNS-based blue/green across clusters",
                "mechanism": "External-DNS + weighted routing",
                "switch": "Update DNS weights to shift traffic",
            },
        }

mc = MultiClusterGitOps()
arch = mc.architecture()
print("Clusters managed:", list(arch["workload_clusters"].keys()))

strategies = mc.deployment_strategies()
for name, s in strategies.items():
    print(f"\n{name}: {s['description']}")

FAQ ??????????????????????????????????????????

Q: Flux CD ????????? ArgoCD ???????????????????????????????????????????

A: Flux CD ???????????? set of controllers ????????????????????????????????? headless ??????????????? UI (????????? CLI ???????????? Grafana dashboard) ??????????????????????????? composable ??????????????????????????????????????? controllers ?????????????????????????????? native Kubernetes CRDs ????????????????????? ?????????????????? multi-tenancy ?????? ArgoCD ?????? UI ?????????????????? ?????? deployment status, diff, rollback ????????????????????? Application-centric approach ??????????????????????????????????????????????????????????????? visual management ????????????????????????????????? CNCF projects ??????????????????????????? production ???????????????????????? team preference ??????????????????????????? CLI ????????? automation ??????????????? Flux ?????????????????????????????? UI ??????????????? ArgoCD

Q: Flux reconciliation ?????????????????????????????????????

A: Reconciliation ???????????? core loop ????????? Flux ????????? controller ?????? reconciliation loop ?????????????????? Source Controller ????????? source (Git/Helm/OCI) ????????? interval ???????????????????????? ????????????????????????????????????????????????????????? (new commit, new chart version) ????????????????????? artifact ???????????? Kustomize/Helm Controller ????????????????????? artifact ???????????? apply changes ???????????? cluster ????????????????????????????????? desired state (Git) ????????? actual state (cluster) ???????????????????????????????????? reconcile ??????????????????????????? ???????????????????????? event-driven ????????? poll ???????????????????????? webhook receiver ????????????????????? reconcile ?????????????????????????????? Git push

Q: ?????????????????????????????? cluster ?????????????????? (kubectl edit) ???????????????????????????????

A: Flux ?????? detect drift ??????????????? reconciliation ??????????????? ????????????????????? prune: true Flux ?????? revert ????????????????????????????????????????????????????????????????????? Git (desired state) ??????????????????????????????????????? GitOps ????????? Git ???????????? single source of truth ????????????????????????????????????????????? ??????????????????????????? Git ???????????? commit Flux ?????? apply ???????????????????????????????????? ??????????????????????????????????????????????????? ?????????????????? suspend Flux ???????????????????????? ??????????????? cluster ?????????????????? ???????????? commit changes ???????????? Git ?????????????????? ???????????????????????? resume Flux

Q: Secrets ????????????????????????????????????????????? GitOps?

A: ???????????????????????? plaintext secrets ?????? Git ?????????????????????????????? SOPS + age/KMS ???????????????????????? secrets ?????? Git Flux ?????????????????? SOPS decryption ??????????????? ??????????????????????????? Kustomization spec.decryption Sealed Secrets ????????? Bitnami Sealed Secrets encrypt secrets ???????????? public key decrypt ?????????????????????????????? cluster External Secrets Operator ????????? secrets ????????? AWS Secrets Manager, HashiCorp Vault, Azure Key Vault ???????????? cluster ??????????????????????????? ??????????????? SOPS ?????????????????????????????????????????? (????????????, native Flux support) External Secrets ?????????????????? enterprise (centralized, audit trail)

📖 บทความที่เกี่ยวข้อง

HTTP/3 QUIC Event Driven Designอ่านบทความ → Flux CD GitOps Service Level Objective SLOอ่านบทความ → Data Lakehouse Event Driven Designอ่านบทความ → Healthchecks.io Domain Driven Design DDDอ่านบทความ → oVirt Virtualization Event Driven Designอ่านบทความ →

📚 ดูบทความทั้งหมด →