- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
kubeadm工作原理-kubeadm init原理分析-kubeadm join原理分析。kubeadm是社区维护的Kubernetes集群一键部署利器,使用两条命令即可完成k8s集群中master节点以及node节点的部署,其底层原理是利用了k8s TLS bootstrap特性。
kubeadm是社区维护的Kubernetes集群一键部署利器,使用两条命令即可完成k8s集群中master节点以及node节点的部署,其底层原理是利用了k8s TLS bootstrap特性。
(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认证后,每个节点的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的详细分析这里暂时不展开。
在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的结果是完成一个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 phases
initRunner.AppendPhase(phases.NewPreflightPhase()) // 1.环境检查
initRunner.AppendPhase(phases.NewKubeletStartPhase()) // 2.配置并启动kubelet
initRunner.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证书configmap
initRunner.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 Agent
Loaded: loaded (/usr/lib/systemd/system/kubelet.service; disabled; vendor preset: enabled)
Drop-In: /usr/lib/systemd/system/kubelet.service.d
└─10-kubeadm.conf
Active: 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-certs
secret中的证书的秘钥。
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-certs
namespace: kube-system
ownerReferences:
- apiVersion: v1
blockOwnerDeletion: true
controller: true
kind: Secret
name: 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: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0F...
server: https://192.168.1.10:6443
name: ""
contexts: null
current-context: ""
kind: Config
preferences: {}
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:6443
name: test-cluster
contexts:
- context:
cluster: test-cluster
user: system:node:test-cluster-master-1
name: system:node:test-cluster-master-1
current-context: system:node:test-cluster-master-1
kind: Config
preferences: {}
users:
- name: system:node:test-cluster-master-1
user:
client-certificate: /var/lib/kubelet/pki/kubelet-client-current.pem
client-key: /var/lib/kubelet/pki/kubelet-client-current.pem
(13)安装Addon。安装coredns与kube-proxy,kubeadm init流程结束。
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.启动kubelet
joinRunner.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:6443
name: default-cluster
contexts:
- context:
cluster: default-cluster
namespace: default
user: default-auth
name: default-context
current-context: default-context
kind: Config
preferences: {}
users:
- name: default-auth
user:
client-certificate: /var/lib/kubelet/pki/kubelet-client-current.pem
client-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流程结束。
我刚刚继承了一个旧的 PostgreSQL 安装,需要进行一些诊断以找出该数据库运行缓慢的原因。在 MS SQL 上,您可以使用 Profiler 等工具来查看正在运行的查询,然后查看它们的执行计划。
将目标从Analytics(分析)导入到AdWords中,然后在Analytics(分析)中更改目标条件时,是否可以通过更改将目标“重新导入”到AdWords,还是可以自动选择? 最佳答案 更改目标值
我正在使用google analytics api来获取数据。我正在获取数据,但我想验证两个参数,它们在特定日期范围内始终为0。我正在获取['ga:transactions']和['ga:goalCo
我使用Google API从Google Analytics(分析)获取数据,但指标与Google Analytics(分析)的网络界面不同。 即:我在2015年3月1日获得数据-它返回综合浏览量79
我在我的Web应用程序中使用sammy.js进行剔除。我正在尝试向其中添加Google Analytics(分析)。我很快找到了following plugin来实现页面跟踪。 我按照步骤操作,页面如
当使用 Xcode 分析 (product>analyze) 时,有没有办法忽略给定文件中的任何错误? 例如编译指示之类的? 我们只想忽略第三方代码的任何警告,这样当我们的代码出现问题时,它对我们
目录 EFK 1. 日志系统 2. 部署ElasticSearch 2.1 创建handless服务 2.2 创建s
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
GCC/G++ 是否有可用于输出分析的选项? 能够比较以前的代码与新代码之间的差异(大小、类/结构的大小)将很有用。然后可以将它们与之前的输出进行比较以进行比较,这对于许多目的都是有用的。 如果没有此
我正在浏览 LYAH,并一直在研究处理列表时列表理解与映射/过滤器的使用。我已经分析了以下两个函数,并包含了教授的输出。如果我正确地阅读了教授的内容,我会说 FiltB 的运行速度比 FiltA 慢很
在 MySQL 中可以使用 SET profiling = 1; 设置分析 查询 SHOW PROFILES; 显示每个查询所用的时间。我想知道这个时间是只包括服务器的执行时间还是还包括将结果发送到前
我用 Python 编写了几个用于生成阶乘的模块,我想测试运行时间。我找到了一个分析示例 here我使用该模板来分析我的模块: import profile #fact def main():
前几天读了下mysqld_safe脚本,个人感觉还是收获蛮大的,其中细致的交代了MySQL数据库的启动流程,包括查找MySQL相关目录,解析配置文件以及最后如何调用mysqld程序来启动实例等,有着
上一篇:《人工智能大语言模型起源篇,低秩微调(LoRA)》 (14)Rae 和同事(包括78位合著者!)于2022年发表的《Scaling Language Models: Methods, A
1 内网基础 内网/局域网(Local Area Network,LAN),是指在某一区域内有多台计算机互联而成的计算机组,组网范围通常在数千米以内。在局域网中,可以实现文件管理、应用软件共享、打印机
1 内网基础 内网/局域网(Local Area Network,LAN),是指在某一区域内有多台计算机互联而成的计算机组,组网范围通常在数千米以内。在局域网中,可以实现文件管理、应用软件共享、打印机
我有四列形式的数据。前三列代表时间,value1,value 2。第四列是二进制,全为 0 或 1。当第四列中对应的二进制值为0时,有没有办法告诉excel删除时间、值1和值2?我知道这在 C++ 或
我正在运行一个进行长时间计算的 Haskell 程序。经过一些分析和跟踪后,我注意到以下内容: $ /usr/bin/time -v ./hl test.hl 9000045000050000 Com
我有一个缓慢的 asp.net 程序正在运行。我想分析生产服务器以查看发生了什么,但我不想显着降低生产服务器的速度。 一般而言,配置生产盒或仅本地开发盒是标准做法吗?另外,您建议使用哪些程序来实现这一
我目前正在尝试分析 Haskell 服务器。服务器永远运行,所以我只想要一个固定时间的分析报告。我尝试只运行该程序 3 分钟,然后礼貌地要求它终止,但不知何故,haskell 分析器不遵守术语信号,并
我是一名优秀的程序员,十分优秀!