实现细节

特性状态: Kubernetes v1.10 [稳定]

kubeadm initkubeadm join 共同提供了一种优秀的用户体验,可以从头开始创建裸机 Kubernetes 集群,且符合最佳实践。但是,kubeadm 是如何做到的,这一点可能并不明显。

本文档提供了关于其内部工作原理的额外细节,旨在分享关于 Kubernetes 集群最佳实践的知识。

核心设计原则

kubeadm initkubeadm join 设置的集群应具备以下特点:

  • 安全:它应采用最新的最佳实践,例如:
    • 强制执行 RBAC
    • 使用 Node Authorizer
    • 使用控制平面组件之间的安全通信
    • 使用 API 服务器和 kubelet 之间的安全通信
    • 锁定 kubelet API
    • 锁定对 kube-proxy 和 CoreDNS 等系统组件访问 API 的权限
    • 锁定 Bootstrap Token 可访问的内容
  • 用户友好:用户无需运行超过几个命令:
    • kubeadm init
    • export KUBECONFIG=/etc/kubernetes/admin.conf
    • kubectl apply -f <选择的网络插件的 YAML 文件>
    • kubeadm join --token <token> <端点>:<端口>
  • 可扩展:
    • 它不应偏爱任何特定的网络提供商。配置集群网络不在其范围之内
    • 它应提供使用配置文件来自定义各种参数的可能性

常量和已知值及路径

为了降低复杂性并简化构建在 kubeadm 之上的高级工具的开发,它对已知路径和文件名使用了一组有限的常量值。

Kubernetes 目录 /etc/kubernetes 在应用程序中是一个常量,因为它在大多数情况下是给定的路径,也是最直观的位置;其他常量路径和文件名包括:

  • /etc/kubernetes/manifests 作为 kubelet 查找静态 Pod 清单(manifests)的路径。静态 Pod 清单的文件名为:

    • etcd.yaml
    • kube-apiserver.yaml
    • kube-controller-manager.yaml
    • kube-scheduler.yaml
  • /etc/kubernetes/ 作为存储包含控制平面组件身份的 kubeconfig 文件的路径。kubeconfig 文件的文件名为:

    • kubelet.conf (TLS 引导期间为 bootstrap-kubelet.conf)
    • controller-manager.conf
    • scheduler.conf
    • admin.conf 用于集群管理员和 kubeadm 本身
    • super-admin.conf 用于可以绕过 RBAC 的集群超级管理员
  • 证书和密钥文件的文件名为:

    • ca.crt, ca.key 用于 Kubernetes 证书颁发机构
    • apiserver.crt, apiserver.key 用于 API 服务器证书
    • apiserver-kubelet-client.crt, apiserver-kubelet-client.key 用于 API 服务器安全连接 kubelet 时使用的客户端证书
    • sa.pub, sa.key 用于 controller manager 在签署 ServiceAccount 时使用的密钥
    • front-proxy-ca.crt, front-proxy-ca.key 用于前端代理证书颁发机构
    • front-proxy-client.crt, front-proxy-client.key 用于前端代理客户端

kubeadm 配置文件格式

大多数 kubeadm 命令支持 --config 标志,该标志允许从磁盘传递配置文件。配置文件的格式遵循通用的 Kubernetes API apiVersion / kind 方案,但被视为组件配置格式。一些 Kubernetes 组件,例如 kubelet,也支持基于文件的配置。

不同的 kubeadm 子命令需要不同 kind 的配置文件。例如,kubeadm init 需要 InitConfigurationkubeadm join 需要 JoinConfigurationkubeadm upgrade 需要 UpgradeConfiguration,以及 kubeadm reset 需要 ResetConfiguration

命令 kubeadm config migrate 可用于将旧格式的配置文件迁移到较新(当前)的配置格式。kubeadm 工具仅支持从已弃用的配置格式迁移到当前格式。

有关更多详细信息,请参阅 kubeadm 配置参考 页面。

kubeadm init 工作流程内部设计

kubeadm init 由一系列要执行的原子工作任务组成,如 kubeadm init内部工作流程 中所述。

kubeadm init phase 命令允许用户单独调用每个任务,最终提供一个可重用和可组合的 API/工具箱,可供其他 Kubernetes 引导工具、任何 IT 自动化工具或高级用户用于创建自定义集群。

预检检查

Kubeadm 在开始初始化之前执行一系列预检检查,旨在验证先决条件并避免常见的集群启动问题。用户可以使用 --ignore-preflight-errors 选项跳过特定的预检检查或所有检查。

  • [警告] 如果要使用的 Kubernetes 版本(通过 --kubernetes-version 标志指定)比 kubeadm CLI 版本高至少一个次要版本。
  • Kubernetes 系统要求
    • 如果运行在 Linux 上
      • [错误] 如果内核版本低于最低要求版本
      • [错误] 如果所需的 cgroups 子系统未设置
  • [错误] 如果 CRI 端点没有响应
  • [错误] 如果用户不是 root
  • [错误] 如果机器主机名不是有效的 DNS 子域名
  • [警告] 如果无法通过网络查找访问主机名
  • [错误] 如果 kubelet 版本低于 kubeadm 支持的最低 kubelet 版本(当前次要版本 -1)
  • [错误] 如果 kubelet 版本比所需的控制平面版本高至少一个次要版本(不支持的版本偏差)
  • [警告] 如果 kubelet 服务不存在或已禁用
  • [警告] 如果 firewalld 处于活动状态
  • [错误] 如果 API 服务器的 bindPort 或端口 10250/10251/10252 被占用
  • [错误] 如果 /etc/kubernetes/manifest 文件夹已存在且不为空
  • [错误] 如果 swap 已开启
  • [错误] 如果命令路径中不存在 ipiptablesmountnsenter 命令
  • [警告] 如果命令路径中不存在 ethtooltctouch 命令
  • [警告] 如果 API 服务器、controller manager、scheduler 的额外参数标志包含一些无效选项
  • [警告] 如果连接到 https://API.AdvertiseAddress:API.BindPort 通过代理进行
  • [警告] 如果连接到 services 子网通过代理进行(仅检查第一个地址)
  • [警告] 如果连接到 Pods 子网通过代理进行(仅检查第一个地址)
  • 如果提供了外部 etcd
    • [错误] 如果 etcd 版本低于最低要求版本
    • [错误] 如果指定了 etcd 证书或密钥,但未提供
  • 如果未提供外部 etcd(因此将安装本地 etcd)
    • [错误] 如果端口 2379 被占用
    • [错误] 如果 Etcd.DataDir 文件夹已存在且不为空
  • 如果授权模式是 ABAC
    • [错误] 如果 abac_policy.json 不存在
  • 如果授权模式是 WebHook
    • [错误] 如果 webhook_authz.conf 不存在

生成必要的证书

Kubeadm 为不同目的生成证书和私钥对:

  • 用于 Kubernetes 集群的自签名证书颁发机构,保存到 ca.crt 文件和 ca.key 私钥文件中

  • API 服务器的服务端证书,使用 ca.crt 作为 CA 生成,并保存到 apiserver.crt 文件及其私钥 apiserver.key 中。此证书应包含以下备用名称:

    • Kubernetes Service 的内部 clusterIP(services CIDR 中的第一个地址,例如,如果服务子网是 10.96.0.0/12,则为 10.96.0.1
    • Kubernetes DNS 名称,例如,如果 --service-dns-domain 标志值为 cluster.local,则为 kubernetes.default.svc.cluster.local,此外还有默认 DNS 名称 kubernetes.default.svckubernetes.defaultkubernetes
    • 节点名称
    • --apiserver-advertise-address
    • 用户指定的其他备用名称
  • 用于 API 服务器安全连接 kubelet 的客户端证书,使用 ca.crt 作为 CA 生成,并保存到 apiserver-kubelet-client.crt 文件及其私钥 apiserver-kubelet-client.key 中。此证书应属于 system:masters 组织

  • 用于签署 ServiceAccount Token 的私钥,保存到 sa.key 文件及其公钥 sa.pub

  • 用于前端代理的证书颁发机构,保存到 front-proxy-ca.crt 文件及其密钥 front-proxy-ca.key

  • 用于前端代理客户端的客户端证书,使用 front-proxy-ca.crt 作为 CA 生成,并保存到 front-proxy-client.crt 文件及其私钥 front-proxy-client.key

证书默认存储在 /etc/kubernetes/pki 中,但此目录可以使用 --cert-dir 标志进行配置。

请注意:

  1. 如果给定的证书和私钥对都存在,并且其内容被评估为符合上述规范,则将使用现有文件,并跳过给定证书的生成阶段。这意味着用户可以将现有的 CA 复制到 /etc/kubernetes/pki/ca.{crt,key},然后 kubeadm 将使用这些文件签署其余证书。另请参阅 使用自定义证书
  2. 对于 CA,可以提供 ca.crt 文件但 불안 ca.key 文件。如果所有其他证书和 kubeconfig 文件都已就位,kubeadm 会识别此情况并激活 ExternalCA,这也意味着 controller-manager 中的 csrsigner 控制器不会启动
  3. 如果 kubeadm 运行在 外部 CA 模式下;所有证书都必须由用户提供,因为 kubeadm 无法自行生成它们
  4. 如果 kubeadm 在 --dry-run 模式下执行,证书文件将写入临时文件夹中
  5. 证书生成可以使用 kubeadm init phase certs all 命令单独调用

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

Kubeadm 为控制平面组件生成包含身份的 kubeconfig 文件:

  • kubelet 在 TLS 引导期间使用的 kubeconfig 文件 - /etc/kubernetes/bootstrap-kubelet.conf。此文件内部包含用于节点向集群认证的 bootstrap-token 或嵌入式客户端证书。

    此客户端证书应:

    • 属于 system:nodes 组织,这是 Node Authorization 模块的要求
    • 具有 Common Name (CN) system:node:<hostname-lowercased>
  • controller-manager 的 kubeconfig 文件,/etc/kubernetes/controller-manager.conf;此文件内部嵌入了包含 controller-manager 身份的客户端证书。此客户端证书应具有 CN system:kube-controller-manager,这是默认 RBAC 核心组件角色 所定义的

  • scheduler 的 kubeconfig 文件,/etc/kubernetes/scheduler.conf;此文件内部嵌入了包含 scheduler 身份的客户端证书。此客户端证书应具有 CN system:kube-scheduler,这是默认 RBAC 核心组件角色 所定义的

此外,还会生成一个用于 kubeadm 作为管理实体的 kubeconfig 文件,并存储在 /etc/kubernetes/admin.conf 中。此文件包含一个证书,其 Subject 为 O = kubeadm:cluster-admins, CN = kubernetes-adminkubeadm:cluster-admins 是一个由 kubeadm 管理的组。在 kubeadm init 期间,通过使用不需要 RBAC 的 super-admin.conf 文件,它绑定到 cluster-admin ClusterRole。此 admin.conf 文件必须保留在控制平面节点上,不应与额外用户共享。

kubeadm init 期间,还会生成另一个 kubeconfig 文件,并存储在 /etc/kubernetes/super-admin.conf 中。此文件包含一个证书,其 Subject 为 O = system:masters, CN = kubernetes-super-adminsystem:masters 是一个绕过 RBAC 的超级用户组,这使得 super-admin.conf 在集群因 RBAC 配置错误而被锁定时非常有用。super-admin.conf 文件必须存储在安全位置,不应与额外用户共享。

有关 RBAC 和内置 ClusterRole 及组的更多信息,请参阅 RBAC 用户面向角色绑定

您可以运行 kubeadm kubeconfig user 为额外用户生成 kubeconfig 文件。

另请注意:

  1. ca.crt 证书嵌入在所有 kubeconfig 文件中。
  2. 如果给定的 kubeconfig 文件存在,并且其内容被评估为符合上述规范,则将使用现有文件,并跳过给定 kubeconfig 的生成阶段
  3. 如果 kubeadm 运行在 ExternalCA 模式下,所有必需的 kubeconfig 也必须由用户提供,因为 kubeadm 无法自行生成它们
  4. 如果 kubeadm 在 --dry-run 模式下执行,kubeconfig 文件将写入临时文件夹中
  5. kubeconfig 文件的生成可以使用 kubeadm init phase kubeconfig all 命令单独调用

为控制平面组件生成静态 Pod 清单

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

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

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

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

  • 所有静态 Pod 都使用 system-node-critical 优先类

  • 所有静态 Pod 都设置了 hostNetwork: true,以便在网络配置之前允许控制平面启动;因此:

    • controller-manager 和 scheduler 用于引用 API 服务器的地址是 127.0.0.1
    • 如果 etcd 服务器在本地设置,etcd-server 地址将设置为 127.0.0.1:2379
  • controller-manager 和 scheduler 都启用了领导者选举

  • controller-manager 和 scheduler 将引用包含各自唯一身份的 kubeconfig 文件

  • 所有静态 Pod 都获得你指定的额外标志或补丁,如 向控制平面组件传递自定义参数 中所述

  • 所有静态 Pod 都获得用户指定的额外卷(Host path)

请注意:

  1. 默认情况下,所有镜像都将从 registry.k8s.io 拉取。有关自定义镜像仓库的信息,请参阅 使用自定义镜像
  2. 如果 kubeadm 在 --dry-run 模式下执行,静态 Pod 文件将写入临时文件夹中
  3. 控制平面组件的静态 Pod 清单生成可以使用 kubeadm init phase control-plane all 命令单独调用

API 服务器

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

  • 要绑定的 apiserver-advertise-addressapiserver-bind-port;如果未提供,这些值默认为机器上默认网络接口的 IP 地址和端口 6443
  • 用于 Services 的 service-cluster-ip-range
  • 如果指定了外部 etcd 服务器,则使用 etcd-servers 地址及相关的 TLS 设置(etcd-cafileetcd-certfileetcd-keyfile);如果未提供外部 etcd 服务器,则将使用本地 etcd(通过 host network)
  • 如果指定了 cloud provider,则配置相应的 --cloud-provider 参数以及 --cloud-config 路径(如果该文件存在)(这是实验性功能,处于 alpha 阶段,并将在未来版本中移除)

无条件设置的其他 API 服务器标志包括:

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

  • --enable-bootstrap-token-auth=true 以启用 BootstrapTokenAuthenticator 身份认证模块。有关更多详细信息,请参阅 TLS 引导

  • --allow-privileged 设置为 true(例如,kube-proxy 需要)

  • --requestheader-client-ca-file 设置为 front-proxy-ca.crt

  • --enable-admission-plugins 设置为:

    • NamespaceLifecycle,例如避免删除系统保留的命名空间
    • LimitRangerResourceQuota,用于在命名空间上强制执行限制
    • ServiceAccount,用于强制执行 Service Account 自动化
    • PersistentVolumeLabel,根据 cloud provider 的定义将地域或区域标签附加到 PersistentVolume(此准入控制器已弃用,并将在未来版本中移除。从 v1.9 开始,除非明确选择使用 gce 或 aws 作为 cloud provider,否则 kubeadm 默认不会部署此准入控制器)
    • DefaultStorageClass,用于在 PersistentVolumeClaim 对象上强制执行默认存储类
    • DefaultTolerationSeconds
    • NodeRestriction,用于限制 kubelet 可以修改的内容(例如,仅限制此节点上的 Pod)
  • --kubelet-preferred-address-types 设置为 InternalIP,ExternalIP,Hostname; 这使得在节点主机名无法解析的环境中 kubectl logs 和其他 API 服务器与 kubelet 的通信能够正常工作

  • 使用前一步骤中生成的证书的标志:

    • --client-ca-file 设置为 ca.crt
    • --tls-cert-file 设置为 apiserver.crt
    • --tls-private-key-file 设置为 apiserver.key
    • --kubelet-client-certificate 设置为 apiserver-kubelet-client.crt
    • --kubelet-client-key 设置为 apiserver-kubelet-client.key
    • --service-account-key-file 设置为 sa.pub
    • --requestheader-client-ca-file 设置为 front-proxy-ca.crt
    • --proxy-client-cert-file 设置为 front-proxy-client.crt
    • --proxy-client-key-file 设置为 front-proxy-client.key
  • 用于保护前端代理 (API Aggregation) 通信的其他标志:

    • --requestheader-username-headers=X-Remote-User
    • --requestheader-group-headers=X-Remote-Group
    • --requestheader-extra-headers-prefix=X-Remote-Extra-
    • --requestheader-allowed-names=front-proxy-client

Controller manager

controller manager 的静态 Pod 清单受用户提供的以下参数影响:

  • 如果调用 kubeadm 时指定了 --pod-network-cidr,则通过设置以下参数启用某些 CNI 网络插件所需的子网管理器功能:

    • --allocate-node-cidrs=true
    • 根据给定的 CIDR 设置 --cluster-cidr--node-cidr-mask-size 标志

无条件设置的其他标志包括:

  • --controllers 启用所有默认控制器以及用于 TLS 引导的 BootstrapSignerTokenCleaner 控制器。有关更多详细信息,请参阅 TLS 引导

  • --use-service-account-credentials 设置为 true

  • 使用前一步骤中生成的证书的标志:

    • --root-ca-file 设置为 ca.crt
    • --cluster-signing-cert-file 设置为 ca.crt,如果 External CA 模式已禁用,否则设置为 ""
    • --cluster-signing-key-file 设置为 ca.key,如果 External CA 模式已禁用,否则设置为 ""
    • --service-account-private-key-file 设置为 sa.key

Scheduler

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

为本地 etcd 生成静态 Pod 清单

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

  • 监听 localhost:2379 并使用 HostNetwork=true
  • dataDir 向主机的 filesystem 创建一个 hostPath 挂载
  • 用户指定的任何额外标志

请注意:

  1. etcd 容器镜像默认将从 registry.gcr.io 拉取。有关自定义镜像仓库的信息,请参阅 使用自定义镜像
  2. 如果你在 --dry-run 模式下运行 kubeadm,etcd 静态 Pod 清单将写入临时文件夹中。
  3. 你可以使用 kubeadm init phase etcd local 命令直接调用本地 etcd 的静态 Pod 清单生成。

等待控制平面启动

在控制平面节点上,kubeadm 最多等待 4 分钟,直到控制平面组件和 kubelet 可用。它通过对相应的组件的 /healthz/livez 端点执行健康检查来实现这一点。

控制平面启动后,kubeadm 完成以下段落所述的任务。

将 kubeadm ClusterConfiguration 保存到 ConfigMap 中以供后续参考

kubeadm 将传递给 kubeadm init 的配置保存在 kube-system 命名空间下名为 kubeadm-config 的 ConfigMap 中。

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

请注意:

  1. 在保存 ClusterConfiguration 之前,会从配置中去除令牌等敏感信息。
  2. 可以使用命令 kubeadm init phase upload-config 单独调用上传控制平面节点配置的功能。

标记节点为控制平面节点

控制平面可用后,kubeadm 会执行以下操作

  • 使用 node-role.kubernetes.io/control-plane="" 标签标记节点为控制平面节点。
  • 使用 node-role.kubernetes.io/control-plane:NoSchedule 污点标记节点。

请注意,标记控制平面阶段的阶段可以使用命令 kubeadm init phase mark-control-plane 单独调用。

配置节点加入时的 TLS 引导

Kubeadm 使用使用 Bootstrap Token 进行认证来将新节点加入现有集群;更多详细信息请参阅 设计提案

kubeadm init 会确保为此过程正确配置所有内容,包括以下步骤以及设置 API 服务器和控制器标志(如前面段落所述)。

创建引导令牌

kubeadm init 会创建第一个引导令牌,该令牌可以是自动生成,也可以由用户使用 --token 标志提供;根据引导令牌规范中的说明,令牌应作为名为 bootstrap-token-<token-id> 的 Secret 保存在 kube-system 命名空间下。

请注意:

  1. kubeadm init 创建的默认令牌将用于在 TLS 引导过程中验证临时用户;这些用户将是 system:bootstrappers:kubeadm:default-node-token 组的成员。
  2. 令牌有效期有限,默认为 24 小时(可以使用 —token-ttl 标志更改此间隔)。
  3. 可以使用 kubeadm token 命令创建更多令牌,该命令还提供其他有用的令牌管理功能。

允许加入的节点调用 CSR API

Kubeadm 确保 system:bootstrappers:kubeadm:default-node-token 组中的用户能够访问证书签名 API。

这是通过在上述组和默认 RBAC 角色 system:node-bootstrapper 之间创建名为 kubeadm:kubelet-bootstrap 的 ClusterRoleBinding 来实现的。

设置新引导令牌的自动批准

Kubeadm 确保引导令牌的 CSR 请求将由 csrapprover 控制器自动批准。

这是通过在 system:bootstrappers:kubeadm:default-node-token 组和默认角色 system:certificates.k8s.io:certificatesigningrequests:nodeclient 之间创建名为 kubeadm:node-autoapprove-bootstrap 的 ClusterRoleBinding 来实现的。

还应创建角色 system:certificates.k8s.io:certificatesigningrequests:nodeclient,授予对 /apis/certificates.k8s.io/certificatesigningrequests/nodeclient 的 POST 权限。

设置带有自动批准的节点证书轮换

Kubeadm 确保为节点启用证书轮换,并且节点的新的证书请求将由 csrapprover 控制器自动批准其 CSR 请求。

这是通过在 system:nodes 组和默认角色 system:certificates.k8s.io:certificatesigningrequests:selfnodeclient 之间创建名为 kubeadm:node-autoapprove-certificate-rotation 的 ClusterRoleBinding 来实现的。

创建公共的 cluster-info ConfigMap

此阶段在 kube-public 命名空间中创建 cluster-info ConfigMap。

此外,它还创建了一个 Role 和一个 RoleBinding,授予未经身份验证的用户(即 RBAC 组 system:unauthenticated 中的用户)访问此 ConfigMap 的权限。

安装插件

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

proxy

kube-system 命名空间中为 kube-proxy 创建一个 ServiceAccount;然后将 kube-proxy 部署为 DaemonSet。

  • 连接控制平面的凭据(ca.crttoken)来自该 ServiceAccount。
  • API 服务器的位置 (URL) 来自一个 ConfigMap。
  • kube-proxy 的 ServiceAccount 被绑定到 system:node-proxier ClusterRole 中的权限。

DNS

  • CoreDNS 服务出于与旧版 kube-dns 插件兼容的原因被命名为 kube-dns

  • kube-system 命名空间中为 CoreDNS 创建一个 ServiceAccount。

  • coredns 的 ServiceAccount 被绑定到 system:coredns ClusterRole 中的权限。

在 Kubernetes 1.21 版本中,移除了通过 kubeadm 使用 kube-dns 的支持。即使相关的 Service 被命名为 kube-dns,您仍然可以使用 kubeadm 来使用 CoreDNS。

kubeadm join 阶段内部设计

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

这被分解为发现(让节点信任 Kubernetes API 服务器)和 TLS 引导(让 Kubernetes API 服务器信任节点)。

参阅使用 Bootstrap Token 进行认证或相应的设计提案

预检检查

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

另请注意:

  1. kubeadm join 的预检检查基本上是 kubeadm init 预检检查的子集。
  2. 如果您要加入 Windows 节点,则会跳过 Linux 特定的检查。
  3. 在任何情况下,用户都可以使用 --ignore-preflight-errors 选项跳过特定的预检检查(或最终跳过所有预检检查)。

发现 cluster-info

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

共享令牌发现

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

为了防止“中间人”攻击,采取了几个步骤

  • 首先,通过不安全连接检索 CA 证书(这是可能的,因为在 kubeadm init 期间,已授予 system:unauthenticated 用户对 cluster-info 的访问权限)。

  • 然后 CA 证书会通过以下验证步骤

    • 基本验证:使用令牌 ID 对 JWT 签名进行验证。
    • 公钥验证:使用提供的 --discovery-token-ca-cert-hash。此值可在 kubeadm init 的输出中找到,或使用标准工具计算(哈希是按照 RFC7469 计算 Subject Public Key Info (SPKI) 对象的字节得出的)。--discovery-token-ca-cert-hash 标志可以重复多次,以允许使用多个公钥。
    • 作为附加验证,通过安全连接检索 CA 证书,然后与最初检索到的 CA 进行比较。

文件/HTTPS 发现

如果使用 --discovery-file 调用 kubeadm join,则使用文件发现;该文件可以是本地文件,也可以通过 HTTPS URL 下载;在 HTTPS 的情况下,使用主机上安装的 CA 捆绑包来验证连接。

使用文件发现时,集群 CA 证书直接包含在文件本身中;实际上,发现文件是一个 kubeconfig 文件,其中仅设置了 servercertificate-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 升级工作流程内部设计

kubeadm upgrade 包含用于处理由 kubeadm 创建的 Kubernetes 集群升级的子命令。您必须在控制平面节点上运行 kubeadm upgrade apply(您可以选择哪个节点);这会启动升级过程。然后您在所有剩余节点(包括工作节点和控制平面节点)上运行 kubeadm upgrade node

kubeadm upgrade applykubeadm upgrade node 都包含一个 phase 子命令,该子命令提供对升级过程内部阶段的访问。更多详细信息请参阅 kubeadm upgrade phase

其他实用的升级命令包括 kubeadm upgrade plankubeadm upgrade diff

所有升级子命令都支持传递配置文件。

kubeadm upgrade plan

在运行 kubeadm upgrade apply 之前,您可以选择运行 kubeadm upgrade planplan 子命令会检查哪些版本可用于升级,并验证您当前集群是否可升级。

kubeadm upgrade diff

这会显示将应用于控制平面节点的现有静态 Pod 清单的差异。执行相同操作的更详细方法是运行 kubeadm upgrade apply --dry-runkubeadm upgrade node --dry-run

kubeadm upgrade apply

kubeadm upgrade apply 会为所有节点的升级准备集群,同时还会升级在其上运行的控制平面节点。它执行的步骤包括:

  • 运行类似于 kubeadm initkubeadm join 的预检检查,确保容器镜像已下载且集群处于适合升级的状态。
  • 升级磁盘上 /etc/kubernetes/manifests 中的控制平面清单文件,并在文件发生更改时等待 kubelet 重启组件。
  • 将更新的 kubeadm 和 kubelet 配置作为 kubeadm-configkubelet-config ConfigMaps(两者都在 kube-system 命名空间中)上传到集群。
  • 将此节点的更新的 kubelet 配置写入 /var/lib/kubelet/config.yaml 中。
  • 为 RBAC 规则配置引导令牌和 cluster-info ConfigMap。这与 kubeadm init 阶段相同,并确保集群继续支持使用引导令牌加入的节点。
  • 仅当集群中所有现有的 kube-apiserver 都已升级到目标版本时,才会有条件地升级 kube-proxy 和 CoreDNS 插件。
  • 执行任何升级后任务,例如清理特定于发行版本的已弃用功能。

kubeadm upgrade node

在集群升级启动后(通过运行 kubeadm upgrade apply),kubeadm upgrade node 会升级单个控制平面节点或工作节点。该命令通过检查文件 /etc/kubernetes/manifests/kube-apiserver.yaml 是否存在来检测节点是否为控制平面节点。如果找到该文件,kubeadm 工具会推断此节点上有一个正在运行的 kube-apiserver Pod。

  • 运行类似于 kubeadm upgrade apply 的预检检查。
  • 对于控制平面节点,升级磁盘上 /etc/kubernetes/manifests 中的控制平面清单文件,并在文件发生更改时等待 kubelet 重启组件。
  • 将此节点的更新的 kubelet 配置写入 /var/lib/kubelet/config.yaml 中。
  • (对于控制平面节点)仅在集群中所有现有的 API 服务器都已升级到目标版本的前提下,才会条件性地升级 kube-proxy 和 CoreDNS 插件
  • 执行任何升级后任务,例如清理特定于发行版本的已弃用功能。

kubeadm reset 工作流程内部设计

您可以在之前执行过 kubeadm 命令的节点上使用 kubeadm reset 子命令。此子命令会**尽最大努力**清理节点。如果某些操作失败,您必须介入并执行手动清理。

该命令支持阶段。更多详细信息请参阅 kubeadm reset phase

该命令支持配置文件。

此外

  • IPVS、iptables 和 nftables 规则**不**会被清理。
  • CNI (网络插件) 配置**不**会被清理。
  • 用户主目录中的 .kube/ **不**会被清理。

该命令包括以下阶段

  • 在节点上运行预检检查以确定其是否健康。
  • 对于控制平面节点,删除所有本地 etcd 成员数据。
  • 停止 kubelet。
  • 停止运行中的容器。
  • 解挂 /var/lib/kubelet 中所有已挂载的目录。
  • 删除由 kubeadm 管理的 /var/lib/kubelet/etc/kubernetes 中的所有文件和目录。
最后修改于 2024 年 11 月 11 日太平洋标准时间上午 11:04:kubeadm: update authored docs for 1.32 (bbdb8dd9f3)