实现细节
Kubernetes v1.10 [稳定]
kubeadm init
和 kubeadm join
共同提供了一种优秀的用户体验,可以从头开始创建裸机 Kubernetes 集群,且符合最佳实践。但是,kubeadm
是如何做到的,这一点可能并不明显。
本文档提供了关于其内部工作原理的额外细节,旨在分享关于 Kubernetes 集群最佳实践的知识。
核心设计原则
kubeadm init
和 kubeadm join
设置的集群应具备以下特点:
- 安全:它应采用最新的最佳实践,例如:
- 强制执行 RBAC
- 使用 Node Authorizer
- 使用控制平面组件之间的安全通信
- 使用 API 服务器和 kubelet 之间的安全通信
- 锁定 kubelet API
- 锁定对 kube-proxy 和 CoreDNS 等系统组件访问 API 的权限
- 锁定 Bootstrap Token 可访问的内容
- 用户友好:用户无需运行超过几个命令:
kubeadm init
export KUBECONFIG=/etc/kubernetes/admin.conf
kubectl apply -f <选择的网络插件的 YAML 文件>
kubeadm join --token <token> <端点>:<端口>
- 可扩展:
- 它不应偏爱任何特定的网络提供商。配置集群网络不在其范围之内
- 它应提供使用配置文件来自定义各种参数的可能性
常量和已知值及路径
为了降低复杂性并简化构建在 kubeadm 之上的高级工具的开发,它对已知路径和文件名使用了一组有限的常量值。
Kubernetes 目录 /etc/kubernetes
在应用程序中是一个常量,因为它在大多数情况下是给定的路径,也是最直观的位置;其他常量路径和文件名包括:
/etc/kubernetes/manifests
作为 kubelet 查找静态 Pod 清单(manifests)的路径。静态 Pod 清单的文件名为:etcd.yaml
kube-apiserver.yaml
kube-controller-manager.yaml
kube-scheduler.yaml
/etc/kubernetes/
作为存储包含控制平面组件身份的 kubeconfig 文件的路径。kubeconfig 文件的文件名为:kubelet.conf
(TLS 引导期间为bootstrap-kubelet.conf
)controller-manager.conf
scheduler.conf
admin.conf
用于集群管理员和 kubeadm 本身super-admin.conf
用于可以绕过 RBAC 的集群超级管理员
证书和密钥文件的文件名为:
ca.crt
,ca.key
用于 Kubernetes 证书颁发机构apiserver.crt
,apiserver.key
用于 API 服务器证书apiserver-kubelet-client.crt
,apiserver-kubelet-client.key
用于 API 服务器安全连接 kubelet 时使用的客户端证书sa.pub
,sa.key
用于 controller manager 在签署 ServiceAccount 时使用的密钥front-proxy-ca.crt
,front-proxy-ca.key
用于前端代理证书颁发机构front-proxy-client.crt
,front-proxy-client.key
用于前端代理客户端
kubeadm 配置文件格式
大多数 kubeadm 命令支持 --config
标志,该标志允许从磁盘传递配置文件。配置文件的格式遵循通用的 Kubernetes API apiVersion
/ kind
方案,但被视为组件配置格式。一些 Kubernetes 组件,例如 kubelet,也支持基于文件的配置。
不同的 kubeadm 子命令需要不同 kind
的配置文件。例如,kubeadm init
需要 InitConfiguration
,kubeadm join
需要 JoinConfiguration
,kubeadm upgrade
需要 UpgradeConfiguration
,以及 kubeadm reset
需要 ResetConfiguration
。
命令 kubeadm config migrate
可用于将旧格式的配置文件迁移到较新(当前)的配置格式。kubeadm 工具仅支持从已弃用的配置格式迁移到当前格式。
有关更多详细信息,请参阅 kubeadm 配置参考 页面。
kubeadm init 工作流程内部设计
kubeadm init
由一系列要执行的原子工作任务组成,如 kubeadm init
的 内部工作流程 中所述。
kubeadm init phase
命令允许用户单独调用每个任务,最终提供一个可重用和可组合的 API/工具箱,可供其他 Kubernetes 引导工具、任何 IT 自动化工具或高级用户用于创建自定义集群。
预检检查
Kubeadm 在开始初始化之前执行一系列预检检查,旨在验证先决条件并避免常见的集群启动问题。用户可以使用 --ignore-preflight-errors
选项跳过特定的预检检查或所有检查。
- [警告] 如果要使用的 Kubernetes 版本(通过
--kubernetes-version
标志指定)比 kubeadm CLI 版本高至少一个次要版本。 - Kubernetes 系统要求
- 如果运行在 Linux 上
- [错误] 如果内核版本低于最低要求版本
- [错误] 如果所需的 cgroups 子系统未设置
- 如果运行在 Linux 上
- [错误] 如果 CRI 端点没有响应
- [错误] 如果用户不是 root
- [错误] 如果机器主机名不是有效的 DNS 子域名
- [警告] 如果无法通过网络查找访问主机名
- [错误] 如果 kubelet 版本低于 kubeadm 支持的最低 kubelet 版本(当前次要版本 -1)
- [错误] 如果 kubelet 版本比所需的控制平面版本高至少一个次要版本(不支持的版本偏差)
- [警告] 如果 kubelet 服务不存在或已禁用
- [警告] 如果 firewalld 处于活动状态
- [错误] 如果 API 服务器的 bindPort 或端口 10250/10251/10252 被占用
- [错误] 如果
/etc/kubernetes/manifest
文件夹已存在且不为空 - [错误] 如果 swap 已开启
- [错误] 如果命令路径中不存在
ip
、iptables
、mount
、nsenter
命令 - [警告] 如果命令路径中不存在
ethtool
、tc
、touch
命令 - [警告] 如果 API 服务器、controller manager、scheduler 的额外参数标志包含一些无效选项
- [警告] 如果连接到 https://API.AdvertiseAddress:API.BindPort 通过代理进行
- [警告] 如果连接到 services 子网通过代理进行(仅检查第一个地址)
- [警告] 如果连接到 Pods 子网通过代理进行(仅检查第一个地址)
- 如果提供了外部 etcd
- [错误] 如果 etcd 版本低于最低要求版本
- [错误] 如果指定了 etcd 证书或密钥,但未提供
- 如果未提供外部 etcd(因此将安装本地 etcd)
- [错误] 如果端口 2379 被占用
- [错误] 如果
Etcd.DataDir
文件夹已存在且不为空
- 如果授权模式是 ABAC
- [错误] 如果
abac_policy.json
不存在
- [错误] 如果
- 如果授权模式是 WebHook
- [错误] 如果
webhook_authz.conf
不存在
- [错误] 如果
注意
预检检查可以使用kubeadm init phase preflight
命令单独调用。生成必要的证书
Kubeadm 为不同目的生成证书和私钥对:
用于 Kubernetes 集群的自签名证书颁发机构,保存到
ca.crt
文件和ca.key
私钥文件中API 服务器的服务端证书,使用
ca.crt
作为 CA 生成,并保存到apiserver.crt
文件及其私钥apiserver.key
中。此证书应包含以下备用名称:- Kubernetes Service 的内部 clusterIP(services CIDR 中的第一个地址,例如,如果服务子网是
10.96.0.0/12
,则为10.96.0.1
) - Kubernetes DNS 名称,例如,如果
--service-dns-domain
标志值为cluster.local
,则为kubernetes.default.svc.cluster.local
,此外还有默认 DNS 名称kubernetes.default.svc
、kubernetes.default
、kubernetes
- 节点名称
--apiserver-advertise-address
- 用户指定的其他备用名称
- Kubernetes Service 的内部 clusterIP(services CIDR 中的第一个地址,例如,如果服务子网是
用于 API 服务器安全连接 kubelet 的客户端证书,使用
ca.crt
作为 CA 生成,并保存到apiserver-kubelet-client.crt
文件及其私钥apiserver-kubelet-client.key
中。此证书应属于system:masters
组织用于签署 ServiceAccount Token 的私钥,保存到
sa.key
文件及其公钥sa.pub
用于前端代理的证书颁发机构,保存到
front-proxy-ca.crt
文件及其密钥front-proxy-ca.key
用于前端代理客户端的客户端证书,使用
front-proxy-ca.crt
作为 CA 生成,并保存到front-proxy-client.crt
文件及其私钥front-proxy-client.key
中
证书默认存储在 /etc/kubernetes/pki
中,但此目录可以使用 --cert-dir
标志进行配置。
请注意:
- 如果给定的证书和私钥对都存在,并且其内容被评估为符合上述规范,则将使用现有文件,并跳过给定证书的生成阶段。这意味着用户可以将现有的 CA 复制到
/etc/kubernetes/pki/ca.{crt,key}
,然后 kubeadm 将使用这些文件签署其余证书。另请参阅 使用自定义证书 - 对于 CA,可以提供
ca.crt
文件但 불안ca.key
文件。如果所有其他证书和 kubeconfig 文件都已就位,kubeadm 会识别此情况并激活 ExternalCA,这也意味着 controller-manager 中的csrsigner
控制器不会启动 - 如果 kubeadm 运行在 外部 CA 模式下;所有证书都必须由用户提供,因为 kubeadm 无法自行生成它们
- 如果 kubeadm 在
--dry-run
模式下执行,证书文件将写入临时文件夹中 - 证书生成可以使用
kubeadm init phase certs all
命令单独调用
为控制平面组件生成 kubeconfig 文件
Kubeadm 为控制平面组件生成包含身份的 kubeconfig 文件:
kubelet 在 TLS 引导期间使用的 kubeconfig 文件 -
/etc/kubernetes/bootstrap-kubelet.conf
。此文件内部包含用于节点向集群认证的 bootstrap-token 或嵌入式客户端证书。此客户端证书应:
- 属于
system:nodes
组织,这是 Node Authorization 模块的要求 - 具有 Common Name (CN)
system:node:<hostname-lowercased>
- 属于
controller-manager 的 kubeconfig 文件,
/etc/kubernetes/controller-manager.conf
;此文件内部嵌入了包含 controller-manager 身份的客户端证书。此客户端证书应具有 CNsystem:kube-controller-manager
,这是默认 RBAC 核心组件角色 所定义的scheduler 的 kubeconfig 文件,
/etc/kubernetes/scheduler.conf
;此文件内部嵌入了包含 scheduler 身份的客户端证书。此客户端证书应具有 CNsystem:kube-scheduler
,这是默认 RBAC 核心组件角色 所定义的
此外,还会生成一个用于 kubeadm 作为管理实体的 kubeconfig 文件,并存储在 /etc/kubernetes/admin.conf
中。此文件包含一个证书,其 Subject 为 O = kubeadm:cluster-admins, CN = kubernetes-admin
。kubeadm:cluster-admins
是一个由 kubeadm 管理的组。在 kubeadm init
期间,通过使用不需要 RBAC 的 super-admin.conf
文件,它绑定到 cluster-admin
ClusterRole。此 admin.conf
文件必须保留在控制平面节点上,不应与额外用户共享。
在 kubeadm init
期间,还会生成另一个 kubeconfig 文件,并存储在 /etc/kubernetes/super-admin.conf
中。此文件包含一个证书,其 Subject 为 O = system:masters, CN = kubernetes-super-admin
。system:masters
是一个绕过 RBAC 的超级用户组,这使得 super-admin.conf
在集群因 RBAC 配置错误而被锁定时非常有用。super-admin.conf
文件必须存储在安全位置,不应与额外用户共享。
有关 RBAC 和内置 ClusterRole 及组的更多信息,请参阅 RBAC 用户面向角色绑定。
您可以运行 kubeadm kubeconfig user
为额外用户生成 kubeconfig 文件。
注意
生成的配置文件包含嵌入的身份认证密钥,您应将其视为机密。另请注意:
ca.crt
证书嵌入在所有 kubeconfig 文件中。- 如果给定的 kubeconfig 文件存在,并且其内容被评估为符合上述规范,则将使用现有文件,并跳过给定 kubeconfig 的生成阶段
- 如果 kubeadm 运行在 ExternalCA 模式下,所有必需的 kubeconfig 也必须由用户提供,因为 kubeadm 无法自行生成它们
- 如果 kubeadm 在
--dry-run
模式下执行,kubeconfig 文件将写入临时文件夹中 - kubeconfig 文件的生成可以使用
kubeadm init phase kubeconfig all
命令单独调用
为控制平面组件生成静态 Pod 清单
Kubeadm 将控制平面组件的静态 Pod 清单文件写入 /etc/kubernetes/manifests
。kubelet 会监视此目录,以便在启动时创建 Pod。
静态 Pod 清单共享一组通用属性:
所有静态 Pod 都部署在
kube-system
命名空间中所有静态 Pod 都带有
tier:control-plane
和component:{component-name}
标签所有静态 Pod 都使用
system-node-critical
优先类所有静态 Pod 都设置了
hostNetwork: true
,以便在网络配置之前允许控制平面启动;因此:- controller-manager 和 scheduler 用于引用 API 服务器的地址是
127.0.0.1
- 如果 etcd 服务器在本地设置,
etcd-server
地址将设置为127.0.0.1:2379
- controller-manager 和 scheduler 用于引用 API 服务器的地址是
controller-manager 和 scheduler 都启用了领导者选举
controller-manager 和 scheduler 将引用包含各自唯一身份的 kubeconfig 文件
所有静态 Pod 都获得你指定的额外标志或补丁,如 向控制平面组件传递自定义参数 中所述
所有静态 Pod 都获得用户指定的额外卷(Host path)
请注意:
- 默认情况下,所有镜像都将从
registry.k8s.io
拉取。有关自定义镜像仓库的信息,请参阅 使用自定义镜像 - 如果 kubeadm 在
--dry-run
模式下执行,静态 Pod 文件将写入临时文件夹中 - 控制平面组件的静态 Pod 清单生成可以使用
kubeadm init phase control-plane all
命令单独调用
API 服务器
API 服务器的静态 Pod 清单受用户提供的以下参数影响:
- 要绑定的
apiserver-advertise-address
和apiserver-bind-port
;如果未提供,这些值默认为机器上默认网络接口的 IP 地址和端口 6443 - 用于 Services 的
service-cluster-ip-range
- 如果指定了外部 etcd 服务器,则使用
etcd-servers
地址及相关的 TLS 设置(etcd-cafile
、etcd-certfile
、etcd-keyfile
);如果未提供外部 etcd 服务器,则将使用本地 etcd(通过 host network) - 如果指定了 cloud provider,则配置相应的
--cloud-provider
参数以及--cloud-config
路径(如果该文件存在)(这是实验性功能,处于 alpha 阶段,并将在未来版本中移除)
无条件设置的其他 API 服务器标志包括:
--insecure-port=0
以避免到 API 服务器的不安全连接--enable-bootstrap-token-auth=true
以启用BootstrapTokenAuthenticator
身份认证模块。有关更多详细信息,请参阅 TLS 引导--allow-privileged
设置为true
(例如,kube-proxy 需要)--requestheader-client-ca-file
设置为front-proxy-ca.crt
--enable-admission-plugins
设置为:NamespaceLifecycle
,例如避免删除系统保留的命名空间LimitRanger
和ResourceQuota
,用于在命名空间上强制执行限制ServiceAccount
,用于强制执行 Service Account 自动化PersistentVolumeLabel
,根据 cloud provider 的定义将地域或区域标签附加到 PersistentVolume(此准入控制器已弃用,并将在未来版本中移除。从 v1.9 开始,除非明确选择使用 gce 或 aws 作为 cloud provider,否则 kubeadm 默认不会部署此准入控制器)DefaultStorageClass
,用于在 PersistentVolumeClaim 对象上强制执行默认存储类DefaultTolerationSeconds
NodeRestriction
,用于限制 kubelet 可以修改的内容(例如,仅限制此节点上的 Pod)
--kubelet-preferred-address-types
设置为InternalIP,ExternalIP,Hostname;
这使得在节点主机名无法解析的环境中kubectl logs
和其他 API 服务器与 kubelet 的通信能够正常工作使用前一步骤中生成的证书的标志:
--client-ca-file
设置为ca.crt
--tls-cert-file
设置为apiserver.crt
--tls-private-key-file
设置为apiserver.key
--kubelet-client-certificate
设置为apiserver-kubelet-client.crt
--kubelet-client-key
设置为apiserver-kubelet-client.key
--service-account-key-file
设置为sa.pub
--requestheader-client-ca-file
设置为front-proxy-ca.crt
--proxy-client-cert-file
设置为front-proxy-client.crt
--proxy-client-key-file
设置为front-proxy-client.key
用于保护前端代理 (API Aggregation) 通信的其他标志:
--requestheader-username-headers=X-Remote-User
--requestheader-group-headers=X-Remote-Group
--requestheader-extra-headers-prefix=X-Remote-Extra-
--requestheader-allowed-names=front-proxy-client
Controller manager
controller manager 的静态 Pod 清单受用户提供的以下参数影响:
如果调用 kubeadm 时指定了
--pod-network-cidr
,则通过设置以下参数启用某些 CNI 网络插件所需的子网管理器功能:--allocate-node-cidrs=true
- 根据给定的 CIDR 设置
--cluster-cidr
和--node-cidr-mask-size
标志
无条件设置的其他标志包括:
--controllers
启用所有默认控制器以及用于 TLS 引导的BootstrapSigner
和TokenCleaner
控制器。有关更多详细信息,请参阅 TLS 引导。--use-service-account-credentials
设置为true
使用前一步骤中生成的证书的标志:
--root-ca-file
设置为ca.crt
--cluster-signing-cert-file
设置为ca.crt
,如果 External CA 模式已禁用,否则设置为""
--cluster-signing-key-file
设置为ca.key
,如果 External CA 模式已禁用,否则设置为""
--service-account-private-key-file
设置为sa.key
Scheduler
scheduler 的静态 Pod 清单不受用户提供的参数影响。
为本地 etcd 生成静态 Pod 清单
如果你指定了外部 etcd,则跳过此步骤,否则 kubeadm 会生成一个静态 Pod 清单文件,用于创建在 Pod 中运行的本地 etcd 实例,该实例具有以下属性:
- 监听
localhost:2379
并使用HostNetwork=true
- 从
dataDir
向主机的 filesystem 创建一个hostPath
挂载 - 用户指定的任何额外标志
请注意:
- etcd 容器镜像默认将从
registry.gcr.io
拉取。有关自定义镜像仓库的信息,请参阅 使用自定义镜像。 - 如果你在
--dry-run
模式下运行 kubeadm,etcd 静态 Pod 清单将写入临时文件夹中。 - 你可以使用
kubeadm init phase etcd local
命令直接调用本地 etcd 的静态 Pod 清单生成。
等待控制平面启动
在控制平面节点上,kubeadm 最多等待 4 分钟,直到控制平面组件和 kubelet 可用。它通过对相应的组件的 /healthz
或 /livez
端点执行健康检查来实现这一点。
控制平面启动后,kubeadm 完成以下段落所述的任务。
将 kubeadm ClusterConfiguration 保存到 ConfigMap 中以供后续参考
kubeadm 将传递给 kubeadm init
的配置保存在 kube-system
命名空间下名为 kubeadm-config
的 ConfigMap 中。
这将确保将来执行的 kubeadm 操作(例如 kubeadm upgrade
)能够确定实际/当前集群状态,并基于这些数据做出新的决策。
请注意:
- 在保存 ClusterConfiguration 之前,会从配置中去除令牌等敏感信息。
- 可以使用命令
kubeadm init phase upload-config
单独调用上传控制平面节点配置的功能。
标记节点为控制平面节点
控制平面可用后,kubeadm 会执行以下操作
- 使用
node-role.kubernetes.io/control-plane=""
标签标记节点为控制平面节点。 - 使用
node-role.kubernetes.io/control-plane:NoSchedule
污点标记节点。
请注意,标记控制平面阶段的阶段可以使用命令 kubeadm init phase mark-control-plane
单独调用。
配置节点加入时的 TLS 引导
Kubeadm 使用使用 Bootstrap Token 进行认证来将新节点加入现有集群;更多详细信息请参阅 设计提案。
kubeadm init
会确保为此过程正确配置所有内容,包括以下步骤以及设置 API 服务器和控制器标志(如前面段落所述)。
注意
可以使用命令kubeadm init phase bootstrap-token
配置节点的 TLS 引导,该命令会执行以下段落中描述的所有配置步骤;或者,也可以单独调用每个步骤。创建引导令牌
kubeadm init
会创建第一个引导令牌,该令牌可以是自动生成,也可以由用户使用 --token
标志提供;根据引导令牌规范中的说明,令牌应作为名为 bootstrap-token-<token-id>
的 Secret 保存在 kube-system
命名空间下。
请注意:
kubeadm init
创建的默认令牌将用于在 TLS 引导过程中验证临时用户;这些用户将是system:bootstrappers:kubeadm:default-node-token
组的成员。- 令牌有效期有限,默认为 24 小时(可以使用
—token-ttl
标志更改此间隔)。 - 可以使用
kubeadm token
命令创建更多令牌,该命令还提供其他有用的令牌管理功能。
允许加入的节点调用 CSR API
Kubeadm 确保 system:bootstrappers:kubeadm:default-node-token
组中的用户能够访问证书签名 API。
这是通过在上述组和默认 RBAC 角色 system:node-bootstrapper
之间创建名为 kubeadm:kubelet-bootstrap
的 ClusterRoleBinding 来实现的。
设置新引导令牌的自动批准
Kubeadm 确保引导令牌的 CSR 请求将由 csrapprover 控制器自动批准。
这是通过在 system:bootstrappers:kubeadm:default-node-token
组和默认角色 system:certificates.k8s.io:certificatesigningrequests:nodeclient
之间创建名为 kubeadm:node-autoapprove-bootstrap
的 ClusterRoleBinding 来实现的。
还应创建角色 system:certificates.k8s.io:certificatesigningrequests:nodeclient
,授予对 /apis/certificates.k8s.io/certificatesigningrequests/nodeclient
的 POST 权限。
设置带有自动批准的节点证书轮换
Kubeadm 确保为节点启用证书轮换,并且节点的新的证书请求将由 csrapprover 控制器自动批准其 CSR 请求。
这是通过在 system:nodes
组和默认角色 system:certificates.k8s.io:certificatesigningrequests:selfnodeclient
之间创建名为 kubeadm:node-autoapprove-certificate-rotation
的 ClusterRoleBinding 来实现的。
创建公共的 cluster-info ConfigMap
此阶段在 kube-public
命名空间中创建 cluster-info
ConfigMap。
此外,它还创建了一个 Role 和一个 RoleBinding,授予未经身份验证的用户(即 RBAC 组 system:unauthenticated
中的用户)访问此 ConfigMap 的权限。
注意
对cluster-info
ConfigMap 的访问**不**受速率限制。如果将集群的 API 服务器暴露到互联网,这可能是一个问题也可能不是问题;这里最坏的情况是拒绝服务攻击,攻击者利用 kube-apiserver 能处理的所有正在进行的请求来提供 cluster-info
ConfigMap。安装插件
Kubeadm 通过 API 服务器安装内部 DNS 服务器和 kube-proxy 插件组件。
注意
此阶段可以使用命令kubeadm init phase addon all
单独调用。proxy
在 kube-system
命名空间中为 kube-proxy
创建一个 ServiceAccount;然后将 kube-proxy 部署为 DaemonSet。
- 连接控制平面的凭据(
ca.crt
和token
)来自该 ServiceAccount。 - API 服务器的位置 (URL) 来自一个 ConfigMap。
kube-proxy
的 ServiceAccount 被绑定到system:node-proxier
ClusterRole 中的权限。
DNS
CoreDNS 服务出于与旧版
kube-dns
插件兼容的原因被命名为kube-dns
。在
kube-system
命名空间中为 CoreDNS 创建一个 ServiceAccount。coredns
的 ServiceAccount 被绑定到system:coredns
ClusterRole 中的权限。
在 Kubernetes 1.21 版本中,移除了通过 kubeadm 使用 kube-dns
的支持。即使相关的 Service 被命名为 kube-dns
,您仍然可以使用 kubeadm 来使用 CoreDNS。
kubeadm join 阶段内部设计
与 kubeadm init
类似,kubeadm join
的内部工作流程也由一系列需要执行的原子工作任务组成。
这被分解为发现(让节点信任 Kubernetes API 服务器)和 TLS 引导(让 Kubernetes API 服务器信任节点)。
参阅使用 Bootstrap Token 进行认证或相应的设计提案。
预检检查
kubeadm
在开始加入之前会执行一组预检检查,目的是验证先决条件并避免常见的集群启动问题。
另请注意:
kubeadm join
的预检检查基本上是kubeadm init
预检检查的子集。- 如果您要加入 Windows 节点,则会跳过 Linux 特定的检查。
- 在任何情况下,用户都可以使用
--ignore-preflight-errors
选项跳过特定的预检检查(或最终跳过所有预检检查)。
发现 cluster-info
有两种主要的发现方案。第一种是使用共享令牌和 API 服务器的 IP 地址。第二种是提供一个文件(它是标准 kubeconfig 文件的一个子集)。
共享令牌发现
如果使用 --discovery-token
调用 kubeadm join
,则使用令牌发现;在这种情况下,节点基本上会从 kube-public
命名空间中的 cluster-info
ConfigMap 中检索集群 CA 证书。
为了防止“中间人”攻击,采取了几个步骤
首先,通过不安全连接检索 CA 证书(这是可能的,因为在
kubeadm init
期间,已授予system:unauthenticated
用户对cluster-info
的访问权限)。然后 CA 证书会通过以下验证步骤
- 基本验证:使用令牌 ID 对 JWT 签名进行验证。
- 公钥验证:使用提供的
--discovery-token-ca-cert-hash
。此值可在kubeadm init
的输出中找到,或使用标准工具计算(哈希是按照 RFC7469 计算 Subject Public Key Info (SPKI) 对象的字节得出的)。--discovery-token-ca-cert-hash
标志可以重复多次,以允许使用多个公钥。 - 作为附加验证,通过安全连接检索 CA 证书,然后与最初检索到的 CA 进行比较。
注意
您可以通过在命令行上传递--discovery-token-unsafe-skip-ca-verification
标志来跳过 CA 验证。这会削弱 kubeadm 的安全模型,因为其他人可能会冒充 Kubernetes API 服务器。文件/HTTPS 发现
如果使用 --discovery-file
调用 kubeadm join
,则使用文件发现;该文件可以是本地文件,也可以通过 HTTPS URL 下载;在 HTTPS 的情况下,使用主机上安装的 CA 捆绑包来验证连接。
使用文件发现时,集群 CA 证书直接包含在文件本身中;实际上,发现文件是一个 kubeconfig 文件,其中仅设置了 server
和 certificate-authority-data
属性,如kubeadm join
参考文档中所述;与集群建立连接后,kubeadm 会尝试访问 cluster-info
ConfigMap,如果可用,则使用它。
TLS 引导
一旦集群信息已知,就会写入 bootstrap-kubelet.conf
文件,从而允许 kubelet 进行 TLS 引导。
TLS 引导机制使用共享令牌与 Kubernetes API 服务器临时进行身份验证,以提交本地生成的密钥对的证书签名请求 (CSR)。
请求随后会自动获得批准,操作完成,保存 ca.crt
文件和 kubelet.conf
文件供 kubelet 用于加入集群,同时删除 bootstrap-kubelet.conf
文件。
注意
- 临时身份验证会根据在
kubeadm init
过程中保存的令牌(或使用kubeadm token
命令创建的其他令牌)进行验证。 - 临时身份验证解析为
system:bootstrappers:kubeadm:default-node-token
组的用户成员,该组在kubeadm init
过程中被授予了 CSR API 的访问权限。 - 自动 CSR 批准由 csrapprover 控制器管理,根据
kubeadm init
过程中的配置进行。
kubeadm 升级工作流程内部设计
kubeadm upgrade
包含用于处理由 kubeadm 创建的 Kubernetes 集群升级的子命令。您必须在控制平面节点上运行 kubeadm upgrade apply
(您可以选择哪个节点);这会启动升级过程。然后您在所有剩余节点(包括工作节点和控制平面节点)上运行 kubeadm upgrade node
。
kubeadm upgrade apply
和 kubeadm upgrade node
都包含一个 phase
子命令,该子命令提供对升级过程内部阶段的访问。更多详细信息请参阅 kubeadm upgrade phase
。
其他实用的升级命令包括 kubeadm upgrade plan
和 kubeadm upgrade diff
。
所有升级子命令都支持传递配置文件。
kubeadm upgrade plan
在运行 kubeadm upgrade apply
之前,您可以选择运行 kubeadm upgrade plan
。plan
子命令会检查哪些版本可用于升级,并验证您当前集群是否可升级。
kubeadm upgrade diff
这会显示将应用于控制平面节点的现有静态 Pod 清单的差异。执行相同操作的更详细方法是运行 kubeadm upgrade apply --dry-run
或 kubeadm upgrade node --dry-run
。
kubeadm upgrade apply
kubeadm upgrade apply
会为所有节点的升级准备集群,同时还会升级在其上运行的控制平面节点。它执行的步骤包括:
- 运行类似于
kubeadm init
和kubeadm join
的预检检查,确保容器镜像已下载且集群处于适合升级的状态。 - 升级磁盘上
/etc/kubernetes/manifests
中的控制平面清单文件,并在文件发生更改时等待 kubelet 重启组件。 - 将更新的 kubeadm 和 kubelet 配置作为
kubeadm-config
和kubelet-config
ConfigMaps(两者都在kube-system
命名空间中)上传到集群。 - 将此节点的更新的 kubelet 配置写入
/var/lib/kubelet/config.yaml
中。 - 为 RBAC 规则配置引导令牌和
cluster-info
ConfigMap。这与kubeadm init
阶段相同,并确保集群继续支持使用引导令牌加入的节点。 - 仅当集群中所有现有的 kube-apiserver 都已升级到目标版本时,才会有条件地升级 kube-proxy 和 CoreDNS 插件。
- 执行任何升级后任务,例如清理特定于发行版本的已弃用功能。
kubeadm upgrade node
在集群升级启动后(通过运行 kubeadm upgrade apply
),kubeadm upgrade node
会升级单个控制平面节点或工作节点。该命令通过检查文件 /etc/kubernetes/manifests/kube-apiserver.yaml
是否存在来检测节点是否为控制平面节点。如果找到该文件,kubeadm 工具会推断此节点上有一个正在运行的 kube-apiserver Pod。
- 运行类似于
kubeadm upgrade apply
的预检检查。 - 对于控制平面节点,升级磁盘上
/etc/kubernetes/manifests
中的控制平面清单文件,并在文件发生更改时等待 kubelet 重启组件。 - 将此节点的更新的 kubelet 配置写入
/var/lib/kubelet/config.yaml
中。 - (对于控制平面节点)仅在集群中所有现有的 API 服务器都已升级到目标版本的前提下,才会条件性地升级 kube-proxy 和 CoreDNS 插件。
- 执行任何升级后任务,例如清理特定于发行版本的已弃用功能。
kubeadm reset 工作流程内部设计
您可以在之前执行过 kubeadm 命令的节点上使用 kubeadm reset
子命令。此子命令会**尽最大努力**清理节点。如果某些操作失败,您必须介入并执行手动清理。
该命令支持阶段。更多详细信息请参阅 kubeadm reset phase
。
该命令支持配置文件。
此外
- IPVS、iptables 和 nftables 规则**不**会被清理。
- CNI (网络插件) 配置**不**会被清理。
- 用户主目录中的
.kube/
**不**会被清理。
该命令包括以下阶段
- 在节点上运行预检检查以确定其是否健康。
- 对于控制平面节点,删除所有本地 etcd 成员数据。
- 停止 kubelet。
- 停止运行中的容器。
- 解挂
/var/lib/kubelet
中所有已挂载的目录。 - 删除由 kubeadm 管理的
/var/lib/kubelet
和/etc/kubernetes
中的所有文件和目录。