Phân tích Overhead của eBPF và điều chỉnh tham số Kernel
Trong môi trường sản xuất, hiệu năng của Service Mesh phụ thuộc lớn vào cách kernel xử lý các hook eBPF. Việc mặc định của kernel có thể gây ra tình trạng "context switch" quá mức hoặc buffer đầy dẫn đến mất gói tin (packet drop).
Chúng ta cần điều chỉnh các tham số trong sysctl để tối ưu hóa tốc độ truyền dẫn và giảm thiểu độ trễ khi eBPF hoạt động.
Trước tiên, kiểm tra các tham số hiện tại liên quan đến mạng và eBPF:
sysctl -a | grep -E "net.core|net.ipv4.tcp|bpf"
Kết quả mong đợi: Bạn sẽ thấy các giá trị mặc định của kernel, ví dụ net.core.netdev_budget thường là 60, hoặc net.core.rmem_default là 212992.
Để tối ưu hóa, chúng ta cần tăng kích thước buffer nhận và gửi, đồng thời điều chỉnh tham số budget của thiết bị mạng để eBPF có thể xử lý nhiều gói tin hơn trong mỗi chu kỳ interrupt.
Tạo file cấu hình để áp dụng các thay đổi này:
cat > /etc/sysctl.d/99-cilium-eBPF-optim.conf
Áp dụng các thay đổi vào kernel ngay lập tức:
sysctl --system
Kết quả mong đợi: Không có lỗi báo về. Các tham số đã được cập nhật trong memory.
Để verify kết quả, chạy lại lệnh kiểm tra và so sánh các giá trị quan trọng:
sysctl net.core.rmem_max net.core.netdev_budget
Kết quả mong đợi: Giá trị net.core.rmem_max phải là 134217728 và net.core.netdev_budget phải là 500.
Đặc biệt với eBPF, cần đảm bảo map size của Cilium không bị giới hạn quá thấp gây ra lỗi ENOSPC khi traffic tăng đột biến.
Chỉnh sửa file cấu hình Cilium (thường nằm trong /etc/cilium/cilium-config.yaml hoặc Helm values) để tăng kích thước map:
cat > /etc/cilium/cilium-config.yaml
Khởi động lại Cilium agent để áp dụng cấu hình mới:
kubectl rollout restart deployment/cilium -n kube-system
Kết quả mong đợi: Pod Cilium sẽ restart và các map mới sẽ được tạo với kích thước lớn hơn. Kiểm tra bằng lệnh:
kubectl logs -f -n kube-system -l k8s-app=cilium | grep "map size"
Verify rằng không có lỗi map full hoặc failed to insert trong log.
Sử dụng bpftrace để debug các vấn đề gói tin bị drop
Khi các gói tin bị drop, log thông thường của Cilium đôi khi không đủ chi tiết để xác định nguyên nhân chính xác (ví dụ: drop do policy, drop do checksum sai, hay drop do XDP).
Chúng ta sẽ sử dụng công cụ bpftrace để hook vào các điểm nóng (hotspots) trong kernel và trace lại quá trình xử lý gói tin.
Đầu tiên, cài đặt bpftrace nếu chưa có (trên Ubuntu/Debian):
apt-get update && apt-get install -y bpftrace
Kết quả mong đợi: Package bpftrace được cài đặt thành công.
Để debug tình trạng gói tin bị drop tại lớp XDP (XDP là nơi xử lý sớm nhất, nếu drop ở đây thì overhead thấp nhưng khó debug), chạy lệnh sau để đếm số lượng gói tin bị drop theo lý do:
bpftrace -e 'tracepoint:xdp:xdp_dev_map * { @[printf("%s: %s", comm, xdp_action)] = count(); }'
Kết quả mong đợi: Bạn sẽ thấy bảng thống kê các hành động XDP. Nếu thấy XDP_DROP tăng cao, nghĩa là gói tin đang bị loại bỏ ngay tại driver mạng hoặc XDP program của Cilium.
Để debug sâu hơn, xác định xem gói tin bị drop do Policy hay do lỗi checksum, sử dụng script bpftrace chuyên biệt cho Cilium:
cat > /tmp/cilium-drop-tracer.bt ip4.src,
args->ip4.dst,
"XDP_DROP");
}
}
tracepoint:kprobe:cilium_sock_ebpf_drop {
printf("%-15d %-10s %-20s %-15s %-10s\n",
pid,
comm,
args->src_ip,
args->dst_ip,
"SOCK_DROP");
}
EOF
Chạy script này để bắt đầu trace:
bpftrace /tmp/cilium-drop-tracer.bt
Kết quả mong đợi: Lệnh sẽ chạy và in ra dòng log mỗi khi có gói tin bị drop, kèm theo IP nguồn, đích và lý do drop (XDP_DROP hoặc SOCK_DROP).
Để kiểm tra drop do Policy Engine (L3/L4), sử dụng tracepoint cụ thể của Cilium:
bpftrace -e 'tracepoint:cilium:drop { printf("Drop reason: %d, src: %s, dst: %s, proto: %d\n", args->reason, args->src_ip, args->dst_ip, args->proto); }'
Code này cần được chạy trên node nơi xảy ra sự cố. Kết quả mong đợi là bạn sẽ thấy mã lỗi cụ thể (ví dụ: 1 là policy deny, 2 là drop do endpoint không tồn tại).
Để debug vấn đề kết nối giữa các Pod trong cùng một node (L2), sử dụng tracepoint về L2 forward:
bpftrace -e 'tracepoint:cilium:l2_forward { printf("L2 Forward: src=%s dst=%s\n", args->src_mac, args->dst_mac); }'
Kết quả mong đợi: Nếu thấy dòng log này nhưng không thấy kết nối thành công, có thể do MAC address resolution sai hoặc vấn đề về bridge.
Với các vấn đề về TCP, sử dụng bpftrace để theo dõi trạng thái kết nối bị reset:
bpftrace -e 'tracepoint:kprobe:tcp_v4_send_reset { printf("TCP RST: src=%s dst=%s\n", args->src_ip, args->dst_ip); }'
Kết quả mong đợi: Nếu thấy nhiều RST, có thể do firewall, policy, hoặc ứng dụng đóng kết nối không đúng chuẩn.
Verify kết quả debug bằng cách tạo traffic giả lập và quan sát log của bpftrace:
ping -c 5
Kết quả mong đợi: Nếu ping thất bại, bpftrace sẽ in ra lý do drop tương ứng với gói tin đó.
Giải quyết sự cố về kết nối giữa các cluster hoặc namespace
Trong kiến trúc Multi-Cluster hoặc Multi-Namespace, sự cố thường xuất hiện do định tuyến sai (routing), CNI conflict, hoặc Policy không đồng bộ.
Đầu tiên, kiểm tra trạng thái của Cluster Mesh (nếu đang dùng Cilium Cluster Mesh):
cilium status
Kết quả mong đợi: Dòng Cluster Mesh phải hiển thị Ready hoặc Connected. Nếu thấy Disconnected, cần kiểm tra tunnel.
Kiểm tra xem Cilium có nhận diện đúng các endpoint của cluster khác không:
cilium endpoint list -o wide
Kết quả mong đợi: Danh sách endpoint bao gồm cả các Pod từ cluster khác (nhận biết qua External Identity hoặc Cluster column).
Nếu kết nối giữa các namespace bị chặn, kiểm tra xem có tồn tại CiliumNetworkPolicy nào đang deny traffic hay không:
kubectl get ciliumnetworkpolicy --all-namespaces -o yaml | grep -A 10 "toEndpoints"
Kết quả mong đợi: Bạn sẽ thấy các rule cụ thể. Nếu thấy fromEndpoints hoặc toEndpoints có selector quá chặt, đó là nguyên nhân.
Để debug sự cố định tuyến trong Cluster Mesh, sử dụng lệnh cilium bpf để xem bảng định tuyến:
cilium bpf ip route
Kết quả mong đợi: Bảng route phải có các tuyến dẫn đến mạng của cluster khác thông qua interface tunnel (ví dụ: cilium_host hoặc cilium_net).
Nếu traffic bị mất giữa các cluster, kiểm tra log của Cilium về việc drop do policy:
kubectl logs -n kube-system -l k8s-app=cilium | grep -i "policy deny"
Kết quả mong đợi: Nếu thấy log này, cần xem chi tiết rule bị vi phạm bằng:
cilium policy report --all-namespaces
Kết quả mong đợi: Một bảng báo cáo chi tiết về việc traffic nào bị drop bởi policy nào, giúp bạn điều chỉnh rule.
Trong trường hợp sử dụng BGP cho Cluster Mesh, kiểm tra trạng thái BGP:
cilium bgp status
Kết quả mong đợi: Trạng thái BGP phải là Established với các peer.
Để kiểm tra khả năng reachability giữa hai Pod ở cluster khác nhau:
kubectl exec -it -n -- ping -c 3
Nếu ping thất bại, sử dụng cilium monitor để xem chi tiết gói tin:
kubectl exec -it -n kube-system -- cilium monitor -t drop
Kết quả mong đợi: Bạn sẽ thấy log chi tiết của gói tin bị drop, bao gồm verdict: DROP và reason (ví dụ: policy denied hoặc no route).
Verify kết quả sửa lỗi bằng cách ping lại và kiểm tra cilium monitor chuyển sang verdict: FORWARDED hoặc verdict: DELIVERED.
Best Practices về bảo mật và tối ưu hóa trong môi trường sản xuất
Để đảm bảo Service Mesh hoạt động ổn định và bảo mật trong môi trường sản xuất, cần áp dụng các nguyên tắc sau:
1. Áp dụng Default Deny Policy
Tạo một CiliumNetworkPolicy mặc định để chặn mọi traffic nếu không được phép rõ ràng. Điều này ngăn chặn các cuộc tấn công lateral movement.
cat > /tmp/default-deny-policy.yaml
Áp dụng policy này:
kubectl apply -f /tmp/default-deny-policy.yaml
Kết quả mong đợi: Tất cả traffic trong namespace default bị chặn, trừ traffic đến kube-apiserver và kube-dns. Verify bằng cách ping từ Pod này sang Pod khác trong cùng namespace (sẽ fail).
2. Giới hạn quyền của Cilium Agent
Đảm bảo Cilium agent chỉ có quyền cần thiết. Sử dụng PodSecurityContext và ServiceAccount tối thiểu.
cat > /tmp/cilium-rbac-minimal.yaml
Áp dụng RBAC:
kubectl apply -f /tmp/cilium-rbac-minimal.yaml
Kết quả mong đợi: Cilium agent vẫn hoạt động bình thường nhưng không có quyền truy cập vào các tài nguyên nhạy cảm khác.
3. Cấu hình Resource Limits cho Cilium
Đặt giới hạn CPU và RAM cho Cilium để tránh việc nó chiếm hết tài nguyên node khi traffic tăng đột biến.
cat > /tmp/cilium-resource-limits.yaml
Áp dụng cấu hình resource:
kubectl apply -f /tmp/cilium-resource-limits.yaml
Kết quả mong đợi: Cilium agent sẽ bị OOMKilled nếu vượt quá 2Gi RAM, giúp bảo vệ node khỏi bị treo hoàn toàn.
4. Sử dụng eBPF XDP cho tất cả traffic
Đảm bảo XDP được bật để giảm latency. Kiểm tra bằng:
cilium status | grep XDP
Kết quả mong đợi: Trạng thái phải là Enabled cho tất cả các interface.
5. Giám sát liên tục với Prometheus
Cấu hình scraping cho các metric quan trọng của Cilium:
cat > /tmp/prometheus-cilium-scrape.yaml
Áp dụng vào Prometheus config.
Kết quả mong đợi: Prometheus sẽ thu thập được các metric như cilium_bpf_xdp_drop_total, cilium_bpf_policy_drop_total để cảnh báo sớm.
Verify toàn bộ hệ thống bằng cách chạy stress test và quan sát các metric:
hey -z 1m -c 100 http:///health
Kết quả mong đợi: Không có packet drop tăng đột biến, CPU của Cilium nằm trong giới hạn, và các policy vẫn hoạt động chính xác.
Điều hướng series:
Mục lục: Series: Xây dựng nền tảng Secure Service Mesh với eBPF, Cilium và Policy Engine
« Phần 6: Giám sát, Tracing và Thu thập metric với eBPF