Technology

Certificate Manager Infrastructure as Code

certificate manager infrastructure as code
Certificate Manager Infrastructure as Code | SiamCafe Blog
2025-06-27· อ. บอม — SiamCafe.net· 8,735 คำ

Certificate Manager IaC

cert-manager Kubernetes TLS Certificate Let's Encrypt Terraform Vault PKI GitOps Issuer ClusterIssuer Wildcard DNS-01 HTTP-01 Automation Renewal

ToolPlatformAuto-renewIaC Supportเหมาะกับ
cert-managerKubernetesใช่YAML/HelmK8s Native
Terraform + ACMEAnyต้อง CI/CDHCLMulti-platform
AWS ACMAWSใช่Terraform/CDKAWS Only
Vault PKIAnyใช่TerraformInternal CA

cert-manager Setup

# === cert-manager Installation ===

# Helm Install
# helm repo add jetstack https://charts.jetstack.io
# helm repo update
# helm install cert-manager jetstack/cert-manager \
#   --namespace cert-manager \
#   --create-namespace \
#   --set installCRDs=true \
#   --set prometheus.enabled=true

# ClusterIssuer — Let's Encrypt Production
# apiVersion: cert-manager.io/v1
# kind: ClusterIssuer
# metadata:
#   name: letsencrypt-prod
# spec:
#   acme:
#     server: https://acme-v02.api.letsencrypt.org/directory
#     email: admin@example.com
#     privateKeySecretRef:
#       name: letsencrypt-prod-key
#     solvers:
#       - http01:
#           ingress:
#             class: nginx
#       - dns01:
#           cloudflare:
#             email: admin@example.com
#             apiTokenSecretRef:
#               name: cloudflare-api-token
#               key: api-token
#         selector:
#           dnsZones:
#             - "example.com"

# Certificate Resource
# apiVersion: cert-manager.io/v1
# kind: Certificate
# metadata:
#   name: app-tls
#   namespace: production
# spec:
#   secretName: app-tls-secret
#   issuerRef:
#     name: letsencrypt-prod
#     kind: ClusterIssuer
#   dnsNames:
#     - app.example.com
#     - api.example.com
#   duration: 2160h    # 90 days
#   renewBefore: 720h  # 30 days before

from dataclasses import dataclass
from typing import List

@dataclass
class CertStatus:
    name: str
    domains: List[str]
    issuer: str
    expiry_days: int
    auto_renew: bool
    status: str

certs = [
    CertStatus("app-tls", ["app.example.com"], "letsencrypt-prod", 62, True, "Ready"),
    CertStatus("api-tls", ["api.example.com"], "letsencrypt-prod", 45, True, "Ready"),
    CertStatus("wildcard-tls", ["*.example.com"], "letsencrypt-prod", 30, True, "Renewing"),
    CertStatus("internal-tls", ["db.internal"], "vault-pki", 180, True, "Ready"),
    CertStatus("staging-tls", ["*.staging.example.com"], "letsencrypt-staging", 88, True, "Ready"),
]

print("=== Certificate Status ===")
for c in certs:
    domains = ", ".join(c.domains)
    alert = "WARN" if c.expiry_days < 31 else "OK"
    print(f"  [{alert}] {c.name} — {c.status}")
    print(f"    Domains: {domains} | Issuer: {c.issuer} | Expires: {c.expiry_days}d")

Terraform Integration

# === Terraform Certificate Management ===

# Terraform — Deploy cert-manager
# resource "helm_release" "cert_manager" {
#   name       = "cert-manager"
#   repository = "https://charts.jetstack.io"
#   chart      = "cert-manager"
#   namespace  = "cert-manager"
#   version    = "1.14.0"
#
#   set { name = "installCRDs"; value = "true" }
#   set { name = "prometheus.enabled"; value = "true" }
# }

# Terraform — ClusterIssuer
# resource "kubernetes_manifest" "letsencrypt_issuer" {
#   manifest = {
#     apiVersion = "cert-manager.io/v1"
#     kind       = "ClusterIssuer"
#     metadata   = { name = "letsencrypt-prod" }
#     spec = {
#       acme = {
#         server = "https://acme-v02.api.letsencrypt.org/directory"
#         email  = var.admin_email
#         privateKeySecretRef = { name = "letsencrypt-prod-key" }
#         solvers = [{
#           dns01 = {
#             route53 = { region = var.aws_region }
#           }
#         }]
#       }
#     }
#   }
# }

# Terraform — AWS ACM Certificate
# resource "aws_acm_certificate" "main" {
#   domain_name       = "example.com"
#   validation_method = "DNS"
#   subject_alternative_names = ["*.example.com"]
#
#   lifecycle { create_before_destroy = true }
# }
#
# resource "aws_route53_record" "cert_validation" {
#   for_each = {
#     for dvo in aws_acm_certificate.main.domain_validation_options :
#     dvo.domain_name => dvo
#   }
#   name    = each.value.resource_record_name
#   type    = each.value.resource_record_type
#   zone_id = aws_route53_zone.main.zone_id
#   records = [each.value.resource_record_value]
#   ttl     = 60
# }

infra_components = {
    "cert-manager Helm": "Deploy cert-manager to K8s cluster",
    "ClusterIssuer": "Configure Let's Encrypt ACME issuer",
    "IAM Role": "DNS validation permissions for Route53",
    "Secret": "Store API tokens for DNS providers",
    "Certificate CRD": "Define certificates per service",
    "Ingress Annotation": "Auto-provision TLS for Ingress",
    "Monitoring": "Prometheus alerts for cert expiry",
}

print("\nTerraform Components:")
for comp, desc in infra_components.items():
    print(f"  [{comp}]: {desc}")

GitOps และ Monitoring

# === GitOps Certificate Management ===

# Git Repo Structure
# certificates/
# ├── base/
# │   ├── cert-manager-helm.yaml
# │   ├── cluster-issuer-prod.yaml
# │   └── cluster-issuer-staging.yaml
# ├── production/
# │   ├── app-certificate.yaml
# │   ├── api-certificate.yaml
# │   └── wildcard-certificate.yaml
# ├── staging/
# │   └── staging-certificate.yaml
# └── monitoring/
#     └── prometheus-rules.yaml

# Prometheus Alert Rules
# groups:
#   - name: cert-manager
#     rules:
#       - alert: CertExpiringSoon
#         expr: certmanager_certificate_expiration_timestamp_seconds
#               - time() < 86400 * 14
#         for: 1h
#         labels: { severity: warning }
#         annotations:
#           summary: "Certificate {{ $labels.name }} expires in < 14 days"
#       - alert: CertNotReady
#         expr: certmanager_certificate_ready_status{condition="False"} == 1
#         for: 15m
#         labels: { severity: critical }

# Grafana Dashboard Queries
# - Certificate count: count(certmanager_certificate_ready_status)
# - Expiring soon: count(certmanager_certificate_expiration_timestamp_seconds - time() < 86400*30)
# - Renewal rate: rate(certmanager_certificate_renewal_timestamp_seconds[24h])

monitoring = {
    "Total Certificates": "12 managed",
    "Ready": "11 (91.7%)",
    "Renewing": "1",
    "Expiring < 30d": "1",
    "Failed Renewals (30d)": "0",
    "Avg Renewal Time": "45 seconds",
    "Issuers": "2 (LE Prod + Vault PKI)",
}

print("Certificate Monitoring:")
for k, v in monitoring.items():
    print(f"  {k}: {v}")

# Best Practices
practices = [
    "ใช้ ClusterIssuer แทน Issuer สำหรับ Cluster-wide",
    "ตั้ง renewBefore 30 วัน ไม่ใช่ 7 วัน",
    "ใช้ DNS-01 Challenge สำหรับ Wildcard",
    "Monitor cert expiry ด้วย Prometheus",
    "เก็บ Certificate Config ใน Git ทั้งหมด",
    "ใช้ Vault PKI สำหรับ Internal Services",
    "ทดสอบกับ Let's Encrypt Staging ก่อน Production",
]

print(f"\n\nBest Practices:")
for i, p in enumerate(practices, 1):
    print(f"  {i}. {p}")

เคล็ดลับ

Best Practices สำหรับนักพัฒนา

การเขียนโค้ดที่ดีไม่ใช่แค่ทำให้โปรแกรมทำงานได้ แต่ต้องเขียนให้อ่านง่าย ดูแลรักษาง่าย และ Scale ได้ หลัก SOLID Principles เป็นพื้นฐานสำคัญที่นักพัฒนาทุกู้คืนควรเข้าใจ ได้แก่ Single Responsibility ที่แต่ละ Class ทำหน้าที่เดียว Open-Closed ที่เปิดให้ขยายแต่ปิดการแก้ไข Liskov Substitution ที่ Subclass ต้องใช้แทน Parent ได้ Interface Segregation ที่แยก Interface ให้เล็ก และ Dependency Inversion ที่พึ่งพา Abstraction ไม่ใช่ Implementation

เรื่อง Testing ก็ขาดไม่ได้ ควรเขียน Unit Test ครอบคลุมอย่างน้อย 80% ของ Code Base ใช้ Integration Test ทดสอบการทำงานร่วมกันของ Module ต่างๆ และ E2E Test สำหรับ Critical User Flow เครื่องมือยอดนิยมเช่น Jest, Pytest, JUnit ช่วยให้การเขียน Test เป็นเรื่องง่าย

เรื่อง Version Control ด้วย Git ใช้ Branch Strategy ที่เหมาะกับทีม เช่น Git Flow สำหรับโปรเจคใหญ่ หรือ Trunk-Based Development สำหรับทีมที่ Deploy บ่อย ทำ Code Review ทุก Pull Request และใช้ CI/CD Pipeline ทำ Automated Testing และ Deployment

cert-manager คืออะไร

K8s Operator TLS Certificate อัตโนมัติ Let's Encrypt Vault Helm CRD Issuer ClusterIssuer ต่ออายุอัตโนมัติ Secret Ingress

ทำไมต้องจัดการ Certificate ด้วย IaC

Cert Expiry Outage IaC Code Version Control Git Audit Trail Automation Reproducible GitOps ArgoCD Testing ก่อน Production

cert-manager กับ Terraform ใช้ร่วมกันอย่างไร

Terraform สร้าง Infra DNS K8s cert-manager จัดการ Cert Helm Provider ClusterIssuer IAM Role DNS Validation ร่วมกัน

Wildcard กับ Per-domain Certificate เลือกอย่างไร

Wildcard ทุก Subdomain ง่าย DNS-01 Leaked ทุกตัวโดน Per-domain แยก Service ปลอดภัย HTTP-01 Revoke ทีละตัว แนะนำ Per-domain

สรุป

cert-manager Kubernetes TLS Certificate Let's Encrypt Terraform Vault PKI IaC GitOps ClusterIssuer DNS-01 HTTP-01 Wildcard Prometheus Monitoring Auto-renewal Helm ArgoCD

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

Certificate Manager CDN Configurationอ่านบทความ → Cloudflare Low Code No Codeอ่านบทความ → Certificate Manager Schema Evolutionอ่านบทความ → Certificate Manager CI CD Automation Pipelineอ่านบทความ → Certificate Manager Tech Conference 2026อ่านบทความ →

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