深入剖析Kubernetes系列连载(九)kubeadm init 和 kubeadm join

skywalkerwty 发表于 2021/03/20 13:50:26 2021/03/20
【摘要】 Kubernetes的学习往往让人摸不着头脑,很难理解其中的原理。深入剖析Kubernetes系列连载是学习《深入剖析Kubernetes》课程的笔记和总结,记录学习的过程,并且传递知识。而如果现在 kubelet 本身就运行在一个容器里,那么直接操作宿主机就会变得很麻烦,kubeadm选择了一种妥协方案:把 kubelet 直接运行在宿主机上,然后使用容器部署其他的 Kubernetes ...


Kubernetes的学习往往让人摸不着头脑,很难理解其中的原理。

深入剖析Kubernetes系列连载是学习《深入剖析Kubernetes》课程的笔记和总结,记录学习的过程,并且传递知识。

而如果现在 kubelet 本身就运行在一个容器里,那么直接操作宿主机就会变得很麻烦,kubeadm选择了一种妥协方案:把 kubelet 直接运行在宿主机上,然后使用容器部署其他的 Kubernetes 组件。

kubeadm init 的工作流程
当你执行 kubeadm init 指令后,kubeadm 首先要做的,是一系列的检查工作,以确定这台机器可以用来部署 Kubernetes。

“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 是否已经安装?

……

生成对外提供服务所需的各种证书和对应的目录

kubeadm 为 Kubernetes 项目生成的证书文件都放在 Master 节点的/etc/kubernetes/pki 目录下。在这个目录下,最主要的证书文件是 ca.crt 和对应的私钥ca.key。

此外,用户使用 kubectl 获取容器日志等 streaming 操作时,需要通过 kube-apiserver向 kubelet 发起请求,这个连接也必须是安全的。kubeadm 为这一步生成的是apiserver-kubelet-client.crt 文件,对应的私钥是 apiserver-kubelet-client.key。

生成访问 kube-apiserver 所需的配置文件

ls /etc/kubernetes/
admin.conf controller-manager.conf kubelet.conf scheduler.conf

这些文件里面记录的是,当前这个 Master 节点的服务器地址、监听端口、证书目录等信息。这样,对应的客户端(比如 scheduler,kubelet 等),可以直接加载相应的文件,使用里面的信息与 kube-apiserver 建立安全连接。

生成 Pod 配置文件

Kubernetes 有三个 Master 组件 kube-apiserver、kube-controller-manager、kube-scheduler,而它们都会被使用 Pod 的方式部署起来。

在 Kubernetes 中,有一种特殊的容器启动方法叫做“Static Pod”。它允许你把要部署的Pod 的 YAML 文件放在一个指定的目录里。这样,当这台机器上的 kubelet 启动时,它会自动检查这个目录,加载所有的 Pod YAML 文件,然后在这台机器上启动它们。

在 kubeadm 中,Master 组件的 YAML 文件会被生成在 /etc/kubernetes/manifests 路径下。比如,kube-apiserver.yaml:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    scheduler.alpha.kubernetes.io/critical-pod: ""
  creationTimestamp: null
  labels:
    component: kube-apiserver
    tier: control-plane
  name: kube-apiserver
  namespace: kube-system
spec:
  containers:
  - command:
    - kube-apiserver
    - --authorization-mode=Node,RBAC
    - --runtime-config=api/all=true
    - --advertise-address=10.168.0.2
    ...
    - --tls-cert-file=/etc/kubernetes/pki/apiserver.crt
    - --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
    image: k8s.gcr.io/kube-apiserver-amd64:v1.11.1
    imagePullPolicy: IfNotPresent
    livenessProbe:
      ...
    name: kube-apiserver
    resources:
      requests:
        cpu: 250m
    volumeMounts:
    - mountPath: /usr/share/ca-certificates
      name: usr-share-ca-certificates
      readOnly: true
    ...
  hostNetwork: true
  priorityClassName: system-cluster-critical
  volumes:
  - hostPath:
      path: /etc/ca-certificates
      type: DirectoryOrCreate
    name: etc-ca-certificates
  ...

这个 Pod 里只定义了一个容器,它使用的镜像是:k8s.gcr.io/kube-apiserveramd64:v1.11.1 。这个镜像是 Kubernetes 官方维护的一个组件镜像。

这个容器的启动命令(commands)是 kube-apiserver --authorizationmode=Node,RBAC …,这样一句非常长的命令。其实,它就是容器里 kube-apiserver这个二进制文件再加上指定的配置参数而已。

如果你要修改一个已有集群的 kube-apiserver 的配置,需要修改这个 YAML 文件。这些组件的参数也可以在部署时指定。

kubeadm 还会再生成一个 Etcd 的 Pod YAML 文件,用来通过同样的Static Pod 的方式启动 Etcd。所以,最后 Master 组件的 Pod YAML 文件如下所示:

$ ls /etc/kubernetes/manifests/
etcd.yaml kube-apiserver.yaml kube-controller-manager.yaml kube-scheduler.yaml

一旦这些 YAML 文件出现在被 kubelet 监视的 /etc/kubernetes/manifests 目录下,kubelet 就会自动创建这些 YAML 文件中定义的 Pod,即 Master 组件的容器

Master 容器启动后,kubeadm 会通过检查 localhost:6443/healthz 这个 Master 组件的健康检查 URL,等待 Master 组件完全运行起来生成bootstrap token

只要持有这个token,任何一个安装了 kubelet 和 kubadm 的节点,都可以通过 kubeadm join 加入到这个集群当中。

ConfigMap

在 token 生成之后,kubeadm 会将 ca.crt 等 Master 节点的重要信息,通过ConfigMap 的方式保存在 Etcd 当中,供后续部署 Node 节点使用。这个 ConfigMap 的名字是 cluster-info

安装默认插件

Kubernetes 默认 kube-proxy 和 DNS这两个插件是必须安装的。它们分别用来提供整个集群的服务发现和 DNS 功能。其实,这两个插件也只是两个容器镜像而已,所以 kubeadm 只要用 Kubernetes 客户端创建两个Pod 就可以了

配置 kubeadm 的部署参数

$ kubeadm init --config kubeadm.yaml

apiVersion: kubeadm.k8s.io/v1alpha2
kind: MasterConfiguration
kubernetesVersion: v1.11.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
  ...
...
apiServerExtraArgs:
  advertise-address: 192.168.0.103
  anonymous-auth: false
  enable-admission-plugins: AlwaysPullImages,DefaultStorageClass
  audit-log-path: /home/johndoe/audit.log

kubeadm 就会使用上面这些信息替换 /etc/kubernetes/manifests/kubeapiserver.yaml 里的 command 字段里的参数了

而这个 YAML 文件提供的可配置项远不止这些。比如,你还可以修改 kubelet 和 kubeproxy 的配置,修改 Kubernetes 使用的基础镜像的 URL(默认的k8s.gcr.io/xxx镜像URL 在国内访问是有困难的),指定自己的证书文件,指定特殊的容器运行时等等。

为什么执行 kubeadm join 需要这样一个 token 呢?

因为,任何一台机器想要成为 Kubernetes 集群中的一个节点,就必须在集群的 kubeapiserver 上注册。可是,要想跟 apiserver 打交道,这台机器就必须要获取到相应的证书文件(CA 文件)。可是,为了能够一键安装,我们就不能让用户去 Master 节点上手动拷贝这些文件。

所以,kubeadm 至少需要发起一次“不安全模式”的访问到 kube-apiserver,从而拿到保存在 ConfigMap 中的cluster-info(它保存了 APIServer 的授权信息)。而 bootstrap token,扮演的就是这个过程中的安全验证的角色。

只要有了 cluster-info 里的 kube-apiserver 的地址、端口、证书,kubelet 就可以以“安全模式”连接到 apiserver 上,这样一个新的节点就部署完成了

 

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区),文章链接,文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:cloudbbs@huaweicloud.com进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。