Technology

Crossplane Composition Troubleshooting แก้ปัญหา

crossplane composition troubleshooting แกปญหา
Crossplane Composition Troubleshooting แก้ปัญหา | SiamCafe Blog
2025-11-13· อ. บอม — SiamCafe.net· 11,859 คำ

Crossplane Composition

Crossplane Composition Troubleshooting XRD XR Managed Resources Provider Kubernetes CRD GitOps Reconcile Self-healing Patches Functions Platform API

ConceptAbbreviationPurposeScopeCreated By
CompositeResourceDefinitionXRDDefine API SchemaClusterPlatform Team
CompositionN/AResource TemplateClusterPlatform Team
Composite ResourceXRDesired StateClusterDeveloper
ClaimXRCNamespaced XRNamespaceDeveloper
Managed ResourceMRActual Cloud ResourceClusterCrossplane

Common Issues

# === Crossplane Troubleshooting Commands ===

# Step 1: Check Provider Status
# kubectl get providers
# NAME                  INSTALLED   HEALTHY   PACKAGE                                AGE
# provider-aws          True        True      xpkg.upbound.io/upbound/provider-aws   5d

# Step 2: Check XRD
# kubectl get xrd
# NAME                              ESTABLISHED   OFFERED   AGE
# databases.platform.example.com    True          True      3d

# Step 3: Check Composition
# kubectl get composition
# kubectl describe composition database-aws

# Step 4: Check XR / Claim Status
# kubectl get composite
# kubectl describe database.platform.example.com my-database
# Look for:
#   Conditions:
#     Type: Ready    Status: True
#     Type: Synced   Status: True
#   Events:
#     Warning  ComposeResources  cannot compose resources: ...

# Step 5: Check Managed Resources
# kubectl get managed
# kubectl describe rdsinstance.rds.aws.upbound.io my-database-rds
# Look for:
#   Conditions:
#     Type: Ready    Status: False
#     Reason: Creating / ReconcileError

# Step 6: Check Crossplane Logs
# kubectl logs -n crossplane-system deploy/crossplane -f
# kubectl logs -n crossplane-system deploy/provider-aws -f

# Step 7: Check RBAC
# kubectl auth can-i create rdsinstances --as=system:serviceaccount:crossplane-system:provider-aws

from dataclasses import dataclass

@dataclass
class CrossplaneIssue:
    issue: str
    symptom: str
    check_command: str
    cause: str
    fix: str

issues = [
    CrossplaneIssue(
        "Provider Not Healthy",
        "Managed Resources not created",
        "kubectl get providers",
        "Wrong credentials or package version",
        "Check ProviderConfig credentials and package version"
    ),
    CrossplaneIssue(
        "XRD Not Established",
        "Cannot create XR or Claim",
        "kubectl get xrd",
        "Schema error in XRD spec",
        "Fix OpenAPI schema in XRD versions"
    ),
    CrossplaneIssue(
        "Composition Patch Error",
        "XR Ready=False Synced=False",
        "kubectl describe xr",
        "Wrong fieldPath in patches",
        "Fix fromFieldPath/toFieldPath paths"
    ),
    CrossplaneIssue(
        "MR ReconcileError",
        "Managed Resource stuck Creating",
        "kubectl describe managed",
        "AWS/Azure API error or permission",
        "Check Provider logs and IAM permissions"
    ),
    CrossplaneIssue(
        "MR Not Created",
        "No Managed Resources appear",
        "kubectl get managed",
        "Composition not matching XR",
        "Check compositionRef or compositionSelector labels"
    ),
]

print("=== Common Crossplane Issues ===")
for i in issues:
    print(f"  [{i.issue}]")
    print(f"    Symptom: {i.symptom}")
    print(f"    Check: {i.check_command}")
    print(f"    Cause: {i.cause}")
    print(f"    Fix: {i.fix}")

Composition Patches

# === Composition Patch Examples ===

# XRD — Database API
# apiVersion: apiextensions.crossplane.io/v1
# kind: CompositeResourceDefinition
# metadata:
#   name: databases.platform.example.com
# spec:
#   group: platform.example.com
#   names:
#     kind: Database
#     plural: databases
#   claimNames:
#     kind: DatabaseClaim
#     plural: databaseclaims
#   versions:
#     - name: v1alpha1
#       served: true
#       referenceable: true
#       schema:
#         openAPIV3Schema:
#           type: object
#           properties:
#             spec:
#               type: object
#               properties:
#                 region:
#                   type: string
#                   enum: [us-east-1, ap-southeast-1, eu-west-1]
#                 size:
#                   type: string
#                   enum: [small, medium, large]
#                 engine:
#                   type: string
#                   enum: [postgres, mysql]
#               required: [region, size, engine]

# Composition with Patches
# apiVersion: apiextensions.crossplane.io/v1
# kind: Composition
# metadata:
#   name: database-aws
#   labels:
#     provider: aws
# spec:
#   compositeTypeRef:
#     apiVersion: platform.example.com/v1alpha1
#     kind: Database
#   resources:
#     - name: rds-instance
#       base:
#         apiVersion: rds.aws.upbound.io/v1beta1
#         kind: Instance
#         spec:
#           forProvider:
#             engine: postgres
#             engineVersion: "15"
#             instanceClass: db.t3.micro
#             allocatedStorage: 20
#       patches:
#         - type: FromCompositeFieldPath
#           fromFieldPath: spec.region
#           toFieldPath: spec.forProvider.region
#         - type: FromCompositeFieldPath
#           fromFieldPath: spec.size
#           toFieldPath: spec.forProvider.instanceClass
#           transforms:
#             - type: map
#               map:
#                 small: db.t3.micro
#                 medium: db.t3.medium
#                 large: db.t3.large
#         - type: FromCompositeFieldPath
#           fromFieldPath: spec.engine
#           toFieldPath: spec.forProvider.engine

@dataclass
class PatchType:
    patch_type: str
    direction: str
    use_case: str
    example: str

patch_types = [
    PatchType("FromCompositeFieldPath", "XR → MR", "ส่งค่าจาก Claim ไป Resource", "spec.region → spec.forProvider.region"),
    PatchType("ToCompositeFieldPath", "MR → XR", "ส่ง Status กลับ XR", "status.endpoint → status.address"),
    PatchType("CombineFromComposite", "XR(multi) → MR", "รวมค่าหลายตัว", "name+env → resource name"),
    PatchType("FromEnvironmentFieldPath", "Env → MR", "ค่าจาก Environment Config", "env.vpcId → spec.forProvider.vpcId"),
    PatchType("Transform: map", "Value mapping", "แปลงค่า", "small → db.t3.micro"),
    PatchType("Transform: convert", "Type conversion", "แปลง Type", "string → int"),
]

print("\n=== Patch Types ===")
for p in patch_types:
    print(f"  [{p.patch_type}] {p.direction}")
    print(f"    Use Case: {p.use_case}")
    print(f"    Example: {p.example}")

Production Operations

# === Production Crossplane Operations ===

# Health Check Script
# #!/bin/bash
# echo "=== Provider Status ==="
# kubectl get providers -o wide
# echo "=== XRD Status ==="
# kubectl get xrd
# echo "=== Unhealthy XRs ==="
# kubectl get composite -A -o json | jq '.items[] | select(.status.conditions[] | select(.type=="Ready" and .status!="True")) | .metadata.name'
# echo "=== Unhealthy MRs ==="
# kubectl get managed -o json | jq '.items[] | select(.status.conditions[] | select(.type=="Ready" and .status!="True")) | .metadata.name'

@dataclass
class OperationalCheck:
    check: str
    command: str
    expected: str
    frequency: str
    alert: str

checks = [
    OperationalCheck("Providers Healthy", "kubectl get providers", "All HEALTHY=True", "1 min", "Critical if unhealthy"),
    OperationalCheck("XRDs Established", "kubectl get xrd", "All ESTABLISHED=True", "5 min", "Critical if not"),
    OperationalCheck("XR Ready", "kubectl get composite", "All READY=True", "1 min", "Warning if not ready > 5m"),
    OperationalCheck("MR Synced", "kubectl get managed", "All SYNCED=True", "1 min", "Warning if not synced > 10m"),
    OperationalCheck("Crossplane Pods", "kubectl get pods -n crossplane-system", "All Running", "30 sec", "Critical if not running"),
    OperationalCheck("Provider Logs", "kubectl logs deploy/provider-aws", "No ERROR lines", "Real-time", "Critical on errors"),
]

print("Production Health Checks:")
for c in checks:
    print(f"  [{c.check}]")
    print(f"    Command: {c.command}")
    print(f"    Expected: {c.expected} | Freq: {c.frequency}")
    print(f"    Alert: {c.alert}")

best_practices = {
    "Version Pin": "Pin Provider และ Crossplane version ใน Production",
    "Composition Test": "Test Composition ใน Staging ก่อน Production",
    "RBAC": "Least privilege สำหรับ Provider ServiceAccount",
    "GitOps": "ใช้ ArgoCD/Flux จัดการ XRD Composition",
    "Monitoring": "Prometheus metrics สำหรับ Crossplane",
    "Backup": "Backup XRD Composition ทุกวัน",
    "Drift Detection": "ตรวจสอบ Drift ระหว่าง Desired กับ Actual",
}

print(f"\n\nBest Practices:")
for k, v in best_practices.items():
    print(f"  [{k}]: {v}")

เคล็ดลับ

Crossplane คืออะไร

Open Source Kubernetes Cloud Infrastructure CRD Provider AWS Azure GCP Composition GitOps Reconcile Self-healing Terraform Alternative

Composition คืออะไร

Template XR Managed Resources RDS Security Group Subnet Patches ส่งค่า Functions Logic Platform API Developer สร้าง Claim

Troubleshoot Crossplane อย่างไร

Provider Status XRD Established Composition Events XR Conditions Ready Synced Managed Resources Logs RBAC Permission

Patch ใน Composition ทำงานอย่างไร

FromCompositeFieldPath XR→MR ToCompositeFieldPath MR→XR CombineFromComposite Transform Map Convert Policy Required

สรุป

Crossplane Composition Troubleshooting XRD XR Managed Resources Provider Patches Transform GitOps Reconcile Self-healing Production Operations Kubernetes

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

Vue Pinia Store Troubleshooting แก้ปัญหาอ่านบทความ → Crossplane Composition Freelance IT Careerอ่านบทความ → Crossplane Composition Low Code No Codeอ่านบทความ → WebSocket Scaling Troubleshooting แก้ปัญหาอ่านบทความ → Crossplane Composition Cache Strategy Redisอ่านบทความ →

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