.. _k8s_dnsrr:
========================================
基于DNS轮询构建高可用Kubernetes
========================================
.. warning::
我在重新部署 :ref:`priv_cloud_infra` 的Kubernetes集群,采用最新的 1.24 版本。虽然之前已经有一些部署经验,但是这次从头开始部署还是遇到不少挫折,走了不少弯路,所以本文记述比较杂乱(因为我断断续续进行,前后记述有所重复)。如果你希望有一个便捷精简且可重复正确完成的参考手册,请阅读 :ref:`z-k8s` ,我将在这篇文档中去芜存菁,系统整理如何快速完成高可用Kubernetes部署。
.. note::
在 :ref:`ha_k8s_lb` 部署中,负载均衡采用的是 :ref:`haproxy` 结合keeplived实现VIP自动漂移。可以在部署基础上改造DNSRR到负载均衡模式
在完成 :ref:`priv_deploy_etcd_cluster_with_tls_auth` ,具备了扩展etcd架构,就可以开始部署本文 ``基于DNS轮询构建高可用Kubernetes`` 。后续再补充 :ref:`haproxy` 这样的负载均衡,就可以进一步改造成 :ref:`ha_k8s_lb` 架构。
准备etcd访问证书
===================
由于是访问外部扩展etcd集群,所以首先需要将etcd证书复制到管控服务器节点,以便管控服务器服务(如apiserver)启动后能够正常读写etcd:
- 在管控服务器 ``z-k8s-m-1`` / ``z-k8s-m-2`` / ``z-k8s-m-3`` 上创建 ``etcd`` 访问证书目录,并将 :ref:`priv_deploy_etcd_cluster_with_tls_auth` 准备好的证书复制过来:
``etcd`` 客户端所需要的证书可以从 :ref:`priv_deploy_etcd_cluster_with_tls_auth` 配置的 ``etctctl`` 客户端配置找到对应文件
.. literalinclude:: ../../etcd/priv_deploy_etcd_cluster_with_tls_auth/etcdctl_endpoint_env
:language: bash
:caption: etcd客户端配置:使用证书
:emphasize-lines: 4-6
将上述 ``etcdctl`` 客户端配置文件和Kubernetes访问etcd配置文件一一对应如下:
.. csv-table:: kubernetes apiserver访问etcd证书对应关系
:file: k8s_dnsrr/etcd_key.csv
:widths: 40, 60
:header-rows: 1
- 分发kubernetes的apiserver使用的etcd证书:
.. literalinclude:: k8s_dnsrr/deploy_k8s_apiserver_key
:language: bash
:caption: 分发kubernetes的apiserver使用的etcd证书
.. note::
我是在具备密钥认证管理主机 ``z-b-data-1`` 上作为客户端,通过ssh远程登录到 ``z-k8s-m-1`` / ``z-k8s-m-2`` / ``z-k8s-m-3`` ,执行上述 ``deploy_k8s_etcd_key.sh`` 分发密钥
.. _kubeadm-config:
配置第一个管控节点(control plane ndoe)
=======================================
- 创建 ``create_kubeadm-config.sh`` 脚本 :
.. literalinclude:: k8s_dnsrr/create_kubeadm-config
:language: bash
:caption: 创建第一个管控节点配置 kubeadm-config.yaml
.. note::
在 :ref:`containerd_systemdcgroup_true` :ref:`containerd` 就会使用 ``systemd cgroup driver`` 。对应 ``kubelet`` 也需要使用 ``systemd cgroup driver`` : 在Kubernetes官方文档 `Configuring a cgroup driver `_ 指明了:
- ``kubelet`` 可以通过 ``kubeadm-config.yaml`` 中指定 ``cgroupDriver: systemd`` 明确配置 ``kubelet`` 使用 ``systemd cgroup driver`` ,这样 ``kubeadm init`` 创建的集群中 ``kubelet`` 就会正确使用 ``systemd cgroup driver``
- 从 Kubernetes 1.22 开始,即使没有明确配置 ``cgroupDriver: systemd`` , ``kubelet`` 也是默认使用 ``systemd cgroup driver``
- 如果集群创建时没有指定 ``systemd cgroup driver`` (且版本低于1.22),则可以通过 ``kubectl edit cm kubelet-config -n kube-system`` 修订 ``cgroupDriver: systemd``
.. note::
`Kubernetes by kubeadm config yamls `_ 提供了 ``kubeadm-config.yaml`` 配置案例,例如如何修订集群名,网段等。实际上可以进一步参考官方文档定制 apiserver / controller / scheduler 的配置,在这篇文档中也有介绍和引用。非常好
- 执行 ``sh create_kubeadm-config.sh`` 生成 ``kubeadm-config.yaml`` 配置文件
- 创建第一个管控节点:
.. literalinclude:: k8s_dnsrr/kubeadm_init
:language: bash
:caption: 初始化第一个管控节点 kubeadm init
.. note::
实际上只要保证网络畅通(翻墙),并且做好前置准备工作, ``kubeadm init`` 初始化会非常丝滑地完成。此时终端会提示一些非常有用地信息,例如如何启动集群,如何配置管理环境。
如果一切顺利,会有如下提示信息:
.. literalinclude:: k8s_dnsrr/kubeadm_init_output
:language: bash
:caption: 初始化第一个管控节点 kubeadm init 输出信息
表明集群第一个管控节点初始化成功!
- 此时根据提示,执行以下命令为自己的账户准备好管理配置
.. literalinclude:: k8s_dnsrr/kube_config
:language: bash
:caption: 配置个人账户的管理k8s环境
并且提供了如何添加管控平面节点的操作命令(包含密钥,所以必须保密),以及添加工作节点的命令(包含密钥,所以必须保密)
容器没有启动问题
==================
我这里遇到一个问题,就是 ``kubeadm init`` 显示初始化成功,但是我使用 ``docker ps`` 居然看不到任何容器::
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
这怎么回事?
- 检查端口::
netstat -an | grep 6443
可以看到端口已经监听::
tcp 0 0 192.168.6.101:39868 192.168.6.101:6443 ESTABLISHED
tcp 0 0 192.168.6.101:38514 192.168.6.101:6443 ESTABLISHED
tcp 0 0 192.168.6.101:40006 192.168.6.101:6443 TIME_WAIT
tcp 0 0 192.168.6.101:39982 192.168.6.101:6443 TIME_WAIT
tcp 0 0 192.168.6.101:39926 192.168.6.101:6443 ESTABLISHED
tcp 0 0 192.168.6.101:40070 192.168.6.101:6443 TIME_WAIT
tcp6 0 0 :::6443 :::* LISTEN
tcp6 0 0 ::1:51780 ::1:6443 ESTABLISHED
tcp6 0 0 192.168.6.101:6443 192.168.6.101:39868 ESTABLISHED
tcp6 0 0 ::1:6443 ::1:51780 ESTABLISHED
tcp6 0 0 192.168.6.101:6443 192.168.6.101:38514 ESTABLISHED
tcp6 0 0 192.168.6.101:6443 192.168.6.101:39926 ESTABLISHED
难道现在真的已经不再使用docker,直接使用 ``containerd`` 这样的 :ref:`container_runtimes`
- 检查 ``top`` 输出::
Tasks: 149 total, 1 running, 148 sleeping, 0 stopped, 0 zombie
%Cpu(s): 3.0 us, 1.8 sy, 0.0 ni, 92.7 id, 2.2 wa, 0.0 hi, 0.2 si, 0.2 st
MiB Mem : 3929.8 total, 2579.8 free, 531.7 used, 818.4 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 3179.4 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
18408 root 20 0 1173260 336344 71252 S 4.6 8.4 0:32.39 kube-apiserver
437 root 20 0 1855336 97924 63844 S 2.0 2.4 2:49.35 kubelet
19247 root 20 0 818924 89480 59096 S 2.0 2.2 0:02.62 kube-controller
422 root 20 0 1296700 60624 30648 S 0.7 1.5 0:51.12 containerd
262 root 19 -1 93020 37364 36260 S 0.3 0.9 0:07.20 systemd-journal
18028 root 20 0 0 0 0 I 0.3 0.0 0:00.05 kworker/1:0-events
可以看到系统已经运行了 ``kube-apiserver`` 和 ``kube-controller`` ,说明Kubernetes相关容器已经运行,否则也不会有这些进程。
- 检查节点::
kubectl get nodes -o wide
提示信息::
Unable to connect to the server: Forbidden
why?
想到我部署采用DNSRR,也就是解析 ``apiserver.staging.huatai.me`` 域名可能是访问目前尚未加入管控的另外2个服务器,所以我尝试把DNS解析修改成只解析到节点1,也就是第一个加入管控的节点IP。但是依然没有解决
- 检查 ``kubelet.service`` 日志::
sudo journalctl -u kubelet.service | less
看到启动kubelet之后有报错信息,首先就是有关网络没有就绪的错误::
Jul 11 09:06:40 z-k8s-m-1 kubelet[437]: E0711 09:06:40.420728 437 kubelet.go:2424] "Error getting node" err="node \"z-k8s-m-1\" not found"
Jul 11 09:06:40 z-k8s-m-1 kubelet[437]: E0711 09:06:40.521709 437 kubelet.go:2424] "Error getting node" err="node \"z-k8s-m-1\" not found"
Jul 11 09:06:40 z-k8s-m-1 kubelet[437]: E0711 09:06:40.581769 437 kubelet.go:2349] "Container runtime network not ready" networkReady="NetworkReady=false reason:NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized"
Jul 11 09:06:40 z-k8s-m-1 kubelet[437]: E0711 09:06:40.622654 437 kubelet.go:2424] "Error getting node" err="node \"z-k8s-m-1\" not found"
...
Jul 11 09:06:41 z-k8s-m-1 kubelet[437]: I0711 09:06:41.796597 437 kubelet_node_status.go:70] "Attempting to register node" node="z-k8s-m-1"
...
Jul 11 09:06:43 z-k8s-m-1 kubelet[437]: I0711 09:06:43.232192 437 kubelet_node_status.go:108] "Node was previously registered" node="z-k8s-m-1"
Jul 11 09:06:43 z-k8s-m-1 kubelet[437]: I0711 09:06:43.232303 437 kubelet_node_status.go:73] "Successfully registered node" node="z-k8s-m-1"
Jul 11 09:06:43 z-k8s-m-1 kubelet[437]: I0711 09:06:43.427832 437 apiserver.go:52] "Watching apiserver"
Jul 11 09:06:43 z-k8s-m-1 kubelet[437]: I0711 09:06:43.438830 437 topology_manager.go:200] "Topology Admit Handler"
...
Jul 11 09:06:43 z-k8s-m-1 kubelet[437]: E0711 09:06:43.440795 437 pod_workers.go:951] "Error syncing pod, skipping" err="network is not ready: container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized" pod="kube-system/cor
edns-6d4b75cb6d-pf7bs" podUID=79bc049c-0f1a-4387-aeed-ccfb04dfe7ca
Jul 11 09:06:43 z-k8s-m-1 kubelet[437]: E0711 09:06:43.440978 437 pod_workers.go:951] "Error syncing pod, skipping" err="network is not ready: container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized" pod="kube-system/cor
edns-6d4b75cb6d-m2hf6" podUID=b2d40bb9-f431-4c53-a164-215bfcd4da47
...
可以看到访问 apiserver 失败,并且网络 cni plugin 没有初始化。想起来当时在官方文档中看到过必须初始化网络之后才能正常工作。(虽然我之前在 :ref:`single_master_k8s` 经验是无需cni也至少能够看到pod运行,并且能够使用 ``docker ps`` )
此外,在 :ref:`container_runtimes` 从官方文档查到 kubernetes 1.24 之后移除了docker支持,是否不再支持使用docker ? 我检查了 :ref:`container_runtimes` 中对运行时检查 ``sockets`` 方法,确认系统只有 ``containerd`` 的sockets文件
仔细检查了 ``kubeadm init`` 输出信息,可以看到提示安装cni的方法::
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
参考 `Troubleshooting CNI plugin-related errors `_ 提供了排查CNI插件的建议。其中在文档开始就提出:
- 为避免CNI plugin相关错误,首先应该将 :ref:`container_runtimes` 升级到对应Kubernetes版本的已经验证正常工作的CNI plugins版本。例如,对于 Kubernetes 1.24 需要满足:
- containerd v1.6.4 或更高版本, v1.5.11 或更高版本
- CRI-O v1.24.0 或更新版本
我检查了一下我的 ``containerd`` 版本,发现是采用发行版安装的 ``docker.io`` ,所以版本不是最新, ``containerd`` 的版本只是 ``1.5.9`` ,所以很可能是版本过低无法适配。该文档还提示:
在Kubernetes, ``containerd`` 运行时哦人添加一个回环接口 ``lo`` 给pods作为默认特性。containerd运行时配置通过一个 CNI plugin ``loopback`` 来实现,这是 ``containerd`` 发行包默认分发的一部分,例如 ``containerd`` v1.6.0 以及更高版本就将一个CNI v1.0.0兼容loopback插件作为默认CNI plugins。
.. note::
根据上文排查,无法正常启动 ``kubeadmin init`` 容器是因为Kubernetes 1.24,也就是我安装的最新K8s已经移除了CNI plugin,将这部分工作移交给容器运行时自带的CNI plugin来完成。这就要求配套使用最新版本(或满足版本要求)的 ``containerd`` 运行时。最新版本的 ``containerd`` 运行时默认启动 ``loopback`` 就提供了kubernetes管控平面pods运行的条件,这样从开始就可以拉起 Kubernetes 的管控pods,为下一步安装不同的 :ref:`k8s_network` 提供初始运行条件。当Kubernetes集群正常运行后,通过 :ref:`cilium_install_with_external_etcd` 就可以直接在运行起来的kubernetes集群上完成网络定制。
`containerd versioning and release `_ 提供了支持 Kubernetes 不同版本所对应当 ``containerd`` 版本,确实明确指出 Kubernetes 1.24 需要 ``containerd 1.64+,1.5.11+``
再次排查启动问题
===================
我采用以下方式重新开始部署
- 执行 :ref:`kubeadm_reset` 删除掉存在异常的k8s集群
- 重试通过 :ref:`install_containerd_official_binaries` 将发行版 ``containerd`` 升级到 1.64+ ,每个节点都执行一遍,确保采用最新 ``containerd``
- 改进 ``kubeadm-config.yaml`` 自定义集群名(见上文,已经修订到配置中)
重新执行了 ``kubeadmin init`` 但是发现 ``kubectl get nodes`` 依然出现报错 ``Unable to connect to the server: Forbidden``
.. note::
我没有想到从熟悉的 :ref:`docker` 切换到 :ref:`containerd` 遇到这么多麻烦:
- Kubernetes 1.24 中无法使用 ``docker`` 命令,而 ``ctr`` 命令实践下来也是存在问题的(实际容器已经启动,但是没有任何管理输出)
- 需要完整切换到Kubernetes 1.24所使用的标准 cri 接口命令 :ref:`crictl` 才能观察容器运行情况
- 按照 :ref:`crictl` 配置好 ``/etc/crictl.conf`` :
.. literalinclude:: ../../../debug/crictl/crictl.yaml
:language: yaml
:caption: crictl配置文件 /etc/crictl.yaml
- 执行pods检查::
crictl pods
输出显示:
.. literalinclude:: k8s_dnsrr/crictl_pods
:language: bash
- 检查镜像::
crictl images
输出显示:
.. literalinclude:: k8s_dnsrr/crictl_images
- 检查容器::
crictl ps -a
显示主机上运行的容器:
.. literalinclude:: k8s_dnsrr/crictl_containers
以上的排查可以看到 ``z-k8s-m-1`` 服务器上各个容器以及pods是运行正常的
- 检查容器日志,例如检查 apiserver 容器日志::
crictl logs 901b1dc06eed1
未发现报错,看起来 apiserver 运行正常
万般无奈,我再次 google 了一下,终于 ``蚌埠住了`` :
.. figure:: ../../../../_static/kubernetes/deployment/bootstrap_kubernetes_ha/ha_k8s_dnsrr/marmot.gif
``Unable to connect to the server: Forbidden`` 报错原因很简单: ``z-k8s-m-1`` **设置了http代理**
原来,在最初为了翻墙下载google仓库文件,我配置了 :ref:`curl_proxy` ,原来报错信息是因为代理服务器拒绝导致的。多么可笑的失误啊!!!
简单注释掉代理配置的环境变量就顺利可以执行 ``kubectl`` 了::
unset http_proxy
unset https_proxy
.. note::
不过,也别灰心...
这一周的折腾,至少对Kubernetes的 :ref:`container_runtimes` 等新技术有了进一步了解,也顺带学习了一些相关技术...不放弃
- 现在终于能够通过 ``kubectl`` 管理新部署的集群了::
kubectl get nodes
显示输出::
NAME STATUS ROLES AGE VERSION
z-k8s-m-1 NotReady control-plane 18h v1.24.2
- 检查 pods ::
kubectl get pods -n kube-system -o wide
此时输出:
.. literalinclude:: k8s_dnsrr/kubectl_get_pods_before_net
:language: bash
:caption: 没有安装网络前无法启动coredns,此时 kubectl get pods 输出
.. note::
目前还有2个问题没有解决:
- ``z-k8s-m-1`` 节点状态是 ``NotReady``
- ``coredns`` 管控pods无法启动(网络没有配置)
- 这个问题我之前在 :ref:`single_master_k8s` 已经有经验,只要为Kubernetes集群安装正确的网络接口即可启动容器
- 请注意,Kubernetes集群的3大组件 ``apiserver`` / ``scheduler`` / ``controller-manager`` 都是使用物理主机的IP地址 ``192.168.6.101`` ,也就是说,即使没有安装网络接口组件这3个管控组件也是能够启动的;这也是为何在 ``kubeadm-config.yaml`` 配置的 ``controlPlaneEndpoint`` 项域名 ``z-k8s-api.staging.huatai.me`` 就是指向物理主机IP地址的解析
安装 :ref:`cilium`
======================
需要注意,针对 :ref:`priv_deploy_etcd_cluster_with_tls_auth` (扩展外部etcd)需要采用 :ref:`cilium_install_with_external_etcd` :
- 首先在节点安装 :ref:`helm` :
.. literalinclude:: ../../helm/helm_startup/linux_helm_install
:language: bash
:caption: 在Linux平台安装helm
- 设置cilium Helm仓库:
.. literalinclude:: ../../../network/cilium/installation/cilium_install_with_external_etcd/helm_repo_add_cilium
:language: bash
:caption: 设置cilium Helm仓库
- 通过 :ref:`helm` 部署Cilium:
.. literalinclude:: ../../../network/cilium/installation/cilium_install_with_external_etcd/helm_install_cilium
:language: bash
:caption: 为cilium配置访问etcd的Kubernetes secret,安装cilium采用SSL模式访问etcd
- 此时,在安装了 cilium 这样的 CNI 之后,之前部署过程中没有运行起来的coredns容器就能够分配IP地址并运行起来::
kubectl -n kube-system get pods -o wide
输出显示:
.. literalinclude:: k8s_dnsrr/kubectl_get_pods_after_net
:language: bash
:caption: 安装cilium CNI网络之后coredns就可以运行,此时 kubectl get pods 输出可以看到所有pods已分配IP并运行
- 安装cilium客户端:
.. literalinclude:: ../../../network/cilium/installation/cilium_install_with_external_etcd/install_cilium_cli
:language: bash
:caption: 安装cilium CLI
- 检查::
cilium status
.. literalinclude:: ../../../network/cilium/installation/cilium_install_with_external_etcd/cilium_status_after_install
:language: bash
:caption: cilium安装完成后状态验证
.. note::
至此,已初步完成了管控节点安装,接下来就是添加更多管控节点,以及增加工作节点。这个操作可以从最初 ``kubeadmin init`` 输出的提示信息中获取(如果你当时保存了输出信息)
添加第二个管控节点
====================
- 按照 ``kubeadm init`` 输出信息,在第二个管控节点 ``z-k8s-m-2`` 上执行节点添加:
.. literalinclude:: k8s_dnsrr/kubeadm_join_control-plane
:language: bash
:caption: kubeadm join添加control-plane节点
管控节点添加排查
-----------------
.. note::
``kubeadm`` 初始化集群时候生成的 ``certificate`` 和 ``token`` (24小时) 都是有一定有效期限。所以如果在初始化之后,再经过较长时间才添加管控节点和工作节点,就会遇到 ``token`` 和 ``certificate`` 相关错误。此时,需要重新上传certifiate和重新生成token。并且,对于使用 external etcd,还需要通过 ``kubeadm-config.yaml`` 传递etcd参数。
我在执行 ``kubeadm join`` 管控节点添加遇到报错::
error execution phase preflight: couldn't validate the identity of the API Server: could not find a JWS signature in the cluster-info ConfigMap for token ID "XXXXXXX"
To see the stack trace of this error execute with --v=5 or higher
上述报错是因为原有的token已经过期,所以需要重新生成:
.. literalinclude:: k8s_dnsrr/kubeadm_token_create
:language: bash
:caption: kubeadm token create命令重新生成token(解决初始化集群时token过期问题)
- 然后再次执行 ``kubeadm init`` 命令,但是把tokern替换成新生成的有效token(依然保留之前的 ``--certificate-key`` ),此时会提示 ``kubeadm-certs`` 没有找到::
...
[download-certs] Downloading the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
error execution phase control-plane-prepare/download-certs: error downloading certs: error downloading the secret: Secret "kubeadm-certs" was not found in the "kube-system" Namespace. This Secret might have expired. Please, run `kubeadm init phase upload-certs --upload-certs` on a control plane to generate a new one
To see the stack trace of this error execute with --v=5 or higher
根据提示,实际上 ``kubeadm token create`` 只是针对worker节点,对于管控节点,还需要重新上传certificates( 参考 `How do I find the join command for kubeadm on the master? `_ )。也就是对于token失效的时候,新加入管控节点需要有2步:
- 在已经工作的管控节点上重新上传certifiates:
.. literalinclude:: k8s_dnsrr/kubeadm_init_phase_upload-certs
:language: bash
:caption: kubeadm init 重新上传证书
此时提示重新生成了证书::
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
XXXXXXXXXX
- 然后执行重建toke命令(前面执行过可以不用重复):
.. literalinclude:: k8s_dnsrr/kubeadm_token_create
:language: bash
:caption: kubeadm token create命令重新生成token(解决初始化集群时token过期问题)
- 可以执行检查token命令::
kubeadm token list
就显示出刚才重新生成的token
- 将生成的 ``certificate`` 拼接到 ``kubeadm join`` 命令(使用新生成的token)再次添加管控节点。然而还是报错::
[download-certs] Downloading the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
error execution phase control-plane-prepare/download-certs: error downloading certs: the Secret does not include the required certificate or key - name: external-etcd.crt, path: /etc/kubernetes/pki/apiserver-etcd-client.crt
To see the stack trace of this error execute with --v=5 or higher
原来重新生成 ``cartificate`` 的默认命令是针对内部etcd的, ``对于外部etcd,重新初始化证书还是要使用 "包含" etcd配置信息的 kubeadm-config.yaml`` ( 参考 `Control plane certs not working with external etcd #1886 `_ ),即:
.. literalinclude:: k8s_dnsrr/kubeadm_init_phase_upload-certs_external_etcd
:language: bash
:caption: 使用external etcd时,kubeadm init 重新上传证书需要使用 kubeadm-config.yaml
添加工作节点
==================
- 按照 ``kubeadm init`` 输出信息,在工作节点 ``z-k8s-n-1`` 等上执行:
.. literalinclude:: k8s_dnsrr/kubeadm_join_worker
:language: bash
:caption: kubeadm join添加worker节点
完成检查
===========
- 最终完成后检查 ``nodes`` 和 ``podes`` 得到完整列表:
.. literalinclude:: k8s_dnsrr/kubectl_get_nodes
:language: bash
:caption: 完成扩展etcd的K8s集群后检查kubectl get nodes
.. literalinclude:: k8s_dnsrr/kubectl_get_pods
:language: bash
:caption: 完成扩展etcd的K8s集群后检查kubectl get pods
集群创建成功!!!
验证
========
由于摈弃了 :ref:`docker` ,采用 :ref:`nerdctl` 来实现镜像构建和运行(实践步骤记录在 :ref:`nerdctl` )
参考
========
- `Creating Highly Available Clusters with kubeadm `_ 官方文档综合了 :ref:`ha_k8s_stacked` 和 :ref:`ha_k8s_external` ,我在本文实践中拆解了 :ref:`ha_k8s_external`
- `Network Plugins `_
- `cilium Quick Installation `_
- `kubesphere主节点执行kubectl命令提示Unable to connect to the server: Forbidden `_ 感谢这位网友提供的信息: ``找到问题了,是设置了http代理的问题...unset http_proxy...通过master节点30880端口访问是没有问题的,只是执行在master节点执行kubectl命令报错,在worker节点上执行kubectl命令没有任何问题``