kubeadm join
该命令初始化一个新的 Kubernetes 节点并将其加入到现有的集群。
在任何你想加入现有集群的机器上运行此命令。
概要
当加入一个由 kubeadm 初始化好的集群时,我们需要建立双向信任。这被分为两个阶段:发现(让节点信任 Kubernetes 控制平面)和 TLS 引导(让 Kubernetes 控制平面信任节点)。
发现机制主要有两种。第一种是使用共享令牌以及 API 服务器的 IP 地址。第二种是提供一个文件,该文件是标准 kubeconfig 文件的一个子集。发现/kubeconfig 文件支持 token、client-go 身份验证插件 ("exec")、"tokenFile" 和 "authProvider"。此文件可以是本地文件,也可以通过 HTTPS URL 下载。命令形式为 kubeadm join --discovery-token abcdef.1234567890abcdef 1.2.3.4:6443、kubeadm join --discovery-file path/to/file.conf 或 kubeadm join --discovery-file https://url/file.conf。只能使用其中一种形式。如果从 URL 加载发现信息,则必须使用 HTTPS。此外,在这种情况下,会使用主机上安装的 CA 捆绑包来验证连接。
如果你使用共享令牌进行发现,还应传递 --discovery-token-ca-cert-hash 标志来验证 Kubernetes 控制平面提供的根证书颁发机构 (CA) 的公钥。此标志的值指定为 "<哈希类型>:<十六进制编码值>",其中支持的哈希类型为 "sha256"。哈希值是根据主体公钥信息 (SPKI) 对象的字节计算的(如 RFC7469 中所述)。这个值可以在 "kubeadm init" 的输出中找到,也可以使用标准工具计算。可以重复使用 --discovery-token-ca-cert-hash 标志多次,以允许多个公钥。
如果你无法提前知道 CA 公钥哈希,可以传递 --discovery-token-unsafe-skip-ca-verification 标志来禁用此验证。这会削弱 kubeadm 的安全模型,因为其他节点可能会冒充 Kubernetes 控制平面。
TLS 引导机制也通过共享令牌驱动。这用于临时与 Kubernetes 控制平面进行身份验证,以提交本地创建的密钥对的证书签名请求 (CSR)。默认情况下,kubeadm 会设置 Kubernetes 控制平面自动批准这些签名请求。这个令牌通过 --tls-bootstrap-token abcdef.1234567890abcdef 标志传入。
通常,发现和 TLS 引导都使用同一个令牌。在这种情况下,可以使用 --token 标志代替单独指定每个令牌。
"join [api-server-endpoint]" 命令执行以下阶段:
preflight Run join pre-flight checks
control-plane-prepare Prepare the machine for serving a control plane
/download-certs Download certificates shared among control-plane nodes from the kubeadm-certs Secret
/certs Generate the certificates for the new control plane components
/kubeconfig Generate the kubeconfig for the new control plane components
/control-plane Generate the manifests for the new control plane components
kubelet-start Write kubelet settings, certificates and (re)start the kubelet
control-plane-join Join a machine as a control plane instance
/etcd Add a new local etcd member
/mark-control-plane Mark a node as a control-plane
wait-control-plane EXPERIMENTAL: Wait for the control plane to start
kubeadm join [api-server-endpoint] [flags]
选项
--apiserver-advertise-address 字符串 | |
如果该节点应托管新的控制平面实例,这是 API 服务器将通告其监听的 IP 地址。如果未设置,将使用默认网络接口。 | |
--apiserver-bind-port int32 默认值: 6443 | |
如果该节点应托管新的控制平面实例,这是 API 服务器绑定的端口。 | |
--certificate-key 字符串 | |
使用此密钥解密由 init 上传的证书 Secret。证书密钥是一个十六进制编码的字符串,是大小为 32 字节的 AES 密钥。 | |
--config 字符串 | |
kubeadm 配置文件的路径。 | |
--control-plane | |
在此节点上创建新的控制平面实例。 | |
--cri-socket 字符串 | |
要连接的 CRI socket 的路径。如果为空,kubeadm 将尝试自动检测此值;仅在你安装了多个 CRI 或使用非标准 CRI socket 时才使用此选项。 | |
--discovery-file 字符串 | |
对于基于文件的发现,指定加载集群信息的文件或 URL。 | |
--discovery-token 字符串 | |
对于基于令牌的发现,用于验证从 API 服务器获取的集群信息的令牌。 | |
--discovery-token-ca-cert-hash 字符串列表 | |
对于基于令牌的发现,验证根 CA 公钥是否匹配此哈希(格式:"<类型>:<值>")。 | |
--discovery-token-unsafe-skip-ca-verification | |
对于基于令牌的发现,允许在不使用 --discovery-token-ca-cert-hash 固定的情况下加入。 | |
--dry-run | |
不应用任何更改;仅输出将要执行的操作。 | |
-h, --help | |
join 命令的帮助信息 | |
--ignore-preflight-errors 字符串列表 | |
其错误将显示为警告的检查列表。示例:“IsPrivilegedUser,Swap”。值“all”表示忽略所有检查的错误。 | |
--node-name 字符串 | |
指定节点名称。 | |
--patches 字符串 | |
包含名为 "target[suffix][+patchtype].extension" 的文件的目录路径。例如,"kube-apiserver0+merge.yaml" 或 "etcd.json"。"target" 可以是 "kube-apiserver", "kube-controller-manager", "kube-scheduler", "etcd", "kubeletconfiguration", "corednsdeployment" 中的一个。"patchtype" 可以是 "strategic", "merge" 或 "json" 中的一个,它们匹配 kubectl 支持的补丁格式。默认的 "patchtype" 是 "strategic"。"extension" 必须是 "json" 或 "yaml"。"suffix" 是一个可选字符串,可用于按字母数字顺序确定哪些补丁先应用。 | |
--skip-phases 字符串列表 | |
要跳过的阶段列表。 | |
--tls-bootstrap-token 字符串 | |
指定节点加入时用于临时与 Kubernetes 控制平面进行身份验证的令牌。 | |
--token 字符串 | |
当未提供 discovery-token 和 tls-bootstrap-token 时,使用此令牌。 |
从父命令继承的选项
--rootfs 字符串 | |
'真实' 主机根文件系统的路径。这将使 kubeadm chroot 到提供的路径中。 |
join 工作流程
kubeadm join
引导一个 Kubernetes 工作节点或一个控制平面节点,并将其添加到集群。对于工作节点,此操作包括以下步骤:
kubeadm 从 API 服务器下载必要的集群信息。默认情况下,它使用引导令牌和 CA 密钥哈希来验证数据的真实性。根 CA 也可以直接通过文件或 URL 进行发现。
一旦已知集群信息,kubelet 就可以启动 TLS 引导过程。
TLS 引导使用共享令牌临时与 Kubernetes API 服务器进行身份验证,以提交证书签名请求 (CSR);默认情况下,控制平面会自动签署此 CSR 请求。
最后,kubeadm 配置本地 kubelet 使用分配给节点的确定性身份连接到 API 服务器。
对于控制平面节点,还执行额外的步骤:
从集群下载控制平面节点之间共享的证书(如果用户明确请求)。
生成控制平面组件清单、证书和 kubeconfig。
添加新的本地 etcd 成员。
使用 kubeadm 的 join 阶段
Kubeadm 允许你使用 kubeadm join phase
分阶段将节点加入集群。
要查看阶段和子阶段的有序列表,可以调用 kubeadm join --help
。列表将位于帮助屏幕的顶部,每个阶段旁边都会有描述。请注意,通过调用 kubeadm join
,所有阶段和子阶段将按此确切顺序执行。
某些阶段具有独特的标志,因此如果你想查看可用选项列表,请添加 --help
,例如:
kubeadm join phase kubelet-start --help
类似于 kubeadm init phase 命令,kubeadm join phase
允许你使用 --skip-phases
标志跳过一系列阶段。
例如
sudo kubeadm join --skip-phases=preflight --config=config.yaml
Kubernetes v1.22 [beta]
或者,你可以在 JoinConfiguration
中使用 skipPhases
字段。
发现要信任的集群 CA
kubeadm 发现有几个选项,每个选项都有安全方面的权衡。适合你环境的方法取决于你如何供给节点以及你对网络和节点生命周期的安全预期。
基于令牌和 CA 固定的发现
这是 kubeadm 中的默认模式。在此模式下,kubeadm 下载集群配置(包括根 CA)并使用令牌验证其真实性,同时验证根 CA 公钥与提供的哈希匹配,并且 API 服务器证书在根 CA 下有效。
CA 密钥哈希的格式为 sha256:<十六进制编码哈希值>
。默认情况下,哈希值会打印在 kubeadm init
命令的末尾或 kubeadm token create --print-join-command
命令的输出中。它采用标准格式(请参阅 RFC7469),也可以由第三方工具或供给系统计算。例如,使用 OpenSSL CLI:
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
kubeadm join
命令示例
对于工作节点
kubeadm join --discovery-token abcdef.1234567890abcdef --discovery-token-ca-cert-hash sha256:1234..cdef 1.2.3.4:6443
对于控制平面节点
kubeadm join --discovery-token abcdef.1234567890abcdef --discovery-token-ca-cert-hash sha256:1234..cdef --control-plane 1.2.3.4:6443
如果调用 kubeadm init
命令时使用了 --upload-certs
,你还可以使用 --certificate-key
为控制平面节点调用 join
以将证书复制到此节点。
优点
即使其他工作节点或网络被攻破,也能让引导节点安全地发现控制平面节点的信任根。
由于所需的所有信息都包含在一个
kubeadm join
命令中,手动执行很方便。
缺点
- CA 哈希通常在控制平面节点供给之前未知,这使得构建使用 kubeadm 的自动化供给工具更加困难。通过预先生成 CA,你可以绕过此限制。
基于令牌但不固定 CA 的发现
此模式仅依赖对称令牌对建立控制平面信任根的发现信息进行签名 (HMAC-SHA256)。要使用此模式,加入节点必须跳过 CA 公钥的哈希验证,使用 --discovery-token-unsafe-skip-ca-verification
。如果可能,应考虑使用其他模式之一。
kubeadm join
命令示例
kubeadm join --token abcdef.1234567890abcdef --discovery-token-unsafe-skip-ca-verification 1.2.3.4:6443
优点
仍然可以防御许多网络层攻击。
令牌可以提前生成,并与控制平面节点和工作节点共享,然后它们可以并行引导而无需协调。这使得它可以在许多供给场景中使用。
缺点
- 如果攻击者能够通过某个漏洞窃取引导令牌,他们可以使用该令牌(以及网络级访问权限)冒充控制平面节点来欺骗其他引导节点。这在你的环境中可能是也可能不是适当的权衡。
基于文件或 HTTPS 的发现
这提供了一种带外方式来在控制平面节点和引导节点之间建立信任根。如果你正在使用 kubeadm 构建自动化供给,请考虑使用此模式。发现文件的格式是常规的 Kubernetes kubeconfig 文件。
如果发现文件不包含凭据,将使用 TLS 发现令牌。
kubeadm join
命令示例
kubeadm join --discovery-file path/to/file.conf
(本地文件)kubeadm join --discovery-file https://url/file.conf
(远程 HTTPS URL)
优点
- 即使网络或其他工作节点被攻破,也能让引导节点安全地发现控制平面节点的信任根。
缺点
- 需要你有某种方式将发现信息从控制平面节点传输到引导节点。如果发现文件包含凭据,你必须保密并通过安全通道传输。这可能可以通过你的云提供商或供给工具实现。
使用自定义 kubelet 凭据和 kubeadm join
要允许 kubeadm join
使用预定义的 kubelet 凭据并跳过新节点的客户端 TLS 引导和 CSR 批准:
- 在集群中一个拥有
/etc/kubernetes/pki/ca.key
的正常工作的控制平面节点上执行kubeadm kubeconfig user --org system:nodes --client-name system:node:$NODE > kubelet.conf
。$NODE
必须设置为新节点的名称。 - 手动修改生成的
kubelet.conf
以调整集群名称和服务器端点,或者运行kubeadm kubeconfig user --config
(它接受InitConfiguration
)。
如果你的集群没有 ca.key
文件,你必须在外部对 kubelet.conf
中嵌入的证书进行签名。有关更多信息,请参阅 PKI 证书和要求 以及 使用 kubeadm 管理证书。
- 将生成的
kubelet.conf
复制到新节点的/etc/kubernetes/kubelet.conf
。 - 在新节点上执行带有标志
--ignore-preflight-errors=FileAvailable--etc-kubernetes-kubelet.conf
的kubeadm join
命令。
进一步增强安装的安全性
kubeadm 的默认设置可能并非适用于所有人。本节介绍如何以牺牲部分易用性为代价来增强 kubeadm 安装的安全性。
关闭节点客户端证书的自动批准
默认情况下,启用了一个 CSR 自动审批程序,它基本上会批准使用引导令牌进行身份验证时 kubelet 的任何客户端证书请求。如果你不希望集群自动批准 kubelet 客户端证书,可以执行此命令将其关闭:
kubectl delete clusterrolebinding kubeadm:node-autoapprove-bootstrap
之后,kubeadm join
将阻塞,直到管理员手动批准正在进行的 CSR:
使用
kubectl get csr
,你可以看到原始 CSR 处于 Pending 状态。kubectl get csr
输出类似于:
NAME AGE REQUESTOR CONDITION node-csr-c69HXe7aYcqkS1bKmH4faEnHAWxn6i2bHZ2mD04jZyQ 18s system:bootstrap:878f07 Pending
kubectl certificate approve
允许管理员批准 CSR。此操作会告诉证书签名控制器根据 CSR 中请求的属性向请求者颁发证书。kubectl certificate approve node-csr-c69HXe7aYcqkS1bKmH4faEnHAWxn6i2bHZ2mD04jZyQ
输出类似于:
certificatesigningrequest "node-csr-c69HXe7aYcqkS1bKmH4faEnHAWxn6i2bHZ2mD04jZyQ" approved
这会将 CSR 资源更改为 Active 状态。
kubectl get csr
输出类似于:
NAME AGE REQUESTOR CONDITION node-csr-c69HXe7aYcqkS1bKmH4faEnHAWxn6i2bHZ2mD04jZyQ 1m system:bootstrap:878f07 Approved,Issued
这强制执行一个工作流程,即 kubeadm join
仅在运行了 kubectl certificate approve
后才能成功。
关闭对 cluster-info
ConfigMap 的公共访问
为了实现仅使用令牌作为验证信息的加入流程,默认情况下会公开一个 ConfigMap,其中包含验证控制平面节点身份所需的一些数据。虽然此 ConfigMap 中没有私有数据,但有些用户可能无论如何都希望将其关闭。这样做将禁用使用 kubeadm join
流程的 --discovery-token
标志的能力。以下是实现此目的的步骤:
- 从 API 服务器获取
cluster-info
文件:
kubectl -n kube-public get cm cluster-info -o jsonpath='{.data.kubeconfig}' | tee cluster-info.yaml
输出类似于:
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority-data: <ca-cert>
server: https://<ip>:<port>
name: ""
contexts: []
current-context: ""
preferences: {}
users: []
将
cluster-info.yaml
文件用作kubeadm join --discovery-file
的参数。关闭对
cluster-info
ConfigMap 的公共访问:
kubectl -n kube-public delete rolebinding kubeadm:bootstrap-signer-clusterinfo
这些命令应在运行 kubeadm init
之后但在运行 kubeadm join
之前执行。
使用配置文件进行 kubeadm join
注意
配置文件仍处于 Beta 阶段,将来版本可能会发生变化。可以使用配置文件而不是命令行标志来配置 kubeadm join
,并且一些更高级的功能可能仅作为配置文件选项可用。此文件使用 --config
标志传入,并且必须包含 JoinConfiguration
结构。在某些情况下,混合使用 --config
和其他标志可能不被允许。
默认配置可以使用 kubeadm config print 命令打印出来。
如果你的配置未在使用最新版本,建议你使用 kubeadm config migrate 命令进行迁移。
有关配置字段和用法的更多信息,你可以查阅我们的 API 参考文档。
下一步
- kubeadm init 用于引导 Kubernetes 控制平面节点。
- kubeadm token 用于管理
kubeadm join
的令牌。 - kubeadm reset 用于撤销
kubeadm init
或kubeadm join
对此主机所做的任何更改。