概述
本指南将帮助您使用 Kind (Kubernetes in Docker) 快速创建一个 Kubernetes 环境,并在其中部署和验证 Flannel + Multus-CNI 多网段隔离方案。这是一个完整的端到端验证环境,适合开发、测试和学习使用。
环境特点
- 快速部署:5分钟内完成集群创建
- 完整功能:支持多网段隔离验证
- 易于清理:一键删除整个环境
- 资源友好:适合本地开发机器运行
环境要求
系统要求
1
2
3
4
5
6
7
8
| # 检查系统信息
uname -a
# 检查可用内存(建议 8GB+)
free -h
# 检查磁盘空间(建议 20GB+)
df -h
|
必需软件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 1. Docker 安装和配置
# macOS
brew install docker
# 或者下载 Docker Desktop
# Linux (Ubuntu/Debian)
sudo apt-get update
sudo apt-get install docker.io
sudo systemctl enable docker
sudo systemctl start docker
sudo usermod -aG docker $USER
# 验证 Docker
docker version
docker run hello-world
|
1
2
3
4
5
6
7
8
9
10
11
| # 2. Kind 安装
# macOS
brew install kind
# Linux
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
# 验证 Kind
kind version
|
1
2
3
4
5
6
7
8
9
10
11
| # 3. kubectl 安装
# macOS
brew install kubectl
# Linux
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
# 验证 kubectl
kubectl version --client
|
1
2
3
4
5
6
7
8
9
| # 4. Helm 安装(可选)
# macOS
brew install helm
# Linux
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# 验证 Helm
helm version
|
Kind 集群配置
1. 创建 Kind 配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
| # kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: flannel-multus-demo
networking:
# 禁用默认 CNI,我们将手动安装 Flannel
disableDefaultCNI: true
# 配置 Pod 子网
podSubnet: "10.244.0.0/16"
# 配置 Service 子网
serviceSubnet: "10.96.0.0/12"
# API Server 端口
apiServerPort: 6443
nodes:
# 控制平面节点
- role: control-plane
image: kindest/node:v1.28.0
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
# HTTP 端口映射
- containerPort: 80
hostPort: 80
protocol: TCP
# HTTPS 端口映射
- containerPort: 443
hostPort: 443
protocol: TCP
# 额外的网络接口配置
extraMounts:
- hostPath: /dev
containerPath: /dev
propagation: HostToContainer
# 工作节点 1
- role: worker
image: kindest/node:v1.28.0
labels:
node-type: "business"
extraMounts:
- hostPath: /dev
containerPath: /dev
propagation: HostToContainer
# 工作节点 2
- role: worker
image: kindest/node:v1.28.0
labels:
node-type: "storage"
extraMounts:
- hostPath: /dev
containerPath: /dev
propagation: HostToContainer
|
2. 创建集群
1
2
3
4
5
6
7
8
9
| # 创建 Kind 集群
kind create cluster --config=kind-config.yaml
# 验证集群状态
kubectl cluster-info
kubectl get nodes -o wide
# 检查节点标签
kubectl get nodes --show-labels
|
3. 集群基础配置
1
2
3
4
5
6
7
8
| # 等待节点就绪
kubectl wait --for=condition=Ready nodes --all --timeout=300s
# 检查系统 Pod 状态
kubectl get pods -n kube-system
# 由于禁用了默认 CNI,节点会显示 NotReady,这是正常的
kubectl get nodes
|
Flannel 部署
1. 下载 Flannel 配置
1
2
3
4
5
| # 下载官方 Flannel 配置
wget https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
# 或者使用 curl
curl -O https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
|
2. 修改 Flannel 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| # 备份原始配置
cp kube-flannel.yml kube-flannel.yml.backup
# 修改配置以适配 Kind 环境
cat > flannel-kind-patch.yaml << 'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
name: kube-flannel-cfg
namespace: kube-flannel
labels:
tier: node
app: flannel
k8s-app: flannel
data:
cni-conf.json: |
{
"name": "cbr0",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan"
}
}
EOF
|
3. 部署 Flannel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 创建 Flannel 命名空间
kubectl create namespace kube-flannel
# 应用修改后的配置
kubectl apply -f flannel-kind-patch.yaml
# 部署 Flannel
kubectl apply -f kube-flannel.yml
# 等待 Flannel Pod 就绪
kubectl wait --for=condition=Ready pods -l app=flannel -n kube-flannel --timeout=300s
# 验证 Flannel 状态
kubectl get pods -n kube-flannel
kubectl logs -n kube-flannel -l app=flannel
|
4. 验证基础网络
1
2
3
4
5
6
7
8
9
10
11
12
13
| # 检查节点状态(应该变为 Ready)
kubectl get nodes
# 检查 CNI 配置
for node in $(kubectl get nodes -o name | cut -d/ -f2); do
echo "=== Node: $node ==="
docker exec $node ls -la /etc/cni/net.d/
docker exec $node cat /etc/cni/net.d/10-flannel.conflist
done
# 测试基础网络连通性
kubectl run test-pod --image=busybox --rm -it --restart=Never -- /bin/sh
# 在 Pod 中执行:ping kubernetes.default.svc.cluster.local
|
Multus-CNI 部署
1. 创建 Multus 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
| # 创建 Multus 系统命名空间
kubectl create namespace multus-system
# 创建 Multus ConfigMap
cat > multus-config.yaml << 'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
name: multus-cni-config
namespace: multus-system
labels:
tier: node
app: multus
data:
cni-conf.json: |
{
"cniVersion": "0.3.1",
"name": "multus-cni-network",
"type": "multus",
"capabilities": {
"portMappings": true
},
"delegates": [
{
"cniVersion": "0.3.1",
"name": "default-cni-network",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
],
"kubeconfig": "/etc/cni/net.d/multus.d/multus.kubeconfig"
}
EOF
kubectl apply -f multus-config.yaml
|
2. 部署 Multus DaemonSet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
| # 创建 Multus RBAC
cat > multus-rbac.yaml << 'EOF'
apiVersion: v1
kind: ServiceAccount
metadata:
name: multus
namespace: multus-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: multus
rules:
- apiGroups: ["k8s.cni.cncf.io"]
resources:
- '*'
verbs:
- '*'
- apiGroups:
- ""
resources:
- pods
- pods/status
verbs:
- get
- update
- apiGroups:
- ""
- events.k8s.io
resources:
- events
verbs:
- create
- patch
- update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: multus
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: multus
subjects:
- kind: ServiceAccount
name: multus
namespace: multus-system
EOF
kubectl apply -f multus-rbac.yaml
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
| # 创建 Multus DaemonSet
cat > multus-daemonset.yaml << 'EOF'
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: kube-multus-ds
namespace: multus-system
labels:
tier: node
app: multus
name: multus
spec:
selector:
matchLabels:
name: multus
updateStrategy:
type: RollingUpdate
template:
metadata:
labels:
tier: node
app: multus
name: multus
spec:
hostNetwork: true
tolerations:
- operator: Exists
effect: NoSchedule
- operator: Exists
effect: NoExecute
serviceAccountName: multus
containers:
- name: kube-multus
image: ghcr.io/k8snetworkplumbingwg/multus-cni:v4.0.2
command: ["/entrypoint.sh"]
args:
- "--multus-conf-file=auto"
- "--multus-autoconfig-dir=/host/etc/cni/net.d"
- "--cni-conf-dir=/host/etc/cni/net.d"
- "--multus-kubeconfig-file-host=/etc/cni/net.d/multus.d/multus.kubeconfig"
- "--cleanup-config-on-exit=true"
resources:
requests:
cpu: "100m"
memory: "50Mi"
limits:
cpu: "100m"
memory: "50Mi"
securityContext:
privileged: true
volumeMounts:
- name: cni
mountPath: /host/etc/cni/net.d
- name: cnibin
mountPath: /host/opt/cni/bin
- name: multus-cfg
mountPath: /tmp/multus-conf
terminationGracePeriodSeconds: 10
volumes:
- name: cni
hostPath:
path: /etc/cni/net.d
- name: cnibin
hostPath:
path: /opt/cni/bin
- name: multus-cfg
configMap:
name: multus-cni-config
items:
- key: cni-conf.json
path: 70-multus.conf
EOF
kubectl apply -f multus-daemonset.yaml
|
3. 验证 Multus 部署
1
2
3
4
5
6
7
8
9
10
11
12
| # 等待 Multus Pod 就绪
kubectl wait --for=condition=Ready pods -l name=multus -n multus-system --timeout=300s
# 检查 Multus 状态
kubectl get pods -n multus-system
kubectl logs -n multus-system -l name=multus
# 验证 CNI 配置
for node in $(kubectl get nodes -o name | cut -d/ -f2); do
echo "=== Node: $node ==="
docker exec $node ls -la /etc/cni/net.d/
done
|
网络附件定义创建
1. 创建测试命名空间
1
2
3
4
5
6
7
8
9
| # 创建业务命名空间
kubectl create namespace business-apps
kubectl create namespace storage-apps
kubectl create namespace test-apps
# 添加命名空间标签
kubectl label namespace business-apps name=business-apps
kubectl label namespace storage-apps name=storage-apps
kubectl label namespace test-apps name=test-apps
|
2. 创建 MacVLAN 网络(模拟)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| # macvlan-network.yaml
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: macvlan-network
namespace: business-apps
spec:
config: '{
"cniVersion": "0.3.1",
"type": "macvlan",
"master": "eth0",
"mode": "bridge",
"ipam": {
"type": "host-local",
"subnet": "192.168.100.0/24",
"rangeStart": "192.168.100.10",
"rangeEnd": "192.168.100.100",
"gateway": "192.168.100.1"
}
}'
|
3. 创建 Bridge 网络
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| # bridge-network.yaml
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: bridge-network
namespace: storage-apps
spec:
config: '{
"cniVersion": "0.3.1",
"type": "bridge",
"bridge": "br-storage",
"isGateway": true,
"isDefaultGateway": false,
"ipMasq": true,
"hairpinMode": true,
"ipam": {
"type": "host-local",
"subnet": "172.16.0.0/24",
"rangeStart": "172.16.0.10",
"rangeEnd": "172.16.0.100",
"gateway": "172.16.0.1"
}
}'
|
4. 创建 Host-Local 网络
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # host-local-network.yaml
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: host-local-network
namespace: test-apps
spec:
config: '{
"cniVersion": "0.3.1",
"type": "host-local",
"subnet": "10.100.0.0/24",
"rangeStart": "10.100.0.10",
"rangeEnd": "10.100.0.100",
"gateway": "10.100.0.1"
}'
|
5. 应用网络附件定义
1
2
3
4
5
6
7
8
| # 应用所有网络附件定义
kubectl apply -f macvlan-network.yaml
kubectl apply -f bridge-network.yaml
kubectl apply -f host-local-network.yaml
# 验证网络附件定义
kubectl get network-attachment-definitions --all-namespaces
kubectl describe network-attachment-definitions macvlan-network -n business-apps
|
验证应用部署
1. 单网络测试应用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| # single-network-test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: single-network-test
namespace: test-apps
spec:
replicas: 2
selector:
matchLabels:
app: single-network-test
template:
metadata:
labels:
app: single-network-test
spec:
containers:
- name: test-container
image: busybox:1.35
command: ["sleep", "3600"]
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 100m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: single-network-service
namespace: test-apps
spec:
selector:
app: single-network-test
ports:
- port: 80
targetPort: 80
type: ClusterIP
|
2. 多网络测试应用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
| # multi-network-test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: multi-network-test
namespace: business-apps
spec:
replicas: 2
selector:
matchLabels:
app: multi-network-test
template:
metadata:
labels:
app: multi-network-test
annotations:
k8s.v1.cni.cncf.io/networks: |
[
{
"name": "macvlan-network",
"interface": "net1"
}
]
spec:
containers:
- name: test-container
image: nicolaka/netshoot:latest
command: ["sleep", "3600"]
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
name: multi-network-service
namespace: business-apps
spec:
selector:
app: multi-network-test
ports:
- port: 80
targetPort: 80
type: ClusterIP
|
3. 存储网络测试应用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
| # storage-network-test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: storage-network-test
namespace: storage-apps
spec:
replicas: 1
selector:
matchLabels:
app: storage-network-test
template:
metadata:
labels:
app: storage-network-test
annotations:
k8s.v1.cni.cncf.io/networks: |
[
{
"name": "bridge-network",
"interface": "storage0"
}
]
spec:
containers:
- name: storage-container
image: minio/minio:latest
command:
- /bin/bash
- -c
args:
- minio server /data --console-address ":9001"
ports:
- containerPort: 9000
name: api
- containerPort: 9001
name: console
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: 500m
memory: 1Gi
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
emptyDir: {}
|
4. 部署测试应用
1
2
3
4
5
6
7
8
9
10
| # 部署所有测试应用
kubectl apply -f single-network-test.yaml
kubectl apply -f multi-network-test.yaml
kubectl apply -f storage-network-test.yaml
# 等待 Pod 就绪
kubectl wait --for=condition=Ready pods --all --all-namespaces --timeout=300s
# 检查 Pod 状态
kubectl get pods --all-namespaces -o wide
|
网络验证测试
1. 基础网络连通性测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
| # 创建网络测试脚本
cat > network-verification.sh << 'EOF'
#!/bin/bash
echo "=== 1. 基础网络连通性测试 ==="
# 获取测试 Pod
SINGLE_POD=$(kubectl get pods -n test-apps -l app=single-network-test -o jsonpath='{.items[0].metadata.name}')
MULTI_POD=$(kubectl get pods -n business-apps -l app=multi-network-test -o jsonpath='{.items[0].metadata.name}')
STORAGE_POD=$(kubectl get pods -n storage-apps -l app=storage-network-test -o jsonpath='{.items[0].metadata.name}')
echo "测试 Pod:"
echo " Single Network: $SINGLE_POD"
echo " Multi Network: $MULTI_POD"
echo " Storage Network: $STORAGE_POD"
echo "\n=== 2. 网络接口检查 ==="
# 检查单网络 Pod
echo "单网络 Pod 接口:"
kubectl exec -n test-apps $SINGLE_POD -- ip addr show
# 检查多网络 Pod
echo "\n多网络 Pod 接口:"
kubectl exec -n business-apps $MULTI_POD -- ip addr show
# 检查存储网络 Pod
echo "\n存储网络 Pod 接口:"
kubectl exec -n storage-apps $STORAGE_POD -- ip addr show
echo "\n=== 3. 路由表检查 ==="
# 检查路由表
echo "多网络 Pod 路由表:"
kubectl exec -n business-apps $MULTI_POD -- ip route show
echo "\n=== 4. DNS 解析测试 ==="
# DNS 解析测试
echo "DNS 解析测试:"
kubectl exec -n test-apps $SINGLE_POD -- nslookup kubernetes.default.svc.cluster.local
echo "\n=== 5. 服务连通性测试 ==="
# 服务连通性测试
echo "集群内服务访问测试:"
kubectl exec -n test-apps $SINGLE_POD -- wget -qO- --timeout=5 http://single-network-service.test-apps.svc.cluster.local || echo "连接失败"
echo "\n=== 6. 跨命名空间连通性测试 ==="
# 跨命名空间连通性
echo "跨命名空间访问测试:"
kubectl exec -n business-apps $MULTI_POD -- wget -qO- --timeout=5 http://single-network-service.test-apps.svc.cluster.local || echo "连接失败"
echo "\n=== 验证完成 ==="
EOF
chmod +x network-verification.sh
./network-verification.sh
|
2. 多网络接口验证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
| # 详细的多网络接口验证
cat > multi-network-verification.sh << 'EOF'
#!/bin/bash
echo "=== 多网络接口详细验证 ==="
# 获取多网络 Pod
MULTI_POD=$(kubectl get pods -n business-apps -l app=multi-network-test -o jsonpath='{.items[0].metadata.name}')
if [ -z "$MULTI_POD" ]; then
echo "未找到多网络测试 Pod"
exit 1
fi
echo "测试 Pod: $MULTI_POD"
echo "\n=== 1. 网络接口详情 ==="
kubectl exec -n business-apps $MULTI_POD -- ip -d addr show
echo "\n=== 2. 网络接口统计 ==="
kubectl exec -n business-apps $MULTI_POD -- ip -s link show
echo "\n=== 3. 路由表详情 ==="
kubectl exec -n business-apps $MULTI_POD -- ip route show table all
echo "\n=== 4. ARP 表 ==="
kubectl exec -n business-apps $MULTI_POD -- arp -a
echo "\n=== 5. 网络命名空间 ==="
kubectl exec -n business-apps $MULTI_POD -- ip netns list
echo "\n=== 6. 网络连通性测试 ==="
# 测试默认接口连通性
echo "默认接口连通性:"
kubectl exec -n business-apps $MULTI_POD -- ping -c 3 kubernetes.default.svc.cluster.local
# 测试附加接口(如果配置了 IP)
echo "\n检查附加网络接口配置:"
kubectl exec -n business-apps $MULTI_POD -- ip addr show net1 2>/dev/null || echo "net1 接口未配置或不存在"
echo "\n=== 验证完成 ==="
EOF
chmod +x multi-network-verification.sh
./multi-network-verification.sh
|
3. 网络性能测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
| # 网络性能测试
cat > network-performance-test.sh << 'EOF'
#!/bin/bash
echo "=== 网络性能测试 ==="
# 部署 iperf3 服务器
cat > iperf3-server.yaml << 'YAML'
apiVersion: apps/v1
kind: Deployment
metadata:
name: iperf3-server
namespace: test-apps
spec:
replicas: 1
selector:
matchLabels:
app: iperf3-server
template:
metadata:
labels:
app: iperf3-server
spec:
containers:
- name: iperf3-server
image: networkstatic/iperf3:latest
command: ["iperf3", "-s"]
ports:
- containerPort: 5201
---
apiVersion: v1
kind: Service
metadata:
name: iperf3-server-service
namespace: test-apps
spec:
selector:
app: iperf3-server
ports:
- port: 5201
targetPort: 5201
type: ClusterIP
YAML
kubectl apply -f iperf3-server.yaml
# 等待服务就绪
echo "等待 iperf3 服务就绪..."
kubectl wait --for=condition=Ready pods -l app=iperf3-server -n test-apps --timeout=60s
# 获取客户端 Pod
CLIENT_POD=$(kubectl get pods -n business-apps -l app=multi-network-test -o jsonpath='{.items[0].metadata.name}')
if [ -n "$CLIENT_POD" ]; then
echo "\n=== 执行性能测试 ==="
echo "客户端 Pod: $CLIENT_POD"
# TCP 性能测试
echo "\nTCP 性能测试 (10秒):"
kubectl exec -n business-apps $CLIENT_POD -- iperf3 -c iperf3-server-service.test-apps.svc.cluster.local -t 10
# UDP 性能测试
echo "\nUDP 性能测试 (10秒):"
kubectl exec -n business-apps $CLIENT_POD -- iperf3 -c iperf3-server-service.test-apps.svc.cluster.local -u -t 10
else
echo "未找到客户端 Pod"
fi
echo "\n=== 性能测试完成 ==="
EOF
chmod +x network-performance-test.sh
./network-performance-test.sh
|
故障排查和调试
1. 集群状态检查
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| # 创建集群诊断脚本
cat > cluster-diagnosis.sh << 'EOF'
#!/bin/bash
echo "=== Kind 集群诊断 ==="
echo "\n=== 1. 集群基本信息 ==="
kind get clusters
kubectl cluster-info
kubectl version --short
echo "\n=== 2. 节点状态 ==="
kubectl get nodes -o wide
kubectl describe nodes
echo "\n=== 3. 系统 Pod 状态 ==="
kubectl get pods --all-namespaces
kubectl get pods -n kube-system -o wide
kubectl get pods -n kube-flannel -o wide
kubectl get pods -n multus-system -o wide
echo "\n=== 4. 网络配置检查 ==="
for node in $(kubectl get nodes -o name | cut -d/ -f2); do
echo "\n--- Node: $node ---"
echo "CNI 配置:"
docker exec $node ls -la /etc/cni/net.d/
echo "\nCNI 二进制:"
docker exec $node ls -la /opt/cni/bin/
echo "\n网络接口:"
docker exec $node ip addr show
done
echo "\n=== 5. 网络附件定义 ==="
kubectl get network-attachment-definitions --all-namespaces
echo "\n=== 6. 服务和端点 ==="
kubectl get services --all-namespaces
kubectl get endpoints --all-namespaces
echo "\n=== 7. 事件日志 ==="
kubectl get events --all-namespaces --sort-by='.lastTimestamp' | tail -20
echo "\n=== 诊断完成 ==="
EOF
chmod +x cluster-diagnosis.sh
./cluster-diagnosis.sh
|
2. 网络问题排查
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
| # 网络问题排查脚本
cat > network-troubleshoot.sh << 'EOF'
#!/bin/bash
echo "=== 网络问题排查 ==="
echo "\n=== 1. CNI 插件状态 ==="
# 检查 Flannel 状态
echo "Flannel 状态:"
kubectl get pods -n kube-flannel
kubectl logs -n kube-flannel -l app=flannel --tail=50
# 检查 Multus 状态
echo "\nMultus 状态:"
kubectl get pods -n multus-system
kubectl logs -n multus-system -l name=multus --tail=50
echo "\n=== 2. 网络配置验证 ==="
# 验证 CNI 配置文件
for node in $(kubectl get nodes -o name | cut -d/ -f2); do
echo "\n--- Node: $node ---"
echo "CNI 配置文件:"
docker exec $node find /etc/cni/net.d/ -name "*.conf*" -exec cat {} \;
done
echo "\n=== 3. Pod 网络状态 ==="
# 检查 Pod 网络状态
for ns in $(kubectl get namespaces -o name | cut -d/ -f2); do
pods=$(kubectl get pods -n $ns -o name 2>/dev/null)
if [ -n "$pods" ]; then
echo "\n--- Namespace: $ns ---"
for pod in $pods; do
pod_name=$(echo $pod | cut -d/ -f2)
echo "Pod: $pod_name"
kubectl exec -n $ns $pod_name -- ip addr show 2>/dev/null || echo " 无法访问 Pod 网络接口"
done
fi
done
echo "\n=== 4. 网络连通性测试 ==="
# 创建临时测试 Pod
kubectl run network-test --image=busybox --rm -it --restart=Never -- /bin/sh -c "
echo '测试 DNS 解析:'
nslookup kubernetes.default.svc.cluster.local
echo '测试网络连通性:'
ping -c 3 kubernetes.default.svc.cluster.local
" 2>/dev/null || echo "网络测试失败"
echo "\n=== 排查完成 ==="
EOF
chmod +x network-troubleshoot.sh
./network-troubleshoot.sh
|
3. 日志收集
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
| # 日志收集脚本
cat > collect-logs.sh << 'EOF'
#!/bin/bash
LOG_DIR="kind-logs-$(date +%Y%m%d-%H%M%S)"
mkdir -p $LOG_DIR
echo "=== 收集 Kind 集群日志 ==="
echo "日志目录: $LOG_DIR"
# 收集集群信息
echo "收集集群信息..."
kubectl cluster-info > $LOG_DIR/cluster-info.txt
kubectl get nodes -o wide > $LOG_DIR/nodes.txt
kubectl get pods --all-namespaces -o wide > $LOG_DIR/pods.txt
kubectl get services --all-namespaces > $LOG_DIR/services.txt
kubectl get network-attachment-definitions --all-namespaces > $LOG_DIR/network-attachments.txt
# 收集系统 Pod 日志
echo "收集系统 Pod 日志..."
mkdir -p $LOG_DIR/pod-logs
# Flannel 日志
kubectl logs -n kube-flannel -l app=flannel > $LOG_DIR/pod-logs/flannel.log
# Multus 日志
kubectl logs -n multus-system -l name=multus > $LOG_DIR/pod-logs/multus.log
# 测试应用日志
for ns in test-apps business-apps storage-apps; do
pods=$(kubectl get pods -n $ns -o name 2>/dev/null)
if [ -n "$pods" ]; then
for pod in $pods; do
pod_name=$(echo $pod | cut -d/ -f2)
kubectl logs -n $ns $pod_name > $LOG_DIR/pod-logs/${ns}-${pod_name}.log 2>/dev/null
done
fi
done
# 收集事件
echo "收集事件日志..."
kubectl get events --all-namespaces --sort-by='.lastTimestamp' > $LOG_DIR/events.txt
# 收集节点配置
echo "收集节点配置..."
mkdir -p $LOG_DIR/node-configs
for node in $(kubectl get nodes -o name | cut -d/ -f2); do
echo "收集节点 $node 配置..."
docker exec $node ls -la /etc/cni/net.d/ > $LOG_DIR/node-configs/${node}-cni-configs.txt
docker exec $node ip addr show > $LOG_DIR/node-configs/${node}-interfaces.txt
docker exec $node ip route show > $LOG_DIR/node-configs/${node}-routes.txt
done
echo "日志收集完成: $LOG_DIR"
echo "可以使用以下命令打包日志:"
echo "tar -czf ${LOG_DIR}.tar.gz $LOG_DIR"
EOF
chmod +x collect-logs.sh
./collect-logs.sh
|
清理和重置
1. 清理测试资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| # 清理测试应用
cat > cleanup-test-apps.sh << 'EOF'
#!/bin/bash
echo "=== 清理测试应用 ==="
# 删除测试应用
echo "删除测试应用..."
kubectl delete deployment --all -n test-apps
kubectl delete deployment --all -n business-apps
kubectl delete deployment --all -n storage-apps
# 删除服务
echo "删除服务..."
kubectl delete service --all -n test-apps
kubectl delete service --all -n business-apps
kubectl delete service --all -n storage-apps
# 删除网络附件定义
echo "删除网络附件定义..."
kubectl delete network-attachment-definitions --all --all-namespaces
# 删除测试命名空间
echo "删除测试命名空间..."
kubectl delete namespace test-apps
kubectl delete namespace business-apps
kubectl delete namespace storage-apps
echo "测试资源清理完成"
EOF
chmod +x cleanup-test-apps.sh
./cleanup-test-apps.sh
|
2. 重置集群
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| # 重置集群脚本
cat > reset-cluster.sh << 'EOF'
#!/bin/bash
echo "=== 重置 Kind 集群 ==="
read -p "确定要重置集群吗?这将删除所有数据 (y/N): " confirm
if [[ $confirm != [yY] ]]; then
echo "操作已取消"
exit 0
fi
# 删除现有集群
echo "删除现有集群..."
kind delete cluster --name flannel-multus-demo
# 清理 Docker 资源
echo "清理 Docker 资源..."
docker system prune -f
# 重新创建集群
echo "重新创建集群..."
kind create cluster --config=kind-config.yaml
echo "集群重置完成"
echo "请重新部署 Flannel 和 Multus-CNI"
EOF
chmod +x reset-cluster.sh
|
3. 完全清理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| # 完全清理脚本
cat > complete-cleanup.sh << 'EOF'
#!/bin/bash
echo "=== 完全清理 Kind 环境 ==="
read -p "确定要完全清理环境吗?这将删除所有 Kind 集群和相关资源 (y/N): " confirm
if [[ $confirm != [yY] ]]; then
echo "操作已取消"
exit 0
fi
# 删除所有 Kind 集群
echo "删除所有 Kind 集群..."
for cluster in $(kind get clusters); do
echo "删除集群: $cluster"
kind delete cluster --name $cluster
done
# 清理 Docker 资源
echo "清理 Docker 资源..."
docker system prune -af
docker volume prune -f
# 清理配置文件
echo "清理配置文件..."
rm -f kind-config.yaml
rm -f kube-flannel.yml*
rm -f flannel-kind-patch.yaml
rm -f multus-*.yaml
rm -f *-network*.yaml
rm -f *-test.yaml
rm -f *.sh
echo "完全清理完成"
EOF
chmod +x complete-cleanup.sh
|
自动化脚本
1. 一键部署脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
| # 创建一键部署脚本
cat > deploy-all.sh << 'EOF'
#!/bin/bash
set -e
echo "=== Kind + Flannel + Multus-CNI 一键部署 ==="
# 检查依赖
echo "检查依赖..."
command -v docker >/dev/null 2>&1 || { echo "Docker 未安装"; exit 1; }
command -v kind >/dev/null 2>&1 || { echo "Kind 未安装"; exit 1; }
command -v kubectl >/dev/null 2>&1 || { echo "kubectl 未安装"; exit 1; }
# 创建集群
echo "\n=== 1. 创建 Kind 集群 ==="
if kind get clusters | grep -q "flannel-multus-demo"; then
echo "集群已存在,跳过创建"
else
kind create cluster --config=kind-config.yaml
fi
# 等待节点就绪
echo "\n=== 2. 等待节点就绪 ==="
kubectl wait --for=condition=Ready nodes --all --timeout=300s
# 部署 Flannel
echo "\n=== 3. 部署 Flannel ==="
if ! kubectl get namespace kube-flannel >/dev/null 2>&1; then
kubectl create namespace kube-flannel
fi
kubectl apply -f flannel-kind-patch.yaml
kubectl apply -f kube-flannel.yml
kubectl wait --for=condition=Ready pods -l app=flannel -n kube-flannel --timeout=300s
# 部署 Multus-CNI
echo "\n=== 4. 部署 Multus-CNI ==="
if ! kubectl get namespace multus-system >/dev/null 2>&1; then
kubectl create namespace multus-system
fi
kubectl apply -f multus-config.yaml
kubectl apply -f multus-rbac.yaml
kubectl apply -f multus-daemonset.yaml
kubectl wait --for=condition=Ready pods -l name=multus -n multus-system --timeout=300s
# 创建测试命名空间
echo "\n=== 5. 创建测试命名空间 ==="
kubectl create namespace business-apps --dry-run=client -o yaml | kubectl apply -f -
kubectl create namespace storage-apps --dry-run=client -o yaml | kubectl apply -f -
kubectl create namespace test-apps --dry-run=client -o yaml | kubectl apply -f -
# 部署网络附件定义
echo "\n=== 6. 部署网络附件定义 ==="
kubectl apply -f macvlan-network.yaml
kubectl apply -f bridge-network.yaml
kubectl apply -f host-local-network.yaml
# 部署测试应用
echo "\n=== 7. 部署测试应用 ==="
kubectl apply -f single-network-test.yaml
kubectl apply -f multi-network-test.yaml
kubectl apply -f storage-network-test.yaml
# 等待应用就绪
echo "\n=== 8. 等待应用就绪 ==="
kubectl wait --for=condition=Ready pods --all --all-namespaces --timeout=300s
# 验证部署
echo "\n=== 9. 验证部署 ==="
echo "集群状态:"
kubectl get nodes
echo "\nPod 状态:"
kubectl get pods --all-namespaces
echo "\n网络附件定义:"
kubectl get network-attachment-definitions --all-namespaces
echo "\n=== 部署完成 ==="
echo "可以运行以下命令进行验证:"
echo " ./network-verification.sh"
echo " ./multi-network-verification.sh"
echo " ./network-performance-test.sh"
EOF
chmod +x deploy-all.sh
|
2. 快速验证脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
| # 创建快速验证脚本
cat > quick-verify.sh << 'EOF'
#!/bin/bash
echo "=== Kind + Flannel + Multus-CNI 快速验证 ==="
# 检查集群状态
echo "\n=== 1. 集群状态检查 ==="
kubectl get nodes
kubectl get pods --all-namespaces | grep -E "(flannel|multus)"
# 检查网络附件定义
echo "\n=== 2. 网络附件定义检查 ==="
kubectl get network-attachment-definitions --all-namespaces
# 检查测试应用
echo "\n=== 3. 测试应用状态 ==="
kubectl get pods --all-namespaces | grep -E "(test|business|storage)"
# 快速网络测试
echo "\n=== 4. 快速网络测试 ==="
# 获取测试 Pod
TEST_POD=$(kubectl get pods -n test-apps -l app=single-network-test -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
MULTI_POD=$(kubectl get pods -n business-apps -l app=multi-network-test -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
if [ -n "$TEST_POD" ]; then
echo "基础网络测试 (Pod: $TEST_POD):"
kubectl exec -n test-apps $TEST_POD -- ping -c 2 kubernetes.default.svc.cluster.local
else
echo "未找到测试 Pod"
fi
if [ -n "$MULTI_POD" ]; then
echo "\n多网络接口检查 (Pod: $MULTI_POD):"
kubectl exec -n business-apps $MULTI_POD -- ip addr show | grep -E "(eth0|net1)"
else
echo "未找到多网络 Pod"
fi
echo "\n=== 5. 验证结果 ==="
echo "✅ 集群运行正常"
echo "✅ Flannel CNI 工作正常"
echo "✅ Multus-CNI 工作正常"
echo "✅ 网络附件定义已创建"
echo "✅ 测试应用已部署"
echo "\n=== 快速验证完成 ==="
echo "如需详细验证,请运行:"
echo " ./network-verification.sh"
EOF
chmod +x quick-verify.sh
|
总结
本指南提供了使用 Kind 快速创建和验证 Flannel + Multus-CNI 多网段隔离环境的完整方案:
🎯 实现目标
- 快速环境搭建:5分钟内完成完整环境部署
- 多网段隔离验证:验证不同网络平面的隔离效果
- 完整功能测试:包含网络连通性、性能和故障排查
- 自动化运维:提供一键部署和清理脚本
🔧 技术特性
- Kind 集群:轻量级 Kubernetes 环境
- Flannel CNI:提供基础集群网络
- Multus-CNI:支持多网络接口
- 多种网络类型:MacVLAN、Bridge、Host-Local
- 完整验证:网络连通性、性能测试、故障排查
📋 使用流程
- 环境准备:安装 Docker、Kind、kubectl
- 一键部署:运行
./deploy-all.sh
- 快速验证:运行
./quick-verify.sh
- 详细测试:运行各种验证脚本
- 清理环境:运行清理脚本
🚀 扩展应用
- 开发环境:本地开发和测试
- CI/CD 集成:自动化测试流水线
- 培训演示:云原生网络技术学习
- 概念验证:新网络方案验证
这套方案为云原生网络技术的学习和验证提供了完整的实验环境,帮助快速理解和掌握 Kubernetes 多网段隔离技术。