Triển khai Caddy qua Helm Chart với cấu hình tùy chỉnh
Chúng ta cần triển khai Caddy như một service trong cluster Kubernetes, cấu hình nó để lắng nghe trên cổng 443 và phục vụ lưu lượng HTTPS.
Tạo thư mục cấu hình và file values.yaml để override mặc định của Helm chart, đảm bảo Caddy chạy với quyền hạn cần thiết để truy cập Vault.
Đường dẫn: ./caddy/values.yaml
Nội dung hoàn chỉnh:
service:
type: LoadBalancer
ports:
- port: 443
targetPort: 443
protocol: TCP
name: https
image:
repository: caddy
tag: "2.8.4"
extraArgs:
- "--config"
- "/etc/caddy/Caddyfile"
resources:
limits:
cpu: "500m"
memory: "256Mi"
requests:
cpu: "100m"
memory: "128Mi"
volumes:
- name: caddy-config
configMap:
name: caddy-config
volumeMounts:
- name: caddy-config
mountPath: /etc/caddy
subPath: Caddyfile
Kết quả mong đợi: File values.yaml được tạo sẵn sàng để truyền vào lệnh Helm install, cấu hình Caddy để mount Caddyfile từ ConfigMap.
Triển khai Caddy bằng lệnh Helm, sử dụng namespace đã tạo ở phần trước.
helm install caddy -n pki-system --values ./caddy/values.yaml caddy/caddy
Kết quả mong đợi: Helm trả về thông báo "NAME: caddy" và trạng thái "deployed". Pod Caddy chuyển sang trạng thái Running.
Verify kết quả: Kiểm tra trạng thái pod và cổng dịch vụ.
kubectl get pod -n pki-system | grep caddy
kubectl get svc -n pki-system caddy
Kết quả mong đợi: Pod Caddy đang chạy (Running) và Service caddy đang lắng nghe trên cổng 443 với địa chỉ IP External (nếu dùng LoadBalancer) hoặc ClusterIP.
Cấu hình Caddy để liên kết với Vault PKI Engine qua API
Bước quan trọng nhất là cấu hình Caddy để nó biết cách lấy chứng chỉ từ Vault thay vì tự tạo (ACME) hoặc dùng chứng chỉ tĩnh. Chúng ta sẽ dùng cấu hình ACME trong Caddy nhưng chỉ định Vault làm backend.
Tạo ConfigMap chứa Caddyfile cấu hình kết nối đến Vault PKI Engine.
Đường dẫn: ./caddy/caddyfile.yaml (sẽ được tạo thành ConfigMap)
Nội dung hoàn chỉnh của file Caddyfile:
:443 {
reverse_proxy backend-service:80
# Cấu hình ACME để tự động lấy chứng chỉ từ Vault
acme_ca https://vault.pki-system.svc.cluster.local:8200/v1/pki_int/ca/pem
# Cấu hình để Caddy tự động yêu cầu chứng chỉ cho các domain cụ thể
# Lưu ý: Thay thế domain.example.com bằng domain thực tế của bạn
tls {
ca https://vault.pki-system.svc.cluster.local:8200/v1/pki_int/ca/pem
# Nếu muốn dùng chứng chỉ root của Vault làm CA cho internal
# hoặc dùng ACME CA của Vault để cấp phát
}
}
# Cấu hình backend service giả lập (để test traffic)
backend-service {
reverse_proxy 10.0.0.1:80
}
Kết quả mong đợi: File Caddyfile định nghĩa listener 443, proxy về backend và cấu hình ACME CA trỏ vào endpoint Vault PKI.
Tạo ConfigMap từ file Caddyfile vừa viết để Caddy có thể mount vào container.
kubectl create configmap caddy-config -n pki-system --from-file=Caddyfile=./caddy/Caddyfile
Kết quả mong đợi: ConfigMap "caddy-config" được tạo trong namespace pki-system.
Verify kết quả: Kiểm tra nội dung ConfigMap để đảm bảo Caddyfile đã được tạo đúng.
kubectl get configmap caddy-config -n pki-system -o yaml
Kết quả mong đợi: Output YAML hiển thị nội dung Caddyfile trong phần data.
Thiết lập chính sách Caddyfile để tự động yêu cầu và làm mới chứng chỉ
Để Caddy tự động yêu cầu chứng chỉ từ Vault, chúng ta cần cấu hình chính sách trong Caddyfile để kích hoạt quá trình "ACME Challenge" hoặc "Internal PKI" tùy thuộc vào kiến trúc. Ở đây, chúng ta sẽ cấu hình Caddy để tự động request chứng chỉ khi có request HTTPS đầu tiên.
Cập nhật Caddyfile để bao gồm cấu hình "tls" chi tiết hơn, chỉ định tên miền và cơ chế làm mới.
Đường dẫn: ./caddy/Caddyfile (Cập nhật nội dung)
Nội dung hoàn chỉnh:
:443 {
# Xác định domain cần cấp chứng chỉ
# Caddy sẽ tự động yêu cầu chứng chỉ cho domain này từ Vault
# Khi có request đầu tiên vào domain này
reverse_proxy backend-service:80
# Cấu hình ACME để tự động lấy chứng chỉ từ Vault
# Vault phải được cấu hình cho phép ACME CA hoặc Internal PKI
tls {
# Endpoint CA của Vault (PKI Engine)
ca https://vault.pki-system.svc.cluster.local:8200/v1/pki_int/ca/pem
# Cấu hình để Caddy tự động làm mới chứng chỉ trước khi hết hạn
# Caddy tự động làm mới khi còn 2/3 thời gian hạn
renewal window 8h
# Cấu hình để Caddy tự động yêu cầu chứng chỉ cho domain này
# Thay thế domain.example.com bằng domain thực tế
# Nếu dùng internal PKI, cần cấu hình Vault cho phép Caddy truy cập
# qua token hoặc mTLS
}
# Cấu hình để Caddy tự động yêu cầu chứng chỉ cho tất cả domain
# nếu không xác định rõ, cần cấu hình Vault cho phép wildcard
# hoặc cấu hình riêng cho từng domain
}
# Cấu hình backend service
backend-service {
reverse_proxy 10.0.0.1:80
}
Kết quả mong đợi: File Caddyfile cập nhật với các tham số renewal và ca cụ thể.
Áp dụng lại ConfigMap để Caddy nhận cấu hình mới.
kubectl create configmap caddy-config -n pki-system --from-file=Caddyfile=./caddy/Caddyfile --dry-run=client -o yaml | kubectl apply -f -
Kết quả mong đợi: ConfigMap được cập nhật (replaced).
Khởi động lại pod Caddy để áp dụng cấu hình mới.
kubectl rollout restart deployment caddy -n pki-system
Kết quả mong đợi: Pod Caddy được restart và quay lại trạng thái Running.
Verify kết quả: Kiểm tra log của Caddy để xem quá trình yêu cầu chứng chỉ.
kubectl logs -f deployment/caddy -n pki-system | grep -i "tls\|certificate\|acme"
Kết quả mong đợi: Log hiển thị thông báo Caddy đang kết nối đến Vault để yêu cầu chứng chỉ hoặc thông báo đã tải chứng chỉ thành công.
Cấu hình DNS và Load Balancer để định tuyến lưu lượng HTTPS về Caddy
Để hệ thống hoạt động từ bên ngoài cluster, cần cấu hình DNS trỏ vào IP của Load Balancer (nếu dùng cloud provider) hoặc cấu hình Ingress để định tuyến.
Lấy địa chỉ IP của Service LoadBalancer Caddy đã tạo ở phần 1.
kubectl get svc caddy -n pki-system
Kết quả mong đợi: Output hiển thị địa chỉ IP External (ví dụ: 35.198.100.10) hoặc "pending" nếu đang chờ cloud provider cấp IP.
Cấu hình DNS A record trỏ tên miền (ví dụ: pki.example.com) về địa chỉ IP này.
Trên hệ thống DNS của bạn (Cloud DNS, Route53, hoặc local dnsmasq), tạo bản ghi:
hostname: pki.example.com
type: A
value:
ttl: 300
Kết quả mong đợi: DNS resolution trả về đúng IP của Caddy Service.
Verify kết quả: Test kết nối HTTPS từ bên ngoài cluster đến Caddy.
curl -v https://pki.example.com
Kết quả mong đợi: Kết nối thành công, Caddy trả về chứng chỉ số đã lấy từ Vault. Nếu chưa cấu hình DNS, có thể dùng /etc/hosts để test:
echo " pki.example.com" | sudo tee -a /etc/hosts
curl -v https://pki.example.com
Kết quả mong đợi: Output của curl hiển thị "SSL connection using TLS" và chứng chỉ được xác thực (nếu Vault CA đã được tin cậy) hoặc cảnh báo "untrusted certificate" nếu chưa cấu hình CA root vào client.
Điều hướng series:
Mục lục: Series: Series: Xây dựng hệ thống quản lý mật mã và chứng chỉ số tự động (Automated PKI & Certificate Management) với HashiCorp Vault, Caddy và Kubernetes
« Phần 2: Triển khai và cấu hình HashiCorp Vault trong Kubernetes
Phần 4: Tích hợp Kubernetes và Vault để cấp phát chứng chỉ tự động »