Chuẩn bị Docker Registry và đẩy Image lên Cloud
Bước đầu tiên là đảm bảo image Docker đã được build (từ Phần 6) sẵn sàng để đẩy lên Registry công cộng hoặc tư nhân. Chúng ta sẽ sử dụng Docker Hub làm ví dụ, nhưng quy trình này áp dụng tương tự cho Google Container Registry (GCR) hoặc AWS ECR.
Tại sao: Kubernetes cần một địa chỉ public (URL) để pull image về nodes. Image không thể nằm local trên máy chủ nếu không có cơ chế phân phối này.
Kết quả mong đợi: Image xuất hiện trên Docker Hub với tag version cụ thể.
docker tag ai-webapp:latest your-username/ai-webapp:v1.0.0
docker push your-username/ai-webapp:v1.0.0
Verify: Truy cập trang Docker Hub của bạn, xác nhận tag v1.0.0 đã hiện diện và kích thước file đúng như mong đợi.
Quản lý cấu hình và bí mật (ConfigMap & Secret)
Thay vì hardcode biến môi trường vào Dockerfile hoặc code, chúng ta tách biệt cấu hình (ConfigMap) và thông tin nhạy cảm (Secret) ra khỏi container. Điều này giúp quản lý versioning tốt hơn và bảo mật cao hơn.
Tại sao: ConfigMap chứa các biến không nhạy cảm như port, host, log level. Secret chứa key API, token, hoặc password, được Kubernetes mã hóa base64 và mount vào container dưới dạng file hoặc env var.
Kết quả mong đợi: Tạo thành công 2 tài nguyên Kubernetes để inject vào Deployment sau này.
1. Tạo file ConfigMap cho các biến môi trường thông thường:
Đường dẫn: ./k8s/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ai-webapp-config
namespace: production
data:
APP_PORT: "8080"
LOG_LEVEL: "info"
WASM_PATH: "/app/wasm/model.wasm"
TFLITE_PATH: "/app/models/model.tflite"
2. Tạo file Secret cho thông tin nhạy cảm (ví dụ: API Key để gọi backend):
Đường dẫn: ./k8s/secret.yaml
Lưu ý: Kubernetes Secret thường được tạo bằng base64, nhưng lệnh kubectl create secret generic có thể tự xử lý nếu dùng --from-literal.
kubectl create secret generic ai-webapp-secret \
--from-literal=API_KEY="your-secret-api-key-here" \
--from-literal=DB_PASSWORD="your-db-password" \
--namespace=production \
--dry-run=client -o yaml > ./k8s/secret.yaml
Verify: Chạy lệnh kubectl get configmap ai-webapp-config -n production và kubectl get secret ai-webapp-secret -n production để đảm bảo tài nguyên đã tồn tại.
Triển khai ứng dụng (Deployment & Service)
Bây giờ chúng ta định nghĩa cách Kubernetes sẽ chạy container, số lượng replica, và cách các pod giao tiếp với nhau.
Tại sao: Deployment đảm bảo số lượng pod luôn chạy đúng version image. Service cung cấp một địa chỉ IP nội bộ (ClusterIP) ổn định để các pod khác hoặc Ingress truy cập vào pod động.
Kết quả mong đợi: Pod chạy trạng thái "Running", Service đã được tạo và expose port nội bộ.
1. Tạo file Deployment bao gồm cả ConfigMap và Secret:
Đường dẫn: ./k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ai-webapp-deployment
namespace: production
labels:
app: ai-webapp
spec:
replicas: 2
selector:
matchLabels:
app: ai-webapp
template:
metadata:
labels:
app: ai-webapp
spec:
containers:
- name: ai-webapp
image: your-username/ai-webapp:v1.0.0
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: ai-webapp-config
- secretRef:
name: ai-webapp-secret
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
2. Tạo Service để expose Deployment ra bên trong cluster:
Đường dẫn: ./k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
name: ai-webapp-service
namespace: production
spec:
selector:
app: ai-webapp
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP
Apply các file cấu hình vào cluster:
kubectl apply -f ./k8s/deployment.yaml
kubectl apply -f ./k8s/service.yaml
Verify: Kiểm tra trạng thái pod và service:
kubectl get pods -n production -l app=ai-webapp
kubectl get svc ai-webapp-service -n production
Kết quả: Pod phải ở trạng thái "Running" với 2/2 READY. Service phải có IP nội bộ (ví dụ: 10.96.xxx.xxx).
Cấu hình Ingress để expose ra Internet
Service ClusterIP chỉ truy cập được từ bên trong cluster. Để người dùng truy cập qua domain (ví dụ: ai-app.example.com), chúng ta cần Ingress Controller (như Nginx Ingress) và file Ingress Rule.
Tại sao: Ingress đóng vai trò như bộ định tuyến Layer 7 (HTTP/HTTPS), định hướng traffic từ internet vào đúng Service dựa trên host hoặc path.
Kết quả mong đợi: Có thể truy cập ứng dụng qua trình duyệt bằng tên miền đã cấu hình.
Lưu ý: Đảm bảo bạn đã cài đặt Nginx Ingress Controller trước đó (thường qua Helm hoặc kubectl apply). Nếu chưa, hãy chạy helm install ingress-nginx ingress-nginx/ingress-nginx.
1. Tạo file Ingress Rule:
Đường dẫn: ./k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ai-webapp-ingress
namespace: production
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
spec:
ingressClassName: nginx
rules:
- host: ai-app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ai-webapp-service
port:
number: 80
2. Apply file Ingress:
kubectl apply -f ./k8s/ingress.yaml
3. Kiểm tra trạng thái Ingress:
kubectl get ingress ai-webapp-ingress -n production
Verify: Chờ khoảng 1-2 phút để Ingress Controller cập nhật cấu hình. Kiểm tra lại:
kubectl describe ingress ai-webapp-ingress -n production
Kết quả mong đợi: Trường "ADDRESS" trong output sẽ hiển thị IP public của Node hoặc Load Balancer. Bạn có thể thêm dòng vào file /etc/hosts trên máy client:
echo "123.123.123.123 ai-app.example.com" | sudo tee -a /etc/hosts
Sau đó truy cập http://ai-app.example.com trong trình duyệt. Nếu thấy giao diện web của ứng dụng AI, việc deploy thành công.
Xác minh tổng thể và kiểm tra lỗi
Sau khi deploy, cần kiểm tra logs để đảm bảo WebAssembly engine khởi động đúng và không bị crash do thiếu file model hoặc lỗi environment.
Tại sao: Pod có thể chạy nhưng ứng dụng bên trong có thể crash ngay lập tức nếu không load được file .wasm hoặc .tflite. Logs là nguồn thông tin chính để debug.
kubectl logs -f deployment/ai-webapp-deployment -n production
Kiểm tra lại các probe (liveness/readiness). Nếu pod bị restart liên tục (CrashLoopBackOff), hãy kiểm tra:
- Đường dẫn WASM_PATH và TFLITE_PATH trong ConfigMap có khớp với đường dẫn trong Dockerfile không.
- Port 8080 có được mở trong container không.
- Secret đã được mount đúng chưa.
kubectl get events -n production --sort-by='.lastTimestamp'
Kiểm tra xem traffic có đi qua Ingress không bằng cách xem logs của Ingress Controller:
kubectl logs -l app.kubernetes.io/name=ingress-nginx -n ingress-nginx | grep ai-app.example.com
Kết quả mong đợi: Logs hiển thị các dòng khởi động TensorFlow Lite, load WebAssembly module, và server listen trên port 8080. Các dòng request HTTP từ Ingress Controller hiện ra khi bạn truy cập.
Điều hướng series:
Mục lục: Series: Xây dựng nền tảng Real-time AI với WebAssembly, TensorFlow Lite và Kubernetes
« Phần 6: Bao gói ứng dụng Web thành Docker Container
Phần 8: Tích hợp cơ chế mở rộng tự động (Auto-scaling) »