共计 5580 个字符,预计需要花费 14 分钟才能阅读完成。
kubeadm 的工作原理
作者:张首富
工夫:2020-06-04
w x:y18163201
置信应用二进制部署过 k8s 集群的同学们都晓得,二进制部署集群太艰难了,有点根底的人部署起来还有胜利的心愿,要不然只能跟着他人的教程一步一步的去部署,部署的时候齐全不晓得这样操作的意义是啥?出问题了无从下手解决。对于初学者来说真的是节约生命,那有没有什么简略的形式来部署集群呢?这个问题在前几年可能没有很好的答案,然而在当初,答案几乎太多了,比方 kubeadm,rke 等形式,咱们明天就来介绍下 kubeadm 部署集群的工作原理。
这里默认你有点 k8s 根底,晓得他们都是有哪些组件形成的。
在集群部署的时候,他的每一个组件都是一个须要被执行的,独自的二进制文件,在当初容器化那么发达的期间,咱们必定来用 docker 来简化部署。然而容器化部署的时候会有一个很大的问题,如何容器化 kubelet。
咱们晓得 kubelet 是 kubernetes 我的项目用来操作 Docker 等容器运行时的外围组件,在每个 节点上都存在,能够除了跟容器运行时打交道外,kubelet 在配置容器网络、治理容器数据卷事 时,他都须要间接操作宿主机。
如果当初 kubelet 自身就运行在一个容器里,那么间接操作宿主机就会变得很麻烦。对于网络配置来说还好,kubelet 容器能够通过不开启 Network Namespace(–net host)的形式,间接共享宿主机的网络栈。可是,要让 kubelet 隔着容器的 Mount Namespace 和文件系统,操作宿主机的文件系统,就有点儿艰难了。
比方,如果用户想要应用 NFS 做容器的长久化数据卷,那么 kubelet 就须要在容器进行绑定挂载前,在宿主机的指定目录上,先挂载 NFS 的近程目录。
可是,这时候问题来了。因为当初 kubelet 是运行在容器里的,这就意味着它要做的这个“mount -F nfs”命令,被隔离在了一个独自的 Mount Namespace 中。即,kubelet 做的挂载操作,不能被“流传”到宿主机上。
对于这个问题,有人说,能够应用 setns() 零碎调用,在宿主机的 Mount Namespace 中执行这些挂载操作;也有人说,应该让 Docker 反对一个–mnt=host 的参数。然而,到目前为止,在容器里运行 kubelet,仍然没有很好的解决办法,我也不举荐你用容器去部署 Kubernetes 我的项目。
因而为了解决下面这个问题,kubeadm 抉择了一种计划:
- 把 kubelet 间接部署在宿主机上,而后应用容器部署其余的 kubernetes 组件
所以,咱们应用 kubeadm 装置集群的第一步 就是在所有的机器上手动装置 kubeadm、kubelet 和 kubectl 这三个二进制文件。
centos/Redhat 装置:
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/ku…
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/ku… https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
yum -y install kubectl-1.14.0
yum -y install kubelet-1.14.0
yum -y install kubeadm-1.14.0
systemctl enable kubelet #必须要设置,
留神:如果你这个时候启动 kubelet 必定会发现一个报错,提醒短少文件,这个时候不必管它,咱们一会应用 kubeadm init 之后初始化集群就失常了
而后咱们须要创立 kubeadm 的配置文件,指定咱们集群信息。举个例子
cat > kubeadm-config.yaml <<-‘EOF’
apiVersion: kubeadm.k8s.io/v1alpha2
kind: MasterConfiguration
kubernetesVersion: v1.16.0
api:
advertiseAddress: 192.168.0.102
bindPort: 6443
…
etcd:
local:
dataDir: /var/lib/etcd
image: ""
imageRepository: k8s.gcr.io
kubeProxy:
config:
bindAddress: 0.0.0.0
...
kubeletConfiguration:
baseConfig:
address: 0.0.0.0
...
networking:
dnsDomain: cluster.local
podSubnet: “”
serviceSubnet: 10.96.0.0/12
nodeRegistration:
criSocket: /var/run/dockershim.sock
…
EOF
具体能够参考:https://kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm-init/
接下来咱们就能够应用 kubeadm init
来部署 Master 节点了。
kubeadm init 的工作流程
1,Prefligth Checks 查看
kubeadm 首先要做的,是一系列的查看工作,以确定这台机器能够用来部署 Kubernetes。这一步查看,咱们称为“Preflight Checks”,它能够为你省掉很多后续的麻烦。
其实,Preflight Checks 包含了很多方面,比方:
- Linux 内核的版本必须是否是 3.10 以上?
- Linux Cgroups 模块是否可用
- 机器的 hostname 是否规范?在 Kubernetes 我的项目里,机器的名字以及所有存储在 Etcd 中的 API 对象,都必须应用规范的 DNS 命名(RFC 1123)。
- 用户装置的 kubeadm 和 kubelet 的版本是否匹配?
- 机器上是不是曾经装置了 Kubernetes 的二进制文件?
- Kubernetes 的工作端口 10250/10251/10252 端口是不是曾经被占用?
- ip、mount 等 Linux 指令是否存在?
- Docker 是否曾经装置?
- Docker 和 kubelet 应用的驱动程序是否雷同?
- 。。。。
下面这些查看中,一些查看我的项目仅仅触发正告,其它的则会被视为谬误并且退出 kubeadm,除非问题失去解决或者用户指定了 --ignore-preflight-errors=<list-of-errors>
参数。
2,生成自签证书
在查看通过之后,kubeadm 会为你生成 kubernetes 对外提供服务所需的各种证书和对应的目录。
如果用户曾经通过 --cert-dir
配置的证书目录(默认为 /etc/kubernetes/pki
)提供了他们本人的 CA 证书以及 / 或者密钥,那么将会跳过这个步骤。
kubernetes 对外提供服务时,除非专门开启“不平安模式”,否则都要通过 HTTPS 能力拜访 Kube-apiserver。这就须要为 Kubernetes 集群配置好证书文件。
kubeadm 为 Kubernetes 我的项目生成的证书文件都放在 Master 节点的 /etc/kubernetes/pki
目录下。在这个目录下,最次要的证书文件是 ca.crt 和对应的私钥 ca.key。
此外,用户应用 kubectl 获取容器日志等 streaming 操作时,须要通过 kube-apiserver 向 kubelet 发动申请,这个连贯也必须是平安的。kubeadm 为 这一步生成的事 apiserver-kubelet-client.out 文件,对应的私钥是 apiserver-kubelet-client.key。
除此之外,Kubernetes 集群中还有 Aggregate APIServer 等个性,也须要用到专门的证书,这里我就不再一一列举了。能够参考这个文件:https://www.cnblogs.com/shoufu/p/12963081.html 须要指出的是,你能够抉择不让 kubeadm 为你生成这些证书,而是拷贝现有的证书到如下证书的目录里:
/etc/kubernetes/pki/ca.{crt,key}
[root@zsf-test pki]# tree
.
├── apiserver.crt
├── apiserver-etcd-client.crt
├── apiserver-etcd-client.key
├── apiserver.key
├── apiserver-kubelet-client.crt
├── apiserver-kubelet-client.key
├── ca.crt
├── ca.key
├── etcd
│ ├── ca.crt
│ ├── ca.key
│ ├── healthcheck-client.crt
│ ├── healthcheck-client.key
│ ├── peer.crt
│ ├── peer.key
│ ├── server.crt
│ └── server.key
├── front-proxy-ca.crt
├── front-proxy-ca.key
├── front-proxy-client.crt
├── front-proxy-client.key
├── sa.key
└── sa.pub
3, 生成其余组件拜访 kube-apiserver 所须要的配置文件
这些文件的门路是:/etc/kubernetes/xxx.conf
ls /etc/kubernetes/*.conf
/etc/kubernetes/admin.conf /etc/kubernetes/controller-manager.conf /etc/kubernetes/kubelet.conf /etc/kubernetes/scheduler.conf
这些文件外面记录的是,以后这个 Master 节点的服务器地址、监听端口。证书目录等信息。这样,对应的客户端(比方 scheduler,kubelet 等),能够间接加载相应的文件,应用外面的信息与 kube-apiserver 建设平安连贯。
4, 为 Master 组件生成 Pod 配置文件
在 Kubernetes 中,有一种非凡的容器启动办法叫做“Static Pod”。它容许你把要部署的 Pod 的 YAML 文件放在一个指定的目录里。这样,当这台机器上的 kubelet 启动时,它会主动查看这个目录,加载所有的 Pod YAML 文件,而后在这台机器上启动它们。
从这一点也能够看出,kubelet 在 Kubernetes 我的项目中的位置十分高,在设计上它就是一个齐全独立的组件,而其余 Master 组件,则更像是辅助性的零碎容器。
cd /etc/kubernetes/manifests
├── etcd.yaml
├── kube-apiserver.yaml
├── kube-controller-manager.yaml
└── kube-scheduler.yaml
而后 kubeadm 会调用 kubelet 运行这个 yml 文件,等到 Master 容器启动后,kubeadm 会通过查看localhost:6443/healthz
这个 Master 组件的健康检查 url,期待 Master 组件齐全运行起来。
而后,kubeadm 就会为集群生成一个 bootstrap token。在前面,只有持有这个 token,任何一个装置了 kubelet 和 kubadm 的节点,都能够通过 kubeadm join 退出到这个集群当中。
这个 token 的值和应用办法,会在 kubeadm init 完结后被打印进去。
在 token 生成之后,kubeadm 会将 ca.crt 等 Master 节点的重要信息,通过 ConfigMap 的形式保留在 Etcd 当中,供后续部署 Node 节点应用。这个 ConfigMap 的名字是 cluster-info。
kubeadm init 的最初一步,就是装置默认插件。Kubernetes 默认 kube-proxy 和 DNS 这两个插件是必须装置的。它们别离用来提供整个集群的服务发现和 DNS 性能。其实,这两个插件也只是两个容器镜像而已,所以 kubeadm 只有用 Kubernetes 客户端创立两个 Pod 就能够了。
kubeadm join 的工作流程
这个流程其实非常简单,kubeadm init 生成 bootstrap token 之后,你就能够在任意一台装置了 kubelet 和 kubeadm 的机器上执行 kubeadm join 了。
可是,为什么执行 kubeadm join 须要这样一个 token 呢?
因为,任何一台机器想要成为 Kubernetes 集群中的一个节点,就必须在集群的 kube-apiserver 上注册。可是,要想跟 apiserver 打交道,这台机器就必须要获取到相应的证书文件(CA 文件)。可是,为了可能一键装置,咱们就不能让用户去 Master 节点上手动拷贝这些文件。
所以,kubeadm 至多须要发动一次“不平安模式”的拜访到 kube-apiserver,从而拿到保留在 ConfigMap 中的 cluster-info(它保留了 APIServer 的受权信息)。而 bootstrap token,表演的就是这个过程中的平安验证的角色。
只有有了 cluster-info 里的 kube-apiserver 的地址、端口、证书,kubelet 就能够以“平安模式”连贯到 apiserver 上,这样一个新的节点就部署实现了。
接下来,你只有在其余节点上反复这个指令就能够了。
具体装置能够查看文章:
https://zhangguanzhang.github…