Gần đây chúng tôi đã chuyển đổi môi trường sản xuất của chúng tôi sang Kubernetes. Tôi muốn thực thi các giới hạn CPU trên các container. Tôi đang nhận được các số liệu CPU xung đột không khớp với nhau. Đây là thiết lập của tôi:
- Các tác nhân DataDog chạy như một
Daemonset
- Các ứng dụng hiện có đang chạy mà không có giới hạn CPU
- Các container trong câu hỏi là các ứng dụng Ruby đa luồng
- Hai số liệu:
kubernetes.cpu.usage.{avg,max}
vàdocker.cpu.usage
c4.xlarge
các nút cụm (4 vCPUs hoặc 4000m theo thuật ngữ Kubernetes)
kubernetes.cpu.usage.max
báo cáo ~ 600m cho các container trong câu hỏi. docker.cpu.usage
báo cáo ~ 60%. Theo sau đó, giới hạn CPU 1000m sẽ là quá đủ dung lượng trong hoạt động bình thường.
Tôi đặt giới hạn là 1000m. Sau đó docker.container.throttles
đi lên đáng kể trong khi kubernetes.cpu.usage.max
và docker.cpu.usage
giữ nguyên. Tất cả các hệ thống rơi xuống đầu gối của nó trong thời gian này. Điều này không có ý nghĩa với tôi.
Tôi đã nghiên cứu số liệu thống kê Docker. Có vẻ như docker stats
(và API cơ bản) bình thường hóa tải theo lõi CPU. Vì vậy, trong trường hợp của tôi, docker.cpu.usage
từ 60% đến (4000m * 0,60) đến 2400m theo thuật ngữ Kubernetes. Tuy nhiên, điều này không tương quan với bất kỳ số Kubernetes nào. Tôi đã làm một thí nghiệm khác để kiểm tra giả thuyết của mình rằng số Kubernetes không chính xác. Tôi đặt giới hạn là 2600m (đối với một số khoảng trống phụ). Điều này đã không dẫn đến bất kỳ điều tiết. Tuy nhiên Kubernetes quan sát việc sử dụng CPU không thay đổi. Điều này làm tôi bối rối.
Vì vậy, câu hỏi của tôi là:
- Điều này có cảm thấy như một lỗi trong Kubernetes (hoặc một cái gì đó trong ngăn xếp không?)
- Tôi hiểu có đúng không?
Câu hỏi tiếp theo của tôi liên quan đến cách xác định đúng CPU cho các ứng dụng Ruby. Một container sử dụng Puma. Đây là một máy chủ web đa luồng với số lượng luồng có thể định cấu hình. Yêu cầu HTTP được xử lý bởi một trong các luồng. Ứng dụng thứ hai là một máy chủ tiết kiệm sử dụng máy chủ luồng. Mỗi kết nối TCP đến được xử lý bởi luồng riêng của nó. Các luồng thoát khi kết nối đóng lại. Ruby as GIL (Khóa phiên dịch toàn cầu) để chỉ một luồng có thể thực thi mã Ruby tại một thời điểm. Điều đó cho phép nhiều luồng thực thi IO và những thứ tương tự.
Tôi nghĩ cách tiếp cận tốt nhất là giới hạn số lượng luồng đang chạy trong mỗi ứng dụng và xấp xỉ giới hạn CPU Kubernetes dựa trên số lượng luồng. Các quy trình không được giả mạo nên tổng mức sử dụng CPU khó dự đoán hơn.
Câu hỏi ở đây là: làm thế nào để dự đoán đúng mức sử dụng và giới hạn CPU cho các ứng dụng này?