Kubernetes 集群支持多种网络插件,例如:Flannel、Cilium、Calico、Weave。企业生产环境中用的比较多的是 Cilium,所以本节课,选择 Cilium 作为集群的网络插件。
另外,部署完网络插件之后,还需要部署 DNS 服务。Kubernetes 集群标准的 DNS 组件是 CoreDNS。
所以,本节课,来介绍下如何安装:Cilium、CoreDNS。
提示:Flannel 网络插件实现简单、代码精少,如果你想学习 Kubernetes 网络插件的实现,可以学习 Flannel 的。其他网络插件的实现原理跟 Flannel 的大概都是相通的。Flannel 网络插件的安装参考教程 A。
部署 Cilium#
在安装 cilium 前,要前安装好 kube-proxy。
cilium 官方提供了详细的安装文档:Cilium Quick Installation,你可以根据官方的文档来安装,也可以继续跟随本教程来安装。
安装 Cilium 命令#
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then CLI_ARCH=arm64; fi
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
sha256sum --check cilium-linux-${CLI_ARCH}.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/bin
rm -f cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
安装 Cilium 网络插件#
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
helm repo add cilium https://helm.cilium.io/
helm repo update
helm install cilium cilium/cilium --namespace kube-system \
--set image.tag=1.16.2 \
--set cni.binPath=/opt/k8s/bin
注意:
cni.binPath需要和 containerd 配置中的bin_dir保持一致,本教程中为/opt/k8s/bin。
执行完上述命令后,会在集群中安装 cilium 网络插件。通过以下命令可以查看安装进度:
$ kubectl -n kube-system get pods | grep cilium
cilium-ckbfl 1/1 Running 0 94m
cilium-envoy-l4gth 1/1 Running 0 94m
cilium-envoy-tzdjw 1/1 Running 0 94m
cilium-hhsrd 1/1 Running 0 94m
cilium-operator-5874db7569-gn72x 1/1 Running 0 94m
cilium-operator-5874db7569-nkv8k 1/1 Running 0 94m
如果 Pod 都处在 Running 状态,说明 cilium 被正确安装。可以看到,helm install cilium cilium/cilium 会在 Kubernetes 集群中安装以下组件:
- cilium-operator(Deployment):Cilium Operator,负责协调和管理 Cilium 的高级功能;
- cilium(DaemonSet):cilium CNI 网络插件
- cilium-envoy(DaemonSet):Envoy 代理 Pods,与 Cilium 集成来提供增强的网络功能。
也可以通过以下命令来查看 cilium 是否被正确安装:
$ cilium status --wait
/¯¯\
/¯¯\__/¯¯\ Cilium: OK
\__/¯¯\__/ Operator: OK
/¯¯\__/¯¯\ Envoy DaemonSet: OK
\__/¯¯\__/ Hubble Relay: disabled
\__/ ClusterMesh: disabled
DaemonSet cilium Desired: 2, Ready: 2/2, Available: 2/2
DaemonSet cilium-envoy Desired: 2, Ready: 2/2, Available: 2/2
Deployment cilium-operator Desired: 2, Ready: 2/2, Available: 2/2
Containers: cilium Running: 2
cilium-envoy Running: 2
cilium-operator Running: 2
Cluster Pods: 0/0 managed by Cilium
Helm chart version: 1.16.2
Image versions cilium quay.io/cilium/cilium:1.16.2@sha256:4386a858d8d8693418d86934908
cilium-envoy quay.io/cilium/cilium-envoy:v1.29.9-1726784081-a90146d13
cilium-operator quay.io/cilium/operator-generic:v1.16.2@sha256:cccfd3b88
集群网络验证#
执行以下命令创建 2 个测试 Pod:
cd /opt/k8s/work
cat > dnsutils-for-cilium-test-ds.yaml <<EOF
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: dnsutils-for-cilium-test
labels:
addonmanager.kubernetes.io/mode: Reconcile
spec:
selector:
matchLabels:
app: dnsutils-for-cilium-test
template:
metadata:
labels:
app: dnsutils-for-cilium-test
spec:
containers:
- name: my-dnsutils
image: busybox:1.36
imagePullPolicy: IfNotPresent
command:
- sleep
- "infinity"
EOF
kubectl create -f dnsutils-for-cilium-test-ds.yaml
执行以下命令获取 Pod 创建状态:
$ kubectl get pods -o wide -l app=dnsutils-for-cilium-test
NAME READY STATUS RESTARTS AGE IP NODE NOMINATE
dnsutils-for-cilium-test-svzn6 1/1 Running 0 61s 10.0.1.78 k8s-02 <none>
dnsutils-for-cilium-test-vf6ds 1/1 Running 0 61s 10.0.0.147 k8s-01 <none>
待 Pod 都处在 Running 状态后,测试是否可以从一个 Pod 内 ping 通另外一个 Pod 的 IP 地址:
$ kubectl exec -it dnsutils-for-cilium-test-svzn6 -- ping 10.0.0.147
PING 10.0.0.147 (10.0.0.147) 56(84) bytes of data.
64 bytes from 10.0.0.147: icmp_seq=1 ttl=63 time=0.785 ms
64 bytes from 10.0.0.147: icmp_seq=2 ttl=63 time=0.758 ms
...
部署 CoreDNS#
要在 Kubernetes 集群内实现服务发现,必须具备 DNS 组件,以便将服务域名解析为 Pod IP,从而通过 IP 地址进行通信。目前,CoreDNS 是 Kubernetes 环境中最常用的 DNS 解决方案。
在本小节中,我将逐步介绍如何部署 CoreDNS,确保集群内服务的 DNS 解析顺畅无阻。
下载和配置 CoreDNS#
cd /opt/k8s/work
git clone https://github.com/coredns/deployment.git
mv deployment coredns-deployment
部署 CoreDNS#
cd /opt/k8s/work/coredns-deployment/kubernetes
source /opt/k8s/bin/environment.sh
./deploy.sh -i ${CLUSTER_DNS_SVC_IP} -d ${CLUSTER_DNS_DOMAIN} | kubectl apply -f -
检查 CoreDNS 功能#
我们可以通过以下 3 种方式来检查 CoreDNS 功能是否正常:
- 检查 CoreDNS 组件是否正常运行;
- 在 Pod 中访问 Kubernetes 服务;
- 检查 DNS 配置,并测试 DNS 解析。
具体操作如下。
检查 CoreDNS 组件是否正常运行#
$ kubectl get pods -n kube-system -l k8s-app=kube-dns
NAME READY STATUS RESTARTS AGE
coredns-6b59c98dd4-z249x 1/1 Running 0 4m57s
coredns Pod 处在 Running 状态,说明 coredns 部署成功。
在 Pod 中访问 Kubernetes 服务#
新建一个 Deployment:
cd /opt/k8s/work
cat > my-nginx.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 2
selector:
matchLabels:
run: my-nginx
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx:1.7.9
ports:
- containerPort: 80
EOF
kubectl create -f my-nginx.yaml
expose 该 Deployment,生成 my-nginx 服务:
$ kubectl expose deploy my-nginx
service "my-nginx" exposed
$ kubectl get services my-nginx -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
my-nginx ClusterIP 10.254.67.218 <none> 80/TCP 5s run=my-nginx
创建另一个 Pod,查看 /etc/resolv.conf 是否包含 kubelet 配置的 --cluster-dns 和 --cluster-domain,是否能够将服务 my-nginx 解析到上面显示的 Cluster IP 10.254.67.218。
检查 DNS 配置,并测试 DNS 解析#
创建一个测试用的 dnsutils Pod:
cd /opt/k8s/work
cat > dnsutils-ds.yml <<EOF
apiVersion: v1
kind: Service
metadata:
name: dnsutils-ds
labels:
app: dnsutils-ds
spec:
type: NodePort
selector:
app: dnsutils-ds
ports:
- name: http
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: dnsutils-ds
labels:
addonmanager.kubernetes.io/mode: Reconcile
spec:
selector:
matchLabels:
app: dnsutils-ds
template:
metadata:
labels:
app: dnsutils-ds
spec:
containers:
- name: my-dnsutils
image: registry.k8s.io/e2e-test-images/jessie-dnsutils:1.7
imagePullPolicy: IfNotPresent
command:
- sleep
- "infinity"
EOF
kubectl create -f dnsutils-ds.yml
查看测试 Pod 是否成功创建:
$ kubectl get pods -lapp=dnsutils-ds -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READ
dnsutils-ds-9zmbk 1/1 Running 0 78s 10.0.0.156 k8s-01 <none> <non
dnsutils-ds-ljnx4 1/1 Running 0 78s 10.0.1.247 k8s-02 <none> <non
查看 DNS 解析配置是否正确:
$ kubectl exec -it dnsutils-ds-9zmbk -- cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.254.0.2
options ndots:5
使用 DNS 能否成功解析 Kubernetes 内服务域名:
$ kubectl exec -it dnsutils-ds-9zmbk -- nslookup kubernetes
Server: 10.254.0.2
Address: 10.254.0.2#53
Name: kubernetes.default.svc.cluster.local
Address: 10.254.0.1
$ kubectl exec -it dnsutils-ds-9zmbk -- nslookup my-nginx
Server: 10.254.0.2
Address: 10.254.0.2#53
Name: my-nginx.default.svc.cluster.local
Address: 10.254.151.251
可以看到 DNS 能够成功解析 Kubernetes 内以下 2 类服务域名:
- Kubernetes 内置服务域名:
kubernetes->10.254.0.1; - 用户创建的外部服务域名:
my-nginx->10.254.151.251。
查看使用 DNS 能否成功解析公网域名:
$ kubectl exec -it dnsutils-ds-9zmbk -- nslookup www.baidu.com
Server: 10.254.0.2
Address: 10.254.0.2#53
Non-authoritative answer:
Name: www.baidu.com
Address: 10.15.63.90
可以看到 DNS 能够成功解析 www.baidu.com,解析到的 IP 地址为:10.15.63.90。
更全面的 Kubernetes 网络测试#
通过上面的部署,我们已经成功部署了网络插件和 DNS 组件。至此,Kubernetes 的网络功能已经健全,我们可以对 Kubernetes 网络进行更全面的测试。
cilium 官网提供了测试功能,可以用来全面的测试 Kubernetes 网络。可以执行以下命令来测试:
$ cilium connectivity test
ℹ️ Monitor aggregation detected, will skip some flow validation steps
✨ [k8s-cluster] Creating namespace for connectivity check...
...
────────────────────────────────────────────────────────────────────────────────
📋 Test Report
────────────────────────────────────────────────────────────────────────────────
✅ 69/69 tests successful (0 warnings)
69/69 tests successful (0 warnings) 说明所有的 Kubernetes 集群网络连通性测试通过。
这里要注意:
- Kubernetes 连接性测试可能会因为一个或多个 Pod 中打开的文件过多而无法部署。如果你遇到
too many open files这类错误,可以增加 inotify 资源限制; cilium connectivity test测试用例很多,对网络功能测试更加全面和严格,其中有些用例可能会因为集群配置、镜像下载失败等原因失败,有些失败的测试用例,也可能不会影响正常的集群功能。所以,其测试结果仅做参考。