第64节 kubeadm概述、原理、以及部分源码阅读
❤️💕💕新时代拥抱云原生,云原生具有环境统一、按需付费、即开即用、稳定性强特点。Myblog:http://nsddd.top
[TOC]
kubeadm
我们在前面几十个小节学习中也知道了 REST API是Kubernetes的基本结构。组件和外部用户命令之间的所有操作和通信都是API服务器处理的REST API调用。因此,Kubernetes平台中的所有内容都被视为API对象,并且在API中有相应的条目。
大多数操作都可以通过kubectl
命令行界面或其他命令行工具(如kubeadm
)执行,而这些工具又使用API。不过,你也可以使用REST调用直接访问API。
Kubeadm是一个工具,它提供kubeadm init
和kubeadm join
作为创建Kubernetes集群的最佳实践“快捷路径”。
kubeadm是一个用于部署Kubernetes集群的工具。它被设计用于自动化大多数Kubernetes集群的部署任务,从而使Kubernetes集群的部署变得更加简单和高效。kubeadm负责初始化Master节点,并在节点上安装Kubernetes组件。它还可以添加Worker节点,以便将它们添加到集群中。
kubeadm执行必要的操作来启动和运行最小可行集群。按照设计,它只关心引导,而不关心配置机器。同样,安装各种漂亮的插件(比如Kubernetes Dashboard、监控解决方案和特定于云的插件)也不在讨论范围之内。
相反,我们期望在kubeadm的基础上构建更高级、更定制化的工具,理想情况下,使用kubeadm作为所有部署的基础将使创建符合规范的集群变得更容易。
kubeadm init
此命令用于初始化Kubernetes控制平面节点。
init
命令执行以下阶段:
- preflight 运行预检查
- certs:证书生成
- /ca 生成用于为其他Kubernetes组件提供身份的自签名Kubernetes CA
- /apiserver 生成用于提供Kubernetes API的证书
- /apiserver-kubelet-client 生成API服务器用于连接kubelet的证书
- /front-proxy-ca 生成用于提供前置代理身份的自签名CA
- /front-proxy-client 生成前置代理客户端证书
- /etcd-ca 生成用于为etcd提供身份的自签名CA
- /etcd-server 生成用于提供etcd服务的证书
- /etcd-peer 生成供etcd节点相互通信的证书
- /etcd-healthcheck-client 生成用于健康检查etcd的活性探针证书
- /apiserver-etcd-client 生成apiserver用于访问etcd的证书
- /sa 生成用于签署服务帐户令牌的私钥及其公钥
- kubeconfig:生成所有kubeconfig文件,以建立控制平面和管理员kubeconfig文件
- /admin 为管理员和kubeadm本身生成kubeconfig文件
- /kubelet 为kubelet生成kubeconfig文件,仅用于集群引导目的
- /controller-manager 为控制器管理器生成kubeconfig文件
- /scheduler 为调度器生成kubeconfig文件
- kubelet-start 写入kubelet设置并(重新)启动kubelet
- control-plane:生成所有静态Pod清单文件,以建立控制平面
- /apiserver 生成kube-apiserver静态Pod清单
- /controller-manager 生成kube-controller-manager静态Pod清单
- /scheduler 生成kube-scheduler静态Pod清单
- etcd:为本地etcd生成静态Pod清单文件
- /local 为本地单节点etcd实例生成静态Pod清单文件
- upload-config:将kubeadm和kubelet配置上传到ConfigMap
- /kubeadm 将kubeadm ClusterConfiguration上传到ConfigMap
- /kubelet 将kubelet组件配置上传到ConfigMap
- upload-certs 将证书上传到kubeadm-certs
- mark-control-plane 将节点标记为控制平面
- bootstrap-token 生成用于将节点加入集群的引导令牌
- kubelet-finalize:在TLS引导后更新与kubelet相关的设置
- /experimental-cert-rotation 启用kubelet客户端证书轮换
- addon:安装通过一致性测试所需的必要插件
- /coredns 将CoreDNS插件安装到Kubernetes集群
- /kube-proxy 将kube-proxy插件安装到Kubernetes集群
- show-join-command 显示控制平面和工作节点的加入命令
选项
选项 | 类型 | 说明 |
---|---|---|
--apiserver-advertise-address | string | API Server 广告其监听的 IP 地址。如果未设置,则使用默认网络接口。 |
--apiserver-bind-port | int32 | 默认值:6443。API Server绑定的端口。 |
--apiserver-cert-extra-sans | stringSlice | API Server 服务证书的可选额外主体替代名称(SAN),可以是 IP 地址和 DNS 名称。 |
--cert-dir | string | 默认值:"/etc/kubernetes/pki"。 |
--certificate-key | string | 用于加密 kubeadm-certs Secret 中的控制平面证书的密钥。 |
--config | string | kubeadm 配置文件的路径。 |
--cri-socket | string | 要连接的CRI套接字的路径。如果为空,kubeadm将尝试自动检测此值;仅在安装了多个CRI或存在非标准CRI套接字时使用此选项。 |
--dry-run | 不应用任何更改;只输出将要执行的操作。 | |
--experimental-upload-certs | 上传控制平面证书到 kubeadm-certs Secret。 | |
--feature-gates | string | 一组键值对,描述各种功能的特性门。可选项为: |
-h, --help | init 的帮助信息。 | |
--ignore-preflight-errors | stringSlice | 要将其错误显示为警告的检查列表。示例:“IsPrivilegedUser,Swap”。值“all”会忽略所有检查的错误。 |
--image-repository | string | 默认值:“http://k8s.gcr.io/”。选择一个容器注册表以拉取控制平面映像。 |
--kubernetes-version | string | 默认值:“stable-1”。为控制平面选择特定的 Kubernetes 版本。 |
--node-name | string | 指定节点名称。 |
--pod-network-cidr | string | 指定 Pod 网络的 IP 地址范围。如果设置,则控制平面将自动为每个节点分配 CIDR。 |
--service-cidr | string | 默认值:“10.96.0.0/12”。使用替代 IP 地址范围来设置服务 VIP。 |
--service-dns-domain | string | 默认值:“cluster.local”。使用替代域名为服务命名,例如“myorg.internal”。 |
--skip-certificate-key-print | 不打印用于加密控制平面证书的密钥。 | |
--skip-phases | stringSlice | 要跳过的阶段列表。 |
--skip-token-print | 跳过打印由“kubeadm init”生成的默认引导令牌。 | |
--token | string | 用于在节点和控制平面节点之间建立双向信任的令牌。格式为[a-z0-9] {6}。[a-z0-9] {16} - 例如abcdef.0123456789abcdef |
--token-ttl duration | 默认值:24h0m0s。令牌自动删除之前的持续时间(例如1s,2m,3h)。如果设置为“0”,则令牌永不过期。 |
从父命令继承的选项
选项 | 类型 | 描述 |
---|---|---|
--rootfs | string | [EXPERIMENTAL] The path to the 'real' host root filesystem. |
初始化流程
pre-flifht 检查
在执行 kubeadm init 命令之前,kubeadm 会运行一个 preflight 阶段,用于检查集群节点是否满足 Kubernetes 的最低要求。在 preflight 阶段中,kubeadm 会根据用户提供的选项来执行一系列检查,以确保 Kubernetes 控制平面的正常运行。
常用的 preflight 阶段选项包括:
- -config:指定 kubeadm 配置文件的路径;
- -cri-socket:指定容器运行时(CRI)的 socket 文件路径;
- -skip-phases:跳过 preflight 阶段中的某些检查阶段;
- -ignore-preflight-errors:忽略 preflight 阶段中的某些错误。
certificate 生成阶段
在初始化 Kubernetes 控制平面时,kubeadm 还会自动为 Kubernetes 组件生成 TLS 证书和秘钥。这些证书和秘钥用于确保 Kubernetes 组件之间的安全通信。
生成自签名CA(如果提供了,则使用现有CA),为集群中的每个组件设置标识。如果用户提供了自己的CA证书和/或密钥,并将其放入通过 --cert-dir
选项(默认值为/etc/kubernetes/pki
)配置的证书目录中。可以按照使用自定义证书文档中的描述跳过此步骤。API服务器证书拥有用于 --apiserver-cert-extra-sans
参数(必要时小写)的额外SAN条目。
生成 kubeconfig 文件
将kubeconfig文件写到/etc/kubernetes/
中,供kubelet、控制器-管理器和调度器连接API服务器,每个kubeconfig文件都有自己的标识,另外还有一个名为admin.conf
的kubeconfig文件用于管理。
pod
为API服务器、控制器管理器和调度器生成静态Pod清单。如果没有提供外部etcd,则为etcd生成额外的静态Pod清单。
静态Pod清单被写入/etc/kubernetes/manifests
;kubelet监视这个目录,以便在启动时创建pod。
一旦控制平面pod启动并运行,kubeadm init
流程就可以继续。
将标签和污染应用到控制平面节点,这样就不会在那里运行额外的工作负载。
生成令牌,额外的节点可以使用该令牌在将来向控制平面注册自己。用户可以选择通过
--token
选项提供令牌,如kubeadm token文档中所述。配置所有必要的配置,允许节点使用引导令牌和TLS引导机制加入集群:
- 编写一个ConfigMap来提供加入集群所需的所有信息,并设置相关的RBAC访问规则。
- 使引导令牌访问CSR签名API。
- 为新的CSR请求配置自动批准。
有关更多信息,请参见kubeadm join。
通过API服务器安装DNS服务器(CoreDNS)和kube-proxy插件组件。在Kubernetes v1.11和更高版本中,CoreDNS是默认的DNS服务器。如果你要安装kube-dns而不是CoreDNS,必须在kubeadm
ClusterConfiguration
配置DNS插件。
使用kubeadm的初始化阶段
Kubeadm允许你分阶段创建一个控制平面节点。在v1.13中,kubeadm init phase
命令已经从alpha级别的kubeadm alpha phase
升级到了GA级别。
要查看有序的阶段和子阶段列表,可以调用kubeadm init --help
。列表将位于帮助信息的顶部,每个阶段旁边都有一个描述。注意,通过调用kubeadm init
,所有阶段和子阶段都将按照这个顺序执行。
有些阶段有独特的选项,如果你想查看可用的选项列表,请添加--help
,例如:
sudo kubeadm init phase control-plane controller-manager --help
你还可以使用--help
查看特定父阶段的子阶段列表:
sudo kubeadm init phase control-plane --help
kubeadm init
还暴露了一个名为--skip-phase
的选项,该选项可用于跳过某些阶段。该选项接受一个阶段名称列表,这些名称可以从上面的有序列表中获取。
sudo kubeadm init phase control-plane all --config=configfile.yaml
sudo kubeadm init phase etcd local --config=configfile.yaml
# you can now modify the control plane and etcd manifest files
sudo kubeadm init --skip-phases=control-plane,etcd --config=configfile.yaml
sudo kubeadm init phase control-plane all --config=configfile.yaml
sudo kubeadm init phase etcd local --config=configfile.yaml
# you can now modify the control plane and etcd manifest files
sudo kubeadm init --skip-phases=control-plane,etcd --config=configfile.yaml
该示例将编写基于configfile.yaml
中的配置,位于/etc/kubernetes/manifests
中的清单文件。这允许你修改文件,然后使用--skip-phases
选项跳过这些阶段。通过调用最后一个命令,你将创建一个带有自定义清单文件的控制平面节点。
为kubeadm init指定配置文件
可以用配置文件而不是命令行选项来配置kubeadm init
,一些更高级的特性可能只作为配置文件选项使用。该文件通过 --config
选项传递。
可以使用自定义镜像
默认情况下,kubeadm从 k8s.gcr.io
中拉取镜像,除非请求的Kubernetes版本是CI版本,这种情况下,将使用 gcr.io/kubernetes-ci-images
。
这种情况下在国内可能会出现拉取 over time
你可以向kubeadm指定一个配置文件覆盖此行为。允许自定义有:
- 提供一个替代
k8s.gcr.io
的imageRepository
。 - 将
useHyperKubeImage
设置为true
以使用HyperKube图像。 - 为etcd或DNS插件提供特定的
imageRepository
和imageTag
。
请注意,配置字段kubernetesVersion
和命令行选项 --kubernetes-version
都会影响镜像的版本。
使用自定义证书
默认情况下,kubeadm生成集群运行所需的所有证书。你也可以通过提供自己的证书来覆盖此行为。
为此,你必须将它们放在由 --cert-dir
选项或 CertificatesDir
配置文件键指定的目录中。默认情况下,该目录为/etc/kubernetes/pki
。
如果存在给定的证书和私钥对,kubeadm将跳过生成步骤,使用现有文件。例如,这意味着你可以将现有的CA复制到 /etc/kubernetes/pki/ca.crt
和 /etc/kubernetes/pki/ca.key
,kubeadm将使用此CA签署其余的证书。
外部CA模式
也可以只提供ca.crt
文件,而不提供ca.key
文件(这只适用于根CA文件,不适用于其他证书对)。如果所有其他证书和kubeconfig文件都到位,kubeadm将识别此条件并激活“外部CA”模式。kubeadm将在磁盘上没有CA密钥的情况下继续执行。
相反,使用 --controllers=csrsigner
独立运行控制器管理器,并指向CA证书和密钥。
指定 CRI
从v1.6.0开始,Kubernetes就默认启用了CRI容器运行时接口。默认情况下使用的容器运行时是Docker,它是通过kubelet
内置的dockershim
CRI启用的。
从 Kubernetes 1.20 开始,默认容器运行时为 containerd
,而之前的版本默认容器运行时为 Docker
。
成功安装kubeadm
和kubelet
之后,执行以下两个额外步骤:
按照上面运行时shim项目清单中的安装文档,在每个节点上安装运行时shim。
配置kubelet使用远程CRI运行时。请记住将
RUNTIME_ENDPOINT
更改为你自己的值,比如/var/run/{your_runtime}.sock
:cat > /etc/systemd/system/kubelet.service.d/20-cri.conf <<EOF[Service]Environment="KUBELET_EXTRA_ARGS=--container-runtime=remote --container-runtime-endpoint=$RUNTIME_ENDPOINT"EOFsystemctl daemon-reload
现在kubelet
已经准备好使用指定的CRI运行时,可以继续使用kubeadm init
和kubeadm join
来部署Kubernetes集群。
在使用外部CRI实现时,请将在执行 kubeadm init
和kubeadm reset
时添加 --cri-socket
选项。
离线运行 kubeadm
要在没有互联网连接的情况下运行kubeadm,你必须预先拉取所需的控制平面镜像。
在Kubernetes v1.11和更高版本中,你可以使用 kubeadm config images
的子命令获取和拉取镜像:
❯ ./kubeadm config images list
W0319 15:08:46.559718 50461 version.go:112] could not obtain neither client nor remote version; fall back to: 1.0.0-placeholder-version
W0319 15:08:46.561620 50461 images.go:80] could not find officially supported version of etcd for Kubernetes v1.0.0-placeholder-version, falling back
to the nearest etcd version (3.2.24)
registry.k8s.io/kube-apiserver:v1.0.0-placeholder-version
registry.k8s.io/kube-controller-manager:v1.0.0-placeholder-version
registry.k8s.io/kube-scheduler:v1.0.0-placeholder-version
registry.k8s.io/kube-proxy:v1.0.0-placeholder-version
registry.k8s.io/pause:3.9
registry.k8s.io/etcd:3.2.24
registry.k8s.io/coredns/coredns:v1.10.1
拉取:
kubeadm config images pull
kubeadm join
该命令初始化Kubernetes工作节点并将其加入到集群。在希望加入现有集群的所有机器上运行此操作。
kubeadm init
和 kubeadm join
一起提供了良好的用户体验,可以从头开始创建最佳实践的裸Kubernetes集群。然而,kubeadm是如何做到这一点的,可能并不明显。
在加入由kubeadm初始化的集群时,我们需要建立双向信任。这分为发现(让节点信任Kubernetes控制平面)和TLS引导(让Kubernetes控制平面信任节点)。
有两种主要的发现方案。第一种方法是使用共享令牌和API服务器的IP地址。第二种方法是提供一个文件——标准kubeconfig文件的子集。该文件可以是本地文件,也可以通过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包验证连接。
命令阶段
join [api-server-endpoint]
命令执行以下阶段:
The "join [api-server-endpoint]" command executes the following phases:
```
preflight Run join pre-flight checks
control-plane-prepare Prepare the machine for serving a control plane
/download-certs [EXPERIMENTAL] 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
/update-status Register the new control-plane node into the ClusterStatus maintained in the kubeadm-config ConfigMap (DEPRECATED)
/mark-control-plane Mark a node as a control-plane
preflight
:运行加入前检查control-plane-prepare
:准备机器以服务于控制平面/download-certs
:[实验性] 从 kubeadm-certs Secret 下载控制平面节点间共享的证书/certs
:为新的控制平面组件生成证书/kubeconfig
:为新的控制平面组件生成 kubeconfig/control-plane
:为新的控制平面组件生成清单
kubelet-start
:编写 kubelet 设置,证书并启动 kubeletcontrol-plane-join
:将机器作为控制平面实例加入/etcd
:添加一个新的本地 etcd 成员/update-status
:将新的控制平面节点注册到维护在 kubeadm-config ConfigMap 中的 ClusterStatus 中 (已弃用)/mark-control-plane
:将节点标记为控制平面节点
选项
选项 | 类型 | 描述 |
---|---|---|
--apiserver-advertise-address | string | 如果节点应该托管新的控制平面实例,则是 API 服务器将广告它正在侦听的 IP 地址。如果未设置,将使用默认网络接口。 |
--apiserver-bind-port | int32 | 默认值:6443。如果节点应该托管新的控制平面实例,则是 API 服务器绑定的端口。 |
--certificate-key | string | 使用此密钥解密由 init 上传的证书密钥。 |
--config | string | kubeadm 配置文件的路径。 |
--cri-socket | string | 连接的 CRI 套接字的路径。如果为空,kubeadm 将尝试自动检测此值。仅在安装了多个 CRI 或具有非标准 CRI 套接字时使用此选项。 |
--discovery-file | string | 对于基于文件的发现,要从中加载群集信息的文件或 URL。 |
--discovery-token | string | 对于基于令牌的发现,用于验证从 API 服务器获取的群集信息的令牌。 |
--discovery-token-ca-cert-hash | stringSlice | 对于基于令牌的发现,验证根 CA 公钥是否与此哈希值匹配(格式:“ : ”)。 |
--discovery-token-unsafe-skip-ca-verification | 对于基于令牌的发现,允许加入而不使用 --discovery-token-ca-cert-hash 固定。 | |
--experimental-control-plane | 在此节点上创建新的控制平面实例。 | |
-h , --help | join 的帮助信息 | |
--ignore-preflight-errors | stringSlice | 显示为警告的检查列表的错误。示例:“IsPrivilegedUser,Swap”。值“all”会忽略所有检查的错误。 |
--node-name | string | 指定节点名称。 |
--skip-phases | stringSlice | 要跳过的阶段列表。 |
--tls-bootstrap-token | string | 在加入节点时,指定用于临时身份验证 Kubernetes 控制平面的令牌。 |
--token | string | 在未提供 discovery-token 和 tls-bootstrap-token 时使用此令牌。 |
加入流程
kubeadm join
引导Kubernetes工作节点或控制平面节点,并将其添加到集群中。对于工作节点,该操作包括以下步骤:
kubeadm从API服务器下载必要的集群信息。默认情况下,它使用引导令牌和CA密钥的哈希值来验证数据的真实性。根CA也可以通过文件或URL直接获取。
一旦获取了集群信息,kubelet就可以启动TLS引导流程。
TLS引导使用共享令牌与Kubernetes API服务器进行临时认证,提交证书签名请求(CSR);默认情况下,控制平面自动签署此CSR请求。
最后,kubeadm将本地kubelet配置为使用分配给节点的最终标识连接到API服务器。
对于控制平面节点,还要执行额外的步骤:
- 从集群中下载控制平面节点之间共享的证书(如果用户显式地请求)。
- 生成控制平面组件清单、证书和kubeconfig。
- 添加新的本地etcd成员。
- 将此节点添加到kubeadm集群的ClusterStatus中。
使用kubeadm的加入阶段
Kubeadm允许你分阶段将节点加入到集群。kubeadm join phase
命令是在v1.14.0中添加的。
要查看阶段的有序列表和子阶段列表,可以调用kubeadm join --help
。列表将位于帮助的顶部,每个阶段旁边都有一个描述。注意,通过调用kubeadm join
,所有阶段和子阶段都将按照这个顺序执行。
有些阶段有独特的选项,所以如果你想查看可用的选项列表,请添加--help
,例如:
kubeadm join phase kubelet-start --help
与kubeadm init phase
命令类似,kubadm join phase
允许你使用--skip-phase
选项跳过某些阶段。
例如:
sudo kubeadm join --skip-phases=preflight --config=config.yaml
kubeadm upgrade
kubeadm upgrade
是一个用户友好的命令,它将复杂的升级逻辑封装在一个命令后面,支持计划升级和实际执行升级。
如果需要,kubeadm upgrade
还可以用于降级集群。
检查可以升级到哪些版本,并验证当前集群是否可以升级。要跳过internet检查,请传入可选[version]
参数。
❯ ./kubeadm upgrade
Upgrade your cluster smoothly to a newer version with this command
Usage:
kubeadm upgrade [flags]
kubeadm upgrade [command]
Available Commands:
apply Upgrade your Kubernetes cluster to the specified version
diff Show what differences would be applied to existing static pod manifests. See also: kubeadm upgrade apply --dry-run
node Upgrade commands for a node in the cluster
plan Check which versions are available to upgrade to and validate whether your current cluster is upgradeable. To skip the internet check, pass in the optional [version] parameter
kubeadm config
从v1.8.0开始,kubeadm将集群的配置上传到kube-system
名称空间中名为kubeadm-config
的ConfigMap,然后在升级时读取ConfigMap。这支持正确配置系统组件,并提供了无缝的用户体验。
你可以执行kubeadm config view
来查看ConfigMap。如果使用kubeadm v1.7初始化集群。在使用kubeadm upgrade
之前,必须使用kubeadm config upload
创建ConfigMap。
在Kubernetes v1.11.0中,添加了一些新命令。你可以使用kubeadm config print-default
来打印默认配置,而kubeadm config migrate
可以将旧的配置文件转换为新版本。kubeadm config images list
和kubeadm config images pull
可用于列出和拉取kubeadm所需的镜像。
在 Kubernetes v1.13.0
以及以后的版本中,如果要列出/拉出的是kube-dns镜像,而不是CoreDNS镜像,则必须使用这里描述的--config
方式。
❯ kubeadm config upload --help
There is a ConfigMap in the kube-system namespace called "kubeadm-config" that kubeadm uses to store internal configuration about the
cluster. kubeadm CLI v1.8.0+ automatically creates this ConfigMap with the config used with 'kubeadm init', but if you
initialized your cluster using kubeadm v1.7.x or lower, you must use the 'config upload' command to create this
ConfigMap. This is required so that 'kubeadm upgrade' can configure your upgraded cluster correctly.
Usage:
kubeadm config [flags]
kubeadm config [command]
Available Commands:
images Interact with container images used by kubeadm
migrate Read an older version of the kubeadm configuration API types from a file, and output the similar config object for the newer version
print Print configuration
Flags:
-h, --help help for config
--kubeconfig string The kubeconfig file to use when talking to the cluster. If the flag is not set, a set of standard locations can be searched for an existing kubeconfig file. (default "/etc/kubernetes/admin.conf")
Global Flags:
--add-dir-header If true, adds the file directory to the header of the log messages
--log-file string If non-empty, use this log file
--log-file-max-size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
--one-output If true, only write logs to their native severity level (vs also writing to each lower severity level)
--rootfs string [EXPERIMENTAL] The path to the 'real' host root filesystem.
--skip-headers If true, avoid header prefixes in the log messages
--skip-log-headers If true, avoid headers when opening log files
-v, --v Level number for the log level verbosity
kubeadm config upload from-file
上传一个配置文件到集群内的ConfigMap,用于kubeadm配置。
使用这个命令,你可以使用提供给kubeadm init
的相同配置文件将配置上传到集群中的ConfigMap。如果使用v1.7初始化集群。在使用kubeadm upgrade
升级到v1.8之前,你需要使用相同的配置文件运行这个命令。
配置位于kube-system
命名空间中的kubeadm-config
ConfigMap中。
kubeadm config upload from-file [flags]
kubeadm config upload from-file --help
查看支持的 flages
kubeadm config view
使用这个命令,你可以在kubeadm配置所在的集群中查看ConfigMap。
配置位于kube-system
命名空间中的kubeadm-config
ConfigMap中。
kubeadm config view [flags]
kubeadm reset
此命令将还原kubeadm init
和kubeadm join
所做的任何更改。
运行此命令,以恢复 kubeadm init
和 kubeadm join
对该主机所做的任何更改。
kubeadm reset
清理外部etcd
如果使用外部etcd, kubeadm reset
不会删除任何etcd数据。这意味着,如果再次使用相同的etcd端点运行kubeadm init
,您将看到以前集群的状态。
要擦除etcd数据,建议使用etcdctl这样的客户端,例如:
etcdctl del "" --prefix
kubeadm token
引导令牌用于在连接集群的节点和控制平面节点之间建立双向信任,如使用引导令牌进行认证中所述。
kubeadm init
使用24小时TTL创建初始令牌。下面的命令可以管理该令牌,并创建和管理新的令牌。
kubeadm token create
在服务器上创建引导令牌。
kubeadm token create [token]
这个命令将为您创建一个 引导令牌。你可以指定此令牌的用法、“生存时间”和可选的人性化描述。
[token]
是要写的实际令牌。这应该是一个安全生成的随机令牌形式[a-z0-9]{6}.[a-z0-9]{16}
。如果没有给出[token]
,则kubeadm将生成一个随机令牌。
所以所 引导令牌是和 kueadme 对应的:
❯ kubeadm token create qg8u0m.g31qk96l34ns9gz4 ❯ kubectl get secrets -A | grep -i qg8u0m kube-system bootstrap-token-qg8u0m bootstrap.kubernetes.io/token 6 2m10s
kubeadm token delete
删除服务器上的引导令牌。
kubeadm token delete [token-value]
例如:
❯ kubeadm token delete qg8u0m
bootstrap token "qg8u0m" deleted
❯ kubeadm token list
kubeadm token generate
生成并打印引导令牌,但不要在服务器上创建它。
这个命令将输出一个随机生成的引导令牌,可以与init
和join
命令一起使用。
你不必使用此命令来生成令牌。只要格式是[a-z0-9]{6}.[a-z0-9]{16}
,你出可以自己生成。提供此命令是为了方便以给定格式生成令牌。
你还可以使用kubeadm init
而无需指定令牌,它将为你生成并打印一个令牌。
kubeadm token generate [flags]
kubeadm token list
列出服务器上的引导令牌。
kubeadm version
这个命令打印kubeadm的版本。
kubeadm alpha
Kubeadm alpha命令是Kubeadm工具中的一个实验性功能,用于启用Kubernetes集群的某些高级功能。在Kubeadm alpha命令中,用户可以使用各种参数和标志来配置所需的功能并启动Kubernetes集群。
kubeadm alpha certs renew
你可以使用all
子命令更新所有Kubernetes证书,或者有选择地更新它们。
renew
更新Kubernetes集群的证书。
all
更新所有可用证书。
更新运行控制平面所需的所有已知证书。无论过期日期如何,都会无条件地运行续订。为了获得更多的控制,还可以单独运行续订。
kubeadm alpha certs renew all [flags]
kubeadm alpha kubeconfig user
user
子命令可用于为其他用户创建kubeconfig文件。
kubeadm init phase
在v1.8.0中,kubeadm引入了kubeadm alpha phase
命令,目的是使kubeadm更加模块化。在v1.13.0中,这个命令逐渐过渡到kubeadm init phase
。这种模块化使你能够调用引导过程的原子子步骤。因此,你可以让kubeadm完成某些部分,并在需要自定义的地方进行填充。
kubeadm init phase
与kubeadm init
工作流程是一致的,并且两者都使用相同的代码。
kubeadm join phase
在v1.14.0中,kubeadm引入了kubeadm join phase
命令,目的是使kubeadm更加模块化。这种模块化使你能够调用加入(join)过程的原子子步骤。因此,你可以让kubeadm完成某些部分,并在需要自定义的地方进行填充。
kubeadm join phase
与kubeadm join
工作流程是一致的,并且在后台两者都使用相同的代码。
细节
kubeadm 围绕着 init 和 join 为主体开展的。
kubeadm init
和kubeadm join
所建立的集群应该是:
安全的:
它应该采用最新的最佳实践,如:
- 强制执行RBAC
- 使用节点授权器
- 使用控制平面组件之间的安全通信
- 使用API服务器和kubelet之间的安全通信
- 锁定kubelet API
- 锁定对kube-proxy和CoreDNS等系统组件的API访问
- 锁定引导令牌可以访问的内容
- 等待
易用的:
用户运行的两个命令不应该超两个:
kubeadm init
export KUBECONFIG=/etc/kubernetes/admin.conf
kubectl apply -f <network-of-choice.yaml>
kubeadm join --token <token> <master-ip>:<master-port>
可扩展的:
- 例如,它应该不支持所有网络提供者,相反,配置网络已超出了范围
- 应该提供使用配置文件定制各种参数的可能性
常量和著名的值与路径
为了降低复杂性并简化基于kubeadm实现的部署解决方案的开发,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
(bootstrap-kubelet.conf
在TLS引导期间)controller-manager.conf
scheduler.conf
admin.conf
用于集群管理员和kubeadm自己
- 证书和密钥文件名称:
ca.crt
、ca.key
用于Kubernetes证书授权apiserver.crt
、apiserver.key
用于API服务器证书apiserver-kubelet-client.crt
、apiserver-kubelet-client.key
作为API服务器的客户端证书用于连接安全地连接kubeletsa.pub
、sa.key
在签名ServiceAccount
时,作为控制器管理器的密钥front-proxy-ca.crt
、front-proxy-ca.key
用于前端代理证书授权front-proxy-client.crt
、front-proxy-client.key
用于前端代理客户端
kubeadm初始化流程的内部设计
kubeadm init
内部流程(第二个段落标题)由一系列要执行的原子工作任务组成,如kubeadm init
中所述。
kubeadm init phase
命令允许用户分别调用每个任务,并最终提供一个可重用和可组合的API/工具箱,其他Kubernetes引导工具、任何IT自动化工具或高级用户都可以使用该API/工具箱创建自定义集群。
预检查(preflight)
Kubeadm在启动 init 之前执行一组预先检查,目的是验证先决条件并避免常见的集群启动问题。在任何情况下,用户都可以使用--ignore-preflight-errors
选项跳过特定的预先检查(或者最终跳过所有的预先检查)。
- [警告]如果要使用的Kubernetes版本(使用
--kubernetes-version
选项指定)至少比kubeadm CLI版本高一个次要版本。 - Kubernetes系统要求:
- 如果运行在linux上:
- [错误]如果不是拥有特定KernelSpec的内核3.10+或4
- [错误]如果需要的cgroups子系统没有建立
- 如果使用docker:
- [警告/错误]如果Docker服务不存在,如果它被禁用,如果它不是活动的。
- [错误]如果Docker端点不存在或不工作
- [警告]如果docker版本>17.03
- 如果使用其它CRI引擎:
- [错误]如果crictl套接字没有应答
- 如果运行在linux上:
- [错误]如果用户不是root
- [错误]如果机器主机名不是有效的DNS子域名
- [警告]如果无法通过网络查找访问主机名
- [错误]如果kubelet版本低于kubeadm支持的最小kubelet版本(当前次要版本 - 1)
- [错误]如果kubelet版本比所需的控制平面版本(不支持的版本倾斜)高至少一个次要版本
- [警告]如果kubelet服务不存在或被禁用
- [警告]如果firewalld是活动的
- [错误]如果API服务器bindPort或端口使用的是
10250/10251/10252
- [错误]如果
/etc/kubernetes/manifest
文件夹已经存在且不是空的 - [错误]如果
/proc/sys/net/bridge/bridge-nf-call-iptables
文件不存在或不包含1 - [错误]如果advertise地址是ipv6,
/proc/sys/net/bridge/bridge-nf-call-ip6tables
不存在或不包含1。 - [错误]如果swap是打开的
- [错误]如果命令路径中不存在
ip
、iptables
、mount
、nsenter
命令 - [警告]如果命令路径中没有
ebtables
、ethtool
、socat
、tc
、touch
、crictl
命令 - [警告]如果API服务器、控制器管理器、调度器的额外参数包含一些无效选项
- [警告]如果通过代理连接到https://API.AdvertiseAddress:API.BindPort
- [警告]如果通过代理连接到服务子网(仅选中第一个地址)
- [警告]如果通过代理连接到Pod子网(仅选中第一个地址)
- 如果提供外部etcd:
- [错误]如果etcd版本小于3.0.14
- [错误]如果指定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
,则集群IP为10.96.0.1
) - Kubernetes DNS名称;例如:如果指定
--service-dns-domain
为cluster.local
,则DNS名称为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
组织中用于签名服务账户令牌的私钥,并保存至
sa.key
文件及其公钥文件sa.pub
用于前端代理授权的证书,并保存至
front-proxy-ca.crt
文件及其密钥文件yfront-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识别这种情况并激活外部CA模式,这也意味着在控制器管理器的csrsigner
控制器不会启动。 - 如果kubeadm在外部CA模式下运行;所有证书都必须由用户提供,因为kubeadm不能自己生成证书。
- 在kubeadm以
--dry-run
模式执行时,证书文件被写入一个临时文件夹。 - 可以使用
kubeadm init phase certs all
命令单独调用证书生成。
为控制平面组件生成kubeconfig文件
带有控制平面组件标识的Kubeadm kubeconfig文件:
一个kubeconfig文件,供kubelet使用,
/etc/kubernetes/kubelet.conf
;在这个文件中嵌入了一个带有kubelet标识的客户端证书。此客户证书应该:
- 在
system:nodes
组织中,根据节点授权模块的要求 - CN为
system:node:<hostname-lowercased>
- 在
一个kubeconfig文件,供控制器管理器使用,
/etc/kubernetes/controller-manager.conf
;在这个文件中嵌入了一个带有控制器管理器标识的客户端证书。这个客户端证书的CN应该为system:kube-controller-manager
,这是由默认的RBAC核心组件角色定义的一个kubeconfig文件,供调度器使用,
/etc/kubernetes/scheduler.conf
;在这个文件中嵌入了一个带有调度器标识的客户端证书。这个客户端证书CN应该为system:kube-scheduler
,这是由默认的RBAC核心组件角色定义的
此外,还生成一个kubeadm自身和管理员使用的kubeconfig文件,并将其保存到/etc/kubernetes/admin.conf
文件中。这里的admin
定义了管理集群并希望完全控制(root)集群的实际人员。用于admin
的嵌入式客户端证书应该:
- 在
system:masters
组织中,如默认的RBAC用户面向角色绑定所定义的那样 - 包含一个CN,但它可以是任何值。Kubeadm使用CN
kubernetes-admin
请注意:
ca.crt
证书被嵌入到所有kubeconfig文件中。- 如果存在一个给定的kubeconfig文件,并且它的内容符合上面的规范,那么将使用现有的文件,并且跳过给定kubeconfig的生成阶段。
- 如果kubeadm在外部CA模式下运行,那么用户还必须提供所有必需的kubeconfig,因为kubeadm本身不能生成任何kubeonfig
- 在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都有
scheduler.alpha.kubernetes.io/critical-pod
注解(这将转移到适当的解决方案,即在就绪时使用Pod优先级和抢占)hostNetwork: true
设置在所有静态pod上,允许在配置网络之前启动控制平面;结果:
- 控制器管理器和调度器用来引用API服务器的
address
是127.0.0.1
- 如果使用本地etcd服务器,
etcd-servers
地址将被设置为127.0.0.1:2379
- 控制器管理器和调度器用来引用API服务器的
控制器管理器和调度器都启用了选主功能
控制器管理器和调度器将使用各自的惟一标识引用kubeconfig文件
所有静态pod获取用户指定的所有额外选项,如向控制平面传递自定义选项中所述
所有静态pod获取用户(
hostPath
)指定的所有额外卷
请注意:
- 所有的镜像,对于
--kubernetes-version
或当前架构,将从k8s.gcr.io
拉取。如果指定了替代镜像仓库或CI镜像仓库,则使用此仓库;如果所有控制平面组件都应该使用特定的容器镜像,则将使用此镜像。有关详细信息,请参见使用自定义镜像 - 在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-proxy)--requestheader-client-ca-file
为front-proxy-ca.crt
--enable-admission-plugins
为:
NamespaceLifecycle
避免删除系统保留的命名空间LimitRanger
和ResourceQuota
执行命名空间限制ServiceAccount
执行服务账户自动化PersistentVolumeLabel
将地区(region)或区域(zone)标签附加到云提供商定义的持久卷上(不推荐使用此准入控制器,并将在将来的版本中删除)。在默认情况下,当不明确选择使用gce
或aws
作为云提供商时,在v1.9以上版本中,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
为-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
控制器管理器
API服务器的静态Pod清单受用户提供的参数影响:
如果调用kubeadm时指定了
--pod-network-cidr
,则通过设置以下选项可以启用某些CNI网络插件所需的子网管理器特性:
--allocate-node-cidrs=true
--cluster-cidr
和--node-cidr-mask-size
选项(根据指定的CIDR)- 如果指定了云提供商,则配置相应的
--cloud-provider
,如果存在--cloud-config
路径(这是实验性的、alpha级别,将在未来版本中删除)
其他无条件设置的选项有:
--controllers
为TLS引导启用所有默认控制器以及BootstrapSigner
和TokenCleaner
控制器。有关详细信息,请参见TLS引导--use-service-account-credentials
为true
- 使用前面步骤生成的证书的选项:
--root-ca-file
为ca.crt
--cluster-signing-cert-file
为ca.crt
,如果禁用了外部CA模式,则设置为""
--cluster-signing-key-file
为ca.key
,如果禁用了外部CA模式,则设置为""
--service-account-private-key-file
为sa.key
调度器
调度器的静态Pod清单不受用户提供的参数的影响。
为本地etcd生成静态Pod清单
如果用户指定了一个外部etcd,则跳过此步骤,否则kubeadm将生成一个静态Pod清单文件,用于创建在Pod中运行的本地etcd实例,该实例具有以下属性:
- 在
localhost:2379
上进行监听并使用HostNetwork=true
- 将
hostPath
从dataDir
挂载到主机的文件系统 - 用户指定的任何额外选项
请注意:
- etcd镜像将从
k8.gcr.io
中拉取。如果指定了另一个镜像仓库,则使用此镜像仓库;如果指定了其他镜像名称,则将使用此镜像名称。有关详细信息,请参见使用自定义镜像 - 在kubeadm以
--dry-run
模式执行时,静态Pod文件被写入一个临时文件夹 - 本地etcd的静态Pod清单生成可以使用
kubeadm init phase etcd local
命令单独调用
可选的动态Kublet配置
要使用此功能,请调用 kubeadm alpha kubelet config enable-dynamic
。它将kubelet初始化配置写入 /var/lib/kubelet/config/init/kubelet
文件。
初始化配置用于在此特定节点上启动kubelet,为kubelet的drop-in文件提供了另一种选择;这些配置将被kubelet基本配置所替代,如下面的步骤所述。有关更多信息,请参见通过配置文件设置Kubelet参数。
请注意:
- 要使动态kubelet配置工作,
--dynamic-config-dir=/var/lib/kubelet/config/dynamic
应该在/etc/systemd/system/kubelet.service.d/10-kubeadm.conf
中指定 - 使用配置文件
--config some-file.yaml
向kubeadm init
或kubeadm join
传递一个KubeletConfiguration
对象,可以更改kubelet配置。可以使用---
分隔符将KubeletConfiguration
对象与其他对象(如InitConfiguration
)分隔开。有关更多细节,请查看kubeadm config print-default
命令。
等待控制平面启动
这是kubeadm集群的关键时刻。kubeadm将等待localhost:6443/healthz
返回ok
,但是为了检测死锁条件,如果localhost:10255/healthz
(kubelet存活)或localhost:10255/healthz/syncloop
(kubelet就绪)在40秒和60秒后都没有返回ok
,则kubeadm将快速失败。
kubeadm依赖于kubelet来拉取控制平面镜像,并将其作为静态pod正常运行。控制平面启动后,kubeadm将完成以如下段落中描述的任务。
(在v1.9中为可选的alpha级别)写入kubelet基本配置
如果使用 --feature-gates=DynamicKubeletConfig
调用kubeadm:
- 将kubelet基本配置写入
kube-system
命名空间中的kubelet-base-config-v1.9
ConfigMap - 创建RBAC规则,授予对所有引导令牌和所有kubelet实例(即
system:bootstrappers:kubeadm:default-node-token
和system:nodes
组)的ConfigMap的读访问权 - 通过
Node.spec.configSource
指向新创建的ConfigMap,为初始控制平面节点启用动态kubelet配置特性。
将kubeadm集群配置保存在ConfigMap中,供以后使用
kubeadm将通过选项或配置文件传递给kubeadm init
的配置保存在kube-system
命名空间中名为kubeadm-config
的ConfigMap中。
这将确保将来执行kubeadm操作(如:kubeadm upgrade
)将能够确定实际/当前集群状态,并基于该数据做出新的决策。
请注意:
- 在上传之前,敏感信息,例如令牌,将从配置中删除
- 可以使用
kubeadm init phase upload-config
命令单独调用主节点配置的上传 - 如果使用kubeadm v1.7初始化集群。在升级到v1.8之前,你必须手动创建主节点配置ConfigMap。为了简化这一任务,实现了
kubeadm config upload (from-flags|from-file)
标记主节点
一旦控制平面可用,kubeadm就会执行以下操作:
- 为主节点添加
node-role.kubernetes.io/master=""
标签 - 为主节点添加
node-role.kubernetes.io/master:NoSchedule
污染
请注意:
- 可以使用
kubeadm init phase mark-control-plane
命令单独调用标记控制平面阶段
配置TLS引导用于节点加入集群
Kubeadm使用引导令牌进行认证,将新节点连接到现有集群;有关更多细节,请参见设计提案。
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
的集群角色绑定来实现的。
为新的引导令牌设置自动批准
Kubeadm确保引导令牌将由csrapprover
控制器自动批准其CSR请求。
这是通过在system:bootstrappers:kubeadm:default-node-token
组和默认角色 system:certificates.k8s.io:certificatesigningrequests:nodeclient
之间创建一个名为 kubeadm:node-autoapprove-bootstrap
的集群角色绑定来实现的。
应该也创建了 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
的集群角色绑定来实现的。
创建公共cluster-info ConfigMap
这个阶段在kube-public
命名空间中创建cluster-info
ConfigMap。
此外,它还创建了一个角色和一个角色绑定,授予未经认证的用户(即 system:unauthenticated
组中的用户)访问该ConfigMap的权限。
请注意:
- 对
cluster-info
ConfigMap的访问不受速率限制。如果你把你的主节点暴露在互联网上,这可能是个问题,也可能不是;最坏的情况是DoS攻击,攻击者使用API服务器能够处理的所有正在运行的请求来访问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 - 主节点的位置来自ConfigMap
kube-proxy
ServiceAccount绑定到system:node-proxier
ClusterRole中的特权
DNS
请注意:
- CoreDNS服务被命名为
kube-dns
。这样做是为了防止当用户将集群DNS从kube-dns切换到CoreDNS(反之亦然)时服务中的任何中断 - 在Kubernetes v1.10或更早的版本中,必须使用
--feature-gates=CoreDNS=true
启用CoreDNS - 在Kubernetes v1.11和v1.12版本中,CoreDNS是默认的DNS服务器,必须使用
--feature-gates=CoreDNS=false
调用kubeadm来安装kube-dns - 在Kubernetes v1.13及更高版本中,CoreDNS特性开关不再可用,可以使用这里描述的
--config
方法安装kube-dns
在kube-system
命名空间中创建了一个用于CoreDNS或kube-dns的ServiceAccount。
部署kube-dns
部署和服务:
- 这是相对未经修改的上游核心部署
kube-dns
服务帐户绑定到system:kube-dns
ClusterRole的特权
可选的自托管
要在现有的静态Pod控制平面上启用自托管,请使用kubeadm alpha selfhosting pivot
。
自托管基本上用DaemonSet替换了用于控制平面组件的pod吊舱;这是通过对API服务器、调度器和控制器管理器静态吊舱执行以下步骤实现的:
- 从磁盘加载静态Pod规约
- 从静态Pod清单文件中提取PodSpec
- 修改PodSpec使之与自托管兼容,更多细节:
- 添加节点选择器属性,定向至拥有
node-role.kubernetes.io/master=""
标签的节点 - 添加
node-role.kubernetes.io/master:NoSchedule
污染的容忍 - 将
spec.DNSPolicy
设置为ClusterFirstWithHostNet
- 添加节点选择器属性,定向至拥有
- 使用上面提到的PodSpec,为自托管组件构建一个新的DaemonSet对象。
- 在
kube-system
命名空间中创建DaemonSet资源,并等待pod开始运行。 - 删除静态Pod清单文件。kubelet将停止原来运行的静态pod托管组件
请注意,自托管尚未恢复到节点重启;这可以通过外部检查点或控制平面pod的kubelet检查点来修复。有关更多细节,请参见自托管。
kubeadm join phase的内部设计
与kubeadm init
类似,kubeadm join
内部工作流程也由一系列要执行的原子工作任务组成。
这分为发现(让节点信任Kubernetes主节点)和TLS引导(让Kubernetes主节点信任该节点)。
参见使用引导令牌进行认证或相应的设计提案。
预先(preflight)检查
kubeadm
在启动加入集群之前执行一组预先检查,目的是验证先决条件并避免常见的集群启动问题。
请注意:
kubeadm join
预先检查基本上是kubeadm init
预先检查的子集- 从v1.9开始,kubeadm为CRI-generic功能提供了更好的支持;在这种情况下,为crictl跳过或替换docker特定的控件。
- 从v1.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证书经过以下验证步骤:
- 基本验证:对JWT签名使用令牌ID
- 公钥验证:使用提供的
--discovery-token-ca-cert-hash
。这个值在kubeadm init
的输出中可用,或者可以使用标准工具计算(哈希是通过Subject Public Key Info (SPKI)对象的字节计算的,如RFC7469中所示)。--discovery-token-ca-cert-hash flag
选项可以重复多次,以允许多个公钥。 - 作为附加验证,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引导(相反,直到v.1.7 TLS引导才由kubeadm管理)。
TLS引导机制使用共享令牌与Kubernetes主节点进行临时认证,为本地创建的密钥对提交证书签名请求(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
流程的配置进行管理
(在v1.9中为可选的alpha级别)写入kubelet初始化配置
如果使用 --feature-gates=DynamicKubeletConfig
调用kubeadm
:
- 使用引导令牌凭证将kubelet基本配置写入
kube-system
命名空间中的kubelet-base-config-v1.9
ConfigMap,并将其作为 kubelet初始化文件/var/lib/kubelet/config/init/kubelet
写入磁盘。 - 一旦kubelet开始使用节点自己的凭据(
/etc/kubernetes/kubelet.conf
),更新当前节点配置,指定的节点或kubelet和配置来源于上述ConfigMap。
请注意:
- 要使动态kubelet配置工作,需要在
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf
中设置--dynamic-config-dir=/var/lib/kubelet/config/dynamic
选项。
END 链接
✴️版权声明 © :本书所有内容遵循CC-BY-SA 3.0协议(署名-相同方式共享)©