Kubernetes (K8S) 网络原理

Kubernetes 网络动手实验

通过实际操作来深入理解 Kubernetes 网络原理。以下实验将帮助你探索 Pod 网络、Service 网络、Ingress 和 CNI 插件的工作原理。

实验环境准备

在开始实验之前,你需要准备一个 Kubernetes 集群。可以使用以下工具之一:

  • Minikube:单节点 Kubernetes 集群,适合本地开发和测试
  • Kind:在 Docker 容器中运行的 Kubernetes 集群
  • K3s:轻量级 Kubernetes 发行版,适合边缘计算和 IoT
  • 云服务商提供的 Kubernetes 服务:如 GKE、AKS、EKS 等
# 安装 Minikube # Windows choco install minikube # macOS brew install minikube # Linux curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 sudo install minikube-linux-amd64 /usr/local/bin/minikube # 启动 Minikube minikube start

确保你已经安装了 kubectl 命令行工具,用于与 Kubernetes 集群交互:

# 验证 kubectl 是否正确配置 kubectl version kubectl get nodes

实验 1:探索 Pod 网络

1.1 创建并检查 Pod 网络接口

在这个实验中,我们将创建一个 Pod 并检查其网络接口。

1

创建一个简单的 Nginx Pod:

kubectl run nginx --image=nginx
2

等待 Pod 运行:

kubectl get pod nginx
3

检查 Pod 的 IP 地址:

kubectl get pod nginx -o wide
4

进入 Pod 并检查网络接口:

kubectl exec -it nginx -- bash ip addr route -n cat /etc/resolv.conf exit
5

在节点上查看与 Pod 相关的网络接口(需要 SSH 到节点):

# 如果使用 Minikube minikube ssh # 查看网络接口 ip addr | grep -A 5 cni # 查看网桥 bridge link show # 查看与 Pod 相关的 iptables 规则 sudo iptables-save | grep

1.2 测试 Pod 之间的通信

在这个实验中,我们将创建多个 Pod 并测试它们之间的通信。

1

创建第二个 Pod:

kubectl run busybox --image=busybox -- sleep 3600
2

获取两个 Pod 的 IP 地址:

kubectl get pods -o wide
3

从 busybox Pod 访问 nginx Pod:

# 替换 为实际的 IP 地址 kubectl exec -it busybox -- wget -O-
4

使用 tcpdump 捕获 Pod 之间的通信(需要 SSH 到节点):

# 如果使用 Minikube minikube ssh # 安装 tcpdump sudo apt-get update && sudo apt-get install -y tcpdump # 捕获 Pod 之间的通信 sudo tcpdump -i any host and host -n

实验 2:探索 Service 网络

2.1 创建并检查 Service

在这个实验中,我们将创建一个 Service 并检查其工作原理。

1

为 nginx Pod 创建一个 Service:

kubectl expose pod nginx --port=80 --name=nginx-service
2

检查 Service 详情:

kubectl get service nginx-service kubectl describe service nginx-service
3

检查 Service 的 Endpoints:

kubectl get endpoints nginx-service
4

通过 Service 访问 nginx Pod:

kubectl exec -it busybox -- wget -O- nginx-service
5

检查与 Service 相关的 iptables 规则(需要 SSH 到节点):

# 如果使用 Minikube minikube ssh # 查看 iptables 规则 sudo iptables-save | grep KUBE-SERVICES sudo iptables-save | grep

2.2 测试 Service 负载均衡

在这个实验中,我们将创建一个具有多个 Pod 的 Deployment,并测试 Service 的负载均衡功能。

1

创建一个 Deployment:

kubectl create deployment web --image=nginx --replicas=3
2

为 Deployment 创建一个 Service:

kubectl expose deployment web --port=80 --name=web-service
3

检查 Service 的 Endpoints:

kubectl get endpoints web-service
4

修改 Nginx 的默认页面,使每个 Pod 显示不同的内容:

# 获取 Pod 名称 kubectl get pods -l app=web # 为每个 Pod 设置不同的页面内容 kubectl exec -it -- bash -c 'echo "Pod 1" > /usr/share/nginx/html/index.html' kubectl exec -it -- bash -c 'echo "Pod 2" > /usr/share/nginx/html/index.html' kubectl exec -it -- bash -c 'echo "Pod 3" > /usr/share/nginx/html/index.html'
5

多次访问 Service,观察负载均衡效果:

# 创建一个临时 Pod 用于测试 kubectl run test-client --image=busybox --rm -it -- sh # 在临时 Pod 中多次访问 Service for i in $(seq 1 10); do wget -O- -q web-service; done

2.3 创建不同类型的 Service

在这个实验中,我们将创建不同类型的 Service,包括 ClusterIP、NodePort 和 LoadBalancer。

1

创建 NodePort 类型的 Service:

kubectl expose deployment web --port=80 --type=NodePort --name=web-nodeport
2

获取 NodePort 端口号:

kubectl get service web-nodeport
3

通过节点 IP 和 NodePort 访问服务:

# 如果使用 Minikube minikube ip curl $(minikube ip):
4

创建 LoadBalancer 类型的 Service(在支持的环境中):

kubectl expose deployment web --port=80 --type=LoadBalancer --name=web-lb
5

检查 LoadBalancer Service 状态:

kubectl get service web-lb

注意:在 Minikube 环境中,LoadBalancer 类型的 Service 不会获得外部 IP。可以使用 minikube tunnel 命令来模拟 LoadBalancer 功能。

实验 3:探索 Ingress

3.1 部署 Ingress 控制器

在这个实验中,我们将部署 Nginx Ingress 控制器并创建 Ingress 资源。

1

在 Minikube 中启用 Ingress 插件:

minikube addons enable ingress
2

验证 Ingress 控制器是否运行:

kubectl get pods -n ingress-nginx
3

创建两个示例应用:

# 创建第一个应用 kubectl create deployment app1 --image=nginx kubectl expose deployment app1 --port=80 --name=app1-service # 修改第一个应用的默认页面 kubectl exec -it $(kubectl get pods -l app=app1 -o jsonpath='{.items[0].metadata.name}') -- bash -c 'echo "App 1" > /usr/share/nginx/html/index.html' # 创建第二个应用 kubectl create deployment app2 --image=nginx kubectl expose deployment app2 --port=80 --name=app2-service # 修改第二个应用的默认页面 kubectl exec -it $(kubectl get pods -l app=app2 -o jsonpath='{.items[0].metadata.name}') -- bash -c 'echo "App 2" > /usr/share/nginx/html/index.html'
4

创建 Ingress 资源:

# 创建一个简单的 Ingress 资源 cat > ingress.yaml << 'EOF' apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: demo-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - host: demo.example.com # 根据实际情况修改 http: paths: - path: /app1 pathType: Prefix backend: service: name: app1-service port: number: 80 - path: /app2 pathType: Prefix backend: service: name: app2-service port: number: 80 EOF # 应用配置 kubectl apply -f ingress.yaml
5

检查 Ingress 资源:

kubectl get ingress kubectl describe ingress example-ingress
6

测试 Ingress 路由:

# 获取 Minikube IP minikube ip # 添加 hosts 文件条目(需要管理员权限) # Windows: C:\Windows\System32\drivers\etc\hosts # Linux/macOS: /etc/hosts # 添加以下行: # example.com # 测试访问 curl -H "Host: example.com" http:///app1 curl -H "Host: example.com" http:///app2

3.2 配置 TLS

在这个实验中,我们将为 Ingress 配置 TLS。

1

生成自签名证书:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=demo.example.com"
2

创建 TLS Secret:

kubectl create secret tls demo-tls --key tls.key --cert tls.crt
3

更新 Ingress 配置,添加 TLS:

# 创建带 TLS 的 Ingress cat > ingress-tls.yaml << 'EOF' apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: demo-ingress-tls spec: tls: - hosts: - demo.example.com secretName: demo-tls rules: - host: demo.example.com http: paths: - path: /app1 pathType: Prefix backend: service: name: app1-service port: number: 80 - path: /app2 pathType: Prefix backend: service: name: app2-service port: number: 80 EOF # 应用配置 kubectl apply -f ingress-tls.yaml
4

测试 HTTPS 访问:

curl -k -H "Host: example.com" https:///app1 curl -k -H "Host: example.com" https:///app2

实验 4:探索 CNI 插件

4.1 检查 CNI 配置

在这个实验中,我们将检查 Kubernetes 集群中的 CNI 配置。

1

SSH 到 Kubernetes 节点:

# 如果使用 Minikube minikube ssh
2

检查 CNI 配置文件:

ls -la /etc/cni/net.d/ cat /etc/cni/net.d/*
3

检查 CNI 插件二进制文件:

ls -la /opt/cni/bin/
4

检查 Pod CIDR 分配:

# 返回到本地终端 exit # 检查节点的 Pod CIDR kubectl get nodes -o jsonpath='{.items[*].spec.podCIDR}'

4.2 分析 CNI 插件工作原理

在这个实验中,我们将分析 CNI 插件的工作原理。

1

查看 kubelet 日志中与 CNI 相关的部分:

# 如果使用 Minikube minikube ssh # 查看 kubelet 日志 journalctl -u kubelet | grep -i cni
2

检查网络接口和路由:

# 查看网络接口 ip addr # 查看路由表 ip route # 查看网桥 bridge link show
3

检查 iptables 规则:

# 查看 iptables 规则 sudo iptables-save
4

创建一个新的 Pod 并观察网络变化:

# 返回到本地终端 exit # 创建一个新的 Pod kubectl run test-pod --image=nginx # 等待 Pod 运行 kubectl get pod test-pod # 再次 SSH 到节点 minikube ssh # 查看新创建的网络接口 ip addr | grep -A 5 cni # 查看新的路由 ip route | grep

实验 5:网络策略

5.1 创建并测试网络策略

在这个实验中,我们将创建网络策略并测试其效果。注意:此实验需要支持网络策略的 CNI 插件(如 Calico)。

1

创建测试命名空间和 Pod:

# 创建命名空间 kubectl create namespace policy-test # 创建服务器 Pod kubectl run web --image=nginx -n policy-test --labels=app=web # 创建客户端 Pod kubectl run client-a --image=busybox -n policy-test --labels=app=client-a -- sleep 3600 kubectl run client-b --image=busybox -n policy-test --labels=app=client-b -- sleep 3600
2

测试连通性(所有客户端都应该能够访问服务器):

# 获取服务器 Pod 的 IP kubectl get pod web -n policy-test -o wide # 从客户端 A 访问服务器 kubectl exec -it client-a -n policy-test -- wget -O- # 从客户端 B 访问服务器 kubectl exec -it client-b -n policy-test -- wget -O-
3

创建网络策略,只允许客户端 A 访问服务器:

# 创建 network-policy.yaml 文件 cat > network-policy.yaml << 'EOF' apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: frontend-policy namespace: default spec: podSelector: matchLabels: app: frontend policyTypes: - Ingress - Egress ingress: - from: - namespaceSelector: matchLabels: purpose: production - podSelector: matchLabels: role: api ports: - protocol: TCP port: 80 egress: - to: - podSelector: matchLabels: app: db ports: - protocol: TCP port: 5432 EOF # 应用网络策略 kubectl apply -f network-policy.yaml
4

再次测试连通性(只有客户端 A 应该能够访问服务器):

# 从客户端 A 访问服务器(应该成功) kubectl exec -it client-a -n policy-test -- wget -O- # 从客户端 B 访问服务器(应该失败) kubectl exec -it client-b -n policy-test -- wget -O-
5

清理资源:

kubectl delete namespace policy-test

总结

通过以上实验,你应该对 Kubernetes 网络的工作原理有了更深入的理解。这些实验涵盖了 Pod 网络、Service 网络、Ingress 和 CNI 插件等核心概念,帮助你将理论知识应用到实践中。

在实际工作中,你可能会遇到更复杂的网络场景,如多集群网络、混合云网络等。建议你继续深入学习 Kubernetes 网络,探索更高级的主题。

返回首页