99 Ngày Spring — Ngày 95: Deploy lên Kubernetes
Kubernetes nhận một mô tả trạng thái mong muốn, ví dụ ba bản sao của image này, rồi liên tục kéo thực tế về trạng thái đó. Với Spring Boot, phần việc chính là cho Kubernetes biết khi nào ứng dụng sống, khi nào sẵn sàng nhận request, và tắt ứng dụng sao cho không rớt request đang xử lý.

1. Deployment, Service và Ingress
Deployment quản lý các pod chạy cùng một image và thay chúng dần khi có phiên bản mới. Service cấp một địa chỉ ổn định và cân bằng tải tới các pod đang sẵn sàng. Ingress đưa HTTP từ ngoài cluster vào Service. Luôn khai báo requests và limits về tài nguyên: scheduler dựa vào requests để xếp pod, và JVM dựa vào limit bộ nhớ để tính kích thước heap.
apiVersion: apps/v1
kind: Deployment
metadata: { name: orders }
spec:
replicas: 3
selector: { matchLabels: { app: orders } }
template:
metadata: { labels: { app: orders } }
spec:
containers:
- name: orders
image: ghcr.io/motdev/orders:3f9c2ab
ports: [{ containerPort: 8080 }]
envFrom:
- configMapRef: { name: orders-config }
- secretRef: { name: orders-secrets }
resources:
requests: { cpu: 250m, memory: 512Mi }
limits: { memory: 768Mi }2. Probe từ Actuator
Spring Boot tự bật hai nhóm health khi chạy trên Kubernetes: /actuator/health/liveness và /actuator/health/readiness. Liveness trả lời ứng dụng có bị kẹt không; thất bại thì pod bị khởi động lại. Readiness trả lời có nên gửi request tới pod này không; thất bại thì pod bị rút khỏi Service nhưng không bị giết. Đừng đưa kiểm tra database vào liveness: database chết sẽ làm mọi pod bị khởi động lại liên tục mà không giải quyết được gì.
startupProbe:
httpGet: { path: /actuator/health/liveness, port: 8080 }
periodSeconds: 5
failureThreshold: 30 # up to 150s to start
livenessProbe:
httpGet: { path: /actuator/health/liveness, port: 8080 }
periodSeconds: 10
readinessProbe:
httpGet: { path: /actuator/health/readiness, port: 8080 }
periodSeconds: 53. ConfigMap và Secret
ConfigMap chứa cấu hình không nhạy cảm, Secret chứa phần nhạy cảm; cả hai đưa vào pod dưới dạng biến môi trường hoặc file được mount. Đây chính là cấu hình từ môi trường của ngày 91, nên cùng một image chạy được ở mọi namespace. Lưu ý Secret của Kubernetes mặc định chỉ được mã hóa base64: cần bật mã hóa lúc lưu và phân quyền RBAC, hoặc đồng bộ từ một secret manager bên ngoài.
apiVersion: v1
kind: ConfigMap
metadata: { name: orders-config }
data:
SPRING_PROFILES_ACTIVE: prod
PAYMENT_BASE_URL: https://pay.internal.example
SERVER_SHUTDOWN: graceful
SPRING_LIFECYCLE_TIMEOUT_PER_SHUTDOWN_PHASE: 25s4. Rolling update không rớt request
Khi thay pod, Kubernetes gửi SIGTERM rồi chờ terminationGracePeriodSeconds trước khi giết hẳn. Với server.shutdown=graceful, Spring Boot ngừng nhận request mới và chờ các request đang chạy hoàn tất trong thời hạn đã đặt. Thời hạn đó phải ngắn hơn thời gian chờ của Kubernetes. Kết hợp với readiness probe và maxUnavailable bằng 0, luôn có đủ pod sẵn sàng trong suốt quá trình cập nhật.
Dùng tag image bất biến; không dùng latest.
Chạy ít nhất hai bản sao và trải chúng trên nhiều node.
Đặt limit bộ nhớ; cân nhắc không đặt limit CPU để tránh bị bóp lúc khởi động.
Xem kubectl rollout status sau mỗi lần triển khai và biết lệnh rollout undo.
Kubernetes chỉ biết về ứng dụng qua những gì bạn khai báo: probe, tài nguyên và tín hiệu dừng. Ngày 96 tối ưu chính ứng dụng: performance tuning.
Tài liệu đối chiếu
https://docs.spring.io/spring-boot/reference/actuator/endpoints.html
https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
Site Admin
Engineer and writer. Building things with TypeScript and distributed systems.
Bình luận (0)
Bạn cần đăng nhập bằng Google để bình luận.
Hãy là người bình luận đầu tiên.


