一、kubeadm概述

kubeadm是社区维护的Kubernetes集群一键部署利器,使用两条命令即可完成k8s集群中master节点以及node节点的部署,其底层原理是利用了k8s TLS bootstrap特性。

二、kubeadm部署k8s集群示例

1、k8s master节点部署

$ kubeadm init

此外,我们也可以自己编写yaml文件来自定义kubeadm的启动过程和一些组件的启动参数等等

$ kubeadm init --config xxx.yaml

        2、​ k8s node节点部署(将一个node节点加入到已有集群当中)

$ kubeadm join <kube-apiserver的ip + 端口> --token <token>

此外,我们也可以自己编写yaml文件来自定义kubeadm的启动过程和一些组件的启动参数,包括kube-apiserver的ip与端口、token等

$ kubeadm join --config xxx.yaml

关于自定义yaml文件以及更多的kubeadm用法请参考:https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/

三、​k8s TLS bootstrap概述

当k8s集群开启了TLS认证后,每个节点的kubelet组件都要使用由kube-apiserver的CA签发的有效证书才能与kube-apiserver通信;当节点非常多的时候,为每个节点都单独签署证书是一件非常繁琐而又耗时的事情。

此时k8s TLS bootstrap功能应运而生。

k8s TLS bootstrap功能就是让kubelet先使用一个预先商定好的低权限token连接到kube-apiserver,向kube-apiserver申请证书,然后kube-controller-manager给kubelet动态签署证书,后续kubelet都将通过动态签署的证书与kube-apiserver通信。

关于k8s TLS bootstrap的详细分析这里暂时不展开。

四、kubeadm原理解析

在k8s master中,会先启动一个kubelet,控制面组件通过kubelet static pod特性启动,在k8s master控制面组件启动成功后,其他节点需要加入到k8s集群时,使用TLS bootstrap来简化加入的过程,先通过bootstrap-token与kube-apiserver通信,自动从kube-controller-manager处签发拿到与kube-apiserver通信的证书,然后自动生成与kube-apiserver通信的kubeconfig文件,后续将使用kubeconfig文件与kube-apiserver进行通信。

五、kubeadm init 详细流程解析

kubeadm init的结果是完成一个k8s master节点的部署,包括kube-apiserver、kube-controller-manager、kube-scheduler、etcd等控制面组件以及kubelet数据面组件,即该master节点既是控制面又是数据面,所以master节点上也是可以运行pod的;

以下为kubeadm init的处理流程代码(基于k8s v1.17.4版本),一共13步:

// cmd/kubeadm/app/cmd/init.go-NewCmdInit()...// initialize the workflow runner with the list of phasesinitRunner.AppendPhase(phases.NewPreflightPhase()) // 1.环境检查initRunner.AppendPhase(phases.NewKubeletStartPhase()) // 2.配置并启动kubeletinitRunner.AppendPhase(phases.NewCertsPhase()) // 3.证书生成initRunner.AppendPhase(phases.NewKubeConfigPhase()) // 4.kubeconfig文件生成initRunner.AppendPhase(phases.NewControlPlanePhase()) // 5.控制面组件yaml生成initRunner.AppendPhase(phases.NewEtcdPhase()) // 6.etcd组件yaml生成initRunner.AppendPhase(phases.NewWaitControlPlanePhase()) // 7.等待控制面组件运行initRunner.AppendPhase(phases.NewUploadConfigPhase()) // 8.上传配置initRunner.AppendPhase(phases.NewUploadCertsPhase()) // 9.上传CA证书/私钥initRunner.AppendPhase(phases.NewMarkControlPlanePhase()) // 10.master节点打污点initRunner.AppendPhase(phases.NewBootstrapTokenPhase()) // 11.生成bootstrap token和ca证书configmapinitRunner.AppendPhase(phases.NewKubeletFinalizePhase()) // 12.更换kubelet证书initRunner.AppendPhase(phases.NewAddonPhase()) // 13.安装Addon...

    1、环境检查

检查项包括操作系统内核版本、k8s组件暴露服务的指定端口是否被占用、docker是否安装、iptables命令是否安装等等,其实这一步还包括了拉取kubeadm部署所需的镜像;

  2、配置并启动kubelet

创建kubelet启动所需的配置文件,并启动kubelet,kubeadm使用了systemd的方式部署启动kubelet;

# systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node AgentLoaded: loaded (/usr/lib/systemd/system/kubelet.service; disabled; vendor preset: enabled)Drop-In: /usr/lib/systemd/system/kubelet.service.d└─10-kubeadm.confActive: active (running) ...

为什么master上还需要配置启动kubelet呢?

因为kubeadm init的时候需要将master控制面组件kube-apiserver、kube-controller-manager、kube-scheduler、etcd以pod的方式运行起来,而现在又没有在运行的控制面以及kubelet,怎么办呢,kubeadm的做法是,给master节点上也安装启动kubelet,然后使用kubelet static pod特性将master控制面组件运行起来。

关于static pod,详细内容可参考:https://kubernetes.io/zh/docs/tasks/configure-pod-container/static-pod/

        3、证书生成

        即生成kubernetes对外提供服务所需的各种证书,放到/etc/kubernetes/pki目录下:

# ls /etc/kubernetes/pki
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  front-proxy-ca.crt  front-proxy-ca.key  front-proxy-client.crt  front-proxy-client.key  sa.key  sa.pub

        4、kubeconfig配置文件生成

        即生成master节点上kube-controller-manager、kube-scheduler、kubelet组件等访问kube-apiserver的kubeconfig文件,放到/etc/kubernetes目录下,文件包含了apiserver的地址、监听端口、证书等信息,使用该kubeconfig文件即可直接与kube-apiserver通信;

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

master上的kubelet启动后,使用kubeadm生成的kubeconfig与kube-apiserver进行通信,通过证书轮换,向kube-apiserver申请新的证书,由kube-controller-manager签发证书返回。

        注意:这里master上的kubelet不会使用TLS bootstrap特性。

 5、控制面组件yaml文件生成

即kubeadm为4个控制面组件kube-apiserver、kube-controller-manager、kube-scheduler生成pod yaml文件,放到/etc/kubernetes/manifests目录下,然后kubelet会根据static pod特性,使用pod的方式将它们部署起来;

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

        6、Etcd组件yaml文件生成

即kubeadm为etcd组件生成pod yaml文件,放到/etc/kubernetes/manifests目录下,然后kubelet会根据static pod特性,使用pod的方式将etcd部署起来;

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

        7、等待控制面组件运行

        kubeadm会不间断检查localhost:6443/healthz这个url,等待master组件完全启动;

    8、上传配置

这里会创建2个configmap有,都创建在kube-system命名空间下,名称分别是kubeadm-config、kubelet-config-xxx(k8s版本),分别存储着kubeadm的集群配置信息、kubelet的配置信息;

    9、上传CA证书/私钥

该步骤默认不执行,通过增加——upload-certs参数启用,它会将相关的CA证书/私钥加密后作为data,在kube-system命名空间下创建名称为kubeadm-certs的secret,给后续的master节点kubeadm join使用,这样join时可以直接从secret中解密出CA证书/私钥,然后签发其他证书,而无需手工复制相关CA证书/私钥;

kubeadm init执行完成后,会输出一个名称为certificateKey的值,然后在其他master节点join时,加上--certificate-key参数即可。

certificateKey是在添加新的master节点时用来解密kubeadm-certssecret中的证书的秘钥。

kubeadm-certs示例如下,其中的证书和私钥均已加密,通过certificateKey解密即可使用:

apiVersion: v1
data:ca.crt: KfdZpEDF1wJfaexXls5...ca.key: VXfm7luIyM3QT+Rd04+...etcd-ca.crt: wwSzqCcltkrP26...etcd-ca.key: gqusZazZLF33Ip...front-proxy-ca.crt: EmfgKP6...front-proxy-ca.key: wKMYSrk...sa.key: pscxeFTGoCFZ6hrE1XK...sa.pub: keey1WPkWdj2TjEb/oM...
kind: Secret
metadata:name: kubeadm-certsnamespace: kube-systemownerReferences:- apiVersion: v1blockOwnerDeletion: truecontroller: truekind: Secretname: bootstrap-token-xxxxxx......
type: Opaque

  注意:secret kubeadm-certs和解密密钥certificateKey会在两个小时后失效。

        10、master节点打污点

将该master节点打上污点,不作为计算节点数据面使用;

        11、生成bootstrap token和ca证书configmap

kubeadm会为该k8s集群生成一个bootstrap token并打印出来,后续的node节点通过这个token,通过kubeadm join命令,使用TLS bootstrap特性即可加入到这个k8s集群中,当然,这里还包括了为该token创建RBAC的各个对象,赋予该token创建CSR证书签名请求的权限、自动批复CSR请求的权限、轮换证书请求自动批复的权限等,这里不展开介绍,后续分析k8s TLS bootstrap原理时再做分析;

kubeadm init执行完成后,也可以通过以下命令获取token:

# kubeadm token list

kubeadm还会将ca.crt、apiserver url等信息,保存到一个configmap当中,给后续加入该k8s集群的node节点使用,configmap名称为cluster-info,位于kube-public命名空间下;

# kubectl get configmap -n kube-public -o yaml cluster-info
apiVersion: v1
data:kubeconfig: |apiVersion: v1clusters:- cluster:certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0F...server: https://192.168.1.10:6443name: ""contexts: nullcurrent-context: ""kind: Configpreferences: {}users: null
kind: ConfigMap
metadata:

        12、更换kubelet证书

前面说过,master上的kubelet启动后,使用kubeadm生成的kubeconfig与kube-apiserver进行通信,通过证书轮换,向kube-apiserver申请新的证书,由kube-controller-manager签发证书返回。而这里说的更换kubelet证书,其实就是将kubelet与kube-apiserver通信的kubeconfig文件中的证书替换成由kube-controller-manager签发返回的证书,即将kubeconfig文件中的client-certificate与client-key的值都替换成/var/lib/kubelet/pki/kubelet-client-current.pem;

apiVersion: v1
clusters:
- cluster:certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0F...server: https://192.168.1.10:6443name: test-cluster
contexts:
- context:cluster: test-clusteruser: system:node:test-cluster-master-1name: system:node:test-cluster-master-1
current-context: system:node:test-cluster-master-1
kind: Config
preferences: {}
users:
- name: system:node:test-cluster-master-1user:client-certificate: /var/lib/kubelet/pki/kubelet-client-current.pemclient-key: /var/lib/kubelet/pki/kubelet-client-current.pem

        13、安装Addon

安装coredns与kube-proxy,kubeadm init流程结束。

六、kubeadm join 详细流程解析

kubeadm join的结果是完成一个k8s master节点或node节点加入一个已有的k8s集群。

以下为kubeadm join的处理流程代码(基于k8s v1.17.4版本),一共5步:

// cmd/kubeadm/app/cmd/join.go-NewCmdInit()...joinRunner.AppendPhase(phases.NewPreflightPhase()) // 1.环境检查joinRunner.AppendPhase(phases.NewControlPlanePreparePhase()) // 2.控制面准备joinRunner.AppendPhase(phases.NewCheckEtcdPhase()) // 3.检查etcd是否健康joinRunner.AppendPhase(phases.NewKubeletStartPhase()) // 4.启动kubeletjoinRunner.AppendPhase(phases.NewControlPlaneJoinPhase()) // 5.控制面操作...

        1、环境检查

检查项包括操作系统内核版本、k8s组件暴露服务的指定端口是否被占用、docker是否安装、iptables命令是否安装等等,但这里的环境检查与kubeadm init时的检查有点不同,这里会区分是join的master节点还是node节点,如果是node节点,则仅仅进行node相关的检查;

另外,这里还会获取kube-public命名空间下的configmap对象cluster-info,从中CA、master api等信息;

        2、控制面准备

如果是node的join,这一步的逻辑不会执行。这里会从kube-system命名空间中加载名称为kubeadm-certs的secret对象,然后生成控制面组件kube-apiserver、kube-controller-manager、kube-scheduler所需的证书,最后生成它们的部署yaml,放置到kubelet的static pod目录下,被kubelet使用static pod特性启动;

        3、检查etcd是否健康

        4、启动kubelet

根据CA、bootstrap token等信息生成/etc/kubernetes/bootstrap-kubelet.conf文件,通过TLS bootstrap机制,kubelet使用bootstrap token来向kube-apiserver申请证书,由kube-controller-manager签发证书返回,然后kubelet根据返回的证书生成kubeconfig文件并写入到/etc/kubernetes/kubelet.conf文件,后续kubelet将会使用该kubeconfig文件来与kube-apiserver通信;

# cat /etc/kubernetes/kubelet.conf
apiVersion: v1
clusters:
- cluster:certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0F...server: https://192.168.1.10:6443name: default-cluster
contexts:
- context:cluster: default-clusternamespace: defaultuser: default-authname: default-context
current-context: default-context
kind: Config
preferences: {}
users:
- name: default-authuser:client-certificate: /var/lib/kubelet/pki/kubelet-client-current.pemclient-key: /var/lib/kubelet/pki/kubelet-client-current.pem

        注意:bootstrap-kubelet.conf文件会在kubelet.conf文件生成后,被kubeadm删除掉;

        5、控制面操作

        如果是node的join,这一步的逻辑不会执行。控制面操作包括生成etcd的static pod yaml、更新kube-system命名空间下的configmap对象kubeadm-config,将该控制节点信息更新进去、将该master节点打上污点,不作为计算节点数据面使用;至此,kubeadm join流程结束。

到此 Kubernetes kubeadm init 与 join 原理分析介绍完成。

Kubernetes Kubeadm init 与 join 原理分析相关推荐

  1. kubeadm工作原理-kubeadm init原理分析-kubeadm join原理分析

    kubeadm概述 kubeadm是社区维护的Kubernetes集群一键部署利器,使用两条命令即可完成k8s集群中master节点以及node节点的部署,其底层原理是利用了k8s TLS boots ...

  2. 第148天学习打卡(Kubernetes kubeadm init 成功部署 部署网络插件 部署容器化应用)

    继续安装 c3j9i2htclj6thlta6Z ~]# clear [root@iZ2vc3j9i2htclj6thlta6Z ~]# systemctl stop firewalld [root@ ...

  3. ThreadLocal应用与原理分析

    ThreadLocal的作用 ThreadLocal类用来提供线程内部的局部变量,并且这些变量依靠线程独立存在.可以在多个线程中互不干扰的进行存储数据和修改数据,通过set,get 和remove方法 ...

  4. 为什么Kubernetes从节点会join失败

    有段时间没有鼓捣Kubernetes了,今天重置Kubernetes集群后,slave节点不能加入master节点了,我把问题和解决方案分享给大家. 我本地的Kubernetes集群包括一个主节点和一 ...

  5. 编译原理语义分析代码_Pix2Pix原理分析与代码解读

    原理分析: 图像.视觉中很多问题都涉及到将一副图像转换为另一幅图像(Image-to-Image Translation Problem),这些问题通常都使用特定的方法来解决,不存在一个通用的方法.但 ...

  6. Kubernetes kubeadm部署

    Kubernetes kubeadm部署 一.Docker的安装与设置 1. 安装Docker 安装yum-utils,并更新docker稳定版的源 sudo yum install -y yum-u ...

  7. kubeadm init 问题和解决问题记录

    安装 kubeadm: 使用阿里云来安装kube** cat /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl ...

  8. 一次 SQL 查询优化原理分析(900W+ 数据,从 17s 到 300ms)

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:Muscleape jianshu.com/p/0768eb ...

  9. Android JNI原理分析

    引言:分析Android源码6.0的过程,一定离不开Java与C/C++代码直接的来回跳转,那么就很有必要掌握JNI,这是链接Java层和Native层的桥梁,本文涉及相关源码: frameworks ...

最新文章

  1. Google Glog使用
  2. Iaas、Caas、Paas、Faas!选择正确的平台!
  3. Redis和消息队列使用实战
  4. CSS技巧和经验列表
  5. MySQL和Oracle中的隐式转换
  6. 05-JDBC学习手册:JDBC2.0 新特性之批量处理数据
  7. mysql8.0其他机器访问_论文导读|基于机器学习的高速缓存预取
  8. 伪静态隐藏域名后缀_你想知道的动态URL、静态URl、伪静态URL概念及区别都在这里!...
  9. openstack nova 手动修改虚拟机状态
  10. 标准单元测试步骤:A -B-C-D-E-F
  11. 计算机科学系绩效分配方案,山西大学计算机与信息技术学院岗位绩效实施方案.docx...
  12. 弹窗php整人,bat整人代码,超级弹窗代码
  13. [原创]gsoap的基本使用方法『C++web服务工具包』
  14. linux模糊删除文件
  15. onChange和onClick的区别
  16. 将字符串转化为变量名的几种方法
  17. ddos攻击的简单应急处理办法
  18. 工银融e联服务器安全证书失败,注册工行工银融e联客户端时遇到您已经注册我......
  19. ESD静电放电最常用的三种模型及其防护设计
  20. 关于mysql如何精准的查询法文字母

热门文章

  1. 认识Python继承:super()
  2. 音视频开发(四)——编码音频
  3. (论文笔记)An Attention Enhanced Graph Convolutional LSTM Network for Skeleton-Based Action Recognition
  4. VOC格式xml标签与YOLO格式txt标签相互转换
  5. 远程桌面访问之VNC使用指南
  6. HEG运行错误:GetBeginAndEndLocs
  7. justjavac:从辍学到成为Deno核心代码贡献者,我的十年编程生涯
  8. html工作周报,可查看(周报).html
  9. go sync.Cond 源码解析
  10. 声纹技术(三):声纹识别技术