[关闭]
@cdmonkey 2023-08-11T05:52:36.000000Z 字数 13246 阅读 63

Kubernetes 部署

Kubernetes


https://kubernetes.feisky.xyz/components/federation.html
http://rootsongjc.github.io/blogs/kubernetes-installation-on-centos
Binary: https://www.kubernetes.org.cn/4963.html

慕课网:

https://git.imooc.com/coding-335/kubernetes-ha-kubeadm

说明:

一、环境准备

基本配置

hosts

若是使用 kubeadm 工具进行部署,通常就是将功能部件部署为守护进程。
使用 kubeadm 进行安装,其优点是优雅、简单、支持高可用及升级方便;缺点是不易维护、文档简陋。

  1. # /etc/hosts
  2. 172.16.142.51 k8s-master01
  3. 172.16.142.52 k8s-master02
  4. 172.16.142.53 k8s-master03
  5. 172.16.142.54 k8s-node01
  6. 172.16.142.55 k8s-node02
  7. 172.16.198.180 k8s-master-lb # 若不是高可用部署,则这个IP为 k8s-master01 IP地址

安装依赖包

安装一些必要软件包:

  1. yum install -y conntrack ipvsadm ipset jq sysstat curl iptables libseccomp net-tools telnet yum-utils \
  2. device-mapper-persistent-data lvm2

所有主机上要关闭防火墙、NetworkManager、SELinux,禁用 swap 设备,并设置时间同步(必须要同步)。还要配置好 Hosts 文件,使得相互间能够识别主机名。另外不允许运行其他一切 DNS 服务。

关闭 SELinux

  1. setenforce 0
  2. sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
  3. sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/sysconfig/selinux
  4. # 其实这两个文件是同一个文件:
  5. [root@k8s-node01 ~]# ll /etc/sysconfig/selinux
  6. lrwxrwxrwx. 1 root root 17 Apr 21 2021 /etc/sysconfig/selinux -> ../selinux/config

关闭 Swap

关闭当前已启用的所有交换分区设备:

  1. [root@k8s-master01 ~]# swapoff -a && sysctl -w vm.swappiness=0
  2. [root@k8s-master01 ~]# free -m
  3. total used free shared buff/cache available
  4. Mem: 3951 108 3486 16 356 3595
  5. Swap: 0 0 0
  6. # 而后编辑 fstab 配置文件,注释掉用于挂载Swap设备的配置行:
  7. [root@k8s-master01 ~]# sed -i '/swap/s/^\(.*\)$/#\1/g' /etc/fstab

关闭防火墙

  1. systemctl stop firewalld && systemctl disable firewalld
  2. # 清空防火墙规则:
  3. iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat && iptables -P FORWARD ACCEPT

其他一些需要关闭并禁用的:

  1. systemctl disable --now dnsmasq
  2. systemctl disable --now firewalld
  3. systemctl disable --now NetworkManager

注意:某些公有云需要使用 NetworkManager,若是这样就不要关闭。

安装 IPVS

若是要使用 ipvs 模型的 proxy,各个节点内核还需要载入 ipvs 相关各模块,否则只能使用 iptables。
必要软件包前面已经安装了。

https://mp.weixin.qq.com/s/3aLXsI66kzlLbigEK1hOTw

所有节点配置 ipvs 模块:

  1. cat > /etc/sysconfig/modules/ipvs.modules <<EOF
  2. #!/bin/bash
  3. modprobe -- ip_vs
  4. modprobe -- ip_vs_rr
  5. modprobe -- ip_vs_wrr
  6. modprobe -- ip_vs_sh
  7. modprobe -- nf_conntrack
  8. EOF
  9. chmod 755 /etc/sysconfig/modules/ipvs.modules # 配置权限
  10. bash /etc/sysconfig/modules/ipvs.modules # 载入模块
  11. lsmod | grep -e ip_vs -e nf_conntrack # 检查模块载入情况

说明:若内核版本是 4.19,则 nf_conntrack_ipv4 变为了 nf_conntrack

内核调优

这一步我感觉并非必须。

  1. cat > /etc/sysctl.d/kubernetes.conf <<EOF
  2. net.bridge.bridge-nf-call-iptables=1
  3. net.bridge.bridge-nf-call-ip6tables=1
  4. net.ipv4.ip_forward=1
  5. vm.swappiness=0
  6. vm.overcommit_memory=1
  7. vm.panic_on_oom=0
  8. fs.inotify.max_user_watches=89100
  9. EOF
  10. # 生效配置文件:
  11. sysctl -p /etc/sysctl.d/kubernetes.conf

前面两行是打开 Iptables 内生之桥接相关功能(干啥用的?)
若是有下面这个报错:

  1. sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-iptables: No such file or directory
  2. sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-ip6tables: No such file or directory

请执行:

  1. modprobe br_netfilter

所有节点配置完内核后,重启服务器,保证重启后内核依旧载入。

  1. reboot
  2. lsmod | grep --color=auto -e ip_vs -e nf_conntrack

配置软件源

最后就是要配置软件源。除了普通的软件源及 epel 源外,还需要配置 docker、kubernetes 源。

  1. # 首先是 docker 仓库:
  2. wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
  3. # 而后还要手工生成 kubernetes 仓库配置文件:
  4. cat <<EOF > /etc/yum.repos.d/kubernetes.repo
  5. [kubernetes]
  6. name=Kubernetes
  7. baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
  8. enabled=1
  9. gpgcheck=1
  10. repo_gpgcheck=1
  11. gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
  12. EOF

专用 kubectl 服务器

另外,可配置 Master01 免密登录其他主机,安装过程中生成配置文件及证书均于这台机器上进行,集群管理同样是于这台机器上进行。阿里云及 AWS 上通常都需要一台单独 kubectl 服务器。

  1. [root@k8s-master01 ~]# ssh-keygen -t rsa
  2. for i in k8s-master01 k8s-master02 k8s-master03 k8s-node01 k8s-node02; do ssh-copy-id -i ~/.ssh/id_rsa.pub root@$i;done

系统升级

首先对除内核以外的进行升级:

  1. # 暂时先不对内核进行升级。CentOS7 建议升级,而 CentOS8 可按需进行
  2. yum update -y --exclude=kernel* && reboot
  3. # 升级完成后查看系统版本:
  4. [root@k8s-node02 ~]# cat /etc/redhat-release
  5. CentOS Linux release 7.9.2009 (Core)

Update kernel

从大量生产实践看,一定要升级至 4.18 及其更高版本。这里我们升级至 4.19。

RPM 包下载地址:https://elrepo.org/linux/kernel
归档版本下载:https://www.kernel.org

二、集群安装

能够看到,共涉及三个网段。实验中 Node network 使用了 172.16.142.0/24 这个段。

1. 安装 Docker

首先于所有节点上安装 Docker,安装前要确定 Kubernetes 版本及 Docker 版本。
要怎样确定 Kubernetes 版本及其需要使用之 Docker 版本呢?通常可查阅其源码更新日志:

https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG

CLog.png-70.7kB

目前,1.18 版本更新日志中并未提及相关 docker 版本信息,但是 1.17 更新日志中有提及(于日志页面中直接搜索 docker):

Update the latest validated version of Docker to 19.03 (#84476, @neolit123)

因而这里使用了最新的 Kubernetes 1.18.7,而 Docker 版本需要选择 19.03。

  1. # 查看可安装 docker 版本:
  2. yum list docker-ce.x86_64 --showduplicates | sort -r
  3. Loading mirror speeds from cached hostfile
  4. Loaded plugins: fastestmirror
  5. Installed Packages
  6. ...
  7. docker-ce.x86_64 3:19.03.12-3.el7 docker-ce-stable
  8. ...

能够看到,最新版本就是 19.03,因而直接安装就行了:

  1. yum install -y docker-ce docker-ce-selinux
  2. # Package docker-ce-selinux is obsoleted by docker-ce, trying to install 3:docker-ce-19.03.12-3.el7.x86_64 instead
  3. # 因而直接执行下面这个指令就行:
  4. yum install -y docker-ce

若是要安装指定版本,可使用命令:

  1. # 注意: 版本号不包含冒号 : 与之前的数字
  2. yum install -y --setopt=obsoletes=0 docker-ce-19.03.12-3.el7

2. 安装其他必要工具

最后于所有节点上安装三个集群必要工具:kubeadm、kubelet、kubectl

  1. # 找到要安装的版本号:
  2. yum list kubeadm --showduplicates | sort -r
  3. # 安装指定版本,这里用的是 1.18.6
  4. yum install -y kubeadm-1.18.6-0 kubelet-1.18.6-0 kubectl-1.18.6-0 --disableexcludes=kubernetes
  5. # 若不指定版本,直接进行安装就行:
  6. yum install -y kubeadm kubelet kubectl
  7. # 其实只安装 kubeadm 就行,其他两个工具会作为依赖一并安装:
  8. yum install -y kubeadm
  9. # kubeadm: 部署集群用的命令
  10. # kubelet: 于集群中每台机器上都要运行的组件,负责管理pod、容器生命周期
  11. # kubectl: 集群管理工具。可选,只要于控制集群之节点上安装即可

目前看,kubeadm 版本对应着所要安装的 Kubernetes 版本。——错误!

3. 配置并启动 docker 服务

需要于所有节点上把 docker 服务启动起来。启动前,有些启动参数最好是配置上,但是属于可选操作。

  1. # graph: 设置数据目录:选择比较大的分区。缺省为 /var/lib/docker
  2. # exec-opts: 设置Cgroup driver。缺省是cgroupfs,推荐设置为systemd
  3. # The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
  4. mkdir -pv /etc/docker
  5. cat <<EOF > /etc/docker/daemon.json
  6. {
  7. "data-root": "/docker/data/path",
  8. "registry-mirrors": [
  9. "https://ip0q6hqs.mirror.aliyuncs.com"
  10. ],
  11. "insecure-registries": ["0.0.0.0/0"],
  12. "exec-opts": ["native.cgroupdriver=systemd"]
  13. }
  14. EOF

关于缺省存储路径配置,需要注意:

  1. # docker 17.03.2 以前配置为 graph
  2. # docker 17.04.x 以后配置为 data-root

根据 CRI installation 文档中的内容:
对于使用 systemd 作为 Init 的 Linux 发行版,使用 systemd 作为 docker 的 cgroup 驱动能够确保服务器节点于资源紧张之情况下更为稳定,因而这里修改各个节点 cgroup 驱动为 systemd。

若要通过默认 k8s.gcr.io 镜像仓库获得 K8s 系统组件相关镜像,需要于 docker Unit File 中指定代理信息:

  1. # 这一步不执行目前没啥问题。
  2. [root@k8s-master ~]# vim /usr/lib/systemd/system/docker.service
  3. Environment="HTTPS_PROXY=PROTOCOL://HOST:PORT"
  4. Environment="NO_PROXY=172.20.0.0/16,127.0.0.0/8"

老师曰:一旦使用了代理,则加速就没有必要了。

  1. # 请于 [Service] 配置中 ExecStart=/usr/bin/dockerd 这一行后面新增一行:
  2. # 这样能够使得 FORWARD 链其缺省策略重新设为 ACCEPT
  3. ExecStartPost=/usr/sbin/iptables -P FORWARD ACCEPT

最后启动服务,并且使其开机自启动:

  1. [root@k8s-master ~]# systemctl daemon-reload
  2. [root@k8s-master ~]# systemctl start docker
  3. [root@k8s-master ~]# systemctl enable docker

4. 初始化 Master

注意:这部分操作需要于 Master 节点上执行。同时还要了解 Master 上需要安装的控制平面组件:

 kube-apiserver
 kube-scheduler 作用是调度 pods 分配到那个 node 里,简单来说就是资源调度。
 kube-controller-manager

关于 kubeadm 工具,请参见:

https://kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm

准备镜像

首先可查看一下缺省初始化配置信息:

  1. [root@k8s-master ~]# kubeadm config print init-defaults
  2. ...
  3. imageRepository: k8s.gcr.io # 能够看到,缺省镜像仓库是gcr.io,国内不能正常访问。

初始化操作会从互联网下载所需镜像,过程比较漫长。运行初始化命令之前先运行这个命令,从而先行获得相关镜像文件,而后再执行初始化,感觉就好多了。

  1. # 可先查看所需镜像:
  2. [root@rust-master01 ~]# kubeadm config images list
  3. W0821 13:56:31.902895 30984 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
  4. k8s.gcr.io/kube-apiserver:v1.18.8
  5. k8s.gcr.io/kube-controller-manager:v1.18.8
  6. k8s.gcr.io/kube-scheduler:v1.18.8
  7. k8s.gcr.io/kube-proxy:v1.18.8
  8. k8s.gcr.io/pause:3.2
  9. k8s.gcr.io/etcd:3.4.3-0
  10. k8s.gcr.io/coredns:1.6.7
  11. # 获得镜像:
  12. kubeadm config images pull

肯定是下载不了。可使用这个脚本:

http://t.cn/EilykIW

还有一个问题需要注意,阿里云上可能没有 1.18.8 这个较新版本之镜像,目前只有 1.18.6 这个版本。因而这里将获得之官方 1.18.8 镜像推送至阿里云私有仓库,所以脚本修改为:

  1. [root@k8s-master ~]# cat pull_k8s_images.sh
  2. #!/bin/bash
  3. for i in `kubeadm config images list`; do
  4. imageName=${i#k8s.gcr.io/}
  5. aliyun_registry="registry.cn-beijing.aliyuncs.com/cdmonkey_k8s"
  6. docker pull ${aliyun_registry}/$imageName
  7. docker tag ${aliyun_registry}/$imageName k8s.gcr.io/$imageName
  8. docker rmi ${aliyun_registry}/$imageName
  9. done

执行脚本之前需要进行登录:

  1. docker login --username=cdmonkey2019 registry.cn-beijing.aliyuncs.com

查看下载好的镜像:

  1. [root@rust-master01 ~]# docker image list
  2. REPOSITORY TAG IMAGE ID CREATED SIZE
  3. k8s.gcr.io/kube-proxy v1.18.8 0fb7201f92d0 7 days ago 117MB
  4. k8s.gcr.io/kube-apiserver v1.18.8 92d040a0dca7 7 days ago 173MB
  5. k8s.gcr.io/kube-controller-manager v1.18.8 6a979351fe5e 7 days ago 162MB
  6. k8s.gcr.io/kube-scheduler v1.18.8 6f7135fb47e0 7 days ago 95.3MB
  7. k8s.gcr.io/pause 3.2 80d28bedfe5d 6 months ago 683kB
  8. k8s.gcr.io/coredns 1.6.7 67da37a9a360 6 months ago 43.8MB
  9. k8s.gcr.io/etcd 3.4.3-0 303ce5db0e90 10 months ago 288MB

注意:Node 节点只需要准备好 kube-proxy、pause 这两个镜像就行了。

至此,相关镜像准备妥当完毕了。

配置 kubelet

  1. vim /etc/sysconfig/kubelet
  2. KUBELET_EXTRA_ARGS=--cgroup-driver=systemd # 这里一定要同 Docker 相应配置保持一致

注意,到这里还不能直接启动 kubelet 服务,会有报错,需要执行完初始化才行。请见:
https://github.com/kubernetes/kubernetes/issues/65863

进行初始化

请确保这两个指令执行过了,省得初始化完成后抛出相关警告信息。

  1. systemctl enable docker.service
  2. systemctl enable kubelet.service

最后执行初始化指令:

  1. kubeadm init --kubernetes-version=v1.16.7 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 --ignore-preflight-errors=Swap
  2. # 版本号需要准确指定。
  3. # 若是没啥问题就能看到最后的成功信息:
  4. Your Kubernetes control-plane has initialized successfully!
  5. To start using your cluster, you need to run the following as a regular user:
  6. mkdir -p $HOME/.kube
  7. sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  8. sudo chown $(id -u):$(id -g) $HOME/.kube/config
  9. You should now deploy a pod network to the cluster.
  10. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  11. https://kubernetes.io/docs/concepts/cluster-administration/addons/
  12. Then you can join any number of worker nodes by running the following on each as root:
  13. kubeadm join 172.16.138.11:6443 --token glqmmh.q0pqn2m48bx58tx9 \
  14. --discovery-token-ca-cert-hash sha256:07d5cfc2d45de9756e664126d9dcaef004b7b9e016c8389c8b4029193562826d
  15. # 一定要备份最后给出了将节点加入集群的命令。

注意:若是使用 Calico,建议使用 --pod-network-cidr=10.224.0.0/16 而不是 244

若是初始化时卡在某一步不能继续下去时,可使用

  1. journalctl -xeu kubelet # 查看初始化日志,找到错误原因

相关参数说明:

  1. --kubernetes-version # 指定 kubeadm 版本
  2. --pod-network-cidr # 指定 Pod 所属网段。
  3. # 因为是选择 flannel 作为 Pod 网络插件,因而指定 –pod-network-cidr=10.244.0.0/16
  4. --service-cidr # 指定 Service 所属网段
  5. --ignore-preflight-errors=Swap # 忽略 Swap 报错
  6. --upload-certs #

这些参数可通过命令行直接配置,还可写入专门的 kubeadm 配置文件,并使用 --config 进行引用。若是需要修改 kubernetes 服务配置选项,就必须指定这个配置文件。

  1. # Generate the configuration file:
  2. [root@master01 tools]# kubeadm config print init-defaults > kubeadm-init.yaml

使用配置文件的好处是方便变更配置,像是镜像仓库地址啥的。

后续操作这里直接使用根用户。

  1. [root@k8s-master ~]# mkdir -p $HOME/.kube
  2. [root@k8s-master ~]# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

至此,第一个 Master 节点初始化完成。这时可访问健康状态检查的地址:

  1. curl -k https://localhost:6443/healthz # 返回一个 ok 就对了

集群初始化若是遇有问题,可使用下面的命令进行清理:

  1. kubeadm reset
  2. ifconfig cni0 down
  3. ip link delete cni0
  4. ifconfig flannel.1 down
  5. ip link delete flannel.1
  6. rm -rf /var/lib/cni/

5. 初始化kubectl

kubectl 指令是 API Server 客户端命令行工具。
这个指令实现了除集群部署外几乎全部管理操作,是 k8s 管理员最常用命令之一。

  1. # 其实就是初始化完成后要执行的那两条指令。前面执行过了,这里就不用再执行了。
  2. [root@k8s-master ~]# mkdir .kube
  3. [root@k8s-master ~]# cp /etc/kubernetes/admin.conf .kube/config

而后,可使用 kubectl 指令进行客户端命令检测,同时了解集群组件当前状态:

  1. [root@k8s-master ~]# kubectl get nodes
  2. NAME STATUS ROLES AGE VERSION
  3. k8s-master NotReady master 17h v1.14.0
  4. # 还可使用:
  5. [root@k8s-master ~]# kubectl get pods --all-namespaces
  6. [root@k8s-master ~]# kubectl get componentstatus
  7. NAME STATUS MESSAGE ERROR
  8. scheduler Healthy ok
  9. controller-manager Healthy ok
  10. etcd-0 Healthy {"health":"true"}

6. 安装网络组件

flannel

只需要于 Master 节点执行安装操作就行,但是所有节点必须要准备好镜像。

https://github.com/coreos/flannel

首先需要手动下载镜像:

  1. docker pull quay.azk8s.cn/coreos/flannel:v0.11.0-amd64
  2. docker tag quay.azk8s.cn/coreos/flannel:v0.11.0-amd64 quay.io/coreos/flannel:v0.11.0-amd64
  3. docker rmi quay.azk8s.cn/coreos/flannel:v0.11.0-amd64

进行安装:

  1. [root@master01 ~]# mkdir -pv /etc/kubernetes/flannel
  2. [root@master01 ~]# cd /etc/kubernetes/flannel
  3. wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
  4. # 可能需要翻墙下载
  5. [root@master01 flannel]# kubectl apply -f kube-flannel.yml

而后使用命令确认其输出结果中 Pod 状态为 Running

  1. [root@master01 flannel]# kubectl get pods -n kube-system
  2. NAME READY STATUS RESTARTS AGE
  3. coredns-5644d7b6d9-f85ms 1/1 Running 0 3h44m
  4. coredns-5644d7b6d9-tjdzd 1/1 Running 0 3h44m
  5. etcd-master01 1/1 Running 0 3h43m
  6. kube-apiserver-master01 1/1 Running 0 3h43m
  7. kube-controller-manager-master01 1/1 Running 0 3h43m
  8. ...

注意:只有 Running 才是就绪状态,显示别的都不是就绪状态。

还可查看 Pod 具体情况:

  1. # kubectl describe pod <Pod Name>
  2. kubectl describe pod kube-flannel-ds-amd64-jqh9z --namespace=kube-system
  3. # 输出内容很多,于最后面能够看到是镜像获取失败。
  4. # 我们可耐心等待,因为 K8s 会进行重试,还可直接执行 docker pull 下载这个镜像。

这里有一个小工具可供使用,用于获取镜像。

https://ss.samblade.top/docker-get.html

  1. docker-get quay.io/coreos/flannel:v0.11.0-amd64

全部显示为 Running 后再次查看节点信息:

  1. [root@k8s-master ~]# kubectl get node
  2. NAME STATUS ROLES AGE VERSION
  3. k8s-master Ready master 19h v1.14.0 # 能够看到,Master节点已变为就绪状态。

Calico

请参见相关文档。

7. 加入node节点

若未禁用 Swap 设备,编辑 kubelet 配置文件,设置其忽略 Swap 启用的状态错误:

  1. # 提示:若是节点上已禁用了所有 Swap 设备,则无须执行这个步骤。
  2. [root@k8s-node1 ~]# vim /etc/sysconfig/kubelet
  3. KUBELET_EXTRA_ARGS="--fail-swap-on=false"

而后要使用 master 节点初始化过程中记录的 kubeadm join 指令新增节点。

  1. kubeadm join 172.16.138.11:6443 --token glqmmh.q0pqn2m48bx58tx9 \
  2. --discovery-token-ca-cert-hash sha256:07d5cfc2d45de9756e664126d9dcaef004b7b9e016c8389c8b4029193562826d
  3. # 注意:这条命令一定保存好,因为后期没法重现!
  4. ...
  5. This node has joined the cluster:
  6. * Certificate signing request was sent to apiserver and a response was received.
  7. * The Kubelet was informed of the new secure connection details.
  8. Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

执行完 join 指令后查看各节点状态信息:

  1. [root@master01 flannel]# kubectl get nodes
  2. NAME STATUS ROLES AGE VERSION
  3. master01 Ready master 3h40m v1.16.7
  4. worker01 Ready <none> 3h34m v1.16.7
  5. worker02 Ready <none> 3h33m v1.16.7

使用 Kubeadm 工具搭建的 K8s 集群,已经缺省集成了安全策略,因而要将 Master 节点 PKI 目录下所有文件拷贝至所有 node 节点上。

  1. scp -r /etc/kubernetes/pki/* root@k8s-node1:/etc/kubernetes/pki

若需要每个节点均能够执行 kubectl 指令,就需要于每个节点上执行这个指令的初始化操作:

  1. # 首先每个节点上创建相关目录:
  2. [root@k8s-node1 ~]# mkdir .kube
  3. # 从主节点拷贝配置文件:
  4. scp /etc/kubernetes/admin.conf root@k8s-node1:~/.kube/config

参考内容:

https://blog.frognew.com/2019/04/kubeadm-install-kubernetes-1.14.html
https://jicki.me/kubernetes/2019/05/09/kubeadm-1.14.1

官方文档:

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注