Trong môi trường Kubernetes, các container thường được giới hạn tài nguyên thông qua cgroup. Tuy nhiên, các ứng dụng Java (chạy trên JVM) trước phiên bản 8u191 hoặc JDK 10 trở xuống không tự động nhận diện giới hạn tài nguyên từ cgroup, dẫn đến việc JVM có thể sử dụng vượt mức tài nguyên được cấp phát cho container.
Từ JDK 8u191 và JDK 10 trở lên, JVM đã hỗ trợ tự động phát hiện giới hạn bộ nhớ và CPU từ cgroup v1. Để kích hoạt tính năng này, cần đảm bảo:
- Sử dụng phiên bản JVM hỗ trợ cgroup (từ 8u191+ hoặc 10+)
- Kubernetes đang chạy với cgroup v1 (mặc định trên hầu hết các hệ thống Linux hiện tại)
- Không ghi đè tham số
-Xmxhoặc-XX:MaxRAMPercentagemột cách cố định
Ví dụ cấu hình khuyến nghị trong Dockerfile hoặc manifest Kubernetes:
# Thiết lập biến môi trường để JVM tuân theo giới hạn container
ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"
Hoặc trong file triển khai Kubernetes:
spec:
containers:
- name: app
image: my-java-app:latest
env:
- name: JAVA_OPTS
value: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"
resources:
limits:
memory: "512Mi"
cpu: "500m"
requests:
memory: "256Mi"
cpu: "200m"
Lưu ý: -XX:+UseContainerSupport là mặc định bật từ JDK 10+, nhưng nên khai báo rõ ràng để đảm bảo tương thích ngược.
Kiến trúc Kubernetes cơ bản
Kubernetes gồm các thành phần chính:
- Control Plane: kube-apiserver, etcd, kube-scheduler, kube-controller-manager, cloud-controller-manager
- Node Components: kubelet, kube-proxy, container runtime (Docker, containerd, CRI-O)
Vòng đời Pod
Pod trải qua các trạng thái: Pending → Running → (Succeeded / Failed). Trạng thái NotReady thường do kubelet lỗi hoặc container crash.
Xử lý sự cố thường gặp
1. Node ở trạng thái NotReady do bật swap:
# Tắt swap tạm thời
sudo swapoff -a
# Vô hiệu hóa swap vĩnh viễn
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
# Khởi động lại kubelet
sudo systemctl restart kubelet
2. Lỗi docker login do proxy:
# Di chuyển file cấu hình proxy
sudo mv /usr/lib/systemd/system/docker.service.d/http-proxy.conf{,.bak}
# Reload và khởi động lại Docker
sudo systemctl daemon-reload
sudo systemctl restart docker
Truy cập dịch vụ qua NodePort
Sau khi triển khai service kiểu NodePort, có thể truy cập qua địa chỉ IP của bất kỳ node nào kèm cổng được ánh xạ:
kubectl get svc nginx
# Output: nginx NodePort 10.99.204.232 <none> 80:31681/TCP
Truy cập: http://<NODE_IP>:31681
Tài nguyên học tập đáng chú ý
- Hướng dẫn kiến trúc Kubernetes: kubernetes.io
- Tài liệu thực hành từ qikqiak.com: troubleshooting, networking, CI/CD
- Hướng dẫn Helm, Prometheus, Istio trong hệ sinh thái Cloud Native