使用多控制平面 - 高可用集群

概述

minikube 使用 具有共址 etcd 节点的堆叠控制平面节点,并通过 kube-vipARP 模式实现 Kubernetes 高可用集群拓扑。

本教程将向您展示如何在 minikube 上启动和探索多控制平面 - 高可用集群。

先决条件

  • minikube > v1.32.0
  • kubectl

可选

  • ip_vs 内核模块:ip_vs、ip_vs_rr 和 nf_conntrack

基本原理

kube-vip 支持通过使用 IPVS(IP 虚拟服务器)和第 4 层(基于 TCP)轮询在控制平面节点之间分配 API 请求来实现 控制平面负载均衡

如果这些 ip_vs 内核模块可用,minikube 将尝试自动启用控制平面负载均衡,而(有关更多详细信息,请参阅 驱动程序 部分)

  • 对于基于 VM 的驱动程序(例如,kvm2 或 qemu):minikube 将自动尝试加载 ip_vs 内核模块
  • 对于基于容器或裸机的驱动程序(例如,docker 或“none”):minikube 将仅检查 ip_vs 内核模块是否已加载,但不会尝试自动加载它们(以避免意外修改底层主机的操作系统/内核),因此用户需要使其可用(如果适用且需要)

注意事项

虽然 minikube 高可用集群在丢失任何一个控制平面节点后将继续运行(尽管处于降级模式),但请记住,可能有一些组件仅附加到主控制平面节点,例如存储 provisioner。

教程

  • 可选:如果您计划在 Linux 操作系统之上使用基于容器或裸机的驱动程序,请检查是否已加载 ip_vs 内核模块
lsmod | grep ip_vs
ip_vs_rr               12288  1
ip_vs                 233472  3 ip_vs_rr
nf_conntrack          217088  9 xt_conntrack,nf_nat,nf_conntrack_tftp,nft_ct,xt_nat,nf_nat_tftp,nf_conntrack_netlink,xt_MASQUERADE,ip_vs
nf_defrag_ipv6         24576  2 nf_conntrack,ip_vs
libcrc32c              12288  5 nf_conntrack,nf_nat,btrfs,nf_tables,ip_vs
  • 使用您选择的驱动程序和容器运行时启动高可用集群(这里我们选择 docker 驱动程序和 containerd 容器运行时)
minikube start --ha --driver=docker --container-runtime=containerd --profile ha-demo
😄  [ha-demo] minikube v1.32.0 on Opensuse-Tumbleweed 20240311
✨  Using the docker driver based on user configuration
📌  Using Docker driver with root privileges
👍  Starting "ha-demo" primary control-plane node in "ha-demo" cluster
🚜  Pulling base image v0.0.42-1710284843-18375 ...
🔥  Creating docker container (CPUs=2, Memory=5266MB) ...
📦  Preparing Kubernetes v1.28.4 on containerd 1.6.28 ...
    ▪ Generating certificates and keys ...
    ▪ Booting up control plane ...
    ▪ Configuring RBAC rules ...
🔗  Configuring CNI (Container Networking Interface) ...
    ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟  Enabled addons: storage-provisioner, default-storageclass

👍  Starting "ha-demo-m02" control-plane node in "ha-demo" cluster
🚜  Pulling base image v0.0.42-1710284843-18375 ...
🔥  Creating docker container (CPUs=2, Memory=5266MB) ...
🌐  Found network options:
    ▪ NO_PROXY=192.168.49.2
📦  Preparing Kubernetes v1.28.4 on containerd 1.6.28 ...
    ▪ env NO_PROXY=192.168.49.2
🔎  Verifying Kubernetes components...

👍  Starting "ha-demo-m03" control-plane node in "ha-demo" cluster
🚜  Pulling base image v0.0.42-1710284843-18375 ...
🔥  Creating docker container (CPUs=2, Memory=5266MB) ...
🌐  Found network options:
    ▪ NO_PROXY=192.168.49.2,192.168.49.3
📦  Preparing Kubernetes v1.28.4 on containerd 1.6.28 ...
    ▪ env NO_PROXY=192.168.49.2
    ▪ env NO_PROXY=192.168.49.2,192.168.49.3
🔎  Verifying Kubernetes components...
🏄  Done! kubectl is now configured to use "ha-demo" cluster and "default" namespace by default
  • 列出您的高可用集群节点
kubectl get nodes -owide
NAME          STATUS   ROLES           AGE     VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION    CONTAINER-RUNTIME
ha-demo       Ready    control-plane   4m21s   v1.28.4   192.168.49.2   <none>        Ubuntu 22.04.4 LTS   6.7.7-1-default   containerd://1.6.28
ha-demo-m02   Ready    control-plane   4m      v1.28.4   192.168.49.3   <none>        Ubuntu 22.04.4 LTS   6.7.7-1-default   containerd://1.6.28
ha-demo-m03   Ready    control-plane   3m37s   v1.28.4   192.168.49.4   <none>        Ubuntu 22.04.4 LTS   6.7.7-1-default   containerd://1.6.28
  • 检查您的高可用集群的状态
minikube profile list
|---------|-----------|------------|----------------|------|---------|--------|-------|--------|
| Profile | VM Driver |  Runtime   |       IP       | Port | Version | Status | Nodes | Active |
|---------|-----------|------------|----------------|------|---------|--------|-------|--------|
| ha-demo | docker    | containerd | 192.168.49.254 | 8443 | v1.28.4 | HAppy  |     3 |        |
|---------|-----------|------------|----------------|------|---------|--------|-------|--------|
  • 检查您的高可用集群节点的状态
minikube status -p ha-demo
ha-demo
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

ha-demo-m02
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

ha-demo-m03
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
  • 对于高可用集群,kubeconfig 指向虚拟 Kubernetes API 服务器 IP
kubectl config view --context ha-demo
apiVersion: v1
clusters:
- cluster:
    certificate-authority: /home/prezha/.minikube/ca.crt
    extensions:
    - extension:
        last-update: Thu, 14 Mar 2024 21:38:07 GMT
        provider: minikube.sigs.k8s.io
        version: v1.32.0
      name: cluster_info
    server: https://192.168.49.254:8443
  name: ha-demo
contexts:
- context:
    cluster: ha-demo
    extensions:
    - extension:
        last-update: Thu, 14 Mar 2024 21:38:07 GMT
        provider: minikube.sigs.k8s.io
        version: v1.32.0
      name: context_info
    namespace: default
    user: ha-demo
  name: ha-demo
current-context: ha-demo
kind: Config
preferences: {}
users:
- name: ha-demo
  user:
    client-certificate: /home/prezha/.minikube/profiles/ha-demo/client.crt
    client-key: /home/prezha/.minikube/profiles/ha-demo/client.key
  • 当前领导者和跟随者 API 服务器的概述
minikube ssh -p ha-demo -- 'find /var/lib/minikube/binaries -iname kubectl -exec sudo {} --kubeconfig=/var/lib/minikube/kubeconfig logs -n kube-system pod/kube-vip-ha-demo \; -quit'
time="2024-03-14T21:38:34Z" level=info msg="Starting kube-vip.io [v0.7.1]"
time="2024-03-14T21:38:34Z" level=info msg="namespace [kube-system], Mode: [ARP], Features(s): Control Plane:[true], Services:[false]"
time="2024-03-14T21:38:34Z" level=info msg="prometheus HTTP server started"
time="2024-03-14T21:38:34Z" level=info msg="Starting Kube-vip Manager with the ARP engine"
time="2024-03-14T21:38:34Z" level=info msg="Beginning cluster membership, namespace [kube-system], lock name [plndr-cp-lock], id [ha-demo]"
I0314 21:38:34.042420       1 leaderelection.go:250] attempting to acquire leader lease kube-system/plndr-cp-lock...
I0314 21:38:34.069509       1 leaderelection.go:260] successfully acquired lease kube-system/plndr-cp-lock
time="2024-03-14T21:38:34Z" level=info msg="Node [ha-demo] is assuming leadership of the cluster"
time="2024-03-14T21:38:34Z" level=info msg="Starting IPVS LoadBalancer"
time="2024-03-14T21:38:34Z" level=info msg="IPVS Loadbalancer enabled for 1.2.1"
time="2024-03-14T21:38:34Z" level=info msg="Gratuitous Arp broadcast will repeat every 3 seconds for [192.168.49.254]"
time="2024-03-14T21:38:34Z" level=info msg="Kube-Vip is watching nodes for control-plane labels"
time="2024-03-14T21:38:34Z" level=info msg="Added backend for [192.168.49.254:8443] on [192.168.49.3:8443]"
time="2024-03-14T21:38:48Z" level=info msg="Added backend for [192.168.49.254:8443] on [192.168.49.4:8443]"
minikube ssh -p ha-demo -- 'find /var/lib/minikube/binaries -iname kubectl -exec sudo {} --kubeconfig=/var/lib/minikube/kubeconfig logs -n kube-system pod/kube-vip-ha-demo-m02 \; -quit'
time="2024-03-14T21:38:25Z" level=info msg="Starting kube-vip.io [v0.7.1]"
time="2024-03-14T21:38:25Z" level=info msg="namespace [kube-system], Mode: [ARP], Features(s): Control Plane:[true], Services:[false]"
time="2024-03-14T21:38:25Z" level=info msg="prometheus HTTP server started"
time="2024-03-14T21:38:25Z" level=info msg="Starting Kube-vip Manager with the ARP engine"
time="2024-03-14T21:38:25Z" level=info msg="Beginning cluster membership, namespace [kube-system], lock name [plndr-cp-lock], id [ha-demo-m02]"
I0314 21:38:25.990817       1 leaderelection.go:250] attempting to acquire leader lease kube-system/plndr-cp-lock...
time="2024-03-14T21:38:34Z" level=info msg="Node [ha-demo] is assuming leadership of the cluster"
minikube ssh -p ha-demo -- 'find /var/lib/minikube/binaries -iname kubectl -exec sudo {} --kubeconfig=/var/lib/minikube/kubeconfig logs -n kube-system pod/kube-vip-ha-demo-m03 \; -quit'
time="2024-03-14T21:38:48Z" level=info msg="Starting kube-vip.io [v0.7.1]"
time="2024-03-14T21:38:48Z" level=info msg="namespace [kube-system], Mode: [ARP], Features(s): Control Plane:[true], Services:[false]"
time="2024-03-14T21:38:48Z" level=info msg="prometheus HTTP server started"
time="2024-03-14T21:38:48Z" level=info msg="Starting Kube-vip Manager with the ARP engine"
time="2024-03-14T21:38:48Z" level=info msg="Beginning cluster membership, namespace [kube-system], lock name [plndr-cp-lock], id [ha-demo-m03]"
I0314 21:38:48.856781       1 leaderelection.go:250] attempting to acquire leader lease kube-system/plndr-cp-lock...
time="2024-03-14T21:38:48Z" level=info msg="Node [ha-demo] is assuming leadership of the cluster"
  • 多 etcd 实例的概述
minikube ssh -p ha-demo -- 'find /var/lib/minikube/binaries -iname kubectl -exec sudo {} --kubeconfig=/var/lib/minikube/kubeconfig exec -ti pod/etcd-ha-demo -n kube-system -- /bin/sh -c "ETCDCTL_API=3 etcdctl member list --write-out=table --cacert=/var/lib/minikube/certs/etcd/ca.crt --cert=/var/lib/minikube/certs/etcd/server.crt --key=/var/lib/minikube/certs/etcd/server.key" \; -quit'
+------------------+---------+-------------+---------------------------+---------------------------+------------+
|        ID        | STATUS  |    NAME     |        PEER ADDRS         |       CLIENT ADDRS        | IS LEARNER |
+------------------+---------+-------------+---------------------------+---------------------------+------------+
| 3c464e4a52eb93c5 | started | ha-demo-m03 | https://192.168.49.4:2380 | https://192.168.49.4:2379 |      false |
| 59bde6852118b2a5 | started | ha-demo-m02 | https://192.168.49.3:2380 | https://192.168.49.3:2379 |      false |
| aec36adc501070cc | started |     ha-demo | https://192.168.49.2:2380 | https://192.168.49.2:2379 |      false |
+------------------+---------+-------------+---------------------------+---------------------------+------------+
  • 丢失一个控制平面节点 - 集群降级,但不是问题!
minikube node delete m02 -p ha-demo
🔥  Deleting node m02 from cluster ha-demo
✋  Stopping node "ha-demo-m02"  ...
🛑  Powering off "ha-demo-m02" via SSH ...
🔥  Deleting "ha-demo-m02" in docker ...
💀  Node m02 was successfully deleted.
kubectl get nodes -owide
NAME          STATUS   ROLES           AGE     VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION    CONTAINER-RUNTIME
ha-demo       Ready    control-plane   7m16s   v1.28.4   192.168.49.2   <none>        Ubuntu 22.04.4 LTS   6.7.7-1-default   containerd://1.6.28
ha-demo-m03   Ready    control-plane   6m32s   v1.28.4   192.168.49.4   <none>        Ubuntu 22.04.4 LTS   6.7.7-1-default   containerd://1.6.28
minikube profile list
|---------|-----------|------------|----------------|------|---------|----------|-------|--------|
| Profile | VM Driver |  Runtime   |       IP       | Port | Version |  Status  | Nodes | Active |
|---------|-----------|------------|----------------|------|---------|----------|-------|--------|
| ha-demo | docker    | containerd | 192.168.49.254 | 8443 | v1.28.4 | Degraded |     2 |        |
|---------|-----------|------------|----------------|------|---------|----------|-------|--------|
  • 添加一个控制平面节点
minikube node add --control-plane -p ha-demo
😄  Adding node m04 to cluster ha-demo as [worker control-plane]
👍  Starting "ha-demo-m04" control-plane node in "ha-demo" cluster
🚜  Pulling base image v0.0.42-1710284843-18375 ...
🔥  Creating docker container (CPUs=2, Memory=5266MB) ...
📦  Preparing Kubernetes v1.28.4 on containerd 1.6.28 ...
🔎  Verifying Kubernetes components...
🏄  Successfully added m04 to ha-demo!
kubectl get nodes -owide
NAME          STATUS   ROLES           AGE     VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION    CONTAINER-RUNTIME
ha-demo       Ready    control-plane   8m34s   v1.28.4   192.168.49.2   <none>        Ubuntu 22.04.4 LTS   6.7.7-1-default   containerd://1.6.28
ha-demo-m03   Ready    control-plane   7m50s   v1.28.4   192.168.49.4   <none>        Ubuntu 22.04.4 LTS   6.7.7-1-default   containerd://1.6.28
ha-demo-m04   Ready    control-plane   36s     v1.28.4   192.168.49.5   <none>        Ubuntu 22.04.4 LTS   6.7.7-1-default   containerd://1.6.28
minikube profile list
|---------|-----------|------------|----------------|------|---------|--------|-------|--------|
| Profile | VM Driver |  Runtime   |       IP       | Port | Version | Status | Nodes | Active |
|---------|-----------|------------|----------------|------|---------|--------|-------|--------|
| ha-demo | docker    | containerd | 192.168.49.254 | 8443 | v1.28.4 | HAppy  |     3 |        |
|---------|-----------|------------|----------------|------|---------|--------|-------|--------|
  • 添加一个工作节点
minikube node add -p ha-demo
😄  Adding node m05 to cluster ha-demo as [worker]
👍  Starting "ha-demo-m05" worker node in "ha-demo" cluster
🚜  Pulling base image v0.0.42-1710284843-18375 ...
🔥  Creating docker container (CPUs=2, Memory=5266MB) ...
📦  Preparing Kubernetes v1.28.4 on containerd 1.6.28 ...
🔎  Verifying Kubernetes components...
🏄  Successfully added m05 to ha-demo!
kubectl get nodes -owide
NAME          STATUS   ROLES           AGE     VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION    CONTAINER-RUNTIME
ha-demo       Ready    control-plane   9m35s   v1.28.4   192.168.49.2   <none>        Ubuntu 22.04.4 LTS   6.7.7-1-default   containerd://1.6.28
ha-demo-m03   Ready    control-plane   8m51s   v1.28.4   192.168.49.4   <none>        Ubuntu 22.04.4 LTS   6.7.7-1-default   containerd://1.6.28
ha-demo-m04   Ready    control-plane   97s     v1.28.4   192.168.49.5   <none>        Ubuntu 22.04.4 LTS   6.7.7-1-default   containerd://1.6.28
ha-demo-m05   Ready    <none>          22s     v1.28.4   192.168.49.6   <none>        Ubuntu 22.04.4 LTS   6.7.7-1-default   containerd://1.6.28
  • 通过部署一个 hello 服务进行测试,该服务只是返回提供请求的 IP 地址
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 100%
  selector:
    matchLabels:
      app: hello
  template:
    metadata:
      labels:
        app: hello
    spec:
      affinity:
        # ⬇⬇⬇ This ensures pods will land on separate hosts
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions: [{ key: app, operator: In, values: [hello] }]
              topologyKey: "kubernetes.io/hostname"
      containers:
        - name: hello-from
          image: pbitty/hello-from:latest
          ports:
            - name: http
              containerPort: 80
      terminationGracePeriodSeconds: 1
---
apiVersion: v1
kind: Service
metadata:
  name: hello
spec:
  type: NodePort
  selector:
    app: hello
  ports:
    - protocol: TCP
      nodePort: 31000
      port: 80
      targetPort: http
EOF
deployment.apps/hello created
kubectl rollout status deployment/hello
deployment "hello" successfully rolled out
  • 查看我们的 Pod 的 IP 地址,以便将来参考
kubectl get pods -owide
NAME                     READY   STATUS    RESTARTS   AGE   IP           NODE          NOMINATED NODE   READINESS GATES
hello-7bf57d9696-64v6m   1/1     Running   0          18s   10.244.3.2   ha-demo-m04   <none>           <none>
hello-7bf57d9696-7gtlk   1/1     Running   0          18s   10.244.2.2   ha-demo-m03   <none>           <none>
hello-7bf57d9696-99qsw   1/1     Running   0          18s   10.244.0.4   ha-demo       <none>           <none>
  • 查看我们的服务,以了解要访问的 URL
minikube service list -p ha-demo
|-------------|------------|--------------|---------------------------|
|  NAMESPACE  |    NAME    | TARGET PORT  |            URL            |
|-------------|------------|--------------|---------------------------|
| default     | hello      |           80 | http://192.168.49.2:31000 |
| default     | kubernetes | No node port |                           |
| kube-system | kube-dns   | No node port |                           |
|-------------|------------|--------------|---------------------------|
  • 让我们访问几次 URL,看看会返回什么
curl  http://192.168.49.2:31000
Hello from hello-7bf57d9696-99qsw (10.244.0.4)

curl  http://192.168.49.2:31000
Hello from hello-7bf57d9696-7gtlk (10.244.2.2)

curl  http://192.168.49.2:31000
Hello from hello-7bf57d9696-7gtlk (10.244.2.2)

curl  http://192.168.49.2:31000
Hello from hello-7bf57d9696-64v6m (10.244.3.2)

上次修改时间:2024 年 9 月 28 日:在示例中使用已安装的 kubectl 版本 (2c6754b0c)