第64节 kubeadm概述、原理、以及部分源码阅读


❤️💕💕新时代拥抱云原生,云原生具有环境统一、按需付费、即开即用、稳定性强特点。Myblog:http://nsddd.topopen in new window


[TOC]

kubeadm

我们在前面几十个小节学习中也知道了 REST API是Kubernetes的基本结构。组件和外部用户命令之间的所有操作和通信都是API服务器处理的REST API调用。因此,Kubernetes平台中的所有内容都被视为API对象,并且在API中有相应的条目。

大多数操作都可以通过kubectlopen in new window命令行界面或其他命令行工具(如kubeadmopen in new window)执行,而这些工具又使用API。不过,你也可以使用REST调用直接访问API。

Kubeadm是一个工具,它提供kubeadm initkubeadm join作为创建Kubernetes集群的最佳实践“快捷路径”。

kubeadm是一个用于部署Kubernetes集群的工具。它被设计用于自动化大多数Kubernetes集群的部署任务,从而使Kubernetes集群的部署变得更加简单和高效。kubeadm负责初始化Master节点,并在节点上安装Kubernetes组件。它还可以添加Worker节点,以便将它们添加到集群中。

kubeadm执行必要的操作来启动和运行最小可行集群。按照设计,它只关心引导,而不关心配置机器。同样,安装各种漂亮的插件(比如Kubernetes Dashboard、监控解决方案和特定于云的插件)也不在讨论范围之内。

相反,我们期望在kubeadm的基础上构建更高级、更定制化的工具,理想情况下,使用kubeadm作为所有部署的基础将使创建符合规范的集群变得更容易。

kubeadm init

此命令用于初始化Kubernetes控制平面节点。

init命令执行以下阶段:

  1. preflight 运行预检查
  2. 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 生成用于签署服务帐户令牌的私钥及其公钥
  3. kubeconfig:生成所有kubeconfig文件,以建立控制平面和管理员kubeconfig文件
    • /admin 为管理员和kubeadm本身生成kubeconfig文件
    • /kubelet 为kubelet生成kubeconfig文件,仅用于集群引导目的
    • /controller-manager 为控制器管理器生成kubeconfig文件
    • /scheduler 为调度器生成kubeconfig文件
  4. kubelet-start 写入kubelet设置并(重新)启动kubelet
  5. control-plane:生成所有静态Pod清单文件,以建立控制平面
    • /apiserver 生成kube-apiserver静态Pod清单
    • /controller-manager 生成kube-controller-manager静态Pod清单
    • /scheduler 生成kube-scheduler静态Pod清单
  6. etcd:为本地etcd生成静态Pod清单文件
    • /local 为本地单节点etcd实例生成静态Pod清单文件
  7. upload-config:将kubeadm和kubelet配置上传到ConfigMap
    • /kubeadm 将kubeadm ClusterConfiguration上传到ConfigMap
    • /kubelet 将kubelet组件配置上传到ConfigMap
  8. upload-certs 将证书上传到kubeadm-certs
  9. mark-control-plane 将节点标记为控制平面
  10. bootstrap-token 生成用于将节点加入集群的引导令牌
  11. kubelet-finalize:在TLS引导后更新与kubelet相关的设置
    • /experimental-cert-rotation 启用kubelet客户端证书轮换
  12. addon:安装通过一致性测试所需的必要插件
    • /coredns 将CoreDNS插件安装到Kubernetes集群
    • /kube-proxy 将kube-proxy插件安装到Kubernetes集群
  13. show-join-command 显示控制平面和工作节点的加入命令

选项

选项类型说明
--apiserver-advertise-addressstringAPI Server 广告其监听的 IP 地址。如果未设置,则使用默认网络接口。
--apiserver-bind-portint32默认值:6443。API Server绑定的端口。
--apiserver-cert-extra-sansstringSliceAPI Server 服务证书的可选额外主体替代名称(SAN),可以是 IP 地址和 DNS 名称。
--cert-dirstring默认值:"/etc/kubernetes/pki"。
--certificate-keystring用于加密 kubeadm-certs Secret 中的控制平面证书的密钥。
--configstringkubeadm 配置文件的路径。
--cri-socketstring要连接的CRI套接字的路径。如果为空,kubeadm将尝试自动检测此值;仅在安装了多个CRI或存在非标准CRI套接字时使用此选项。
--dry-run不应用任何更改;只输出将要执行的操作。
--experimental-upload-certs上传控制平面证书到 kubeadm-certs Secret。
--feature-gatesstring一组键值对,描述各种功能的特性门。可选项为:
-h, --helpinit 的帮助信息。
--ignore-preflight-errorsstringSlice要将其错误显示为警告的检查列表。示例:“IsPrivilegedUser,Swap”。值“all”会忽略所有检查的错误。
--image-repositorystring默认值:“http://k8s.gcr.io/”。选择一个容器注册表以拉取控制平面映像。
--kubernetes-versionstring默认值:“stable-1”。为控制平面选择特定的 Kubernetes 版本。
--node-namestring指定节点名称。
--pod-network-cidrstring指定 Pod 网络的 IP 地址范围。如果设置,则控制平面将自动为每个节点分配 CIDR。
--service-cidrstring默认值:“10.96.0.0/12”。使用替代 IP 地址范围来设置服务 VIP。
--service-dns-domainstring默认值:“cluster.local”。使用替代域名为服务命名,例如“myorg.internal”。
--skip-certificate-key-print不打印用于加密控制平面证书的密钥。
--skip-phasesstringSlice要跳过的阶段列表。
--skip-token-print跳过打印由“kubeadm init”生成的默认引导令牌。
--tokenstring用于在节点和控制平面节点之间建立双向信任的令牌。格式为[a-z0-9] {6}。[a-z0-9] {16} - 例如abcdef.0123456789abcdef
--token-ttl duration默认值:24h0m0s。令牌自动删除之前的持续时间(例如1s,2m,3h)。如果设置为“0”,则令牌永不过期。

从父命令继承的选项

选项类型描述
--rootfsstring[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 )配置的证书目录中。可以按照使用自定义证书open in new window文档中的描述跳过此步骤。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流程就可以继续。

  1. 将标签和污染应用到控制平面节点,这样就不会在那里运行额外的工作负载。

  2. 生成令牌,额外的节点可以使用该令牌在将来向控制平面注册自己。用户可以选择通过--token选项提供令牌,如kubeadm tokenopen in new window文档中所述。

  3. 配置所有必要的配置,允许节点使用引导令牌open in new windowTLS引导open in new window机制加入集群:

    • 编写一个ConfigMap来提供加入集群所需的所有信息,并设置相关的RBAC访问规则。
    • 使引导令牌访问CSR签名API。
    • 为新的CSR请求配置自动批准。

    有关更多信息,请参见kubeadm joinopen in new window

  4. 通过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.ioimageRepository
  • useHyperKubeImage设置为true以使用HyperKube图像。
  • 为etcd或DNS插件提供特定的imageRepositoryimageTag

请注意,配置字段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

成功安装kubeadmkubelet之后,执行以下两个额外步骤:

  1. 按照上面运行时shim项目清单中的安装文档,在每个节点上安装运行时shim。

  2. 配置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 initkubeadm join来部署Kubernetes集群。

在使用外部CRI实现时,请将在执行 kubeadm initkubeadm 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 initkubeadm join 一起提供了良好的用户体验,可以从头开始创建最佳实践的裸Kubernetes集群。然而,kubeadm是如何做到这一点的,可能并不明显。

在加入由kubeadm初始化的集群时,我们需要建立双向信任。这分为发现(让节点信任Kubernetes控制平面)和TLS引导(让Kubernetes控制平面信任节点)。

有两种主要的发现方案。第一种方法是使用共享令牌和API服务器的IP地址。第二种方法是提供一个文件——标准kubeconfig文件的子集。该文件可以是本地文件,也可以通过HTTPS URL下载。形式为kubeadm join --discovery-token abcdef.1234567890abcdef 1.2.3.4:6443kubeadm join --discovery-file path/to/file.confkubeadm 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 设置,证书并启动 kubelet
  • control-plane-join:将机器作为控制平面实例加入
    • /etcd:添加一个新的本地 etcd 成员
    • /update-status:将新的控制平面节点注册到维护在 kubeadm-config ConfigMap 中的 ClusterStatus 中 (已弃用)
    • /mark-control-plane:将节点标记为控制平面节点

选项

选项类型描述
--apiserver-advertise-addressstring如果节点应该托管新的控制平面实例,则是 API 服务器将广告它正在侦听的 IP 地址。如果未设置,将使用默认网络接口。
--apiserver-bind-portint32默认值:6443。如果节点应该托管新的控制平面实例,则是 API 服务器绑定的端口。
--certificate-keystring使用此密钥解密由 init 上传的证书密钥。
--configstringkubeadm 配置文件的路径。
--cri-socketstring连接的 CRI 套接字的路径。如果为空,kubeadm 将尝试自动检测此值。仅在安装了多个 CRI 或具有非标准 CRI 套接字时使用此选项。
--discovery-filestring对于基于文件的发现,要从中加载群集信息的文件或 URL。
--discovery-tokenstring对于基于令牌的发现,用于验证从 API 服务器获取的群集信息的令牌。
--discovery-token-ca-cert-hashstringSlice对于基于令牌的发现,验证根 CA 公钥是否与此哈希值匹配(格式:“ : ”)。
--discovery-token-unsafe-skip-ca-verification对于基于令牌的发现,允许加入而不使用 --discovery-token-ca-cert-hash 固定。
--experimental-control-plane在此节点上创建新的控制平面实例。
-h, --helpjoin 的帮助信息
--ignore-preflight-errorsstringSlice显示为警告的检查列表的错误。示例:“IsPrivilegedUser,Swap”。值“all”会忽略所有检查的错误。
--node-namestring指定节点名称。
--skip-phasesstringSlice要跳过的阶段列表。
--tls-bootstrap-tokenstring在加入节点时,指定用于临时身份验证 Kubernetes 控制平面的令牌。
--tokenstring在未提供 discovery-token 和 tls-bootstrap-token 时使用此令牌。

加入流程

kubeadm join引导Kubernetes工作节点或控制平面节点,并将其添加到集群中。对于工作节点,该操作包括以下步骤:

  1. kubeadm从API服务器下载必要的集群信息。默认情况下,它使用引导令牌和CA密钥的哈希值来验证数据的真实性。根CA也可以通过文件或URL直接获取。

  2. 一旦获取了集群信息,kubelet就可以启动TLS引导流程。

    TLS引导使用共享令牌与Kubernetes API服务器进行临时认证,提交证书签名请求(CSR);默认情况下,控制平面自动签署此CSR请求。

  3. 最后,kubeadm将本地kubelet配置为使用分配给节点的最终标识连接到API服务器。

对于控制平面节点,还要执行额外的步骤:

  1. 从集群中下载控制平面节点之间共享的证书(如果用户显式地请求)。
  2. 生成控制平面组件清单、证书和kubeconfig。
  3. 添加新的本地etcd成员。
  4. 将此节点添加到kubeadm集群的ClusterStatus中。

使用kubeadm的加入阶段

Kubeadm允许你分阶段将节点加入到集群。kubeadm join phase命令是在v1.14.0中添加的。

要查看阶段的有序列表和子阶段列表,可以调用kubeadm join --help。列表将位于帮助的顶部,每个阶段旁边都有一个描述。注意,通过调用kubeadm join,所有阶段和子阶段都将按照这个顺序执行。

有些阶段有独特的选项,所以如果你想查看可用的选项列表,请添加--help,例如:

kubeadm join phase kubelet-start --help

kubeadm init phaseopen in new window命令类似,kubadm join phaseopen in new window允许你使用--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 listkubeadm 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 initkubeadm join所做的任何更改。

运行此命令,以恢复 kubeadm initkubeadm join对该主机所做的任何更改。

kubeadm reset

清理外部etcd

如果使用外部etcd, kubeadm reset不会删除任何etcd数据。这意味着,如果再次使用相同的etcd端点运行kubeadm init,您将看到以前集群的状态。

要擦除etcd数据,建议使用etcdctl这样的客户端,例如:

etcdctl del "" --prefix

kubeadm token

引导令牌用于在连接集群的节点和控制平面节点之间建立双向信任,如使用引导令牌进行认证open in new window中所述。

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

生成并打印引导令牌,但不要在服务器上创建它。

这个命令将输出一个随机生成的引导令牌,可以与initjoin命令一起使用。

你不必使用此命令来生成令牌。只要格式是[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 phasekubeadm init工作流程open in new window是一致的,并且两者都使用相同的代码。

kubeadm join phase

在v1.14.0中,kubeadm引入了kubeadm join phase命令,目的是使kubeadm更加模块化。这种模块化使你能够调用加入(join)过程的原子子步骤。因此,你可以让kubeadm完成某些部分,并在需要自定义的地方进行填充。

kubeadm join phasekubeadm join工作流程是一致的,并且在后台两者都使用相同的代码。

细节

kubeadm 围绕着 init 和 join 为主体开展的。

kubeadm initkubeadm 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.crtca.key 用于Kubernetes证书授权
    • apiserver.crtapiserver.key 用于API服务器证书
    • apiserver-kubelet-client.crtapiserver-kubelet-client.key 作为API服务器的客户端证书用于连接安全地连接kubelet
    • sa.pubsa.key 在签名ServiceAccount时,作为控制器管理器的密钥
    • front-proxy-ca.crtfront-proxy-ca.key 用于前端代理证书授权
    • front-proxy-client.crtfront-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套接字没有应答
  • [错误]如果用户不是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是打开的
  • [错误]如果命令路径中不存在ipiptablesmountnsenter命令
  • [警告]如果命令路径中没有ebtablesethtoolsocattctouchcrictl命令
  • [警告]如果API服务器、控制器管理器、调度器的额外参数包含一些无效选项
  • [警告]如果通过代理连接到https://API.AdvertiseAddress:API.BindPortopen in new window
  • [警告]如果通过代理连接到服务子网(仅选中第一个地址)
  • [警告]如果通过代理连接到Pod子网(仅选中第一个地址)
  • 如果提供外部etcd:
    • [错误]如果etcd版本小于3.0.14
    • [错误]如果指定etcd证书或密钥,但没有提供
  • 如果没有提供外部etcd(因此将安装本地etcd):
    • [错误]如果2379端口被占用
    • [错误]如果 Etcd.DataDir文件夹已经存在并且不为空
  • 如果授权模式为ABAC:
    • [错误]如果abac_policy.json文件不存在
  • 如果授权模式是WebHook:
    • [错误]如果webhook_authz .conf文件不存在

请注意:

  1. 可以使用 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-domaincluster.local,则DNS名称为kubernetes.default.svc.cluster.local ,加上默认DNS名称: kubernetes.default.svckubernetes.defaultkubernetes
    • 节点名称
    • --apiserver-advertise-address
    • 由用户指定的其他替代名称
  • 用于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选项进行配置。

请注意:

  1. 如果一个给定的证书和私钥对都存在,并且它的内容符合上面的规范,那么将使用现有的文件,并且跳过给定证书的生成阶段。例如,这意味着用户可以将现有CA复制到/etc/kubernetes/pki/ca.{crt,key},然后kubeadm将使用这些文件来签署其余的证书。
  2. 仅对于CA,可以只提供ca.crt文件而不提供ca.key文件,如果所有其他证书和kubeconfig文件已经到位,kubeadm识别这种情况并激活外部CA模式,这也意味着在控制器管理器的csrsigner控制器不会启动。
  3. 如果kubeadm在外部CA模式open in new window下运行;所有证书都必须由用户提供,因为kubeadm不能自己生成证书。
  4. 在kubeadm以--dry-run模式执行时,证书文件被写入一个临时文件夹。
  5. 可以使用kubeadm init phase certs allopen in new window 命令单独调用证书生成。

为控制平面组件生成kubeconfig文件

带有控制平面组件标识的Kubeadm kubeconfig文件:

  • 一个kubeconfig文件,供kubelet使用,

    /etc/kubernetes/kubelet.conf
    

    ;在这个文件中嵌入了一个带有kubelet标识的客户端证书。此客户证书应该:

  • 一个kubeconfig文件,供控制器管理器使用,/etc/kubernetes/controller-manager.conf;在这个文件中嵌入了一个带有控制器管理器标识的客户端证书。这个客户端证书的CN应该为 system:kube-controller-manager,这是由默认的RBAC核心组件角色open in new window定义的

  • 一个kubeconfig文件,供调度器使用,/etc/kubernetes/scheduler.conf;在这个文件中嵌入了一个带有调度器标识的客户端证书。这个客户端证书CN应该为system:kube-scheduler,这是由默认的RBAC核心组件角色open in new window定义的

此外,还生成一个kubeadm自身和管理员使用的kubeconfig文件,并将其保存到/etc/kubernetes/admin.conf文件中。这里的admin定义了管理集群并希望完全控制(root)集群的实际人员。用于admin的嵌入式客户端证书应该:

请注意:

  1. ca.crt证书被嵌入到所有kubeconfig文件中。
  2. 如果存在一个给定的kubeconfig文件,并且它的内容符合上面的规范,那么将使用现有的文件,并且跳过给定kubeconfig的生成阶段。
  3. 如果kubeadm在外部CA模式下运行,那么用户还必须提供所有必需的kubeconfig,因为kubeadm本身不能生成任何kubeonfig
  4. 在kubeadm以--dry-run模式时,kubeconfig文件被写入一个临时文件夹。
  5. 可以使用kubeadm init phase kubeconfig allopen in new window 命令单独调用Kubeconfig文件生成。

为控制平面组件生成pod吊舱清单

Kubeadm将控制平面组件的静态Pod清单文件写入/etc/kubernetes/manifests;kubelet监控这个目录,以便在启动时创建pod。

静态Pod清单共享一组公共属性:

  • 所有静态pod都部署在kube-system命名空间中

  • 所有静态pod都有 tier:control-planecomponent:{component-name} 标签

  • 所有静态pod都有 scheduler.alpha.kubernetes.io/critical-pod注解(这将转移到适当的解决方案,即在就绪时使用Pod优先级和抢占)

  • hostNetwork: true
    

    设置在所有静态pod上,允许在配置网络之前启动控制平面;结果:

    • 控制器管理器和调度器用来引用API服务器的address127.0.0.1
    • 如果使用本地etcd服务器,etcd-servers地址将被设置为127.0.0.1:2379
  • 控制器管理器和调度器都启用了选主功能

  • 控制器管理器和调度器将使用各自的惟一标识引用kubeconfig文件

  • 所有静态pod获取用户指定的所有额外选项,如向控制平面传递自定义选项open in new window中所述

  • 所有静态pod获取用户(hostPath)指定的所有额外卷

请注意:

  1. 所有的镜像,对于 --kubernetes-version或当前架构,将从k8s.gcr.io拉取。如果指定了替代镜像仓库或CI镜像仓库,则使用此仓库;如果所有控制平面组件都应该使用特定的容器镜像,则将使用此镜像。有关详细信息,请参见使用自定义镜像open in new window
  2. 在kubeadm以--dry-run模式执行时,静态Pod文件被写入一个临时文件夹
  3. 可以使用 kubeadm init phase control-plane allopen in new window命令单独调用主组件的静态Pod清单生成

API服务器

API服务器的静态Pod清单受用户提供的参数影响:

  • 要绑定的apiserver-advertise-addressapiserver-bind-port ;如果没有提供,这些值默认为机器上默认网络接口的IP地址和6443端口
  • 用于服务的service-cluster-ip-range
  • 如果指定了外部etcd服务器,则指定 etcd-servers 地址和相关TLS设置(etcd-cafileetcd-certfileetcd-keyfile);如果不提供外部etcd服务器,则使用本地etcd(通过主机网络)
  • 如果指定了云提供商,则配置相应的 --cloud-provider,如果存在 --cloud-config路径(这是实验性的、alpha级别,将在未来版本中删除)

其他无条件设置的API服务器选项有:

  • --insecure-port=0 避免与API服务器的不安全连接

  • --enable-bootstrap-token-auth=true 启用 BootstrapTokenAuthenticator 认证模块。更多信息,请参见TLS引导open in new window

  • --allow-privilegedtrue (必须,例如:kube-proxy)

  • --requestheader-client-ca-filefront-proxy-ca.crt

  • --enable-admission-plugins
    

    为:

  • --kubelet-preferred-address-typesInternalIP,ExternalIP,Hostname; 这使得kubectl logs和其他API服务器与kubelet的通信可以在节点的主机名无法解析的环境中工作

  • 使用前面步骤生成的证书的选项:

    • --client-ca-fileca.crt
    • --tls-cert-fileapiserver.crt
    • --tls-private-key-fileapiserver.key
    • --kubelet-client-certificateapiserver-kubelet-client.crt
    • --kubelet-client-keyapiserver-kubelet-client.key
    • --service-account-key-filesa.pub
    • --requestheader-client-ca-file 为-proxy-ca.crt`
    • --proxy-client-cert-filefront-proxy-client.crt
    • --proxy-client-key-filefront-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引导启用所有默认控制器以及BootstrapSignerTokenCleaner控制器。有关详细信息,请参见TLS引导open in new window
  • --use-service-account-credentialstrue
  • 使用前面步骤生成的证书的选项:
    • --root-ca-fileca.crt
    • --cluster-signing-cert-fileca.crt,如果禁用了外部CA模式,则设置为""
    • --cluster-signing-key-fileca.key,如果禁用了外部CA模式,则设置为""
    • --service-account-private-key-filesa.key

调度器

调度器的静态Pod清单不受用户提供的参数的影响。

为本地etcd生成静态Pod清单

如果用户指定了一个外部etcd,则跳过此步骤,否则kubeadm将生成一个静态Pod清单文件,用于创建在Pod中运行的本地etcd实例,该实例具有以下属性:

  • localhost:2379 上进行监听并使用 HostNetwork=true
  • hostPathdataDir挂载到主机的文件系统
  • 用户指定的任何额外选项

请注意:

  1. etcd镜像将从k8.gcr.io中拉取。如果指定了另一个镜像仓库,则使用此镜像仓库;如果指定了其他镜像名称,则将使用此镜像名称。有关详细信息,请参见使用自定义镜像open in new window
  2. 在kubeadm以--dry-run模式执行时,静态Pod文件被写入一个临时文件夹
  3. 本地etcd的静态Pod清单生成可以使用kubeadm init phase etcd localopen in new window 命令单独调用

可选的动态Kublet配置

要使用此功能,请调用 kubeadm alpha kubelet config enable-dynamic。它将kubelet初始化配置写入 /var/lib/kubelet/config/init/kubelet文件。

初始化配置用于在此特定节点上启动kubelet,为kubelet的drop-in文件提供了另一种选择;这些配置将被kubelet基本配置所替代,如下面的步骤所述。有关更多信息,请参见通过配置文件设置Kubelet参数open in new window

请注意:

  • 要使动态kubelet配置工作,--dynamic-config-dir=/var/lib/kubelet/config/dynamic 应该在 /etc/systemd/system/kubelet.service.d/10-kubeadm.conf中指定
  • 使用配置文件--config some-file.yamlkubeadm initkubeadm 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-tokensystem:nodes组)的ConfigMap的读访问权
  • 通过 Node.spec.configSource指向新创建的ConfigMap,为初始控制平面节点启用动态kubelet配置特性。

将kubeadm集群配置保存在ConfigMap中,供以后使用

kubeadm将通过选项或配置文件传递给kubeadm init的配置保存在kube-system命名空间中名为kubeadm-config的ConfigMap中。

这将确保将来执行kubeadm操作(如:kubeadm upgrade)将能够确定实际/当前集群状态,并基于该数据做出新的决策。

请注意:

  1. 在上传之前,敏感信息,例如令牌,将从配置中删除
  2. 可以使用kubeadm init phase upload-configopen in new window 命令单独调用主节点配置的上传
  3. 如果使用kubeadm v1.7初始化集群。在升级到v1.8之前,你必须手动创建主节点配置ConfigMap。为了简化这一任务,实现了 kubeadm config upload (from-flags|from-file)open in new window

标记主节点

一旦控制平面可用,kubeadm就会执行以下操作:

  • 为主节点添加 node-role.kubernetes.io/master=""标签
  • 为主节点添加 node-role.kubernetes.io/master:NoSchedule污染

请注意:

配置TLS引导用于节点加入集群

Kubeadm使用引导令牌进行认证open in new window,将新节点连接到现有集群;有关更多细节,请参见设计提案open in new window

kubeadm init确保为该进程正确配置了所有内容,这包括以下步骤以及设置API服务器和控制器选项(如前面各段落中所述)。请注意:

创建引导令牌

kubeadm init创建第一个引导令牌,该令牌可以自动生成,也可以由用户使用 --token箕提供;正如引导令牌规范中所记录的那样,令牌应该以名称 bootstrap-token-<token-id> 作为Secret保存在kube-system命名空间中。请注意:

  1. kubeadm init创建的缺省令牌将用于验证TLS引导过程中的临时用户;这些用户将是system:bootstrappers:kubeadm:default-node-token 组的成员
  2. 令牌的有效性有限,默认为24小时(间隔可以使用—token-ttl 选项更改)
  3. 可以使用kubeadm tokenopen in new window命令创建其他令牌,该命令为令牌管理提供了其他有用的功能

允许要加入的节点调用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的权限。

请注意:

  1. cluster-info ConfigMap的访问不受速率限制。如果你把你的主节点暴露在互联网上,这可能是个问题,也可能不是;最坏的情况是DoS攻击,攻击者使用API服务器能够处理的所有正在运行的请求来访问cluster-info ConfigMap。

安装插件

Kubeadm通过API服务器安装内部DNS服务器和kube-proxy插件组件。请注意:

  1. 此阶段可以使用 kubeadm init phase addon allopen in new window命令单独调用。

proxy

kube-system 命名空间中创建一个用于kube-proxy的ServiceAccount;然后kube-proxy作为DaemonSet部署:

  • 到主节点的凭据(ca.crttoken)来自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检查点来修复。有关更多细节,请参见自托管open in new window

kubeadm join phase的内部设计

kubeadm init类似,kubeadm join内部工作流程也由一系列要执行的原子工作任务组成。

这分为发现(让节点信任Kubernetes主节点)和TLS引导(让Kubernetes主节点信任该节点)。

参见使用引导令牌进行认证open in new window或相应的设计提案open in new window

预先(preflight)检查

kubeadm在启动加入集群之前执行一组预先检查,目的是验证先决条件并避免常见的集群启动问题。

请注意:

  1. kubeadm join预先检查基本上是kubeadm init预先检查的子集
  2. 从v1.9开始,kubeadm为CRI-generic功能提供了更好的支持;在这种情况下,为crictl跳过或替换docker特定的控件。
  3. 从v1.9开始,kubeadm支持运行在Windows上的节点加入集群;在这种情况下,将跳过linux特定的控件。
  4. 在任何情况下,用户都可以使用--ignore-preflight-errors 选项跳过特定的预先检查(或者最终跳过所有的预先检查)。

发现cluster-info

有两种主要的发现方案。第一种方法是使用共享令牌和API服务器的IP地址。第二种方法是提供一个文件(它是标准kubeconfig文件的子集)。

共享令牌发现

如果使用--discovery-token调用kubeadm join,则使用令牌发现;在本例中,节点基本上从kube-public命名空间中的cluster-info ConfigMap中检索集群CA证书。

为了防止“中间人”的攻击,我们采取了以下几个步骤:

  • 首先,通过不安全的连接检索CA证书(这是可能的,因为kubeadm initsystem: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进行比较

请注解:

  1. 通过传递--discovery-token-unsafe-skip-ca-verification 选项,可以路过公钥验证;这削弱了kubeadm安全模型,因为其他人可能冒充Kubernetes主节点。

文件或HTTPS发现

如果使用--discovery-file调用kubeadm join,则使用文件发现;该文件可以是本地文件,也可以通过HTTPS URL下载;对于HTTPS,使用已安装的主节点CA 包验证节点加入集群。

通过文件发现,集群CA证书被添加在文件本身中;事实上,发现文件是一个kubeconfig文件,只设置了 servercertificate-authority-data属性,如 kubeadm joinopen in new window参考文档中所述;当与集群建立连接时,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。

请注意:

  1. 要使动态kubelet配置工作,需要在/etc/systemd/system/kubelet.service.d/10-kubeadm.conf中设置--dynamic-config-dir=/var/lib/kubelet/config/dynamic选项。

END 链接