Scaling Kubernetes to 7,500 nodes

Bài tóm tắt OpenAI 2021 3. Quy mô lớn Độ khó: Nâng cao

OpenAI · 2021 · 3. Quy mô lớn · Độ khó: Nâng cao — bài gốc

Phần tiếp của OpenAI 2018.

Bối cảnh

  • Một cụm duy nhất 7.500 node, chọn vì hạ tầng đơn giản cho phép team nghiên cứu scale mà không đổi code.
  • Workload khác hẳn công ty thông thường:
    • một job ML lớn chiếm trọn các node (GPU nói chuyện trực tiếp qua NVLink), nên ít tranh tài nguyên;
    • scheduler chịu tải theo đợt: một job tạo hàng trăm pod cùng lúc;
    • job MPI: một pod chết là cả job dừng và chạy lại từ checkpoint ("bán trạng thái");
    • hầu như không dùng load balancing hay canary của Kubernetes; dữ liệu đọc từ blob storage.

Thay đổi chính

  • Mạng: bỏ Flannel, dùng mạng pod native của Azure VMSS (IP alias), đạt băng thông như host. Cụm lớn nhất có thể dùng khoảng 200.000 IP; route-based thì bị giới hạn số route. Đếm lưu lượng nội bộ và Internet theo namespace bằng iptables mangle + exporter.
  • API server và etcd chạy trên node riêng, ngoài cụm: 5 API server và 5 etcd cho cụm lớn nhất. Mỗi API server dùng tới 70 GB heap, tăng tuyến tính theo số node.
    • Tải lớn nhất là WATCH trên Endpoints: service mà mọi node đều là thành viên (kubelet, node-exporter), thêm hay bớt một node là bắn tới mọi node. Lưu lượng tăng theo N², có lúc 1 GB/s hoặc hơn. EndpointSlices (Kubernetes 1.17) giảm tải khoảng 1.000 lần.
    • Nguyên tắc: cảnh giác mọi request tới API server tăng theo kích thước cụm; tránh DaemonSet gọi API server, nếu cần thì qua một lớp cache trung gian.
    • Thêm hàng trăm node cùng lúc làm quá tải API server; chỉ cần dàn đều vài giây là đỡ.
  • Prometheus: quá nhiều metric; OOM do Grafana gọi /api/v1/series với truy vấn lấy mọi histogram. Restart thì replay WAL mất nhiều giờ. Đang chuyển sang hệ khác.
  • Health check:
    • thụ động (lỗi ECC của GPU, đĩa, mạng, sự kiện bảo trì của cloud) thì tự cordon, nặng thì evict;
    • chủ động: "preflight" chạy test GPU khi node mới vào (node mang taint tới khi qua test), và chạy định kỳ bằng CronJob.
  • Quota theo team: service team-resource-manager gắn taint theo team, admission webhook gắn toleration theo người gửi job. "Bóng bay" CPU/GPU: pod ưu tiên thấp giữ chỗ để autoscaler không xoá node rảnh (họ dùng autoscaler để thay node hỏng), và bị đá ra ngay khi có job thật.
  • Gang scheduling: hai thí nghiệm cùng xin 100% cụm thì scheduler mặc định có thể cấp mỗi bên một nửa và cả hai đều kẹt. Họ dùng plugin Coscheduling (Kubernetes 1.18).
  • Chưa giải: lưu trữ metric; định hình băng thông Internet của pod.

Bài học cho SWE

  • Ở quy mô lớn, mọi thứ tỷ lệ với N (WATCH, agent mỗi node, request khi node vào cụm) đều thành bão vào control plane. Tương tự thundering herd ở tầng ứng dụng (Hot partition và thundering herd).
  • Nền tảng nội bộ phải được thiết kế theo workload thật (batch, gang, GPU), không theo mặc định của công cụ (Nền tảng nội bộ cho service (đường ray chung)).
  • Kiểm tra phần cứng trước khi nhận việc (preflight) là health check quan trọng khi phần cứng có thể hỏng âm thầm.

Liên quan