Skip to content

轻量云上二进制部署 Kubernetes(下篇)

大家好!这篇是 Kubernetes 部署的下篇,主要内容会聚焦在 Worker 节点组件 和 Ingress Controller 的安装。再坚持一下,等所有组件部署完,就能正式开始在集群里跑自己的应用啦!

下面这张图展示了部署完成后,流量在我实际网站中的大致走向,仅供参考

文章的内容比较多,我将其分成上下两篇来写。这是上篇的传送门:轻量云上二进制部署 Kubernetes(上篇)。下篇主要聚焦在以下部分:

部署 Worker 节点组件

kubernetes worker 节点运行如下组件:

  • kubelet
  • containerd
  • kube-proxy
  • Cilium

部署 kubelet 组件

kubelet 运行在每个 worker 节点上,接收 kube-apiserver 发送的请求,管理 Pod 容器,执行交互式命令,如 exec、run、logs 等

kubelet 启动时自动向 kube-apiserver 注册节点信息,内置的 cadvisor 统计和监控节点的资源使用情况

为确保安全,部署时关闭了 kubelet 的非安全 http 端口,对请求进行认证和授权,拒绝未授权的访问(如 apiserver、heapster 的请求)

部署 containerd 组件

TODO

部署 kube-proxy 组件

TODO

部署 Cilium 网络组件

Kuberneters 集群支持多种网络插件,例如:Flannel、Cilium、Calico、Weave。生产环境中用的比较多的是 Cilium。所以这里我们选择 Cilium 作为集群的网络插件

注意,在安装 Cilium 前,要前安装好 kube-proxy

我们可以根据 Cilium 官方提供的 安装文档 来安装

安装 Cilium 命令

bash
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 网络插件

bash
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.17.6

执行完上述命令之后,会在集群中安装 Cilium 网络插件。通过以下命令可以查看安装进度:

bash
kubectl -n kube-system get pods | grep cilium

输出:

如果 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 是否被正确安装:

bash
cilium status --wait

输出:

最后,验证一下集群网络

执行以下命令创建 2 个测试 Pod
bash
cd /opt/k8s/work
cat > busybox-for-cilium-test-ds.yaml <<EOF
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: busybox-for-cilium-test
  labels:
    addonmanager.kubernetes.io/mode: Reconcile
spec:
  selector:
    matchLabels:
      app: busybox-for-cilium-test
  template:
    metadata:
      labels:
        app: busybox-for-cilium-test
    spec:
      containers:
      - name: my-busybox
        image: busybox:latest
        imagePullPolicy: IfNotPresent
        command:
          - tail
          - "-f"
          - "/dev/null"
        ports:
        - containerPort: 80
EOF
kubectl create -f busybox-for-cilium-test-ds.yaml

获取 Pod 创建状态:

bash
kubectl get pods -o wide -l app=busybox-for-cilium-test

待 Pod 都处在 Running 状态后,测试是否可以从一个 Pod 内 ping 通另外一个 Pod 的 IP 地址:

bash
kubectl exec -it busybox-for-cilium-test-kxv4x -- ping 10.0.0.120

输出:

部署 CoreDNS 服务

部署完网络插件之后,还需要部署 DNS 服务。要在 Kubernetes 集群内实现服务发现,必须具备 DNS 组件,以便将服务域名解析为 Pod IP,从而通过 IP 地址进行通信。目前,CoreDNS 是 Kubernetes 环境中最常用的 DNS 解决方案

下载和配置 CoreDNS

bash
cd /opt/k8s/work
git clone https://github.com/coredns/deployment.git
mv deployment coredns-deployment

部署 coredns

bash
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 组件是否正常运行

bash
$ kubectl get pods -n kube-system -l k8s-app=kube-dns

coredns Pod 处在 Running 状态,说明 coredns 部署成功

验证 Kubernetes 集群功能

经过上面的部署,我们已经成功安装了 Kuberentes 正常工作需要的组件。下面我们来看下如何验证 Kubernetes 集群,查看其是否能正常工作,以确保 Kubernetes 集群被成功部署

检查节点状态

都为 Ready 且版本为 v1.31.1 时正常

创建一个用来测试的 nginx-ds DaemonSet 和 nginx-ds Service

创建测试文件
bash
cd /opt/k8s/work
cat > nginx-ds.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  name: nginx-ds
  labels:
    app: nginx-ds
spec:
  type: NodePort
  selector:
    app: nginx-ds
  ports:
  - name: http
    port: 80
    targetPort: 80
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nginx-ds
  labels:
    addonmanager.kubernetes.io/mode: Reconcile
spec:
  selector:
    matchLabels:
      app: nginx-ds
  template:
    metadata:
      labels:
        app: nginx-ds
    spec:
      containers:
      - name: my-nginx
        image: nginx:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
EOF

创建 DaemonSet 和 Service 资源:

bash
kubectl create -f nginx-ds.yml

检查各节点的 Pod IP 连通性

bash
kubectl get pods  -o wide -l app=nginx-ds

输出:

在所有 Node 上分别 ping 上面 2 个 Pod IP,看是否连通:

bash
source /opt/k8s/bin/environment.sh
for node_ip in ${NODE_IPS[@]}
  do
    echo ">>> ${node_ip}"
    ssh ${node_ip} "ping -c 1 10.0.1.128"
    ssh ${node_ip} "ping -c 1 10.0.0.64"
  done

输出:

检查服务 IP 和端口可达性

bash
kubectl get svc -l app=nginx-ds

可以发现:

  • Service Cluster IP:10.254.128.109
  • 服务端口:80
  • NodePort 端口:30784

在所有 Node 上 curl Service IP:

bash
source /opt/k8s/bin/environment.sh
for node_ip in ${NODE_IPS[@]}
  do
    echo ">>> ${node_ip}"
    ssh ${node_ip} "curl -s 10.254.128.109"
  done

预期输出 Nginx 欢迎页面内容:

检查服务的 NodePort 可达性

在所有 Node 上执行:

bash
source /opt/k8s/bin/environment.sh
for node_ip in ${NODE_IPS[@]}
  do
    echo ">>> ${node_ip}"
    ssh ${node_ip} "curl -s ${node_ip}:30784"
  done

预期输出 Nginx 欢迎页面内容

部署 Ingress Controller

Ingress Controller 的实现有很多种,像 Ingress-NGINX、Traefik、HAProxy、Contour、Kong、Istio Gateway 等,其中 Ingress-NGINX 是最脱颖而出的

Ingress-NGINX 是 Kubernetes 官方维护的项目,目前生态最成熟、而且有官方背书。生产环境使用最多的就是它,因此这里我选择使用 Ingress-NGINX 作为 Ingress Controller

使用 Helm 安装 Ingress-NGINX

在 Debain 12 系统上,准备 values-nodeport.yaml 文件

yaml
controller:
  service:
    type: NodePort
    nodePorts:
      http: 30080
      https: 30443

然后执行命令启动 Ingress-NGINX

sh
helm install ingress-nginx ingress-nginx/ingress-nginx --namespace ingress-nginx --create-namespace -f values-nodeport.yaml

注意,macOS 上使用 Docker Desktop 启动 Kubernetes 集群时,无需指定其它配置,可以直接使用下面命令安装

bash
helm install my-ingress ingress-nginx/ingress-nginx --namespace ingress-nginx-helm --create-namespace

查看 Ingress-NGINX 以及安装成功

bash
helm list -n ingress-nginx
kubectl get svc -n ingress-nginx

输出:

目前,ingress-nginx-controller 已通过 NodePort 暴露服务

接下来,我们将在宿主机上配置 Nginx 反向代理,将外部流量转发至 Ingress Controller,从而实现从宿主机到集群内部的访问链路

具体而言,只需在宿主机的 Nginx 配置中添加反向代理规则:

sh
server {
	listen 443 ssl;
	listen [::]:443 ssl;

	...

	location / {
      proxy_pass http://10.254.66.199:80;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Forwarded-Port 443;
	}
}

...

OK 这样就大功告成了!完结撒花 🎉

以上