跳过正文
  1. 所有文章/

09|部署网络组件 Cilium + CoreDNS

·2361 字·5 分钟
目录
K8S集群部署 - 这篇文章属于一个选集。
§ 9: 本文

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 功能是否正常:

  1. 检查 CoreDNS 组件是否正常运行;
  2. 在 Pod 中访问 Kubernetes 服务;
  3. 检查 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 测试用例很多,对网络功能测试更加全面和严格,其中有些用例可能会因为集群配置、镜像下载失败等原因失败,有些失败的测试用例,也可能不会影响正常的集群功能。所以,其测试结果仅做参考。

参考
#

  1. CoreDNS for Kubernetes Service Discovery
  2. CoreDNS for Kubernetes Service Discovery Take 2
  3. CoreDNS 部署实践
  4. Kubernetes DNS Addons
K8S集群部署 - 这篇文章属于一个选集。
§ 9: 本文