Docker Compose nhiều service trên một VPS: chia tài nguyên sao cho không tranh nhau

Chia sẻ bài viết

Mục lục
Docker Compose nhiều service trên một VPS: chia tài nguyên sao cho không tranh nhau

Trả lời nhanh: Mặc định các container không có hạn mức nên một service lỗi có thể chiếm hết RAM và làm cả máy chết. Cách xử lý: đặt hạn mức bộ nhớ và CPU cho từng service trong file cấu hình, dành sẵn khoảng 1GB cho hệ điều hành, và bật khởi động lại tự động. Dùng lệnh docker stats để biết service nào đang ngốn gì. Với nhóm nhiều service, ổ NVMe quan trọng vì tất cả cùng đọc ghi trên một ổ.

Một service rò rỉ bộ nhớ, và cả máy chết theo. Không phải vì máy yếu mà vì không ai đặt giới hạn cho nó.

Tóm tắt nhanh
  • Container không có hạn mức mặc định, một cái lỗi kéo cả máy sập.
  • Đặt hạn mức RAM và CPU cho từng service là việc bắt buộc.
  • Chừa khoảng 1GB cho hệ điều hành, đừng chia hết cho container.
  • Nhiều container cùng đọc ghi một ổ, đây là lúc NVMe tạo khác biệt.

Đặt hạn mức cho từng service

Khai báo trong file cấu hình:

services:
  api:
    deploy:
      resources:
        limits:
          memory: 1g
          cpus: "1.0"
    restart: unless-stopped

Cách chia thực dụng cho máy 8GB: hệ điều hành 1GB, database 3GB, ứng dụng chính 2GB, phần còn lại chia cho các service phụ. Đừng chia hết, luôn để dư một khoảng đệm.

Tìm container đang ngốn tài nguyên

docker stats            # xem theo thời gian thực
docker stats --no-stream  # chụp một lần rồi thoát

Cột cần nhìn: MEM USAGE so với hạn mức, và BLOCK I/O cho biết container nào đọc ghi ổ nhiều nhất. Container có BLOCK I/O tăng liên tục thường là thủ phạm làm cả nhóm chậm.

Ổ đĩa là tài nguyên bị quên nhiều nhất

Người ta hay chia RAM và CPU rồi quên rằng tất cả container dùng chung một ổ. Database ghi nhật ký giao dịch, ứng dụng ghi log, hệ thống build ghi file trung gian, tất cả đập vào cùng một chỗ.

Đây là lý do một máy nhiều container hưởng lợi từ ổ NVMe nhiều hơn máy chạy một ứng dụng. Hàng đợi lệnh sâu của NVMe xử lý được nhiều yêu cầu song song, còn ổ SATA với hàng đợi nông sẽ tắc.

Vài quy tắc giúp đỡ đau đầu

  • Bật khởi động lại tự động cho mọi service, trừ những cái chạy một lần.
  • Giới hạn kích thước file log, log không giới hạn là nguyên nhân đầy ổ rất phổ biến.
  • Đặt kiểm tra tình trạng để biết service sống hay chết thật sự.
  • Dọn ảnh và khối lưu trữ không dùng định kỳ.
docker system prune -a --volumes   # cẩn thận, xoá cả dữ liệu không gắn với container nào

Đặt hạn mức cho từng dịch vụ

# Trong docker-compose.yml, cho tung service:
#   deploy:
#     resources:
#       limits:
#         memory: 512M
#         cpus: "0.5"
#   logging:
#     driver: json-file
#     options:
#       max-size: "10m"
#       max-file: "3"

# Xem muc dung that de dat han muc cho dung
docker stats --no-stream

# Container nao bi dung vi vuot han muc bo nho
docker inspect TEN_CONTAINER | grep -i oomkilled

# Xem dung luong: anh, vung luu tru, nhat ky
docker system df -v | head -30
du -sh /var/lib/docker/containers/*/*-json.log 2>/dev/null | sort -h | tail -10

Bảng nguồn chiếm ổ và cách dọn

Nguồn chiếm chỗCách kiểmCách dọn
Nhật ký containerdu -sh trên thư mục nhật kýĐặt giới hạn kích thước trong tệp khai báo
Ảnh cũ không dùngdocker system dfDọn định kỳ bằng lệnh dọn dẹp
Vùng lưu trữ mồ côidocker volume ls -f dangling=trueXóa sau khi chắc chắn không cần
Dữ liệu cơ sở dữ liệu phình dầnKiểm kích thước cơ sở dữ liệuDọn dữ liệu cũ, đặt chính sách lưu giữ

Ổ đầy làm mọi dịch vụ trên máy cùng chết một lúc, và đây là sự cố mất nhiều thời gian khắc phục nhất. Đặt cảnh báo khi ổ còn dưới 15% là việc đáng làm ngay từ ngày đầu.

Bốn quy tắc giúp đỡ đau đầu

  • Đặt hạn mức bộ nhớ cho mọi dịch vụ, không có ngoại lệ. Một dịch vụ rò rỉ bộ nhớ sẽ kéo cả máy xuống nếu không có hạn mức.
  • Đặt tự khởi động lại khi dịch vụ chết, nhưng có giới hạn số lần để không che giấu vấn đề thật.
  • Chỉ mở cổng ra ngoài với dịch vụ thật sự cần. Cơ sở dữ liệu và bộ nhớ đệm chỉ nghe trên địa chỉ nội bộ.
  • Giữ tệp khai báo trong kho mã nguồn, để dựng lại được toàn bộ máy khi cần. Đây là bản sao lưu quan trọng nhất mà không tốn dung lượng nào.

Câu hỏi thường gặp

Vì sao một container lỗi làm cả máy chết?

Vì mặc định container không có hạn mức bộ nhớ, nó có thể chiếm hết RAM máy rồi hệ thống bắt đầu tắt các tiến trình khác.

Nên chia RAM thế nào cho nhiều service?

Chừa khoảng 1GB cho hệ điều hành, phần còn lại chia theo nhu cầu thật, ưu tiên database. Luôn để dư một khoảng đệm.

Làm sao biết container nào chậm?

Chạy docker stats và nhìn cột BLOCK I/O. Container đọc ghi nhiều thường là nguyên nhân làm cả nhóm chậm.

Nhiều container trên một VPS có nên không?

Rất phổ biến và hợp lý với dự án vừa. Chỉ cần đặt hạn mức rõ ràng và dùng ổ đủ nhanh vì tất cả dùng chung một ổ.

Hạ tầng NVMe Enterprise của TND
VPS ổ Enterprise U.2 NVMe, CPU xung cao, đặt tại Việt Nam
Truy vấn SQL, PHP dựng trang, build Next.js hay đóng gói app iOS và Android: phần lớn các bước này chạy đơn luồng và đập liên tục vào ổ đĩa. Nghẽn nằm ở tốc độ đọc ghi và xung nhịp CPU, không phải ở việc có thật nhiều nhân. Ổ Enterprise U.2 NVMe chuẩn máy chủ chạy RAID 10 cho IOPS đọc ghi ngẫu nhiên gấp 5 đến 7 lần ổ SATA SSD, khác hẳn NVMe M.2 phổ thông. Chạy trên chip Intel Xeon Platinum dòng xung cao, backup tự động hàng tuần, bàn giao trong 5 phút.
Xem VPS ổ Enterprise U.2 NVMe, bàn giao trong 5 phút

Bài viết liên quan