Kubernetes(一)认识 kubernetes
Kubernets(二)部署非高可用Kubernetes集群的环境准备
Kubernets(三)部署非高可用Kubernetes集群-通过阿里云源安装 kubeadm、kubelet 和 kubectl
Kubernets(四)创建集群
Kubernetes(五)揭开 kubeadm 的神秘面纱
Kubernetes(六)第一个kubernetes 对象
其实,Kubernetes 作为一个 Golang 项目,已经免去了很多类似于 Python 项目要安装语言级别依赖的麻烦。但是,除了将各个组件编译成二进制文件外,用户还要负责为这些二进制文件编写对应的配置文件、配置自启动脚本,以及为 kube-apiserver 配置授权文件等等诸多运维工作。
在 Kubernetes 项目发布初期,它的部署完全要依靠一堆由社区维护的脚本。
后来,各大云厂商一般使用 SaltStack、Ansible 等运维工具自动化地执行这些步骤。
2017 年,在志愿者的推动下,社区才终于发起了一个独立的部署工具,名叫:kubeadm。
这个项目的目的,就是要让用户能够通过这样两条指令完成一个 Kubernetes 集群的部署:
# 创建一个Master节点
$ kubeadm init
# 将一个Node节点加入到当前集群中
$ kubeadm join <Master节点的IP和端口>
之前我们说过 Kubernetes 的架构和它的组件。在部署时,它的每一个组件都是一个需要被执行的、单独的二进制文件。
所以不难想象,SaltStack 这样的运维工具或者由社区维护的脚本的功能,就是要把这些二进制文件传输到指定的机器当中,然后编写控制脚本来启停这些组件。
不过,现在你知道了容器这个技术,是不是有这样的想法:
这些 kubernetes 的组件为能不能用容器部?
这样,我只要给每个 Kubernetes 组件做一个容器镜像,然后在每台宿主机上用 docker run 指令启动这些组件容器,部署不就完成了吗?
这样做会带来一个很麻烦的问题,即:如何容器化 kubelet?
kubelet 是 Kubernetes 项目用来操作 Docker 等容器运行时的核心组件。可是,除了跟容器运行时打交道外,kubelet 在配置容器网络、管理容器数据卷时,都需要直接操作宿主机。
网络的问题还好解决,不过数据卷怎么办?
要让 kubelet 隔着容器的 Mount Namespace 和文件系统,操作宿主机的文件系统,就有点儿困难了。
比如,如果用户想要使用 NFS 做容器的持久化数据卷,那么 kubelet 就需要在容器进行绑定挂载前,在宿主机的指定目录上,先挂载 NFS 的远程目录。
由于现在 kubelet 是运行在容器里的,这就意味着它要做的这个“mount -F nfs”命令,被隔离在了一个单独的 Mount Namespace 中。即,kubelet 做的挂载操作,不能被“传播”到宿主机上。
把 kubelet 直接运行在宿主机上,然后使用容器部署其他的 Kubernetes 组件。
所以,你使用 kubeadm 的第一步,是在机器上手动安装 kubeadm、kubelet 和 kubectl 这三个二进制文件。当然,kubeadm 的作者已经为各个发行版的 Linux 准备好了安装包,所以你只需要执行:
yum install kubeadm kubelet kubectl
接下来,你就可以使用“kubeadm init”部署 Master 节点了。
Kubernetes 对外提供服务时,除非专门开启“不安全模式”,否则都要通过 HTTPS 才能访问 kube-apiserver。
这就需要为 Kubernetes 集群配置好证书文件。
kubeadm 为 Kubernetes 项目生成的证书文件都放在 Master 节点的 /etc/kubernetes/pki
目录下。
在这个目录下,最主要的证书文件是 ca.crt
和对应的私钥 ca.key
。
用户使用 kubectl 获取容器日志等 streaming 操作时,需要通过 kube-apiserver 向 kubelet 发起请求,这个连接也必须是安全的。
kubeadm 为这一步生成的是:
apiserver-kubelet-client.crt
证书apiserver-kubelet-client.key
私钥可以选择不让 kubeadm 为你生成这些证书,而是在初始化集群之前,拷贝现有的证书到如下证书的目录里:
/etc/kubernetes/pki/
最终它们的样子应该像下面一样:
/etc/kubernetes/pki/ca.crt
/etc/kubernetes/pki/ca.key
这时,kubeadm 就会跳过证书生成的步骤,把它完全交给用户处理。
证书生成后,kubeadm 接下来会为其他组件生成访问 kube-apiserver 所需的配置文件。这些文件的路径是:
/etc/kubernetes/xxx.conf
:
[root@k8s-master ~]# 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 建立安全连接。
之前说过 Kubernetes 有三个 Master 组件:
而它们都会被使用 Pod 的方式部署起来。
当然,目前 Kubernetes 集群尚不存在,kubeadm 不会直接执行 docker run 来启动这些容器。
在 Kubernetes 中,有一种特殊的容器启动方法叫做 “Static Pod”。
它允许你把要部署的 Pod 的 YAML 文件放在一个指定的目录里。
这样,当这台机器上的 kubelet 启动时,它会自动检查这个目录,加载所有的 Pod YAML 文件,然后在这台机器上启动它们。
在 Master 节点的服务器上,存放 Master 组件的 YAML 文件目录是:
/etc/kubernetes/manifests/
etcd.yaml 是最后生成的
关于一个 Pod 的 YAML 文件怎么写、里面的字段如何解读。后面后有专门的章节讲解。这里我们只需要注意以下几点信息即可。
在这一步完成后,kubeadm 还会再生成一个 Etcd 的 Pod YAML 文件,用来通过同样的 Static Pod 的方式启动 Etcd。
目录 /etc/kubernetes/manifests
是被kubelet 监视的,kubelet 会自动创建这些 YAML 文件中定义的 Pod。
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 的最后一步,就是安装默认插件。
kube-proxy 和 dns 这两个插件是必须安装的。它们分别用来提供整个集群的服务发现和 DNS 功能。其实,这两个插件也只是两个容器镜像而已,所以 kubeadm 只要用 Kubernetes 客户端创建两个 Pod 就可以了。