🎯 Mục tiêu bài thực hành
- Cài đặt Cilium CNI với Hubble observability
- Cài đặt và cấu hình Gateway API (Envoy Gateway hoặc Cilium Gateway)
- Tạo HTTPRoute cho path-based routing và traffic splitting
- Implement default-deny NetworkPolicy và allow specific traffic
- Quan sát network traffic với Hubble UI
Lab 1: Cài Cilium với Helm
# Tạo cluster kind mới không có CNI mặc định cat > kind-config.yaml <<EOF kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane - role: worker - role: worker networking: disableDefaultCNI: true # Không dùng CNI mặc định podSubnet: "10.244.0.0/16" EOFkind create cluster --config kind-config.yaml --name cilium-lab
Cài Cilium
helm repo add cilium https://helm.cilium.io/ helm repo update
helm install cilium cilium/cilium
--version 1.16.5
--namespace kube-system
--set image.pullPolicy=IfNotPresent
--set ipam.mode=kubernetes
--set hubble.relay.enabled=true
--set hubble.ui.enabled=true
--set gatewayAPI.enabled=trueChờ Cilium ready
kubectl -n kube-system wait --for=condition=ready pod -l k8s-app=cilium --timeout=120s
Verify
cilium status cilium connectivity test --test-namespace=cilium-test
Lab 2: Bật Hubble UI và Quan sát Traffic
# Port-forward Hubble UI kubectl port-forward -n kube-system svc/hubble-ui 12000:80 &Mở browser: http://localhost:12000
Cài Hubble CLI
HUBBLE_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/hubble/master/stable.txt) curl -L --remote-name-all https://github.com/cilium/hubble/releases/download/$HUBBLE_VERSION/hubble-linux-amd64.tar.gz tar xzvf hubble-linux-amd64.tar.gz sudo mv hubble /usr/local/bin/
Port-forward Hubble Relay
kubectl port-forward -n kube-system svc/hubble-relay 4245:80 &
Quan sát traffic
hubble observe --all-namespaces hubble observe --namespace default --since 5m
Lab 3: Deploy Demo Application
kubectl create namespace lab4
Deploy 3 services: frontend, api-v1, api-v2
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: lab4
spec:
replicas: 2
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
apiVersion: v1
kind: Service
metadata:
name: frontend
namespace: lab4
spec:
selector:
app: frontend
ports:
- port: 80
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-v1
namespace: lab4
spec:
replicas: 3
selector:
matchLabels:
app: api
version: v1
template:
metadata:
labels:
app: api
version: v1
spec:
containers:
- name: api
image: hashicorp/http-echo:latest
args: ["-text=API v1 response", "-listen=:8080"]
ports:
- containerPort: 8080
apiVersion: v1
kind: Service
metadata:
name: api-v1
namespace: lab4
spec:
selector:
app: api
version: v1
ports:
- port: 8080
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-v2
namespace: lab4
spec:
replicas: 1
selector:
matchLabels:
app: api
version: v2
template:
metadata:
labels:
app: api
version: v2
spec:
containers:
- name: api
image: hashicorp/http-echo:latest
args: ["-text=API v2 response (canary)", "-listen=:8080"]
ports:
- containerPort: 8080
apiVersion: v1
kind: Service
metadata:
name: api-v2
namespace: lab4
spec:
selector:
app: api
version: v2
ports:
port: 8080 EOF
Lab 4: Gateway API — Path-based Routing
# Cài Gateway API CRDs kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yamlTạo GatewayClass và Gateway (dùng Cilium implementation)
cat <<EOF | kubectl apply -f - apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: cilium spec: controllerName: io.cilium/gateway-controller
apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: main-gw namespace: lab4 spec: gatewayClassName: cilium listeners:
- name: http protocol: HTTP port: 80 allowedRoutes: namespaces: from: Same EOF
Tạo HTTPRoute: path-based routing
cat <<EOF | kubectl apply -f - apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: app-routes namespace: lab4 spec: parentRefs:
- name: main-gw rules:
/api/* → api-v1 (90%) và api-v2 (10%) canary
- matches:
- path: type: PathPrefix value: /api backendRefs:
- name: api-v1 port: 8080 weight: 90
- name: api-v2 port: 8080 weight: 10
/ → frontend
- backendRefs:
- name: frontend port: 80 EOF
Lấy Gateway external IP
kubectl get gateway main-gw -n lab4
Test routing
GW_IP=$(kubectl get gateway main-gw -n lab4 -o jsonpath='{.status.addresses[0].value}') curl http://$GW_IP/ # → frontend curl http://$GW_IP/api/test # → 90% v1, 10% v2
Test canary distribution (chạy 20 requests)
for i in $(seq 1 20); do curl -s http://$GW_IP/api/test; done | sort | uniq -c
Lab 5: NetworkPolicy — Default-Deny
# Trước khi apply policy: mọi pods có thể giao tiếp kubectl exec -n lab4 deploy/frontend -- curl -s http://api-v1:8080 # successApply default-deny ingress
cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny-ingress namespace: lab4 spec: podSelector: {} policyTypes:
- Ingress EOF
Bây giờ tất cả ingress traffic bị block
kubectl exec -n lab4 deploy/frontend -- curl --connect-timeout 5 http://api-v1:8080
curl: (28) Connection timed out
Allow chỉ frontend → api
cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-frontend-to-api namespace: lab4 spec: podSelector: matchLabels: app: api policyTypes:
- Ingress ingress:
- from:
- podSelector: matchLabels: app: frontend ports:
- protocol: TCP port: 8080 EOF
Bây giờ frontend có thể gọi api
kubectl exec -n lab4 deploy/frontend -- curl -s http://api-v1:8080 # success
Nhưng api không thể gọi api (chặn lateral movement)
kubectl exec -n lab4 deploy/api-v1 -- curl --connect-timeout 5 http://api-v2:8080 # timeout
Lab 6: Quan sát với Hubble
# Xem traffic bị drop trong lab4 hubble observe --namespace lab4 --verdict DROPPEDXem tất cả traffic từ frontend
hubble observe --namespace lab4 --pod-name frontend-xxx
Xem flow giữa api-v1 và api-v2
hubble observe --namespace lab4 --from-pod api-v1-xxx --to-pod api-v2-xxx
Hubble UI: Mở http://localhost:12000 → chọn namespace lab4
→ thấy service map với traffic flows
Cleanup
kubectl delete namespace lab4
kind delete cluster --name cilium-lab
Tổng kết
- ✅ Cilium CNI với eBPF networking
- ✅ Hubble: real-time network observability
- ✅ Gateway API: path-based routing và traffic splitting (canary)
- ✅ NetworkPolicy: default-deny + allow specific
- ✅ Debug dropped packets với Hubble