Crossplane CQRS Event Sourcing

Crossplane Composition CQRS Event Sourcing Kubernetes Infrastructure Cloud AWS Azure GCP GitOps ArgoCD Audit Trail Production

PatternPurposeImplementationBenefit
Crossplane Compositionรวม Resources เป็น TemplateXRD + Composition YAMLSelf-service Reusable
CQRSแยก Read/WriteCommand API + Query APIScale แยก Optimize แยก
Event Sourcingเก็บทุก EventEvent Store (PG/Kafka)Audit Time Travel Debug
GitOpsGit เป็น Source of TruthArgoCD + Git RepositoryVersion Control Review

Crossplane Composition

# === Crossplane Composition Example ===

# CompositeResourceDefinition (XRD)
# apiVersion: apiextensions.crossplane.io/v1
# kind: CompositeResourceDefinition
# metadata:
#   name: xdatabases.platform.example.com
# spec:
#   group: platform.example.com
#   names:
#     kind: XDatabase
#     plural: xdatabases
#   claimNames:
#     kind: Database
#     plural: databases
#   versions:
#     - name: v1alpha1
#       schema:
#         openAPIV3Schema:
#           type: object
#           properties:
#             spec:
#               type: object
#               properties:
#                 engine: { type: string, enum: [postgres, mysql] }
#                 size: { type: string, enum: [small, medium, large] }
#                 region: { type: string }

# Composition
# apiVersion: apiextensions.crossplane.io/v1
# kind: Composition
# metadata:
#   name: xdatabase-aws
# spec:
#   compositeTypeRef:
#     apiVersion: platform.example.com/v1alpha1
#     kind: XDatabase
#   resources:
#     - name: rds-instance
#       base:
#         apiVersion: rds.aws.upbound.io/v1beta1
#         kind: Instance
#         spec:
#           forProvider:
#             engine: postgres
#             instanceClass: db.t3.medium
#             allocatedStorage: 20

from dataclasses import dataclass

@dataclass
class CompositionResource:
    claim_param: str
    small: str
    medium: str
    large: str

sizes = [
    CompositionResource("Instance Class",
        "db.t3.micro (2 vCPU 1GB)",
        "db.t3.medium (2 vCPU 4GB)",
        "db.r6g.large (2 vCPU 16GB)"),
    CompositionResource("Storage",
        "20GB gp3",
        "100GB gp3",
        "500GB io2"),
    CompositionResource("Backup Retention",
        "7 days",
        "14 days",
        "30 days"),
    CompositionResource("Multi-AZ",
        "false (Single AZ)",
        "true (Multi-AZ)",
        "true (Multi-AZ + Read Replica)"),
    CompositionResource("Monitoring",
        "Basic (CloudWatch)",
        "Enhanced (60s interval)",
        "Enhanced (1s) + Performance Insights"),
]

print("=== Database Composition Sizes ===")
for s in sizes:
    print(f"  [{s.claim_param}]")
    print(f"    Small: {s.small}")
    print(f"    Medium: {s.medium}")
    print(f"    Large: {s.large}")

CQRS + Event Sourcing

# === CQRS Event Sourcing for Infrastructure ===

# Event Types
# @dataclass
# class InfraEvent:
#     event_id: str
#     resource_id: str
#     event_type: str
#     payload: dict
#     user: str
#     timestamp: datetime
#
# events = [
#     InfraEvent("evt-001", "db-prod-01", "ResourceCreated",
#         {"engine": "postgres", "size": "medium", "region": "ap-southeast-1"},
#         "dev-team", datetime(2025,1,15,10,0)),
#     InfraEvent("evt-002", "db-prod-01", "ResourceScaled",
#         {"old_size": "medium", "new_size": "large", "reason": "traffic spike"},
#         "platform-team", datetime(2025,1,20,14,30)),
# ]

@dataclass
class EventType:
    event: str
    trigger: str
    payload: str
    read_model_update: str

events = [
    EventType("ResourceCreated",
        "Claim สร้างใหม่ → Crossplane สร้าง Resources",
        "resource_id engine size region team",
        "เพิ่ม Resource ใน Inventory + Dashboard"),
    EventType("ResourceUpdated",
        "Claim แก้ไข → Crossplane อัพเดท Resources",
        "resource_id old_config new_config changed_by",
        "อัพเดท Config History + Timeline"),
    EventType("ResourceScaled",
        "Scale Request → Composition Patch",
        "resource_id old_size new_size reason",
        "อัพเดท Capacity Dashboard + Cost"),
    EventType("ResourceFailed",
        "Crossplane detect Resource unhealthy",
        "resource_id error_message severity",
        "อัพเดท Health Dashboard + Alert"),
    EventType("DriftDetected",
        "Crossplane detect Configuration Drift",
        "resource_id expected_state actual_state",
        "อัพเดท Compliance Dashboard + Alert"),
    EventType("ResourceDeleted",
        "Claim ลบ → Crossplane ลบ Resources",
        "resource_id deleted_by reason",
        "ลบจาก Inventory + Archive Event"),
]

print("=== Infrastructure Events ===")
for e in events:
    print(f"  [{e.event}] Trigger: {e.trigger}")
    print(f"    Payload: {e.payload}")
    print(f"    Read Model: {e.read_model_update}")

Production Architecture

# === Production Stack ===

@dataclass
class ArchComponent:
    component: str
    tool: str
    role: str
    scaling: str

architecture = [
    ArchComponent("GitOps",
        "ArgoCD + Git Repository",
        "Source of Truth สำหรับ Crossplane Compositions Claims",
        "ArgoCD HA 3 replicas"),
    ArchComponent("Control Plane",
        "Crossplane + Providers",
        "Reconcile Claims → Cloud Resources",
        "Crossplane Pods HA + Provider Pods"),
    ArchComponent("Event Capture",
        "Custom Controller (Kubebuilder)",
        "Watch Crossplane Resources → Publish Events",
        "Controller HA 2 replicas"),
    ArchComponent("Event Store",
        "Apache Kafka (3 brokers)",
        "Store Infrastructure Events Durable Ordered",
        "Kafka Cluster 3+ brokers"),
    ArchComponent("Read Model",
        "PostgreSQL + Materialized Views",
        "Optimized Read Model สำหรับ Dashboard API",
        "PostgreSQL HA Primary + Replica"),
    ArchComponent("Dashboard",
        "Grafana + Custom UI (React)",
        "Infrastructure Inventory Timeline Audit Compliance",
        "Grafana HA + CDN for UI"),
]

print("=== Production Architecture ===")
for a in architecture:
    print(f"  [{a.component}] Tool: {a.tool}")
    print(f"    Role: {a.role}")
    print(f"    Scale: {a.scaling}")

เคล็ดลับ

  • Composition: สร้าง Composition Template สำหรับทุก Resource ที่ใช้บ่อย
  • Claim: ให้ Developer ใช้ Claim ไม่ต้องรู้ Implementation
  • Events: เก็บทุก Event ใน Kafka สำหรับ Audit Trail
  • GitOps: ใช้ ArgoCD Sync Crossplane Resources จาก Git
  • Drift: ตรวจ Drift อัตโนมัติ Alert เมื่อ State ไม่ตรง

Crossplane คืออะไร

Open Source IaC Kubernetes API Cloud AWS Azure GCP Providers Compositions XRD Claim Self-service GitOps ArgoCD Multi-cloud