Backend

99 Ngày Spring — Ngày 95: Deploy lên Kubernetes

SSite Admin
30 tháng 10, 2026 3 phút đọc 7 lượt xem
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ý.

Deploy lên Kubernetes

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: 5

3. 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: 25s

4. 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/

S

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.

Bài viết liên quan

Kafka trong dự án thực tế: đồng bộ PostgreSQL sang Elasticsearch bằng Debezium CDC

Thiết kế pipeline CDC cho catalog sản phẩm: Kafka Connect, snapshot, update/delete, WAL, retry, retention và dựng lại Elasticsearch bằng index mới cùng alias — kèm cấu hình và sơ đồ thực tế.

30 thg 10, 202633 phút1
99 Ngày Java — Ngày 95: Decorator và Adapter

Thêm hành vi bằng cách bọc đối tượng thay vì sửa nó, các wrapper trong java.io, và adapter để nối hai interface không khớp.

30 thg 10, 20263 phút6
99 Ngày Spring — Ngày 94: CI/CD cho Spring Boot

Workflow GitHub Actions để build, test và đóng image, đánh phiên bản bất biến và triển khai qua nhiều môi trường có kiểm soát.

29 thg 10, 20263 phút7