实现细节
Kubernetes v1.10 [稳定]
kubeadm init
和 kubeadm join
共同提供了一种良好的用户体验,用于从头开始创建裸 Kubernetes 集群,这与最佳实践一致。但是,可能不清楚 kubeadm 如何做到这一点。
本文档提供了有关幕后发生情况的更多详细信息,旨在分享有关 Kubernetes 集群最佳实践的知识。
核心设计原则
kubeadm init
和 kubeadm join
设置的集群应为
- 安全:它应采用最新的最佳实践,例如
- 强制执行 RBAC
- 使用节点授权器
- 在控制平面组件之间使用安全通信
- 在 API 服务器和 kubelet 之间使用安全通信
- 锁定 kubelet API
- 锁定对 API 的访问,以供系统组件(如 kube-proxy 和 CoreDNS)使用
- 锁定引导令牌可以访问的内容
- 用户友好:用户无需运行除几个命令以外的任何其他命令
kubeadm init
export KUBECONFIG=/etc/kubernetes/admin.conf
kubectl apply -f <network-of-choice.yaml>
kubeadm join --token <token> <endpoint>:<port>
- 可扩展:
- 它不应偏袒任何特定的网络提供商。配置集群网络超出了范围
- 它应提供使用配置文件来自定义各种参数的可能性
常量和众所周知的价值观和路径
为了降低复杂性并简化构建在 kubeadm 之上的更高级别工具的开发,它使用了一组有限的常量值来表示众所周知的路径和文件名。
Kubernetes 目录 /etc/kubernetes
是应用程序中的一个常量,因为它在大多数情况下是给定的路径,并且是最直观的路径;其他常量路径和文件名是
/etc/kubernetes/manifests
作为 kubelet 应该查找静态 Pod 清单的路径。静态 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
用于控制器管理器在签署 ServiceAccount 时使用的密钥front-proxy-ca.crt
、front-proxy-ca.key
用于前端代理证书颁发机构front-proxy-client.crt
、front-proxy-client.key
用于前端代理客户端
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
文件夹已存在且不为空 - [错误] 如果交换已开启
- [错误] 如果
conntrack
、ip
、iptables
、mount
、nsenter
命令不在命令路径中 - [警告] 如果
ebtables
、ethtool
、socat
、tc
、touch
、crictl
命令不在命令路径中 - [警告] 如果 API 服务器、控制器管理器、调度器的额外参数标志包含一些无效选项
- [警告] 如果连接到 https://API.AdvertiseAddress:API.BindPort 通过代理
- [警告] 如果连接到服务子网通过代理(仅检查第一个地址)
- [警告] 如果连接到 Pod 子网通过代理(仅检查第一个地址)
- 如果提供外部 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 服务的内部集群 IP(服务 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 服务的内部集群 IP(服务 CIDR 中的第一个地址,例如,如果服务子网为
API 服务器安全连接到 kubelet 的客户端证书,使用
ca.crt
作为 CA 生成,并保存到apiserver-kubelet-client.crt
文件中,其私钥为apiserver-kubelet-client.key
。此证书应位于system:masters
组织中用于签署 ServiceAccount 令牌的私钥,保存到
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,这也意味着控制器管理器中的csrsigner
控制器将不会启动 - 如果 kubeadm 在 外部 CA 模式 下运行;所有证书必须由用户提供,因为 kubeadm 无法自行生成它们
- 如果 kubeadm 在
--dry-run
模式下执行,证书文件将写入临时文件夹 - 可以使用
kubeadm init phase certs all
命令单独调用证书生成。
为控制平面组件生成 kubeconfig 文件
Kubeadm 为控制平面组件生成带有身份信息的 kubeconfig 文件
用于 kubelet 在 TLS 引导期间使用的 kubeconfig 文件 - /etc/kubernetes/bootstrap-kubelet.conf。在这个文件中,包含一个引导令牌或嵌入式客户端证书,用于将此节点与集群进行身份验证。
此客户端证书应
- 位于
system:nodes
组织中,如 节点授权 模块所要求的那样 - 具有通用名称 (CN)
system:node:<hostname-lowercased>
- 位于
用于控制器管理器的 kubeconfig 文件,
/etc/kubernetes/controller-manager.conf
;在这个文件中,嵌入了一个带有控制器管理器身份的客户端证书。此客户端证书应具有 CNsystem:kube-controller-manager
,如默认的 RBAC 核心组件角色 所定义的那样用于调度程序的 kubeconfig 文件,
/etc/kubernetes/scheduler.conf
;在这个文件中,嵌入了一个带有调度程序身份的客户端证书。此客户端证书应具有 CNsystem:kube-scheduler
,如默认的 RBAC 核心组件角色 所定义的那样
此外,还会生成一个用于 kubeadm 作为管理实体的 kubeconfig 文件,并将其存储在 /etc/kubernetes/admin.conf
中。此文件包含一个具有 Subject: O = kubeadm:cluster-admins, CN = kubernetes-admin
的证书。kubeadm:cluster-admins
是由 kubeadm 管理的组。在 kubeadm init
期间,它使用 super-admin.conf
文件绑定到 cluster-admin
ClusterRole,该文件不需要 RBAC。此 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 和内置 ClusterRoles 和组的更多信息,请参见 RBAC 面向用户的角色绑定。
请注意
ca.crt
证书嵌入到所有 kubeconfig 文件中。- 如果给定的 kubeconfig 文件存在,并且其内容被评估为符合上述规范,则将使用现有文件,并且将跳过给定 kubeconfig 的生成阶段
- 如果 kubeadm 在 ExternalCA 模式 下运行,则用户必须提供所有必需的 kubeconfig,因为 kubeadm 本身无法生成任何 kubeconfig
- 如果 kubeadm 在
--dry-run
模式下执行,则 kubeconfig 文件将写入临时文件夹 - 可以使用
kubeadm init phase kubeconfig all
命令单独调用 kubeconfig 文件的生成
为控制平面组件生成静态 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
,以允许控制平面在配置网络之前启动;因此- 控制器管理器和调度程序用于引用 API 服务器的
address
为127.0.0.1
- 如果 etcd 服务器在本地设置,则
etcd-server
地址将设置为127.0.0.1:2379
- 控制器管理器和调度程序用于引用 API 服务器的
控制器管理器和调度程序都启用了领导者选举
控制器管理器和调度程序将引用具有各自唯一身份的 kubeconfig 文件
所有静态 Pod 都获得用户在 将自定义参数传递给控制平面组件 中描述的任何额外标志
所有静态 Pod 都获得用户指定的任何额外卷(主机路径)
请注意
- 默认情况下,所有镜像都将从 registry.k8s.io 中拉取。有关自定义镜像存储库的信息,请参见 使用自定义镜像
- 如果 kubeadm 在
--dry-run
模式下执行,则静态 Pod 文件将写入临时文件夹 - 可以使用
kubeadm init phase control-plane all
命令单独调用控制平面组件的静态 Pod 清单生成
API 服务器
API 服务器的静态 Pod 清单受用户提供的以下参数影响
- 要绑定的
apiserver-advertise-address
和apiserver-bind-port
;如果未提供,这些值将默认为机器上默认网络接口的 IP 地址和端口 6443 - 用于服务的
service-cluster-ip-range
- 如果指定了外部 etcd 服务器,则
etcd-servers
地址和相关的 TLS 设置(etcd-cafile
、etcd-certfile
、etcd-keyfile
);如果未提供外部 etcd 服务器,则将使用本地 etcd(通过主机网络) - 如果指定了云提供商,则将配置相应的
--cloud-provider
参数以及--cloud-config
路径(如果存在此文件)(这是实验性的,alpha 版本,将在未来版本中删除)
其他无条件设置的 API 服务器标志是
--insecure-port=0
,以避免与 API 服务器建立不安全的连接--enable-bootstrap-token-auth=true
,以启用BootstrapTokenAuthenticator
身份验证模块。有关更多详细信息,请参见 TLS 引导--allow-privileged
设置为true
(例如,kube 代理需要)--requestheader-client-ca-file
设置为front-proxy-ca.crt
--enable-admission-plugins
设置为NamespaceLifecycle
,例如,避免删除系统保留的命名空间LimitRanger
和ResourceQuota
,以对命名空间强制执行限制ServiceAccount
,以强制执行服务帐户自动化PersistentVolumeLabel
,根据云提供商的定义,将区域或区域标签附加到 PersistentVolume(此准入控制器已弃用,将在未来版本中删除。从 v1.9 开始,当未明确选择使用gce
或aws
作为云提供商时,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 聚合)通信的其他标志
--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
控制器管理器
控制器管理器的静态 Pod 清单受用户提供的以下参数影响
如果 kubeadm 在调用时指定了
--pod-network-cidr
,则通过设置以下内容,将启用某些 CNI 网络插件所需的子网管理器功能--allocate-node-cidrs=true
- 根据给定的 CIDR 设置
--cluster-cidr
和--node-cidr-mask-size
标志
如果指定了云提供商,则将指定相应的
--cloud-provider
以及--cloud-config
路径(如果存在此配置文件)(这是实验性的,alpha 版本,将在未来版本中删除)
其他无条件设置的标志是
--controllers
,启用所有默认控制器以及BootstrapSigner
和TokenCleaner
控制器,用于 TLS 引导。有关更多详细信息,请参见 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
调度程序
调度程序的静态 Pod 清单不受用户提供的参数影响。
为本地 etcd 生成静态 Pod 清单
如果您指定了外部 etcd,则将跳过此步骤,否则 kubeadm 将生成一个静态 Pod 清单文件,用于在 Pod 中创建本地 etcd 实例,该 Pod 具有以下属性
- 侦听
localhost:2379
并使用HostNetwork=true
- 从
dataDir
到主机文件系统的hostPath
挂载 - 用户指定的任何额外标志
请注意
- etcd 容器镜像将默认从
registry.gcr.io
中拉取。有关自定义镜像存储库的信息,请参见 使用自定义镜像。 - 如果您在
--dry-run
模式下运行 kubeadm,则 etcd 静态 Pod 清单将写入临时文件夹。 - 您可以使用
kubeadm init phase etcd local
命令直接调用本地 etcd 的静态 Pod 清单生成。
等待控制平面启动
kubeadm 将等待(最多 4m0s),直到 localhost:6443/healthz
(kube-apiserver 存活性)返回 ok
。但是,为了检测死锁情况,如果 localhost:10255/healthz
(kubelet 存活性)或 localhost:10255/healthz/syncloop
(kubelet 就绪性)在 40s 和 60s 内分别没有返回 ok
,则 kubeadm 将快速失败。
kubeadm 依赖 kubelet 来拉取控制平面镜像并将其作为静态 Pod 正确运行。控制平面启动后,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 使用 使用引导令牌进行身份验证 将新节点加入现有集群;有关更多详细信息,请参见 设计提案。
kubeadm init
确保所有内容都为该过程正确配置,这包括以下步骤以及如前几段所述设置 API 服务器和控制器标志。
注意
节点的 TLS 引导可以通过命令kubeadm init phase bootstrap-token
配置,执行以下段落中描述的所有配置步骤;或者,可以单独调用每个步骤。创建引导令牌
kubeadm init
创建第一个引导令牌,该令牌要么自动生成,要么由用户使用 --token
标志提供;如引导令牌规范中所述,令牌应作为名称为 bootstrap-token-<token-id>
的秘密保存在 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 确保引导令牌将通过 csrapprover 控制器自动批准其 CSR 请求。
这是通过在 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。
此外,它还创建了一个角色和一个角色绑定,授予未经身份验证的用户(即 RBAC 组 system:unauthenticated
中的用户)访问 ConfigMap 的权限。
注意
对cluster-info
ConfigMap 的访问不受速率限制。如果您将集群的 API 服务器公开到互联网,这可能是也可能不是问题;这里最坏的情况是拒绝服务攻击,攻击者使用 kube-apiserver 可以处理的所有正在进行的请求来提供 cluster-info
ConfigMap。安装附加组件
Kubeadm 通过 API 服务器安装内部 DNS 服务器和 kube-proxy 附加组件。
注意
此阶段可以使用命令kubeadm init phase addon all
单独调用。代理
在 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
。这样做是为了防止用户通过 此处 描述的--config
方法将集群 DNS 从 kube-dns 切换到 CoreDNS 时出现任何服务中断。在
kube-system
命名空间中为 CoreDNS 创建了一个 ServiceAccount。coredns
ServiceAccount 与system:coredns
ClusterRole 中的权限绑定。
在 Kubernetes 版本 1.21 中,删除了对使用 kubeadm 使用 kube-dns
的支持。即使相关服务名为 kube-dns
,您也可以使用 kubeadm 使用 CoreDNS。
kubeadm join 阶段内部设计
与 kubeadm init
类似,kubeadm join
内部工作流程也包含一系列要执行的原子工作任务。
这分为发现(让节点信任 Kubernetes 主节点)和 TLS 引导(让 Kubernetes 主节点信任节点)。
请参阅 使用引导令牌进行身份验证 或相应的 设计提案。
预检
kubeadm
在开始加入之前执行一组预检,目的是验证先决条件并避免常见的集群启动问题。
请注意
kubeadm join
预检基本上是kubeadm init
预检的子集。- 从 1.24 开始,kubeadm 使用 crictl 与所有已知的 CRI 端点通信。
- 从 1.9 开始,kubeadm 提供对加入在 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 中的主题公钥信息 (SPKI) 对象的字节计算的)。--discovery-token-ca-cert-hash 标志
可以重复多次,以允许使用多个公钥。 - 作为额外的验证,通过安全连接检索 CA 证书,然后将其与最初检索的 CA 进行比较。
注意
可以通过传递--discovery-token-unsafe-skip-ca-verification
标志来跳过公钥验证;这会削弱 kubeadm 安全模型,因为其他人可能冒充 Kubernetes 主节点。文件/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
过程中的配置进行管理。