这是本节的多页打印视图。
点击此处打印 .
返回本页常规视图 .
入门
本节列出了设置和运行 Kubernetes 的不同方法。
安装 Kubernetes 时,请根据以下条件选择安装类型:易于维护、安全性、可控制性、可用资源以及操作和管理 Kubernetes 集群所需的专业知识。
你可以下载 Kubernetes ,在本地机器、云或你自己的数据中心上部署 Kubernetes 集群。
诸如 kube-apiserver 或
kube-proxy
等某些 Kubernetes 组件 可以在集群中以容器镜像 部署。
建议 尽可能将 Kubernetes 组件作为容器镜像运行,并且让 Kubernetes 管理这些组件。
但是运行容器的相关组件 —— 尤其是 kubelet,不在此列。
如果你不想自己管理 Kubernetes 集群,则可以选择托管服务,包括经过认证的平台 。
在各种云和裸机环境中,还有其他标准化和定制的解决方案。
学习环境
如果正打算学习 Kubernetes,请使用 Kubernetes 社区支持
或生态系统中的工具在本地计算机上设置 Kubernetes 集群。
请参阅安装工具 。
生产环境
在评估生产环境 的解决方案时,
请考虑要自己管理 Kubernetes 集群(或相关抽象)的哪些方面,将哪些托付给提供商。
对于你自己管理的集群,官方支持的用于部署 Kubernetes 的工具是
kubeadm 。
接下来
Kubernetes 的设计是让其控制平面 在 Linux 上运行的。
在集群中,你可以在 Linux 或其他操作系统(包括 Windows)上运行应用程序。
1 - 学习环境
2 - 生产环境
生产质量的 Kubernetes 集群需要规划和准备。
如果你的 Kubernetes 集群是用来运行关键负载的,该集群必须被配置为弹性的(Resilient)。
本页面阐述你在安装生产就绪的集群或将现有集群升级为生产用途时可以遵循的步骤。
如果你已经熟悉生产环境安装,因此只关注一些链接,则可以跳到接下来 节。
生产环境考量
通常,一个生产用 Kubernetes 集群环境与个人学习、开发或测试环境所使用的 Kubernetes 相比有更多的需求。
生产环境可能需要被很多用户安全地访问,需要提供一致的可用性,以及能够与需求变化相适配的资源。
在你决定在何处运行你的生产用 Kubernetes 环境(在本地或者在云端),
以及你希望承担或交由他人承担的管理工作量时,
需要考察以下因素如何影响你对 Kubernetes 集群的需求:
可用性 :一个单机的 Kubernetes 学习环境
具有单点失效特点。创建高可用的集群则意味着需要考虑:
将控制面与工作节点分开
在多个节点上提供控制面组件的副本
为针对集群的 API 服务器
的流量提供负载均衡
随着负载的合理需要,提供足够的可用的(或者能够迅速变为可用的)工作节点
规模 :如果你预期你的生产用 Kubernetes 环境要承受固定量的请求,
你可能可以针对所需要的容量来一次性完成安装。
不过,如果你预期服务请求会随着时间增长,或者因为类似季节或者特殊事件的原因而发生剧烈变化,
你就需要规划如何处理请求上升时对控制面和工作节点的压力,或者如何缩减集群规模以减少未使用资源的消耗。
安全性与访问管理 :在你自己的学习环境 Kubernetes 集群上,你拥有完全的管理员特权。
但是针对运行着重要工作负载的共享集群,用户账户不止一两个时,
就需要更细粒度的方案来确定谁或者哪些主体可以访问集群资源。
你可以使用基于角色的访问控制(RBAC )
和其他安全机制来确保用户和负载能够访问到所需要的资源,
同时确保工作负载及集群自身仍然是安全的。
你可以通过管理策略 和
容器资源
来针对用户和工作负载所可访问的资源设置约束。
在自行构建 Kubernetes 生产环境之前,
请考虑将这一任务的部分或者全部交给云方案承包服务 提供商或者其他
Kubernetes 合作伙伴 。选项有:
无服务 :仅是在第三方设备上运行负载,完全不必管理集群本身。
你需要为 CPU 用量、内存和磁盘请求等付费。
托管控制面 :让供应商决定集群控制面的规模和可用性,并负责打补丁和升级等操作。
托管工作节点 :配置一个节点池来满足你的需要,由供应商来确保节点始终可用,并在需要的时候完成升级。
集成 :有一些供应商能够将 Kubernetes 与一些你可能需要的其他服务集成,
这类服务包括存储、容器镜像仓库、身份认证方法以及开发工具等。
无论你是自行构造一个生产用 Kubernetes 集群还是与合作伙伴一起协作,
请审阅下面章节以评估你的需求,因为这关系到你的集群的控制面 、工作节点 、用户访问 以及负载资源 。
生产用集群安装
在生产质量的 Kubernetes 集群中,控制面用不同的方式来管理集群和可以分布到多个计算机上的服务。
每个工作节点则代表的是一个可配置来运行 Kubernetes Pod 的实体。
生产用控制面
最简单的 Kubernetes 集群中,整个控制面和工作节点服务都运行在同一台机器上。
你可以通过添加工作节点来提升环境运算能力,正如
Kubernetes 组件 示意图所示。
如果只需要集群在很短的一段时间内可用,或者可以在某些事物出现严重问题时直接丢弃,
这种配置可能符合你的需要。
如果你需要一个更为持久的、高可用的集群,那么就需要考虑扩展控制面的方式。
根据设计,运行在一台机器上的单机控制面服务不是高可用的。
如果你认为保持集群的正常运行并需要确保它在出错时可以被修复是很重要的,
可以考虑以下步骤:
管理证书 :控制面服务之间的安全通信是通过证书来完成的。
证书是在部署期间自动生成的,或者你也可以使用自己的证书机构来生成它们。
参阅 PKI 证书和需求 了解细节。
为 API 服务器配置负载均衡 :配置负载均衡器来将外部的 API 请求散布给运行在不同节点上的 API 服务实例。
参阅创建外部负载均衡器 了解细节。
创建多控制面系统 :为了实现高可用性,控制面不应被限制在一台机器上。
如果控制面服务是使用某 init 服务(例如 systemd)来运行的,每个服务应该至少运行在三台机器上。
不过,将控制面作为服务运行在 Kubernetes Pod 中可以确保你所请求的个数的服务始终保持可用。
调度器应该是可容错的,但不是高可用的。
某些部署工具会安装 Raft 票选算法来对 Kubernetes 服务执行领导者选举。
如果主节点消失,另一个服务会被选中并接手相应服务。
跨多个可用区 :如果保持你的集群一直可用这点非常重要,可以考虑创建一个跨多个数据中心的集群;
在云环境中,这些数据中心被视为可用区。若干个可用区在一起可构成地理区域。
通过将集群分散到同一区域中的多个可用区内,即使某个可用区不可用,整个集群能够继续工作的机会也大大增加。
更多的细节可参阅跨多个可用区运行 。
管理演进中的特性 :如果你计划长时间保留你的集群,就需要执行一些维护其健康和安全的任务。
例如,如果你采用 kubeadm 安装的集群,
则有一些可以帮助你完成
证书管理
和升级 kubeadm 集群
的指令。
参见管理集群 了解一个 Kubernetes
管理任务的较长列表。
如要了解运行控制面服务时可使用的选项,可参阅
kube-apiserver 、
kube-controller-manager 和
kube-scheduler
组件参考页面。
如要了解高可用控制面的例子,可参阅高可用拓扑结构选项 、
使用 kubeadm 创建高可用集群
以及为 Kubernetes 运维 etcd 集群 。
关于制定 etcd 备份计划,可参阅对 etcd 集群执行备份 。
生产用工作节点
生产质量的工作负载需要是弹性的;它们所依赖的其他组件(例如 CoreDNS)也需要是弹性的。
无论你是自行管理控制面还是让云供应商来管理,你都需要考虑如何管理工作节点
(有时也简称为节点 )。
配置节点 :节点可以是物理机或者虚拟机。如果你希望自行创建和管理节点,
你可以安装一个受支持的操作系统,之后添加并运行合适的节点服务 。考虑:
在安装节点时要通过配置适当的内存、CPU 和磁盘读写速率、存储容量来满足你的负载的需求。
是否通用的计算机系统即足够,还是你有负载需要使用 GPU 处理器、Windows 节点或者 VM 隔离。
验证节点 :参阅验证节点配置 以了解如何确保节点满足加入到 Kubernetes 集群的需求。
添加节点到集群中 :如果你自行管理你的集群,你可以通过安装配置你的机器,
之后或者手动加入集群,或者让它们自动注册到集群的 API 服务器。
参阅节点 节,了解如何配置 Kubernetes 以便以这些方式来添加节点。
扩缩节点 :制定一个扩充集群容量的规划,你的集群最终会需要这一能力。
参阅大规模集群考察事项
以确定你所需要的节点数;
这一规模是基于你要运行的 Pod 和容器个数来确定的。
如果你自行管理集群节点,这可能意味着要购买和安装你自己的物理设备。
生产级用户环境
在生产环境中,情况可能不再是你或者一小组人在访问集群,而是几十上百人需要访问集群。
在学习环境或者平台原型环境中,你可能具有一个可以执行任何操作的管理账号。
在生产环境中,你会需要对不同名字空间具有不同访问权限级别的很多账号。
建立一个生产级别的集群意味着你需要决定如何有选择地允许其他用户访问集群。
具体而言,你需要选择验证尝试访问集群的人的身份标识(身份认证),
并确定他们是否被许可执行他们所请求的操作(鉴权):
认证(Authentication) :API 服务器可以使用客户端证书、持有者令牌、
身份认证代理或者 HTTP 基本认证机制来完成身份认证操作。
你可以选择你要使用的认证方法。通过使用插件,
API 服务器可以充分利用你所在组织的现有身份认证方法,
例如 LDAP 或者 Kerberos。
关于认证 Kubernetes 用户身份的不同方法的描述,
可参阅身份认证 。
鉴权(Authorization) :当你准备为一般用户执行权限判定时,
你可能会需要在 RBAC 和 ABAC 鉴权机制之间做出选择。
参阅鉴权概述 ,
了解对用户账户(以及访问你的集群的服务账户)执行鉴权的不同模式。
基于角色的访问控制 (RBAC ):
让你通过为通过身份认证的用户授权特定的许可集合来控制集群访问。
访问许可可以针对某特定名字空间(Role)或者针对整个集群(ClusterRole)。
通过使用 RoleBinding 和 ClusterRoleBinding 对象,这些访问许可可以被关联到特定的用户身上。
基于属性的访问控制 (ABAC ):
让你能够基于集群中资源的属性来创建访问控制策略,基于对应的属性来决定允许还是拒绝访问。
策略文件的每一行都给出版本属性(apiVersion 和 kind)以及一个规约属性的映射,
用来匹配主体(用户或组)、资源属性、非资源属性(/version 或 /apis)和只读属性。
参阅示例 以了解细节。
作为在你的生产用 Kubernetes 集群中安装身份认证和鉴权机制的负责人,要考虑的事情如下:
设置鉴权模式 :当 Kubernetes API 服务器(kube-apiserver )启动时,
所支持的鉴权模式必须使用 --authorization-mode
标志配置。
例如,kube-apiserver.yaml
(位于 /etc/kubernetes/manifests
下)中对应的标志可以设置为 Node,RBAC
。
这样就会针对已完成身份认证的请求执行 Node 和 RBAC 鉴权。
创建用户证书和角色绑定(RBAC) :如果你在使用 RBAC 鉴权,用户可以创建由集群 CA 签名的
CertificateSigningRequest(CSR)。接下来你就可以将 Role 和 ClusterRole 绑定到每个用户身上。
参阅证书签名请求 了解细节。
创建组合属性的策略(ABAC) :如果你在使用 ABAC 鉴权,
你可以设置属性组合以构造策略对所选用户或用户组执行鉴权,
判定他们是否可访问特定的资源(例如 Pod)、名字空间或者 apiGroup。
进一步的详细信息可参阅示例 。
考虑准入控制器 :针对指向 API 服务器的请求的其他鉴权形式还包括
Webhook 令牌认证 。
Webhook 和其他特殊的鉴权类型需要通过向 API
服务器添加准入控制器 来启用。
为负载资源设置约束
生产环境负载的需求可能对 Kubernetes 的控制面内外造成压力。
在针对你的集群的负载执行配置时,要考虑以下条目:
创建额外的服务账户 :用户账户决定用户可以在集群上执行的操作,服务账号则定义的是在特定名字空间中
Pod 的访问权限。默认情况下,Pod 使用所在名字空间中的 default 服务账号。
参阅管理服务账号 以了解如何创建新的服务账号。
例如,你可能需要:
接下来
2.1 - 容器运行时
你需要在集群内每个节点上安装一个
容器运行时
以使 Pod 可以运行在上面。本文概述了所涉及的内容并描述了与节点设置相关的任务。
Kubernetes 1.29
要求你使用符合容器运行时接口 (CRI)的运行时。
有关详细信息,请参阅 CRI 版本支持 。
本页简要介绍在 Kubernetes 中几个常见的容器运行时的用法。
说明:
v1.24 之前的 Kubernetes 版本直接集成了 Docker Engine 的一个组件,名为 dockershim 。
这种特殊的直接整合不再是 Kubernetes 的一部分
(这次删除被作为 v1.20 发行版本的一部分宣布 )。
你可以阅读检查 Dockershim 移除是否会影响你 以了解此删除可能会如何影响你。
要了解如何使用 dockershim 进行迁移,
请参阅从 dockershim 迁移 。
如果你正在运行 v1.29 以外的 Kubernetes 版本,查看对应版本的文档。
以下步骤将通用设置应用于 Linux 上的 Kubernetes 节点。
如果你确定不需要某个特定设置,则可以跳过它。
有关更多信息,请参阅网络插件要求 或特定容器运行时的文档。
转发 IPv4 并让 iptables 看到桥接流量
执行下述指令:
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 设置所需的 sysctl 参数,参数在重新启动后保持不变
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# 应用 sysctl 参数而不重新启动
sudo sysctl --system
通过运行以下指令确认 br_netfilter
和 overlay
模块被加载:
lsmod | grep br_netfilter
lsmod | grep overlay
通过运行以下指令确认 net.bridge.bridge-nf-call-iptables
、net.bridge.bridge-nf-call-ip6tables
和 net.ipv4.ip_forward
系统变量在你的 sysctl
配置中被设置为 1:
sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward
cgroup 驱动
在 Linux 上,控制组(CGroup) 用于限制分配给进程的资源。
kubelet 和底层容器运行时都需要对接控制组来强制执行
为 Pod 和容器管理资源
并为诸如 CPU、内存这类资源设置请求和限制。若要对接控制组,kubelet 和容器运行时需要使用一个 cgroup 驱动 。
关键的一点是 kubelet 和容器运行时需使用相同的 cgroup 驱动并且采用相同的配置。
可用的 cgroup 驱动有两个:
cgroupfs 驱动
cgroupfs
驱动是 kubelet 中默认的 cgroup 驱动 。
当使用 cgroupfs
驱动时, kubelet 和容器运行时将直接对接 cgroup 文件系统来配置 cgroup。
当 systemd 是初始化系统时,
不 推荐使用 cgroupfs
驱动,因为 systemd 期望系统上只有一个 cgroup 管理器。
此外,如果你使用 cgroup v2 ,
则应用 systemd
cgroup 驱动取代 cgroupfs
。
systemd cgroup 驱动
当某个 Linux 系统发行版使用 systemd
作为其初始化系统时,初始化进程会生成并使用一个 root 控制组(cgroup
),并充当 cgroup 管理器。
systemd 与 cgroup 集成紧密,并将为每个 systemd 单元分配一个 cgroup。
因此,如果你 systemd
用作初始化系统,同时使用 cgroupfs
驱动,则系统中会存在两个不同的 cgroup 管理器。
同时存在两个 cgroup 管理器将造成系统中针对可用的资源和使用中的资源出现两个视图。某些情况下,
将 kubelet 和容器运行时配置为使用 cgroupfs
、但为剩余的进程使用 systemd
的那些节点将在资源压力增大时变得不稳定。
当 systemd 是选定的初始化系统时,缓解这个不稳定问题的方法是针对 kubelet 和容器运行时将
systemd
用作 cgroup 驱动。
要将 systemd
设置为 cgroup 驱动,需编辑 KubeletConfiguration
的 cgroupDriver
选项,并将其设置为 systemd
。例如:
apiVersion : kubelet.config.k8s.io/v1beta1
kind : KubeletConfiguration
...
cgroupDriver : systemd
说明:
从 v1.22 开始,在使用 kubeadm 创建集群时,如果用户没有在
KubeletConfiguration
下设置 cgroupDriver
字段,kubeadm 默认使用 systemd
。
在 Kubernetes v1.28 中,启用 KubeletCgroupDriverFromCRI
特性门控 结合支持
RuntimeConfig
CRI RPC 的容器运行时,kubelet 会自动从运行时检测适当的 Cgroup
驱动程序,并忽略 kubelet 配置中的 cgroupDriver
设置。
如果你将 systemd
配置为 kubelet 的 cgroup 驱动,你也必须将 systemd
配置为容器运行时的 cgroup 驱动。参阅容器运行时文档,了解指示说明。例如:
注意:
注意:更改已加入集群的节点的 cgroup 驱动是一项敏感的操作。
如果 kubelet 已经使用某 cgroup 驱动的语义创建了 Pod,更改运行时以使用别的
cgroup 驱动,当为现有 Pod 重新创建 PodSandbox 时会产生错误。
重启 kubelet 也可能无法解决此类问题。
如果你有切实可行的自动化方案,使用其他已更新配置的节点来替换该节点,
或者使用自动化方案来重新安装。
将 kubeadm 管理的集群迁移到 systemd
驱动
如果你希望将现有的由 kubeadm 管理的集群迁移到 systemd
cgroup 驱动,
请按照配置 cgroup 驱动 操作。
CRI 版本支持
你的容器运行时必须至少支持 v1alpha2 版本的容器运行时接口。
Kubernetes 从 1.26 版本开始 仅适用于
v1 版本的容器运行时(CRI)API。早期版本默认为 v1 版本,
但是如果容器运行时不支持 v1 版本的 API,
则 kubelet 会回退到使用(已弃用的)v1alpha2 版本的 API。
容器运行时
说明:  本部分链接到提供 Kubernetes 所需功能的第三方项目。Kubernetes 项目作者不负责这些项目。此页面遵循
CNCF 网站指南 ,按字母顺序列出项目。要将项目添加到此列表中,请在提交更改之前阅读
内容指南 。
containerd
本节概述了使用 containerd 作为 CRI 运行时的必要步骤。
要在系统上安装 containerd,请按照开始使用 containerd
的说明进行操作。创建有效的 config.toml
配置文件后返回此步骤。
你可以在路径 /etc/containerd/config.toml
下找到此文件。
你可以在路径 C:\Program Files\containerd\config.toml
下找到此文件。
在 Linux 上,containerd 的默认 CRI 套接字是 /run/containerd/containerd.sock
。
在 Windows 上,默认 CRI 端点是 npipe://./pipe/containerd-containerd
。
配置 systemd
cgroup 驱动
结合 runc
使用 systemd
cgroup 驱动,在 /etc/containerd/config.toml
中设置:
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
...
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
如果你使用 cgroup v2 ,则推荐 systemd
cgroup 驱动。
说明:
如果你从软件包(例如,RPM 或者 .deb
)中安装 containerd,你可能会发现其中默认禁止了
CRI 集成插件。
你需要启用 CRI 支持才能在 Kubernetes 集群中使用 containerd。
要确保 cri
没有出现在 /etc/containerd/config.toml
文件中 disabled_plugins
列表内。如果你更改了这个文件,也请记得要重启 containerd
。
如果你在初次安装集群后或安装 CNI 后遇到容器崩溃循环,则随软件包提供的 containerd
配置可能包含不兼容的配置参数。考虑按照
getting-started.md
中指定的 containerd config default > /etc/containerd/config.toml
重置 containerd
配置,然后相应地设置上述配置参数。
如果你应用此更改,请确保重新启动 containerd:
sudo systemctl restart containerd
当使用 kubeadm 时,请手动配置
kubelet 的 cgroup 驱动 。
在 Kubernetes v1.28 中,你可以启用 Cgroup 驱动程序的自动检测的 Alpha 级别特性。
详情参阅 systemd cgroup 驱动 。
重载沙箱(pause)镜像
在你的 containerd 配置 中,
你可以通过设置以下选项重载沙箱镜像:
[plugins."io.containerd.grpc.v1.cri" ]
sandbox_image = "registry.k8s.io/pause:3.2"
一旦你更新了这个配置文件,可能就同样需要重启 containerd
:systemctl restart containerd
。
请注意,声明匹配的 pod-infra-container-image
是 kubelet 的最佳实践。
如果未配置,kubelet 可能会尝试对 pause
镜像进行垃圾回收。
containerd 固定 pause 镜像 的工作正在进行中,
将不再需要在 kubelet 上进行此设置。
CRI-O
本节包含安装 CRI-O 作为容器运行时的必要步骤。
要安装 CRI-O,请按照 CRI-O 安装说明 执行操作。
cgroup 驱动
CRI-O 默认使用 systemd cgroup 驱动,这对你来说可能工作得很好。
要切换到 cgroupfs
cgroup 驱动,请编辑 /etc/crio/crio.conf
或在
/etc/crio/crio.conf.d/02-cgroup-manager.conf
中放置一个插入式配置,例如:
[crio.runtime]
conmon_cgroup = "pod"
cgroup_manager = "cgroupfs"
你还应该注意当使用 CRI-O 时,并且 CRI-O 的 cgroup 设置为 cgroupfs
时,必须将 conmon_cgroup
设置为值 pod
。
通常需要保持 kubelet 的 cgroup 驱动配置(通常通过 kubeadm 完成)和 CRI-O 同步。
在 Kubernetes v1.28 中,你可以启用 Cgroup 驱动程序的自动检测的 Alpha 级别特性。
详情参阅 systemd cgroup 驱动 。
对于 CRI-O,CRI 套接字默认为 /var/run/crio/crio.sock
。
重载沙箱(pause)镜像
在你的 CRI-O 配置 中,
你可以设置以下配置值:
[crio.image]
pause_image="registry.k8s.io/pause:3.6"
这一设置选项支持动态配置重加载来应用所做变更:systemctl reload crio
。
也可以通过向 crio
进程发送 SIGHUP
信号来实现。
Docker Engine
说明:
以下操作假设你使用 cri-dockerd
适配器来将
Docker Engine 与 Kubernetes 集成。
在你的每个节点上,遵循安装 Docker Engine
指南为你的 Linux 发行版安装 Docker。
请按照文档中的安装部分指示来安装 cri-dockerd
。
对于 cri-dockerd
,默认情况下,CRI 套接字是 /run/cri-dockerd.sock
。
Mirantis 容器运行时
Mirantis Container Runtime (MCR)
是一种商用容器运行时,以前称为 Docker 企业版。
你可以使用 MCR 中包含的开源 cri-dockerd
组件将 Mirantis Container Runtime 与 Kubernetes 一起使用。
要了解有关如何安装 Mirantis Container Runtime 的更多信息,
请访问 MCR 部署指南 。
检查名为 cri-docker.socket
的 systemd 单元以找出 CRI 套接字的路径。
重载沙箱(pause)镜像
cri-dockerd
适配器能够接受指定用作 Pod 的基础容器的容器镜像(“pause 镜像”)作为命令行参数。
要使用的命令行参数是 --pod-infra-container-image
。
接下来
除了容器运行时,你的集群还需要有效的网络插件 。
2.2 - 使用部署工具安装 Kubernetes
搭建你自己的 Kubernetes 生产集群有许多方法和工具。例如:
2.2.1 - 使用 kubeadm 引导集群
2.2.1.1 - 安装 kubeadm
本页面显示如何安装 kubeadm
工具箱。
有关在执行此安装过程后如何使用 kubeadm 创建集群的信息,
请参见使用 kubeadm 创建集群 。
This installation guide is for Kubernetes v1.29. If you want to use a different Kubernetes version, please refer to the following pages instead:
准备开始
一台兼容的 Linux 主机。Kubernetes 项目为基于 Debian 和 Red Hat 的 Linux
发行版以及一些不提供包管理器的发行版提供通用的指令。
每台机器 2 GB 或更多的 RAM(如果少于这个数字将会影响你应用的运行内存)。
CPU 2 核心及以上。
集群中的所有机器的网络彼此均能相互连接(公网和内网都可以)。
节点之中不可以有重复的主机名、MAC 地址或 product_uuid。请参见这里 了解更多详细信息。
开启机器上的某些端口。请参见这里 了解更多详细信息。
交换分区的配置。kubelet 的默认行为是在节点上检测到交换内存时无法启动。
kubelet 自 v1.22 起已开始支持交换分区。自 v1.28 起,仅针对 cgroup v2 支持交换分区;
kubelet 的 NodeSwap 特性门控处于 Beta 阶段,但默认被禁用。
如果 kubelet 未被正确配置使用交换分区,则你必须 禁用交换分区。
例如,sudo swapoff -a
将暂时禁用交换分区。要使此更改在重启后保持不变,请确保在如
/etc/fstab
、systemd.swap
等配置文件中禁用交换分区,具体取决于你的系统如何配置。
说明:
kubeadm
的安装是通过使用动态链接的二进制文件完成的,安装时假设你的目标系统提供 glibc
。
这个假设在许多 Linux 发行版(包括 Debian、Ubuntu、Fedora、CentOS 等)上是合理的,
但对于不包含默认 glibc
的自定义和轻量级发行版(如 Alpine Linux),情况并非总是如此。
预期的情况是,发行版要么包含 glibc
,
要么提供了一个兼容层 以提供所需的符号。
确保每个节点上 MAC 地址和 product_uuid 的唯一性
你可以使用命令 ip link
或 ifconfig -a
来获取网络接口的 MAC 地址
可以使用 sudo cat /sys/class/dmi/id/product_uuid
命令对 product_uuid 校验
一般来讲,硬件设备会拥有唯一的地址,但是有些虚拟机的地址可能会重复。
Kubernetes 使用这些值来唯一确定集群中的节点。
如果这些值在每个节点上不唯一,可能会导致安装失败 。
检查网络适配器
如果你有一个以上的网络适配器,同时你的 Kubernetes 组件通过默认路由不可达,我们建议你预先添加 IP 路由规则,
这样 Kubernetes 集群就可以通过对应的适配器完成连接。
检查所需端口
启用这些必要的端口 后才能使 Kubernetes 的各组件相互通信。
可以使用 netcat 之类的工具来检查端口是否开放,例如:
你使用的 Pod 网络插件 (详见后续章节) 也可能需要开启某些特定端口。
由于各个 Pod 网络插件的功能都有所不同,请参阅他们各自文档中对端口的要求。
安装容器运行时
为了在 Pod 中运行容器,Kubernetes 使用
容器运行时(Container Runtime) 。
默认情况下,Kubernetes 使用
容器运行时接口(Container Runtime Interface,CRI)
来与你所选择的容器运行时交互。
如果你不指定运行时,kubeadm 会自动尝试通过扫描已知的端点列表来检测已安装的容器运行时。
如果检测到有多个或者没有容器运行时,kubeadm 将抛出一个错误并要求你指定一个想要使用的运行时。
参阅容器运行时
以了解更多信息。
说明:
Docker Engine 没有实现 CRI ,
而这是容器运行时在 Kubernetes 中工作所需要的。
为此,必须安装一个额外的服务 cri-dockerd 。
cri-dockerd 是一个基于传统的内置 Docker 引擎支持的项目,
它在 1.24 版本从 kubelet 中移除 。
下面的表格包括被支持的操作系统的已知端点。
Linux 容器运行时
运行时
Unix 域套接字
containerd
unix:///var/run/containerd/containerd.sock
CRI-O
unix:///var/run/crio/crio.sock
Docker Engine(使用 cri-dockerd)
unix:///var/run/cri-dockerd.sock
Windows 容器运行时
运行时
Windows 命名管道路径
containerd
npipe:////./pipe/containerd-containerd
Docker Engine(使用 cri-dockerd)
npipe:////./pipe/cri-dockerd
安装 kubeadm、kubelet 和 kubectl
你需要在每台机器上安装以下的软件包:
kubeadm 不能 帮你安装或者管理 kubelet
或 kubectl
,
所以你需要确保它们与通过 kubeadm 安装的控制平面的版本相匹配。
如果不这样做,则存在发生版本偏差的风险,可能会导致一些预料之外的错误和问题。
然而,控制平面与 kubelet 之间可以存在一个 次要版本的偏差,但 kubelet
的版本不可以超过 API 服务器的版本。
例如,1.7.0 版本的 kubelet 可以完全兼容 1.8.0 版本的 API 服务器,反之则不可以。
有关安装 kubectl
的信息,请参阅安装和设置 kubectl 文档。
警告:
这些指南不包括系统升级时使用的所有 Kubernetes 程序包。这是因为 kubeadm 和 Kubernetes
有特殊的升级注意事项 。
关于版本偏差的更多信息,请参阅以下文档:
说明: The legacy package repositories (
apt.kubernetes.io
and
yum.kubernetes.io
) have been
deprecated and frozen starting from September 13, 2023 .
Using the new package repositories hosted at pkgs.k8s.io
is strongly recommended and required in order to install Kubernetes versions released after September 13, 2023.
The deprecated legacy repositories, and their contents, might be removed at any time in the future and without
a further notice period. The new package repositories provide downloads for Kubernetes versions starting with v1.24.0.
说明:
每个 Kubernetes 小版本都有一个专用的软件包仓库。
如果你想安装 1.29 以外的次要版本,请参阅所需次要版本的安装指南。
以下指令适用于 Kubernetes 1.29.
更新 apt
包索引并安装使用 Kubernetes apt
仓库所需要的包:
sudo apt-get update
# apt-transport-https 可能是一个虚拟包(dummy package);如果是的话,你可以跳过安装这个包
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
下载用于 Kubernetes 软件包仓库的公共签名密钥。所有仓库都使用相同的签名密钥,因此你可以忽略URL中的版本:
# 如果 `/etc/apt/keyrings` 目录不存在,则应在 curl 命令之前创建它,请阅读下面的注释。
# sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
说明:
在低于 Debian 12 和 Ubuntu 22.04 的发行版本中,/etc/apt/keyrings
默认不存在。
应在 curl 命令之前创建它。
添加 Kubernetes apt
仓库。
请注意,此仓库仅包含适用于 Kubernetes 1.29 的软件包;
对于其他 Kubernetes 次要版本,则需要更改 URL 中的 Kubernetes 次要版本以匹配你所需的次要版本
(你还应该检查正在阅读的安装文档是否为你计划安装的 Kubernetes 版本的文档)。
# 此操作会覆盖 /etc/apt/sources.list.d/kubernetes.list 中现存的所有配置。
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
更新 apt
包索引,安装 kubelet、kubeadm 和 kubectl,并锁定其版本:
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
将 SELinux 设置为 permissive
模式:
以下指令适用于 Kubernetes 1.29。
# 将 SELinux 设置为 permissive 模式(相当于将其禁用)
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
注意:
通过运行命令 setenforce 0
和 sed ...
将 SELinux 设置为 permissive 模式相当于将其禁用。
这是允许容器访问主机文件系统所必需的,例如,某些容器网络插件需要这一能力。
你必须这么做,直到 kubelet 改进其对 SELinux 的支持。
如果你知道如何配置 SELinux 则可以将其保持启用状态,但可能需要设定部分 kubeadm 不支持的配置。
添加 Kubernetes 的 yum
仓库。在仓库定义中的 exclude
参数确保了与
Kubernetes 相关的软件包在运行 yum update
时不会升级,因为升级
Kubernetes 需要遵循特定的过程。请注意,此仓库仅包含适用于
Kubernetes 1.29 的软件包;
对于其他 Kubernetes 次要版本,则需要更改 URL 中的 Kubernetes 次要版本以匹配你所需的次要版本
(你还应该检查正在阅读的安装文档是否为你计划安装的 Kubernetes 版本的文档)。
# 此操作会覆盖 /etc/yum.repos.d/kubernetes.repo 中现存的所有配置
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.29/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.29/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF
安装 kubelet、kubeadm 和 kubectl,并启用 kubelet 以确保它在启动时自动启动:
sudo yum install -y kubelet kubeadm kubectl --disableexcludes= kubernetes
sudo systemctl enable --now kubelet
安装 CNI 插件(大多数 Pod 网络都需要):
CNI_PLUGINS_VERSION = "v1.3.0"
ARCH = "amd64"
DEST = "/opt/cni/bin"
sudo mkdir -p " $DEST "
curl -L "https://github.com/containernetworking/plugins/releases/download/ ${ CNI_PLUGINS_VERSION } /cni-plugins-linux- ${ ARCH } - ${ CNI_PLUGINS_VERSION } .tgz" | sudo tar -C " $DEST " -xz
定义要下载命令文件的目录:
说明:
DOWNLOAD_DIR
变量必须被设置为一个可写入的目录。
如果你在运行 Flatcar Container Linux,可设置 DOWNLOAD_DIR="/opt/bin"
。
DOWNLOAD_DIR = "/usr/local/bin"
sudo mkdir -p " $DOWNLOAD_DIR "
安装 crictl(kubeadm/kubelet 容器运行时接口(CRI)所需):
CRICTL_VERSION = "v1.28.0"
ARCH = "amd64"
curl -L "https://github.com/kubernetes-sigs/cri-tools/releases/download/ ${ CRICTL_VERSION } /crictl- ${ CRICTL_VERSION } -linux- ${ ARCH } .tar.gz" | sudo tar -C $DOWNLOAD_DIR -xz
安装 kubeadm
、kubelet
、kubectl
并添加 kubelet
系统服务:
RELEASE = " $( curl -sSL https://dl.k8s.io/release/stable.txt) "
ARCH = "amd64"
cd $DOWNLOAD_DIR
sudo curl -L --remote-name-all https://dl.k8s.io/release/${ RELEASE } /bin/linux/${ ARCH } /{ kubeadm,kubelet}
sudo chmod +x { kubeadm,kubelet}
RELEASE_VERSION = "v0.16.2"
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/ ${ RELEASE_VERSION } /cmd/krel/templates/latest/kubelet/kubelet.service" | sed "s:/usr/bin: ${ DOWNLOAD_DIR } :g" | sudo tee /usr/lib/systemd/system/kubelet.service
sudo mkdir -p /usr/lib/systemd/system/kubelet.service.d
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/ ${ RELEASE_VERSION } /cmd/krel/templates/latest/kubeadm/10-kubeadm.conf" | sed "s:/usr/bin: ${ DOWNLOAD_DIR } :g" | sudo tee /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
说明:
对于默认不包括 glibc
的 Linux 发行版,请参阅开始之前 一节的注释。
请参照安装工具页面 的说明安装 kubelet
。
激活并启动 kubelet
:
systemctl enable --now kubelet
说明:
Flatcar Container Linux 发行版会将 /usr/
目录挂载为一个只读文件系统。
在启动引导你的集群之前,你需要执行一些额外的操作来配置一个可写入的目录。
参见 kubeadm 故障排查指南
以了解如何配置一个可写入的目录。
kubelet 现在每隔几秒就会重启,因为它陷入了一个等待 kubeadm 指令的死循环。
配置 cgroup 驱动程序
容器运行时和 kubelet 都具有名字为
"cgroup driver"
的属性,该属性对于在 Linux 机器上管理 CGroups 而言非常重要。
警告:
你需要确保容器运行时和 kubelet 所使用的是相同的 cgroup 驱动,否则 kubelet
进程会失败。
相关细节可参见配置 cgroup 驱动 。
故障排查
如果你在使用 kubeadm 时遇到困难,
请参阅我们的故障排查文档 。
接下来
2.2.1.2 - 对 kubeadm 进行故障排查
与任何程序一样,你可能会在安装或者运行 kubeadm 时遇到错误。
本文列举了一些常见的故障场景,并提供可帮助你理解和解决这些问题的步骤。
如果你的问题未在下面列出,请执行以下步骤:
由于缺少 RBAC,无法将 v1.18 Node 加入 v1.17 集群
自从 v1.18 后,如果集群中已存在同名 Node,kubeadm 将禁止 Node 加入集群。
这需要为 bootstrap-token 用户添加 RBAC 才能 GET Node 对象。
但这会导致一个问题,v1.18 的 kubeadm join
无法加入由 kubeadm v1.17 创建的集群。
要解决此问题,你有两种选择:
使用 kubeadm v1.18 在控制平面节点上执行 kubeadm init phase bootstrap-token
。
请注意,这也会启用 bootstrap-token 的其余权限。
或者,也可以使用 kubectl apply -f ...
手动应用以下 RBAC:
apiVersion : rbac.authorization.k8s.io/v1
kind : ClusterRole
metadata :
name : kubeadm:get-nodes
rules :
- apiGroups :
- ""
resources :
- nodes
verbs :
- get
---
apiVersion : rbac.authorization.k8s.io/v1
kind : ClusterRoleBinding
metadata :
name : kubeadm:get-nodes
roleRef :
apiGroup : rbac.authorization.k8s.io
kind : ClusterRole
name : kubeadm:get-nodes
subjects :
- apiGroup : rbac.authorization.k8s.io
kind : Group
name : system:bootstrappers:kubeadm:default-node-token
在安装过程中没有找到 ebtables
或者其他类似的可执行文件
如果在运行 kubeadm init
命令时,遇到以下的警告
[preflight] WARNING: ebtables not found in system path
[preflight] WARNING: ethtool not found in system path
那么或许在你的节点上缺失 ebtables
、ethtool
或者类似的可执行文件。
你可以使用以下命令安装它们:
对于 Ubuntu/Debian 用户,运行 apt install ebtables ethtool
命令。
对于 CentOS/Fedora 用户,运行 yum install ebtables ethtool
命令。
在安装过程中,kubeadm 一直等待控制平面就绪
如果你注意到 kubeadm init
在打印以下行后挂起:
[apiclient] Created API client, waiting for the control plane to become ready
这可能是由许多问题引起的。最常见的是:
网络连接问题。在继续之前,请检查你的计算机是否具有全部联通的网络连接。
容器运行时的 cgroup 驱动不同于 kubelet 使用的 cgroup 驱动。要了解如何正确配置 cgroup 驱动,
请参阅配置 cgroup 驱动 。
控制平面上的 Docker 容器持续进入崩溃状态或(因其他原因)挂起。你可以运行 docker ps
命令来检查以及 docker logs
命令来检视每个容器的运行日志。
对于其他容器运行时,请参阅使用 crictl 对 Kubernetes 节点进行调试 。
当删除托管容器时 kubeadm 阻塞
如果容器运行时停止并且未删除 Kubernetes 所管理的容器,可能发生以下情况:
[preflight] Running pre-flight checks
[reset] Stopping the kubelet service
[reset] Unmounting mounted directories in "/var/lib/kubelet"
[reset] Removing kubernetes-managed containers
(block)
一个可行的解决方案是重新启动 Docker 服务,然后重新运行 kubeadm reset
:
你也可以使用 crictl
来调试容器运行时的状态。
参见使用 CRICTL 调试 Kubernetes 节点 。
Pod 处于 RunContainerError
、CrashLoopBackOff
或者 Error
状态
在 kubeadm init
命令运行后,系统中不应该有 Pod 处于这类状态。
在 kubeadm init
命令执行完后,如果有 Pod 处于这些状态之一,请在 kubeadm
仓库提起一个 issue。coredns
(或者 kube-dns
) 应该处于 Pending
状态,
直到你部署了网络插件为止。
如果在部署完网络插件之后,有 Pod 处于 RunContainerError
、CrashLoopBackOff
或 Error
状态之一,并且 coredns
(或者 kube-dns
)仍处于 Pending
状态,
那很可能是你安装的网络插件由于某种原因无法工作。你或许需要授予它更多的
RBAC 特权或使用较新的版本。请在 Pod Network 提供商的问题跟踪器中提交问题,
然后在此处分类问题。
coredns
停滞在 Pending
状态
这一行为是预期之中 的,因为系统就是这么设计的。kubeadm 的网络供应商是中立的,
因此管理员应该选择安装 Pod 的网络插件 。
你必须完成 Pod 的网络配置,然后才能完全部署 CoreDNS。
在网络被配置好之前,DNS 组件会一直处于 Pending
状态。
HostPort
服务无法工作
此 HostPort
和 HostIP
功能是否可用取决于你的 Pod 网络配置。请联系 Pod 网络插件的作者,
以确认 HostPort
和 HostIP
功能是否可用。
已验证 Calico、Canal 和 Flannel CNI 驱动程序支持 HostPort。
有关更多信息,请参考 CNI portmap 文档 .
如果你的网络提供商不支持 portmap CNI 插件,你或许需要使用
NodePort 服务的功能 或者使用
HostNetwork=true
。
无法通过其服务 IP 访问 Pod
许多网络附加组件尚未启用 hairpin 模式
该模式允许 Pod 通过其服务 IP 进行访问。这是与 CNI 有关的问题。
请与网络附加组件提供商联系,以获取他们所提供的 hairpin 模式的最新状态。
如果你正在使用 VirtualBox (直接使用或者通过 Vagrant 使用),你需要
确保 hostname -i
返回一个可路由的 IP 地址。默认情况下,第一个接口连接不能路由的仅主机网络。
解决方法是修改 /etc/hosts
,请参考示例
Vagrantfile 。
TLS 证书错误
以下错误说明证书可能不匹配。
# kubectl get pods
Unable to connect to the server: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "kubernetes")
验证 $HOME/.kube/config
文件是否包含有效证书,
并在必要时重新生成证书。在 kubeconfig 文件中的证书是 base64 编码的。
该 base64 --decode
命令可以用来解码证书,openssl x509 -text -noout
命令可以用于查看证书信息。
使用如下方法取消设置 KUBECONFIG
环境变量的值:
或者将其设置为默认的 KUBECONFIG
位置:
export KUBECONFIG = /etc/kubernetes/admin.conf
Kubelet 客户端证书轮换失败
默认情况下,kubeadm 使用 /etc/kubernetes/kubelet.conf
中指定的 /var/lib/kubelet/pki/kubelet-client-current.pem
符号链接来配置 kubelet 自动轮换客户端证书。如果此轮换过程失败,你可能会在 kube-apiserver 日志中看到诸如
x509: certificate has expired or is not yet valid
之类的错误。要解决此问题,你必须执行以下步骤:
从故障节点备份和删除 /etc/kubernetes/kubelet.conf
和 /var/lib/kubelet/pki/kubelet-client*
。
在集群中具有 /etc/kubernetes/pki/ca.key
的、正常工作的控制平面节点上
执行 kubeadm kubeconfig user --org system:nodes --client-name system:node:$NODE > kubelet.conf
。
$NODE
必须设置为集群中现有故障节点的名称。
手动修改生成的 kubelet.conf
以调整集群名称和服务器端点,
或传递 kubeconfig user --config
(请参阅为其他用户生成 kubeconfig 文件 )。
如果你的集群没有 ca.key
,你必须在外部对 kubelet.conf
中的嵌入式证书进行签名。
将得到的 kubelet.conf
文件复制到故障节点上,作为 /etc/kubernetes/kubelet.conf
。
在故障节点上重启 kubelet(systemctl restart kubelet
),等待 /var/lib/kubelet/pki/kubelet-client-current.pem
重新创建。
手动编辑 kubelet.conf
指向轮换的 kubelet 客户端证书,方法是将 client-certificate-data
和 client-key-data
替换为:
client-certificate : /var/lib/kubelet/pki/kubelet-client-current.pem
client-key : /var/lib/kubelet/pki/kubelet-client-current.pem
重新启动 kubelet。
确保节点状况变为 Ready
。
在 Vagrant 中使用 flannel 作为 Pod 网络时的默认 NIC
以下错误可能表明 Pod 网络中出现问题:
Error from server (NotFound): the server could not find the requested resource
如果你正在 Vagrant 中使用 flannel 作为 Pod 网络,则必须指定 flannel 的默认接口名称。
Vagrant 通常为所有 VM 分配两个接口。第一个为所有主机分配了 IP 地址 10.0.2.15
,用于获得 NATed 的外部流量。
这可能会导致 flannel 出现问题,它默认为主机上的第一个接口。这导致所有主机认为它们具有相同的公共
IP 地址。为防止这种情况,传递 --iface eth1
标志给 flannel 以便选择第二个接口。
容器使用的非公共 IP
在某些情况下 kubectl logs
和 kubectl run
命令或许会返回以下错误,即便除此之外集群一切功能正常:
Error from server: Get https://10.19.0.41:10250/containerLogs/default/mysql-ddc65b868-glc5m/mysql: dial tcp 10.19.0.41:10250: getsockopt: no route to host
这或许是由于 Kubernetes 使用的 IP 无法与看似相同的子网上的其他 IP 进行通信的缘故,
可能是由机器提供商的政策所导致的。
DigitalOcean 既分配一个共有 IP 给 eth0
,也分配一个私有 IP 在内部用作其浮动 IP 功能的锚点,
然而 kubelet
将选择后者作为节点的 InternalIP
而不是公共 IP。
使用 ip addr show
命令代替 ifconfig
命令去检查这种情况,因为 ifconfig
命令
不会显示有问题的别名 IP 地址。或者指定的 DigitalOcean 的 API 端口允许从 droplet 中
查询 anchor IP:
curl http://169.254.169.254/metadata/v1/interfaces/public/0/anchor_ipv4/address
解决方法是通知 kubelet
使用哪个 --node-ip
。当使用 DigitalOcean 时,可以是(分配给 eth0
的)公网 IP,
或者是(分配给 eth1
的)私网 IP。私网 IP 是可选的。
kubadm NodeRegistrationOptions
结构
的 KubeletExtraArgs
部分被用来处理这种情况。
然后重启 kubelet
:
systemctl daemon-reload
systemctl restart kubelet
coredns
Pod 有 CrashLoopBackOff
或者 Error
状态
如果有些节点运行的是旧版本的 Docker,同时启用了 SELinux,你或许会遇到 coredns
Pod 无法启动的情况。
要解决此问题,你可以尝试以下选项之一:
kubectl -n kube-system get deployment coredns -o yaml | \
sed 's/allowPrivilegeEscalation: false/allowPrivilegeEscalation: true/g' | \
kubectl apply -f -
CoreDNS 处于 CrashLoopBackOff
时的另一个原因是当 Kubernetes 中部署的 CoreDNS Pod 检测到环路时。
有许多解决方法
可以避免在每次 CoreDNS 监测到循环并退出时,Kubernetes 尝试重启 CoreDNS Pod 的情况。
警告:
禁用 SELinux 或设置 allowPrivilegeEscalation
为 true
可能会损害集群的安全性。
etcd Pod 持续重启
如果你遇到以下错误:
rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:247: starting container process caused "process_linux.go:110: decoding init error from pipe caused \"read parent: connection reset by peer\""
如果你使用 Docker 1.13.1.84 运行 CentOS 7 就会出现这种问题。
此版本的 Docker 会阻止 kubelet 在 etcd 容器中执行。
为解决此问题,请选择以下选项之一:
安装较新的推荐版本之一,例如 18.06:
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install docker-ce-18.06.1.ce-3.el7.x86_64
kubeadm init
标志例如 --component-extra-args
允许你将自定义参数传递给像
kube-apiserver 这样的控制平面组件。然而,由于解析 (mapStringString
) 的基础类型值,此机制将受到限制。
如果你决定传递一个支持多个逗号分隔值(例如
--apiserver-extra-args "enable-admission-plugins=LimitRanger,NamespaceExists"
)参数,
将出现 flag: malformed pair, expect string=string
错误。
发生这种问题是因为参数列表 --apiserver-extra-args
预期的是 key=value
形式,
而这里的 NamespacesExists
被误认为是缺少取值的键名。
一种解决方法是尝试分离 key=value
对,像这样:
--apiserver-extra-args "enable-admission-plugins=LimitRanger,enable-admission-plugins=NamespaceExists"
但这将导致键 enable-admission-plugins
仅有值 NamespaceExists
。
已知的解决方法是使用 kubeadm
配置文件 。
在节点被云控制管理器初始化之前,kube-proxy 就被调度了
在云环境场景中,可能出现在云控制管理器完成节点地址初始化之前,kube-proxy 就被调度到新节点了。
这会导致 kube-proxy 无法正确获取节点的 IP 地址,并对管理负载平衡器的代理功能产生连锁反应。
在 kube-proxy Pod 中可以看到以下错误:
server.go:610] Failed to retrieve node IP: host IP unknown; known addresses: []
proxier.go:340] invalid nodeIP, initializing kube-proxy with 127.0.0.1 as nodeIP
一种已知的解决方案是修补 kube-proxy DaemonSet,以允许在控制平面节点上调度它,
而不管它们的条件如何,将其与其他节点保持隔离,直到它们的初始保护条件消除:
kubectl -n kube-system patch ds kube-proxy -p= '{
"spec": {
"template": {
"spec": {
"tolerations": [
{
"key": "CriticalAddonsOnly",
"operator": "Exists"
},
{
"effect": "NoSchedule",
"key": "node-role.kubernetes.io/control-plane"
}
]
}
}
}
}'
此问题的跟踪在这里 。
节点上的 /usr
被以只读方式挂载
在类似 Fedora CoreOS 或者 Flatcar Container Linux 这类 Linux 发行版本中,
目录 /usr
是以只读文件系统的形式挂载的。
在支持 FlexVolume 时,
类似 kubelet 和 kube-controller-manager 这类 Kubernetes 组件使用默认路径
/usr/libexec/kubernetes/kubelet-plugins/volume/exec/
,
而 FlexVolume 的目录必须是可写入的 ,该功能特性才能正常工作。
说明:
FlexVolume 在 Kubernetes v1.23 版本中已被弃用。
为了解决这个问题,你可以使用 kubeadm 的配置文件 来配置
FlexVolume 的目录。
在(使用 kubeadm init
创建的)主控制节点上,使用 --config
参数传入如下文件:
apiVersion : kubeadm.k8s.io/v1beta3
kind : InitConfiguration
nodeRegistration :
kubeletExtraArgs :
volume-plugin-dir : "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
---
apiVersion : kubeadm.k8s.io/v1beta3
kind : ClusterConfiguration
controllerManager :
extraArgs :
flex-volume-plugin-dir : "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
在加入到集群中的节点上,使用下面的文件:
apiVersion : kubeadm.k8s.io/v1beta3
kind : JoinConfiguration
nodeRegistration :
kubeletExtraArgs :
volume-plugin-dir : "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
或者,你可以更改 /etc/fstab
使得 /usr
目录能够以可写入的方式挂载,
不过请注意这样做本质上是在更改 Linux 发行版的某种设计原则。
kubeadm upgrade plan
输出错误信息 context deadline exceeded
在使用 kubeadm
来升级某运行外部 etcd 的 Kubernetes 集群时可能显示这一错误信息。
这并不是一个非常严重的一个缺陷,之所以出现此错误信息,原因是老的 kubeadm
版本会对外部 etcd 集群执行版本检查。你可以继续执行 kubeadm upgrade apply ...
。
这一问题已经在 1.19 版本中得到修复。
kubeadm reset
会卸载 /var/lib/kubelet
如果已经挂载了 /var/lib/kubelet
目录,执行 kubeadm reset
操作的时候会将其卸载。
要解决这一问题,可以在执行了 kubeadm reset
操作之后重新挂载
/var/lib/kubelet
目录。
这是一个在 1.15 中引入的故障,已经在 1.20 版本中修复。
无法在 kubeadm 集群中安全地使用 metrics-server
在 kubeadm 集群中可以通过为 metrics-server
设置 --kubelet-insecure-tls
来以不安全的形式使用该服务。
建议不要在生产环境集群中这样使用。
如果你需要在 metrics-server 和 kubelet 之间使用 TLS,会有一个问题,
kubeadm 为 kubelet 部署的是自签名的服务证书。这可能会导致 metrics-server
端报告下面的错误信息:
x509: certificate signed by unknown authority
x509: certificate is valid for IP-foo not IP-bar
参见为 kubelet 启用签名的服务证书
以进一步了解如何在 kubeadm 集群中配置 kubelet 使用正确签名了的服务证书。
另请参阅 How to run the metrics-server securely 。
因 etcd 哈希值无变化而升级失败
仅适用于通过 kubeadm 二进制文件 v1.28.3 或更高版本升级控制平面节点的情况,
其中此节点当前由 kubeadm v1.28.0、v1.28.1 或 v1.28.2 管理。
以下是你可能遇到的错误消息:
[upgrade/etcd] Failed to upgrade etcd: couldn't upgrade control plane. kubeadm has tried to recover everything into the earlier state. Errors faced: static Pod hash for component etcd on Node kinder-upgrade-control-plane-1 did not change after 5m0s: timed out waiting for the condition
[upgrade/etcd] Waiting for previous etcd to become available
I0907 10:10:09.109104 3704 etcd.go:588] [etcd] attempting to see if all cluster endpoints ([https://172.17.0.6:2379/ https://172.17.0.4:2379/ https://172.17.0.3:2379/]) are available 1/10
[upgrade/etcd] Etcd was rolled back and is now available
static Pod hash for component etcd on Node kinder-upgrade-control-plane-1 did not change after 5m0s: timed out waiting for the condition
couldn't upgrade control plane. kubeadm has tried to recover everything into the earlier state. Errors faced
k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade.rollbackOldManifests
cmd/kubeadm/app/phases/upgrade/staticpods.go:525
k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade.upgradeComponent
cmd/kubeadm/app/phases/upgrade/staticpods.go:254
k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade.performEtcdStaticPodUpgrade
cmd/kubeadm/app/phases/upgrade/staticpods.go:338
...
本次失败的原因是受影响的版本在 PodSpec 中生成的 etcd 清单文件带有不需要的默认值。
这将导致与清单比较的差异,并且 kubeadm 预期 Pod 哈希值将发生变化,但 kubelet 永远不会更新哈希值。
如果你在集群中遇到此问题,有两种解决方法:
有关此错误的更多信息,请查阅此问题的跟踪页面 。
2.2.1.3 - 使用 kubeadm 创建集群
使用 kubeadm
,你能创建一个符合最佳实践的最小化 Kubernetes 集群。
事实上,你可以使用 kubeadm
配置一个通过
Kubernetes 一致性测试 的集群。
kubeadm
还支持其他集群生命周期功能,
例如启动引导令牌 和集群升级。
kubeadm
工具很棒,如果你需要:
一个尝试 Kubernetes 的简单方法。
一个现有用户可以自动设置集群并测试其应用程序的途径。
其他具有更大范围的生态系统和/或安装工具中的构建模块。
你可以在各种机器上安装和使用 kubeadm
:笔记本电脑、一组云服务器、Raspberry Pi 等。
无论是部署到云还是本地,你都可以将 kubeadm
集成到 Ansible 或 Terraform 这类预配置系统中。
准备开始
要遵循本指南,你需要:
一台或多台运行兼容 deb/rpm 的 Linux 操作系统的计算机;例如:Ubuntu 或 CentOS。
每台机器 2 GB 以上的内存,内存不足时应用会受限制。
用作控制平面节点的计算机上至少有 2 个 CPU。
集群中所有计算机之间具有完全的网络连接。你可以使用公共网络或专用网络。
你还需要使用可以在新集群中部署特定 Kubernetes 版本对应的 kubeadm
。
Kubernetes 版本及版本偏差策略 适用于
kubeadm
以及整个 Kubernetes。
查阅该策略以了解支持哪些版本的 Kubernetes 和 kubeadm
。
该页面是为 Kubernetes v1.29 编写的。
kubeadm
工具的整体功能状态为一般可用性(GA)。一些子功能仍在积极开发中。
随着工具的发展,创建集群的实现可能会略有变化,但总体实现应相当稳定。
说明:
根据定义,在 kubeadm alpha
下的所有命令均在 Alpha 级别上受支持。
目标
安装单个控制平面的 Kubernetes 集群
在集群上安装 Pod 网络,以便你的 Pod 可以相互连通
操作指南
主机准备
安装组件
在所有主机上安装容器运行时 和 kubeadm。
详细说明和其他前提条件,请参见安装 kubeadm 。
说明:
如果你已经安装了 kubeadm,
请查看升级 Linux 节点 文档的前两步,
了解如何升级 kubeadm 的说明。
升级时,kubelet 每隔几秒钟重新启动一次,
在 crashloop 状态中等待 kubeadm 发布指令。crashloop 状态是正常现象。
初始化控制平面后,kubelet 将正常运行。
网络设置
kubeadm 与其他 Kubernetes 组件类似,会尝试在与主机默认网关关联的网络接口上找到可用的 IP 地址。
这个 IP 地址随后用于由某组件执行的公告和/或监听。
要在 Linux 主机上获得此 IP 地址,你可以使用以下命令:
ip route show # 查找以 "default via" 开头的行
说明:
如果主机上存在两个或多个默认网关,Kubernetes 组件将尝试使用遇到的第一个具有合适全局单播 IP 地址的网关。
在做出这个选择时,网关的确切顺序可能因不同的操作系统和内核版本而有所差异。
Kubernetes 组件不接受自定义网络接口作为选项,因此必须将自定义 IP
地址作为标志传递给所有需要此自定义配置的组件实例。
说明:
如果主机没有默认网关,并且没有将自定义 IP 地址传递给 Kubernetes 组件,此组件可能会因错误而退出。
要为使用 init
或 join
创建的控制平面节点配置 API 服务器的公告地址,
你可以使用 --apiserver-advertise-address
标志。
最好在 kubeadm API 中使用
InitConfiguration.localAPIEndpoint
和 JoinConfiguration.controlPlane.localAPIEndpoint
来设置此选项。
对于所有节点上的 kubelet,--node-ip
选项可以在 kubeadm 配置文件
(InitConfiguration
或 JoinConfiguration
)的 .nodeRegistration.kubeletExtraArgs
中设置。
有关双协议栈细节参见使用 kubeadm 支持双协议栈 。
你分配给控制平面组件的 IP 地址将成为其 X.509 证书的使用者备用名称字段的一部分。
更改这些 IP 地址将需要签署新的证书并重启受影响的组件,
以便反映证书文件中的变化。有关此主题的更多细节参见
手动续期证书 。
警告:
Kubernetes 项目不推荐此方法(使用自定义 IP 地址配置所有组件实例)。
Kubernetes 维护者建议设置主机网络,使默认网关 IP 成为 Kubernetes 组件自动检测和使用的 IP。
对于 Linux 节点,你可以使用诸如 ip route
的命令来配置网络;
你的操作系统可能还提供更高级的网络管理工具。
如果节点的默认网关是公共 IP 地址,你应配置数据包过滤或其他保护节点和集群的安全措施。
准备所需的容器镜像
这个步骤是可选的,只适用于你希望 kubeadm init
和 kubeadm join
不去下载存放在
registry.k8s.io
上的默认容器镜像的情况。
当你在离线的节点上创建一个集群的时候,kubeadm 有一些命令可以帮助你预拉取所需的镜像。
阅读离线运行 kubeadm
获取更多的详情。
kubeadm 允许你给所需要的镜像指定一个自定义的镜像仓库。
阅读使用自定义镜像 获取更多的详情。
初始化控制平面节点
控制平面节点是运行控制平面组件的机器,
包括 etcd (集群数据库)
和 API 服务器
(命令行工具 kubectl 与之通信)。
(推荐)如果计划将单个控制平面 kubeadm 集群升级成高可用,
你应该指定 --control-plane-endpoint
为所有控制平面节点设置共享端点。
端点可以是负载均衡器的 DNS 名称或 IP 地址。
选择一个 Pod 网络插件,并验证是否需要为 kubeadm init
传递参数。
根据你选择的第三方网络插件,你可能需要设置 --pod-network-cidr
的值。
请参阅安装 Pod 网络附加组件 。
(可选)kubeadm
试图通过使用已知的端点列表来检测容器运行时。
使用不同的容器运行时或在预配置的节点上安装了多个容器运行时,请为 kubeadm init
指定 --cri-socket
参数。
请参阅安装运行时 。
要初始化控制平面节点,请运行:
关于 apiserver-advertise-address 和 ControlPlaneEndpoint 的注意事项
--apiserver-advertise-address
可用于为控制平面节点的 API 服务器设置广播地址,
--control-plane-endpoint
可用于为所有控制平面节点设置共享端点。
--control-plane-endpoint
允许 IP 地址和可以映射到 IP 地址的 DNS 名称。
请与你的网络管理员联系,以评估有关此类映射的可能解决方案。
这是一个示例映射:
192.168.0.102 cluster-endpoint
其中 192.168.0.102
是此节点的 IP 地址,cluster-endpoint
是映射到该 IP 的自定义 DNS 名称。
这将允许你将 --control-plane-endpoint=cluster-endpoint
传递给 kubeadm init
,
并将相同的 DNS 名称传递给 kubeadm join
。稍后你可以修改 cluster-endpoint
以指向高可用性方案中的负载均衡器的地址。
kubeadm 不支持将没有 --control-plane-endpoint
参数的单个控制平面集群转换为高可用性集群。
有关 kubeadm init
参数的更多信息,请参见 kubeadm 参考指南 。
要使用配置文件配置 kubeadm init
命令,
请参见带配置文件使用 kubeadm init 。
要自定义控制平面组件,包括可选的对控制平面组件和 etcd 服务器的活动探针提供 IPv6 支持,
请参阅自定义参数 。
要重新配置一个已经创建的集群,
请参见重新配置一个 kubeadm 集群 。
要再次运行 kubeadm init
,你必须首先卸载集群 。
如果将具有不同架构的节点加入集群,
请确保已部署的 DaemonSet 对这种体系结构具有容器镜像支持。
kubeadm init
首先运行一系列预检查以确保机器为运行 Kubernetes 准备就绪。
这些预检查会显示警告并在错误时退出。然后 kubeadm init
下载并安装集群控制平面组件。这可能会需要几分钟。完成之后你应该看到:
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a Pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
/docs/concepts/cluster-administration/addons/
You can now join any number of machines by running the following on each node
as root:
kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
要使非 root 用户可以运行 kubectl,请运行以下命令,
它们也是 kubeadm init
输出的一部分:
mkdir -p $HOME /.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME /.kube/config
sudo chown $( id -u) :$( id -g) $HOME /.kube/config
或者,如果你是 root
用户,则可以运行:
export KUBECONFIG = /etc/kubernetes/admin.conf
警告:
kubeadm init
生成的 kubeconfig 文件 admin.conf
包含一个带有 Subject: O = kubeadm:cluster-admins, CN = kubernetes-admin
的证书。
kubeadm:cluster-admins
组被绑定到内置的 cluster-admin
ClusterRole 上。
不要与任何人共享 admin.conf
文件。
kubeadm init
生成另一个 kubeconfig 文件 super-admin.conf
,
其中包含带有 Subject: O = system:masters, CN = kubernetes-super-admin
的证书。
system:masters
是一个紧急访问、超级用户组,可以绕过授权层(例如 RBAC)。
不要与任何人共享 super-admin.conf
文件,建议将其移动到安全位置。
有关如何使用 kubeadm kubeconfig user
为其他用户生成 kubeconfig
文件,请参阅为其他用户生成 kubeconfig 文件 。
记录 kubeadm init
输出的 kubeadm join
命令。
你需要此命令将节点加入集群 。
令牌用于控制平面节点和加入节点之间的相互身份验证。
这里包含的令牌是密钥。确保它的安全,
因为拥有此令牌的任何人都可以将经过身份验证的节点添加到你的集群中。
可以使用 kubeadm token
命令列出,创建和删除这些令牌。
请参阅 kubeadm 参考指南 。
安装 Pod 网络附加组件
注意:
本节包含有关网络设置和部署顺序的重要信息。在继续之前,请仔细阅读所有建议。
你必须部署一个基于 Pod 网络插件的容器网络接口 (CNI),
以便你的 Pod 可以相互通信。在安装网络之前,集群 DNS (CoreDNS) 将不会启动。
注意你的 Pod 网络不得与任何主机网络重叠:如果有重叠,你很可能会遇到问题。
(如果你发现网络插件的首选 Pod 网络与某些主机网络之间存在冲突,
则应考虑使用一个合适的 CIDR 块来代替,
然后在执行 kubeadm init
时使用 --pod-network-cidr
参数并在你的网络插件的 YAML 中替换它)。
默认情况下,kubeadm
将集群设置为使用和强制使用
RBAC (基于角色的访问控制)。
确保你的 Pod 网络插件支持 RBAC,以及用于部署它的清单也是如此。
如果要为集群使用 IPv6(双协议栈或仅单协议栈 IPv6 网络),
请确保你的 Pod 网络插件支持 IPv6。
IPv6 支持已在 CNI v0.6.0 版本中添加。
说明:
kubeadm 应该是与 CNI 无关的,对 CNI 驱动进行验证目前不在我们的端到端测试范畴之内。
如果你发现与 CNI 插件相关的问题,应在其各自的问题跟踪器中记录而不是在 kubeadm
或 kubernetes 问题跟踪器中记录。
一些外部项目为 Kubernetes 提供使用 CNI 的 Pod 网络,
其中一些还支持网络策略 。
请参阅实现
Kubernetes 网络模型 的附加组件列表。
请参阅安装插件 页面,
了解 Kubernetes 支持的网络插件的非详尽列表。
你可以使用以下命令在控制平面节点或具有 kubeconfig 凭据的节点上安装 Pod 网络附加组件:
kubectl apply -f <add-on.yaml>
每个集群只能安装一个 Pod 网络。
安装 Pod 网络后,你可以通过在 kubectl get pods --all-namespaces
输出中检查
CoreDNS Pod 是否 Running
来确认其是否正常运行。
一旦 CoreDNS Pod 启用并运行,你就可以继续加入节点。
如果你的网络无法正常工作或 CoreDNS 不在 Running
状态,请查看 kubeadm
的故障排除指南 。
托管节点标签
默认情况下,kubeadm 启用 NodeRestriction
准入控制器来限制 kubelet 在节点注册时可以应用哪些标签。准入控制器文档描述 kubelet --node-labels
选项允许使用哪些标签。
其中 node-role.kubernetes.io/control-plane
标签就是这样一个受限制的标签,
kubeadm 在节点创建后使用特权客户端手动应用此标签。
你可以使用一个有特权的 kubeconfig,比如由 kubeadm 管理的 /etc/kubernetes/admin.conf
,
通过执行 kubectl label
来手动完成操作。
控制平面节点隔离
默认情况下,出于安全原因,你的集群不会在控制平面节点上调度 Pod。
如果你希望能够在单机 Kubernetes 集群等控制平面节点上调度 Pod,请运行:
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
输出看起来像:
node "test-01" untainted
...
这将从任何拥有 node-role.kubernetes.io/control-plane:NoSchedule
污点的节点(包括控制平面节点)上移除该污点。
这意味着调度程序将能够在任何地方调度 Pod。
此外,你可以执行以下命令从控制平面节点中删除
node.kubernetes.io/exclude-from-external-load-balancers
标签,这会将其从后端服务器列表中排除:
kubectl label nodes --all node.kubernetes.io/exclude-from-external-load-balancers-
加入节点
节点是你的工作负载(容器和 Pod 等)运行的地方。要将新节点添加到集群,请对每台计算机执行以下操作:
如果你没有令牌,可以通过在控制平面节点上运行以下命令来获取令牌:
输出类似于以下内容:
TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS
8ewj1p.9r9hcjoqgajrj4gi 23h 2018-06-12T02:51:28Z authentication, The default bootstrap system:
signing token generated by bootstrappers:
'kubeadm init'. kubeadm:
default-node-token
默认情况下,令牌会在 24 小时后过期。如果要在当前令牌过期后将节点加入集群,
则可以通过在控制平面节点上运行以下命令来创建新令牌:
输出类似于以下内容:
如果你没有 --discovery-token-ca-cert-hash
的值,则可以通过在控制平面节点上执行以下命令链来获取它:
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \
openssl dgst -sha256 -hex | sed 's/^.* //'
输出类似于以下内容:
8cb2de97839780a412b93877f8507ad6c94f73add17d5d7058e91741c9d5ec78
说明:
要为 <control-plane-host>:<control-plane-port>
指定 IPv6 元组,必须将 IPv6
地址括在方括号中,例如 [2001:db8::101]:2073
。
输出应类似于:
[preflight] Running pre-flight checks
... (log output of join workflow) ...
Node join complete:
* Certificate signing request sent to control-plane and response
received.
* Kubelet informed of new secure connection details.
Run 'kubectl get nodes' on control-plane to see this machine join.
几秒钟后,当你在控制平面节点上执行 kubectl get nodes
,你会注意到该节点出现在输出中。
说明:
由于集群节点通常是按顺序初始化的,CoreDNS Pod 很可能都运行在第一个控制面节点上。
为了提供更高的可用性,请在加入至少一个新节点后使用
kubectl -n kube-system rollout restart deployment coredns
命令,重新平衡这些 CoreDNS Pod。
(可选)从控制平面节点以外的计算机控制集群
为了使 kubectl 在其他计算机(例如笔记本电脑)上与你的集群通信,
你需要将管理员 kubeconfig 文件从控制平面节点复制到工作站,如下所示:
scp root@<control-plane-host>:/etc/kubernetes/admin.conf .
kubectl --kubeconfig ./admin.conf get nodes
说明:
上面的示例假定为 root 用户启用了 SSH 访问。如果不是这种情况,
你可以使用 scp
将 admin.conf
文件复制给其他允许访问的用户。
admin.conf 文件为用户提供了对集群的超级用户特权。
该文件应谨慎使用。对于普通用户,建议生成一个你为其授予特权的唯一证书。
你可以使用 kubeadm kubeconfig user --client-name <CN>
命令执行此操作。
该命令会将 KubeConfig 文件打印到 STDOUT,你应该将其保存到文件并分发给用户。
之后,使用 kubectl create (cluster)rolebinding
授予特权。
(可选)将 API 服务器代理到本地主机
如果你要从集群外部连接到 API 服务器,则可以使用 kubectl proxy
:
scp root@<control-plane-host>:/etc/kubernetes/admin.conf .
kubectl --kubeconfig ./admin.conf proxy
你现在可以在 http://localhost:8001/api/v1
从本地访问 API 服务器。
清理
如果你在集群中使用了一次性服务器进行测试,则可以关闭这些服务器,而无需进一步清理。
你可以使用 kubectl config delete-cluster
删除对集群的本地引用。
但是,如果要更干净地取消配置集群,
则应首先清空节点 并确保该节点为空,
然后取消配置该节点。
移除节点
使用适当的凭据与控制平面节点通信,运行:
kubectl drain <节点名称> --delete-emptydir-data --force --ignore-daemonsets
在移除节点之前,请重置 kubeadm
安装的状态:
重置过程不会重置或清除 iptables 规则或 IPVS 表。如果你希望重置 iptables,则必须手动进行:
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
如果要重置 IPVS 表,则必须运行以下命令:
现在移除节点:
kubectl delete node <节点名称>
如果你想重新开始,只需运行 kubeadm init
或 kubeadm join
并加上适当的参数。
清理控制平面
你可以在控制平面主机上使用 kubeadm reset
来触发尽力而为的清理。
有关此子命令及其选项的更多信息,请参见
kubeadm reset
参考文档。
版本偏差策略
虽然 kubeadm 允许所管理的组件有一定程度的版本偏差,
但是建议你将 kubeadm 的版本与控制平面组件、kube-proxy 和 kubelet 的版本相匹配。
kubeadm 中的 Kubernetes 版本偏差
kubeadm 可以与 Kubernetes 组件一起使用,这些组件的版本与 kubeadm 相同,或者比它大一个版本。
Kubernetes 版本可以通过使用 --kubeadm init
的 --kubernetes-version
标志或使用 --config
时的
ClusterConfiguration.kubernetesVersion
字段指定给 kubeadm。
这个选项将控制 kube-apiserver、kube-controller-manager、kube-scheduler 和 kube-proxy 的版本。
例子:
kubeadm 的版本为 1.29。
kubernetesVersion
必须为 1.29 或者 1.28。
kubeadm 中 kubelet 的版本偏差
与 Kubernetes 版本类似,kubeadm 可以使用与 kubeadm 相同版本的 kubelet,
或者比 kubeadm 老三个版本的 kubelet。
例子:
kubeadm 的版本为 1.29。
主机上的 kubelet 必须为 1.29、1.28、
1.27 或 1.26。
kubeadm 支持的 kubeadm 的版本偏差
kubeadm 命令在现有节点或由 kubeadm 管理的整个集群上的操作有一定限制。
如果新的节点加入到集群中,用于 kubeadm join
的 kubeadm 二进制文件必须与用 kubeadm init
创建集群或用 kubeadm upgrade
升级同一节点时所用的 kubeadm 版本一致。
类似的规则适用于除了 kubeadm upgrade
以外的其他 kubeadm 命令。
kubeadm join
的例子:
使用 kubeadm init
创建集群时使用版本为 1.29 的 kubeadm。
添加节点所用的 kubeadm 可执行文件为版本 。
对于正在升级的节点,所使用的的 kubeadm 必须与管理该节点的 kubeadm 具有相同的
MINOR 版本或比后者新一个 MINOR 版本。
kubeadm upgrade
的例子:
用于创建或升级节点的 kubeadm 版本为 1.28。
用于升级节点的 kubeadm 版本必须为 1.28 或 1.29。
要了解更多关于不同 Kubernetes 组件之间的版本偏差,
请参见版本偏差策略 。
局限性
集群弹性
此处创建的集群具有单个控制平面节点,运行单个 etcd 数据库。
这意味着如果控制平面节点发生故障,你的集群可能会丢失数据并且可能需要从头开始重新创建。
解决方法:
定期备份 etcd 。
kubeadm 配置的 etcd 数据目录位于控制平面节点上的 /var/lib/etcd
中。
kubeadm deb/rpm 软件包和二进制文件是为 amd64、arm (32-bit)、arm64、ppc64le 和 s390x
构建的遵循多平台提案 。
从 v1.12 开始还支持用于控制平面和附加组件的多平台容器镜像。
只有一些网络提供商为所有平台提供解决方案。
请查阅上方的网络提供商清单或每个提供商的文档以确定提供商是否支持你选择的平台。
故障排除
如果你在使用 kubeadm 时遇到困难,
请查阅我们的故障排除文档 。
下一步
使用 Sonobuoy 验证集群是否正常运行。
有关使用 kubeadm 升级集群的详细信息,
请参阅升级 kubeadm 集群 。
在 kubeadm 参考文档 中了解有关 kubeadm
进阶用法的信息。
了解有关 Kubernetes 概念 和 kubectl
的更多信息。
有关 Pod 网络附加组件的更多列表,请参见集群网络 页面。
请参阅附加组件列表 以探索其他附加组件,
包括用于 Kubernetes 集群的日志记录、监视、网络策略、可视化和控制的工具。
配置集群如何处理集群事件的日志以及在 Pod 中运行的应用程序。
有关所涉及内容的概述,请参见日志架构 。
反馈
2.2.1.4 - 使用 kubeadm API 定制组件
本页面介绍了如何自定义 kubeadm 部署的组件。
你可以使用 ClusterConfiguration
结构中定义的参数,或者在每个节点上应用补丁来定制控制平面组件。
你可以使用 KubeletConfiguration
和 KubeProxyConfiguration
结构分别定制 kubelet 和 kube-proxy 组件。
所有这些选项都可以通过 kubeadm 配置 API 实现。
有关配置中的每个字段的详细信息,你可以导航到我们的
API 参考页面 。
使用 ClusterConfiguration
中的标志自定义控制平面
kubeadm ClusterConfiguration
对象为用户提供了一种方法,
用以覆盖传递给控制平面组件(如 APIServer、ControllerManager、Scheduler 和 Etcd)的默认参数。
各组件配置使用如下字段定义:
apiServer
controllerManager
scheduler
etcd
这些结构包含一个通用的 extraArgs
字段,该字段由 key: value
组成。
要覆盖控制平面组件的参数:
将适当的字段 extraArgs
添加到配置中。
向字段 extraArgs
添加要覆盖的参数值。
用 --config <YOUR CONFIG YAML>
运行 kubeadm init
。
说明:
你可以通过运行 kubeadm config print init-defaults
并将输出保存到你所选的文件中,
以默认值形式生成 ClusterConfiguration
对象。
说明:
ClusterConfiguration
对象目前在 kubeadm 集群中是全局的。
这意味着你添加的任何标志都将应用于同一组件在不同节点上的所有实例。
要在不同节点上为每个组件应用单独的配置,你可以使用补丁 。
说明:
当前不支持重复的参数(keys)或多次传递相同的参数 --foo
。
要解决此问题,你必须使用补丁 。
APIServer 参数
有关详细信息,请参阅 kube-apiserver 参考文档 。
使用示例:
apiVersion : kubeadm.k8s.io/v1beta3
kind : ClusterConfiguration
kubernetesVersion : v1.16.0
apiServer :
extraArgs :
anonymous-auth : "false"
enable-admission-plugins : AlwaysPullImages,DefaultStorageClass
audit-log-path : /home/johndoe/audit.log
ControllerManager 参数
有关详细信息,请参阅 kube-controller-manager 参考文档 。
使用示例:
apiVersion : kubeadm.k8s.io/v1beta3
kind : ClusterConfiguration
kubernetesVersion : v1.16.0
controllerManager :
extraArgs :
cluster-signing-key-file : /home/johndoe/keys/ca.key
deployment-controller-sync-period : "50"
Scheduler 参数
有关详细信息,请参阅 kube-scheduler 参考文档 。
使用示例:
apiVersion : kubeadm.k8s.io/v1beta3
kind : ClusterConfiguration
kubernetesVersion : v1.16.0
scheduler :
extraArgs :
config : /etc/kubernetes/scheduler-config.yaml
extraVolumes :
- name : schedulerconfig
hostPath : /home/johndoe/schedconfig.yaml
mountPath : /etc/kubernetes/scheduler-config.yaml
readOnly : true
pathType : "File"
Etcd 参数
有关详细信息,请参阅 etcd 服务文档 .
使用示例:
apiVersion : kubeadm.k8s.io/v1beta3
kind : ClusterConfiguration
etcd :
local :
extraArgs :
election-timeout : 1000
使用补丁定制
特性状态: Kubernetes v1.22 [beta]
Kubeadm 允许将包含补丁文件的目录传递给各个节点上的 InitConfiguration
和 JoinConfiguration
。
这些补丁可被用作组件配置写入磁盘之前的最后一个自定义步骤。
可以使用 --config <你的 YAML 格式控制文件>
将配置文件传递给 kubeadm init
:
apiVersion : kubeadm.k8s.io/v1beta3
kind : InitConfiguration
patches :
directory : /home/user/somedir
说明:
对于 kubeadm init
,你可以传递一个包含 ClusterConfiguration
和 InitConfiguration
的文件,以 ---
分隔。
你可以使用 --config <你的 YAML 格式配置文件>
将配置文件传递给 kubeadm join
:
apiVersion : kubeadm.k8s.io/v1beta3
kind : JoinConfiguration
patches :
directory : /home/user/somedir
补丁目录必须包含名为 target[suffix][+patchtype].extension
的文件。
例如,kube-apiserver0+merge.yaml
或只是 etcd.json
。
target
可以是 kube-apiserver
、kube-controller-manager
、kube-scheduler
、etcd
和 kubeletconfiguration
之一。
patchtype
可以是 strategy
、merge
或 json
之一,并且这些必须匹配
kubectl 支持 的补丁格式。
默认补丁类型是 strategic
的。
extension
必须是 json
或 yaml
。
suffix
是一个可选字符串,可用于确定首先按字母数字应用哪些补丁。
说明:
如果你使用 kubeadm upgrade
升级 kubeadm 节点,你必须再次提供相同的补丁,以便在升级后保留自定义配置。
为此,你可以使用 --patches
参数,该参数必须指向同一目录。 kubeadm upgrade
目前不支持用于相同目的的 API 结构配置。
自定义 kubelet
要自定义 kubelet,你可以在同一配置文件中的 ClusterConfiguration
或 InitConfiguration
之外添加一个 KubeletConfiguration
,用 ---
分隔。
然后可以将此文件传递给 kubeadm init
,kubeadm 会将相同的
KubeletConfiguration
配置应用于集群中的所有节点。
要在基础 KubeletConfiguration
上应用特定节点的配置,你可以使用
kubeletconfiguration
补丁定制 。
或者你可以使用 kubelet
参数进行覆盖,方法是将它们传递到 InitConfiguration
和 JoinConfiguration
支持的 nodeRegistration.kubeletExtraArgs
字段中。一些 kubelet 参数已被弃用,
因此在使用这些参数之前,请在 kubelet 参考文档 中检查它们的状态。
更多详情,请参阅使用 kubeadm 配置集群中的每个 kubelet
自定义 kube-proxy
要自定义 kube-proxy,你可以在 ClusterConfiguration
或 InitConfiguration
之外添加一个由 ---
分隔的 KubeProxyConfiguration
, 传递给 kubeadm init
。
可以导航到 API 参考页面 查看更多详情,
说明:
kubeadm 将 kube-proxy 部署为 DaemonSet ,
这意味着 KubeProxyConfiguration
将应用于集群中的所有 kube-proxy 实例。
2.2.1.5 - 高可用拓扑选项
本页面介绍了配置高可用(HA)Kubernetes 集群拓扑的两个选项。
你可以设置 HA 集群:
使用堆叠(stacked)控制平面节点,其中 etcd 节点与控制平面节点共存
使用外部 etcd 节点,其中 etcd 在与控制平面不同的节点上运行
在设置 HA 集群之前,你应该仔细考虑每种拓扑的优缺点。
说明:
kubeadm 静态引导 etcd 集群。
阅读 etcd 集群指南 以获得更多详细信息。
堆叠(Stacked)etcd 拓扑
堆叠(Stacked)HA 集群是一种这样的拓扑 ,
其中 etcd 分布式数据存储集群堆叠在 kubeadm 管理的控制平面节点上,作为控制平面的一个组件运行。
每个控制平面节点运行 kube-apiserver
、kube-scheduler
和 kube-controller-manager
实例。
kube-apiserver
使用负载均衡器暴露给工作节点。
每个控制平面节点创建一个本地 etcd 成员(member),这个 etcd 成员只与该节点的 kube-apiserver
通信。
这同样适用于本地 kube-controller-manager
和 kube-scheduler
实例。
这种拓扑将控制平面和 etcd 成员耦合在同一节点上。相对使用外部 etcd 集群,
设置起来更简单,而且更易于副本管理。
然而,堆叠集群存在耦合失败的风险。如果一个节点发生故障,则 etcd 成员和控制平面实例都将丢失,
并且冗余会受到影响。你可以通过添加更多控制平面节点来降低此风险。
因此,你应该为 HA 集群运行至少三个堆叠的控制平面节点。
这是 kubeadm 中的默认拓扑。当使用 kubeadm init
和 kubeadm join --control-plane
时,
在控制平面节点上会自动创建本地 etcd 成员。
外部 etcd 拓扑
具有外部 etcd 的 HA 集群是一种这样的拓扑 ,
其中 etcd 分布式数据存储集群在独立于控制平面节点的其他节点上运行。
就像堆叠的 etcd 拓扑一样,外部 etcd 拓扑中的每个控制平面节点都会运行
kube-apiserver
、kube-scheduler
和 kube-controller-manager
实例。
同样,kube-apiserver
使用负载均衡器暴露给工作节点。但是 etcd 成员在不同的主机上运行,
每个 etcd 主机与每个控制平面节点的 kube-apiserver
通信。
这种拓扑结构解耦了控制平面和 etcd 成员。因此它提供了一种 HA 设置,
其中失去控制平面实例或者 etcd 成员的影响较小,并且不会像堆叠的 HA 拓扑那样影响集群冗余。
但此拓扑需要两倍于堆叠 HA 拓扑的主机数量。
具有此拓扑的 HA 集群至少需要三个用于控制平面节点的主机和三个用于 etcd 节点的主机。
接下来
2.2.1.6 - 利用 kubeadm 创建高可用集群
本文讲述了使用 kubeadm 设置一个高可用的 Kubernetes 集群的两种不同方式:
使用具有堆叠的控制平面节点。这种方法所需基础设施较少。etcd 成员和控制平面节点位于同一位置。
使用外部 etcd 集群。这种方法所需基础设施较多。控制平面的节点和 etcd 成员是分开的。
在下一步之前,你应该仔细考虑哪种方法更好地满足你的应用程序和环境的需求。
高可用拓扑选项 讲述了每种方法的优缺点。
如果你在安装 HA 集群时遇到问题,请在 kubeadm 问题跟踪 里向我们提供反馈。
你也可以阅读升级文档 。
注意:
这篇文档没有讲述在云提供商上运行集群的问题。在云环境中,
此处记录的方法不适用于类型为 LoadBalancer 的服务对象,也不适用于具有动态 PersistentVolume 的对象。
准备开始
根据集群控制平面所选择的拓扑结构不同,准备工作也有所差异:
需要准备:
配置满足 kubeadm 的最低要求
的三台机器作为控制面节点。控制平面节点为奇数有利于机器故障或者分区故障时重新选举。
配置满足 kubeadm 的最低要求
的三台机器作为工作节点
在集群中,确保所有计算机之间存在全网络连接(公网或私网)
在所有机器上具有 sudo 权限
从某台设备通过 SSH 访问系统中所有节点的能力
所有机器上已经安装 kubeadm
和 kubelet
拓扑详情请参考堆叠(Stacked)etcd 拓扑 。
需要准备:
配置满足 kubeadm 的最低要求
的三台机器作为控制面节点。控制平面节点为奇数有利于机器故障或者分区故障时重新选举。
配置满足 kubeadm 的最低要求
的三台机器作为工作节点
在集群中,确保所有计算机之间存在全网络连接(公网或私网)
在所有机器上具有 sudo 权限
从某台设备通过 SSH 访问系统中所有节点的能力
所有机器上已经安装 kubeadm
和 kubelet
还需要准备:
给 etcd 集群使用的另外至少三台机器。为了分布式一致性算法达到更好的投票效果,集群必须由奇数个节点组成。
机器上已经安装 kubeadm
和 kubelet
。
机器上同样需要安装好容器运行时,并能正常运行。
拓扑详情请参考外部 etcd 拓扑 。
容器镜像
每台主机需要能够从 Kubernetes 容器镜像仓库(registry.k8s.io
)读取和拉取镜像。
想要在无法拉取 Kubernetes 仓库镜像的机器上部署高可用集群也是可行的。通过其他的手段保证主机上已经有对应的容器镜像即可。
命令行
一旦集群创建成功,需要在 PC 上安装 kubectl 用于管理 Kubernetes。
为了方便故障排查,也可以在每个控制平面节点上安装 kubectl
。
这两种方法的第一步
为 kube-apiserver 创建负载均衡器
说明:
使用负载均衡器需要许多配置。你的集群搭建可能需要不同的配置。下面的例子只是其中的一方面配置。
创建一个名为 kube-apiserver 的负载均衡器解析 DNS。
在云环境中,应该将控制平面节点放置在 TCP 转发负载平衡后面。
该负载均衡器将流量分配给目标列表中所有运行状况良好的控制平面节点。
API 服务器的健康检查是在 kube-apiserver 的监听端口(默认值 :6443
)
上进行的一个 TCP 检查。
不建议在云环境中直接使用 IP 地址。
负载均衡器必须能够在 API 服务器端口上与所有控制平面节点通信。
它还必须允许其监听端口的入站流量。
确保负载均衡器的地址始终匹配 kubeadm 的 ControlPlaneEndpoint
地址。
阅读软件负载平衡选项指南
以获取更多详细信息。
添加第一个控制平面节点到负载均衡器并测试连接:
nc -v LOAD_BALANCER_IP PORT
由于 API 服务器尚未运行,预期会出现一个连接拒绝错误。
然而超时意味着负载均衡器不能和控制平面节点通信。
如果发生超时,请重新配置负载均衡器与控制平面节点进行通信。
将其余控制平面节点添加到负载均衡器目标组。
使用堆控制平面和 etcd 节点
控制平面节点的第一步
初始化控制平面:
sudo kubeadm init --control-plane-endpoint "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT" --upload-certs
你可以使用 --kubernetes-version
标志来设置要使用的 Kubernetes 版本。
建议将 kubeadm、kebelet、kubectl 和 Kubernetes 的版本匹配。
这个 --control-plane-endpoint
标志应该被设置成负载均衡器的地址或 DNS 和端口。
这个 --upload-certs
标志用来将在所有控制平面实例之间的共享证书上传到集群。
如果正好相反,你更喜欢手动地通过控制平面节点或者使用自动化工具复制证书,
请删除此标志并参考如下部分证书分配手册 。
说明:
标志 kubeadm init
、--config
和 --certificate-key
不能混合使用,
因此如果你要使用
kubeadm 配置 ,你必须在相应的配置结构
(位于 InitConfiguration
和 JoinConfiguration: controlPlane
)添加 certificateKey
字段。
说明:
一些 CNI 网络插件需要更多配置,例如指定 Pod IP CIDR,而其他插件则不需要。参考
CNI 网络文档 。
通过传递 --pod-network-cidr
标志添加 Pod CIDR,或者你可以使用 kubeadm
配置文件,在 ClusterConfiguration
的 networking
对象下设置 podSubnet
字段。
输出类似于:
...
You can now join any number of control-plane node by running the following command on each as a root:
kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07
Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use kubeadm init phase upload-certs to reload certs afterward.
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
将此输出复制到文本文件。 稍后你将需要它来将控制平面节点和工作节点加入集群。
当使用 --upload-certs
调用 kubeadm init
时,主控制平面的证书被加密并上传到 kubeadm-certs
Secret 中。
要重新上传证书并生成新的解密密钥,请在已加入集群节点的控制平面上使用以下命令:
sudo kubeadm init phase upload-certs --upload-certs
你还可以在 init
期间指定自定义的 --certificate-key
,以后可以由 join
使用。
要生成这样的密钥,可以使用以下命令:
kubeadm certs certificate-key
证书密钥是一个十六进制编码的字符串,它是一个 32 字节大小的 AES 密钥。
说明:
kubeadm-certs
Secret 和解密密钥会在两个小时后失效。
注意:
正如命令输出中所述,证书密钥可访问集群敏感数据。请妥善保管!
应用你所选择的 CNI 插件:
请遵循以下指示
安装 CNI 驱动。如果适用,请确保配置与 kubeadm 配置文件中指定的 Pod
CIDR 相对应。
说明:
在进行下一步之前,必须选择并部署合适的网络插件。
否则集群不会正常运行。
输入以下内容,并查看控制平面组件的 Pod 启动:
kubectl get pod -n kube-system -w
其余控制平面节点的步骤
对于每个其他控制平面节点,你应该:
执行先前由第一个节点上的 kubeadm init
输出提供给你的 join 命令。
它看起来应该像这样:
sudo kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07
这个 --control-plane
标志通知 kubeadm join
创建一个新的控制平面。
--certificate-key ...
将导致从集群中的 kubeadm-certs
Secret
下载控制平面证书并使用给定的密钥进行解密。
你可以并行地加入多个控制面节点。
外部 etcd 节点
使用外部 etcd 节点设置集群类似于用于堆叠 etcd 的过程,
不同之处在于你应该首先设置 etcd,并在 kubeadm 配置文件中传递 etcd 信息。
设置 etcd 集群
按照这里 的指示去设置。
根据这里 的描述配置 SSH。
将以下文件从集群中的任一 etcd 节点复制到第一个控制平面节点:
export CONTROL_PLANE = "ubuntu@10.0.0.7"
scp /etc/kubernetes/pki/etcd/ca.crt " ${ CONTROL_PLANE } " :
scp /etc/kubernetes/pki/apiserver-etcd-client.crt " ${ CONTROL_PLANE } " :
scp /etc/kubernetes/pki/apiserver-etcd-client.key " ${ CONTROL_PLANE } " :
用第一台控制平面节点的 user@host
替换 CONTROL_PLANE
的值。
设置第一个控制平面节点
用以下内容创建一个名为 kubeadm-config.yaml
的文件:
---
apiVersion : kubeadm.k8s.io/v1beta3
kind : ClusterConfiguration
kubernetesVersion : stable
controlPlaneEndpoint : "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT" # change this (see below)
etcd :
external :
endpoints :
- https://ETCD_0_IP:2379 # 适当地更改 ETCD_0_IP
- https://ETCD_1_IP:2379 # 适当地更改 ETCD_1_IP
- https://ETCD_2_IP:2379 # 适当地更改 ETCD_2_IP
caFile : /etc/kubernetes/pki/etcd/ca.crt
certFile : /etc/kubernetes/pki/apiserver-etcd-client.crt
keyFile : /etc/kubernetes/pki/apiserver-etcd-client.key
说明:
这里的堆叠(stacked)etcd 和外部 etcd 之前的区别在于设置外部 etcd
需要一个 etcd
的 external
对象下带有 etcd 端点的配置文件。
如果是内部 etcd,是自动管理的。
以下的步骤与设置内置 etcd 的集群是相似的:
在节点上运行 sudo kubeadm init --config kubeadm-config.yaml --upload-certs
命令。
记下输出的 join 命令,这些命令将在以后使用。
应用你选择的 CNI 插件。
说明:
在进行下一步之前,必须选择并部署合适的网络插件。
否则集群不会正常运行。
其他控制平面节点的步骤
步骤与设置内置 etcd 相同:
确保第一个控制平面节点已完全初始化。
使用保存到文本文件的 join 命令将每个控制平面节点连接在一起。
建议一次加入一个控制平面节点。
不要忘记默认情况下,--certificate-key
中的解密秘钥会在两个小时后过期。
列举控制平面之后的常见任务
安装工作节点
你可以使用之前存储的 kubeadm init
命令的输出将工作节点加入集群中:
sudo kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
手动证书分发
如果你选择不将 kubeadm init
与 --upload-certs
命令一起使用,
则意味着你将必须手动将证书从主控制平面节点复制到将要加入的控制平面节点上。
有许多方法可以实现这种操作。下面的例子使用了 ssh
和 scp
:
如果要在单独的一台计算机控制所有节点,则需要 SSH。
在你的主设备上启用 ssh-agent,要求该设备能访问系统中的所有其他节点:
将 SSH 身份添加到会话中:
ssh-add ~/.ssh/path_to_private_key
检查节点间的 SSH 以确保连接是正常运行的
SSH 到任何节点时,请确保添加 -A
标志。
此标志允许你通过 SSH 登录到节点后从该节点上访问你自己 PC 上的 SSH 代理。
如果你不完全信任该节点上的用户会话安全,可以考虑使用其他替代方法。
当在任何节点上使用 sudo 时,请确保保持环境变量设置,以便 SSH
转发能够正常工作:
在所有节点上配置 SSH 之后,你应该在运行过 kubeadm init
命令的第一个控制平面节点上运行以下脚本。
该脚本会将证书从第一个控制平面节点复制到另一个控制平面节点:
在以下示例中,用其他控制平面节点的 IP 地址替换 CONTROL_PLANE_IPS
。
USER = ubuntu # 可定制
CONTROL_PLANE_IPS = "10.0.0.7 10.0.0.8"
for host in ${ CONTROL_PLANE_IPS } ; do
scp /etc/kubernetes/pki/ca.crt " ${ USER } " @$host :
scp /etc/kubernetes/pki/ca.key " ${ USER } " @$host :
scp /etc/kubernetes/pki/sa.key " ${ USER } " @$host :
scp /etc/kubernetes/pki/sa.pub " ${ USER } " @$host :
scp /etc/kubernetes/pki/front-proxy-ca.crt " ${ USER } " @$host :
scp /etc/kubernetes/pki/front-proxy-ca.key " ${ USER } " @$host :
scp /etc/kubernetes/pki/etcd/ca.crt " ${ USER } " @$host :etcd-ca.crt
# 如果你正使用外部 etcd,忽略下一行
scp /etc/kubernetes/pki/etcd/ca.key " ${ USER } " @$host :etcd-ca.key
done
注意:
只需要复制上面列表中的证书。kubeadm 将负责生成其余证书以及加入控制平面实例所需的 SAN。
如果你错误地复制了所有证书,由于缺少所需的 SAN,创建其他节点可能会失败。
然后,在每个即将加入集群的控制平面节点上,你必须先运行以下脚本,然后再运行 kubeadm join
。
该脚本会将先前复制的证书从主目录移动到 /etc/kubernetes/pki
:
USER = ubuntu # 可定制
mkdir -p /etc/kubernetes/pki/etcd
mv /home/${ USER } /ca.crt /etc/kubernetes/pki/
mv /home/${ USER } /ca.key /etc/kubernetes/pki/
mv /home/${ USER } /sa.pub /etc/kubernetes/pki/
mv /home/${ USER } /sa.key /etc/kubernetes/pki/
mv /home/${ USER } /front-proxy-ca.crt /etc/kubernetes/pki/
mv /home/${ USER } /front-proxy-ca.key /etc/kubernetes/pki/
mv /home/${ USER } /etcd-ca.crt /etc/kubernetes/pki/etcd/ca.crt
# 如果你正使用外部 etcd,忽略下一行
mv /home/${ USER } /etcd-ca.key /etc/kubernetes/pki/etcd/ca.key
2.2.1.7 - 使用 kubeadm 创建一个高可用 etcd 集群
说明:
在本指南中,使用 kubeadm 作为外部 etcd 节点管理工具,请注意 kubeadm 不计划支持此类节点的证书更换或升级。
对于长期规划是使用 etcdadm 增强工具来管理这些方面。
默认情况下,kubeadm 在每个控制平面节点上运行一个本地 etcd 实例。也可以使用外部的 etcd 集群,并在不同的主机上提供 etcd 实例。
这两种方法的区别在高可用拓扑的选项 页面中阐述。
这个任务将指导你创建一个由三个成员组成的高可用外部 etcd 集群,该集群在创建过程中可被 kubeadm 使用。
准备开始
三个可以通过 2379 和 2380 端口相互通信的主机。本文档使用这些作为默认端口。
不过,它们可以通过 kubeadm 的配置文件进行自定义。
每个主机都应该能够访问 Kubernetes 容器镜像仓库 (registry.k8s.io),
或者使用 kubeadm config images list/pull
列出/拉取所需的 etcd 镜像。
本指南将把 etcd 实例设置为由 kubelet 管理的静态 Pod 。
一些可以用来在主机间复制文件的基础设施。例如 ssh
和 scp
就可以满足此需求。
建立集群
一般来说,是在一个节点上生成所有证书并且只分发这些必要 的文件到其它节点上。
说明:
kubeadm 包含生成下述证书所需的所有必要的密码学工具;在这个例子中,不需要其他加密工具。
说明:
下面的例子使用 IPv4 地址,但是你也可以使用 IPv6 地址配置 kubeadm、kubelet 和 etcd。
一些 Kubernetes 选项支持双协议栈,但是 etcd 不支持。关于 Kubernetes 双协议栈支持的更多细节,
请参见 kubeadm 的双栈支持 。
将 kubelet 配置为 etcd 的服务管理器。
说明:
你必须在要运行 etcd 的所有主机上执行此操作。
由于 etcd 是首先创建的,因此你必须通过创建具有更高优先级的新文件来覆盖
kubeadm 提供的 kubelet 单元文件。
cat << EOF > /etc/systemd/system/kubelet.service.d/kubelet.conf
# 将下面的 "systemd" 替换为你的容器运行时所使用的 cgroup 驱动。
# kubelet 的默认值为 "cgroupfs"。
# 如果需要的话,将 "containerRuntimeEndpoint" 的值替换为一个不同的容器运行时。
#
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authentication:
anonymous:
enabled: false
webhook:
enabled: false
authorization:
mode: AlwaysAllow
cgroupDriver: systemd
address: 127.0.0.1
containerRuntimeEndpoint: unix:///var/run/containerd/containerd.sock
staticPodPath: /etc/kubernetes/manifests
EOF
cat << EOF > /etc/systemd/system/kubelet.service.d/20-etcd-service-manager.conf
[Service]
ExecStart=
ExecStart=/usr/bin/kubelet --config=/etc/systemd/system/kubelet.service.d/kubelet.conf
Restart=always
EOF
systemctl daemon-reload
systemctl restart kubelet
检查 kubelet 的状态以确保其处于运行状态:
为 kubeadm 创建配置文件。
使用以下脚本为每个将要运行 etcd 成员的主机生成一个 kubeadm 配置文件。
# 使用你的主机 IP 更新 HOST0、HOST1 和 HOST2 的 IP 地址
export HOST0 = 10.0.0.6
export HOST1 = 10.0.0.7
export HOST2 = 10.0.0.8
# 使用你的主机名更新 NAME0、NAME1 和 NAME2
export NAME0 = "infra0"
export NAME1 = "infra1"
export NAME2 = "infra2"
# 创建临时目录来存储将被分发到其它主机上的文件
mkdir -p /tmp/${ HOST0 } / /tmp/${ HOST1 } / /tmp/${ HOST2 } /
HOSTS =( ${ HOST0 } ${ HOST1 } ${ HOST2 } )
NAMES =( ${ NAME0 } ${ NAME1 } ${ NAME2 } )
for i in " ${ !HOSTS[@]} " ; do
HOST = ${ HOSTS [$i ]}
NAME = ${ NAMES [$i ]}
cat << EOF > /tmp/${HOST}/kubeadmcfg.yaml
---
apiVersion: "kubeadm.k8s.io/v1beta3"
kind: InitConfiguration
nodeRegistration:
name: ${NAME}
localAPIEndpoint:
advertiseAddress: ${HOST}
---
apiVersion: "kubeadm.k8s.io/v1beta3"
kind: ClusterConfiguration
etcd:
local:
serverCertSANs:
- "${HOST}"
peerCertSANs:
- "${HOST}"
extraArgs:
initial-cluster: ${NAMES[0]}=https://${HOSTS[0]}:2380,${NAMES[1]}=https://${HOSTS[1]}:2380,${NAMES[2]}=https://${HOSTS[2]}:2380
initial-cluster-state: new
name: ${NAME}
listen-peer-urls: https://${HOST}:2380
listen-client-urls: https://${HOST}:2379
advertise-client-urls: https://${HOST}:2379
initial-advertise-peer-urls: https://${HOST}:2380
EOF
done
生成证书颁发机构。
如果你已经拥有 CA,那么唯一的操作是复制 CA 的 crt
和 key
文件到
etc/kubernetes/pki/etcd/ca.crt
和 /etc/kubernetes/pki/etcd/ca.key
。
复制完这些文件后继续下一步,“为每个成员创建证书”。
如果你还没有 CA,则在 $HOST0
(你为 kubeadm 生成配置文件的位置)上运行此命令。
kubeadm init phase certs etcd-ca
这一操作创建如下两个文件:
/etc/kubernetes/pki/etcd/ca.crt
/etc/kubernetes/pki/etcd/ca.key
为每个成员创建证书。
kubeadm init phase certs etcd-server --config= /tmp/${ HOST2 } /kubeadmcfg.yaml
kubeadm init phase certs etcd-peer --config= /tmp/${ HOST2 } /kubeadmcfg.yaml
kubeadm init phase certs etcd-healthcheck-client --config= /tmp/${ HOST2 } /kubeadmcfg.yaml
kubeadm init phase certs apiserver-etcd-client --config= /tmp/${ HOST2 } /kubeadmcfg.yaml
cp -R /etc/kubernetes/pki /tmp/${ HOST2 } /
# 清理不可重复使用的证书
find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -delete
kubeadm init phase certs etcd-server --config= /tmp/${ HOST1 } /kubeadmcfg.yaml
kubeadm init phase certs etcd-peer --config= /tmp/${ HOST1 } /kubeadmcfg.yaml
kubeadm init phase certs etcd-healthcheck-client --config= /tmp/${ HOST1 } /kubeadmcfg.yaml
kubeadm init phase certs apiserver-etcd-client --config= /tmp/${ HOST1 } /kubeadmcfg.yaml
cp -R /etc/kubernetes/pki /tmp/${ HOST1 } /
find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -delete
kubeadm init phase certs etcd-server --config= /tmp/${ HOST0 } /kubeadmcfg.yaml
kubeadm init phase certs etcd-peer --config= /tmp/${ HOST0 } /kubeadmcfg.yaml
kubeadm init phase certs etcd-healthcheck-client --config= /tmp/${ HOST0 } /kubeadmcfg.yaml
kubeadm init phase certs apiserver-etcd-client --config= /tmp/${ HOST0 } /kubeadmcfg.yaml
# 不需要移动 certs 因为它们是给 HOST0 使用的
# 清理不应从此主机复制的证书
find /tmp/${ HOST2 } -name ca.key -type f -delete
find /tmp/${ HOST1 } -name ca.key -type f -delete
复制证书和 kubeadm 配置。
证书已生成,现在必须将它们移动到对应的主机。
USER = ubuntu
HOST = ${ HOST1 }
scp -r /tmp/${ HOST } /* ${ USER } @${ HOST } :
ssh ${ USER } @${ HOST }
USER@HOST $ sudo -Es
root@HOST $ chown -R root:root pki
root@HOST $ mv pki /etc/kubernetes/
确保已经所有预期的文件都存在
$HOST0
所需文件的完整列表如下:
/tmp/${HOST0}
└── kubeadmcfg.yaml
---
/etc/kubernetes/pki
├── apiserver-etcd-client.crt
├── apiserver-etcd-client.key
└── etcd
├── ca.crt
├── ca.key
├── healthcheck-client.crt
├── healthcheck-client.key
├── peer.crt
├── peer.key
├── server.crt
└── server.key
在 $HOST1
上:
$ HOME
└── kubeadmcfg.yaml
---
/etc/kubernetes/pki
├── apiserver-etcd-client.crt
├── apiserver-etcd-client.key
└── etcd
├── ca.crt
├── healthcheck-client.crt
├── healthcheck-client.key
├── peer.crt
├── peer.key
├── server.crt
└── server.key
在 $HOST2
上:
$ HOME
└── kubeadmcfg.yaml
---
/etc/kubernetes/pki
├── apiserver-etcd-client.crt
├── apiserver-etcd-client.key
└── etcd
├── ca.crt
├── healthcheck-client.crt
├── healthcheck-client.key
├── peer.crt
├── peer.key
├── server.crt
└── server.key
创建静态 Pod 清单。
既然证书和配置已经就绪,是时候去创建清单了。
在每台主机上运行 kubeadm
命令来生成 etcd 使用的静态清单。
root@HOST0 $ kubeadm init phase etcd local --config= /tmp/${ HOST0 } /kubeadmcfg.yaml
root@HOST1 $ kubeadm init phase etcd local --config= $HOME /kubeadmcfg.yaml
root@HOST2 $ kubeadm init phase etcd local --config= $HOME /kubeadmcfg.yaml
可选:检查集群运行状况。
如果 etcdctl
不可用,你可以在容器镜像内运行此工具。
你可以使用 crictl run
这类工具直接在容器运行时执行此操作,而不是通过 Kubernetes。
ETCDCTL_API = 3 etcdctl \
--cert /etc/kubernetes/pki/etcd/peer.crt \
--key /etc/kubernetes/pki/etcd/peer.key \
--cacert /etc/kubernetes/pki/etcd/ca.crt \
--endpoints https://${ HOST0 } :2379 endpoint health
...
https://[ HOST0 IP] :2379 is healthy: successfully committed proposal: took = 16.283339ms
https://[ HOST1 IP] :2379 is healthy: successfully committed proposal: took = 19.44402ms
https://[ HOST2 IP] :2379 is healthy: successfully committed proposal: took = 35.926451ms
将 ${HOST0}
设置为要测试的主机的 IP 地址。
接下来
一旦拥有了一个正常工作的 3 成员的 etcd 集群,
你就可以基于使用 kubeadm 外部 etcd 的方法 ,
继续部署一个高可用的控制平面。
2.2.1.8 - 使用 kubeadm 配置集群中的每个 kubelet
特性状态: Kubernetes v1.11 [stable]
kubeadm CLI 工具的生命周期与 kubelet
解耦;kubelet 是一个守护程序,在 Kubernetes 集群中的每个节点上运行。
当 Kubernetes 初始化或升级时,kubeadm CLI 工具由用户执行,而 kubelet 始终在后台运行。
由于kubelet是守护程序,因此需要通过某种初始化系统或服务管理器进行维护。
当使用 DEB 或 RPM 安装 kubelet 时,配置系统去管理 kubelet。
你可以改用其他服务管理器,但需要手动地配置。
集群中涉及的所有 kubelet 的一些配置细节都必须相同,
而其他配置方面则需要基于每个 kubelet 进行设置,以适应给定机器的不同特性(例如操作系统、存储和网络)。
你可以手动地管理 kubelet 的配置,但是 kubeadm 现在提供一种 KubeletConfiguration
API
类型用于集中管理 kubelet 的配置 。
Kubelet 配置模式
以下各节讲述了通过使用 kubeadm 简化 kubelet 配置模式,而不是在每个节点上手动地管理 kubelet 配置。
将集群级配置传播到每个 kubelet 中
你可以通过 kubeadm init
和 kubeadm join
命令为 kubelet 提供默认值。
有趣的示例包括使用其他容器运行时或通过服务器设置不同的默认子网。
如果你想使用子网 10.96.0.0/12
作为服务的默认网段,你可以给 kubeadm 传递 --service-cidr
参数:
kubeadm init --service-cidr 10.96.0.0/12
现在,可以从该子网分配服务的虚拟 IP。
你还需要通过 kubelet 使用 --cluster-dns
标志设置 DNS 地址。
在集群中的每个管理器和节点上的 kubelet 的设置需要相同。
kubelet 提供了一个版本化的结构化 API 对象,该对象可以配置 kubelet
中的大多数参数,并将此配置推送到集群中正在运行的每个 kubelet 上。
此对象被称为 KubeletConfiguration
。
KubeletConfiguration
允许用户指定标志,例如用骆峰值代表集群的 DNS IP 地址,如下所示:
apiVersion : kubelet.config.k8s.io/v1beta1
kind : KubeletConfiguration
clusterDNS :
- 10.96.0.10
有关 KubeletConfiguration
的更多详细信息,请参阅本节 。
提供特定于某实例的配置细节
由于硬件、操作系统、网络或者其他主机特定参数的差异。某些主机需要特定的 kubelet 配置。
以下列表提供了一些示例。
由 kubelet 配置标志 --resolv-conf
指定的 DNS 解析文件的路径在操作系统之间可能有所不同,
它取决于你是否使用 systemd-resolved
。
如果此路径错误,则在其 kubelet 配置错误的节点上 DNS 解析也将失败。
除非你使用云驱动,否则默认情况下 Node API 对象的 .metadata.name
会被设置为计算机的主机名。
如果你需要指定一个与机器的主机名不同的节点名称,你可以使用 --hostname-override
标志覆盖默认值。
当前,kubelet 无法自动检测容器运行时使用的 cgroup 驱动程序,
但是值 --cgroup-driver
必须与容器运行时使用的 cgroup 驱动程序匹配,以确保 kubelet 的健康运行状况。
要指定容器运行时,你必须用 --container-runtime-endpoint=<path>
标志来指定端点。
应用此类特定于实例的配置的推荐方法是使用
KubeletConfiguration
补丁 。
如果自定义的 KubeletConfiguration
API 对象使用像 kubeadm ... --config some-config-file.yaml
这样的配置文件进行传递,则可以配置 kubeadm 启动的 kubelet。
通过调用 kubeadm config print init-defaults --component-configs KubeletConfiguration
,
你可以看到此结构中的所有默认值。
也可以在基础 KubeletConfiguration
上应用实例特定的补丁。
阅读自定义 kubelet
来获取有关各个字段的更多信息。
使用 kubeadm init
时的工作流程
当调用 kubeadm init
时,kubelet 的配置会被写入磁盘 /var/lib/kubelet/config.yaml
,
并上传到集群 kube-system
命名空间的 kubelet-config
ConfigMap。
kubelet 配置信息也被写入 /etc/kubernetes/kubelet.conf
,其中包含集群内所有 kubelet 的基线配置。
此配置文件指向允许 kubelet 与 API 服务器通信的客户端证书。
这解决了将集群级配置传播到每个 kubelet 的需求。
针对为特定实例提供配置细节 的第二种模式,
kubeadm 的解决方法是将环境文件写入 /var/lib/kubelet/kubeadm-flags.env
,其中包含了一个标志列表,
当 kubelet 启动时,该标志列表会传递给 kubelet 标志在文件中的显示方式如下:
KUBELET_KUBEADM_ARGS = "--flag1=value1 --flag2=value2 ..."
除了启动 kubelet 时所使用的标志外,该文件还包含动态参数,例如 cgroup
驱动程序以及是否使用其他容器运行时套接字(--cri-socket
)。
将这两个文件编组到磁盘后,如果使用 systemd,则 kubeadm 尝试运行以下两个命令:
systemctl daemon-reload && systemctl restart kubelet
如果重新加载和重新启动成功,则正常的 kubeadm init
工作流程将继续。
使用 kubeadm join
时的工作流程
当运行 kubeadm join
时,kubeadm 使用 Bootstrap Token 证书执行 TLS 引导,该引导会获取一份证书,
该证书需要下载 kubelet-config
ConfigMap 并把它写入 /var/lib/kubelet/config.yaml
中。
动态环境文件的生成方式恰好与 kubeadm init
完全相同。
接下来,kubeadm
运行以下两个命令将新配置加载到 kubelet 中:
systemctl daemon-reload && systemctl restart kubelet
在 kubelet 加载新配置后,kubeadm 将写入 /etc/kubernetes/bootstrap-kubelet.conf
KubeConfig 文件中,
该文件包含 CA 证书和引导程序令牌。
kubelet 使用这些证书执行 TLS 引导程序并获取唯一的凭据,该凭据被存储在 /etc/kubernetes/kubelet.conf
中。
当 /etc/kubernetes/kubelet.conf
文件被写入后,kubelet 就完成了 TLS 引导过程。
kubeadm 在完成 TLS 引导过程后将删除 /etc/kubernetes/bootstrap-kubelet.conf
文件。
kubelet 的 systemd drop-in 文件
kubeadm
中附带了有关系统如何运行 kubelet 的 systemd 配置文件。
请注意 kubeadm CLI 命令不会修改此文件。
通过 kubeadm
包
安装的配置文件被写入 /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
并由 systemd 使用。它对原来的
kubelet.service
作了增强。
如果你想进一步覆盖它,可以创建一个目录/etc/systemd/system/kubelet.service.d/
(而不是/usr/lib/systemd/kubelet.service.d/
),并将你自己的自定义配置写入到该目录下的一个文件中。
例如,您可以添加一个新的本地文件/etc/systemd/system/kubelet.service.d/local-overrides.conf
以覆盖“kubeadm”配置的单元设置。
以下是你可能在“/usr/lib/systemd/kubelet.service.d/10 kubeadm.conf”中找到的内容:
说明:
下面的内容只是一个例子。如果你不想使用包管理器,
请遵循(没有包管理器 )
章节的指南。
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
# 这是 "kubeadm init" 和 "kubeadm join" 运行时生成的文件,
# 动态地填充 KUBELET_KUBEADM_ARGS 变量
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# 这是一个文件,用户在不得已下可以将其用作替代 kubelet args。
# 用户最好使用 .NodeRegistration.KubeletExtraArgs 对象在配置文件中替代。
# KUBELET_EXTRA_ARGS 应该从此文件中获取。
EnvironmentFile=-/etc/default/kubelet
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS
此文件指定由 kubeadm 为 kubelet 管理的所有文件的默认位置。
用于 TLS 引导程序的 KubeConfig 文件为 /etc/kubernetes/bootstrap-kubelet.conf
,
但仅当 /etc/kubernetes/kubelet.conf
不存在时才能使用。
具有唯一 kubelet 标识的 KubeConfig 文件为 /etc/kubernetes/kubelet.conf
。
包含 kubelet 的组件配置的文件为 /var/lib/kubelet/config.yaml
。
包含的动态环境的文件 KUBELET_KUBEADM_ARGS
是来源于 /var/lib/kubelet/kubeadm-flags.env
。
包含用户指定标志替代的文件 KUBELET_EXTRA_ARGS
是来源于
/etc/default/kubelet
(对于 DEB),或者 /etc/sysconfig/kubelet
(对于 RPM)。
KUBELET_EXTRA_ARGS
在标志链中排在最后,并且在设置冲突时具有最高优先级。
Kubernetes 可执行文件和软件包内容
Kubernetes 版本对应的 DEB 和 RPM 软件包是:
2.2.1.9 - 使用 kubeadm 支持双协议栈
特性状态: Kubernetes v1.23 [stable]
你的集群包含双协议栈 组网支持,
这意味着集群网络允许你在两种地址族间任选其一。在集群中,控制面可以为同一个
Pod 或者
Service
同时赋予 IPv4 和 IPv6 地址。
准备开始
你需要已经遵从安装 kubeadm
中所给的步骤安装了 kubeadm 工具。
针对你要作为节点 使用的每台服务器,
确保其允许 IPv6 转发。在 Linux 节点上,你可以通过以 root 用户在每台服务器上运行
sysctl -w net.ipv6.conf.all.forwarding=1
来完成设置。
你需要一个可以使用的 IPv4 和 IPv6 地址范围。集群操作人员通常对于 IPv4 使用
私有地址范围。对于 IPv6,集群操作人员通常会基于分配给该操作人员的地址范围,
从 2000::/3
中选择一个全局的单播地址块。你不需要将集群的 IP 地址范围路由到公众互联网。
所分配的 IP 地址数量应该与你计划运行的 Pod 和 Service 的数量相适应。
说明:
如果你在使用 kubeadm upgrade
命令升级现有的集群,kubeadm
不允许更改 Pod
的 IP 地址范围(“集群 CIDR”),也不允许更改集群的服务地址范围(“Service CIDR”)。
创建双协议栈集群
要使用 kubeadm init
创建一个双协议栈集群,你可以传递与下面的例子类似的命令行参数:
# 这里的地址范围仅作示例使用
kubeadm init --pod-network-cidr= 10.244.0.0/16,2001:db8:42:0::/56 --service-cidr= 10.96.0.0/16,2001:db8:42:1::/112
为了更便于理解,参看下面的名为 kubeadm-config.yaml
的 kubeadm
配置文件 ,
该文件用于双协议栈控制面的主控制节点。
---
apiVersion : kubeadm.k8s.io/v1beta3
kind : ClusterConfiguration
networking :
podSubnet : 10.244.0.0 /16,2001:db8:42:0::/56
serviceSubnet : 10.96.0.0 /16,2001:db8:42:1::/112
---
apiVersion : kubeadm.k8s.io/v1beta3
kind : InitConfiguration
localAPIEndpoint :
advertiseAddress : "10.100.0.1"
bindPort : 6443
nodeRegistration :
kubeletExtraArgs :
node-ip : 10.100.0.2 ,fd00:1:2:3::2
InitConfiguration 中的 advertiseAddress
给出 API 服务器将公告自身要监听的
IP 地址。advertiseAddress
的取值与 kubeadm init
的标志
--apiserver-advertise-address
的取值相同。
运行 kubeadm 来实例化双协议栈控制面节点:
kubeadm init --config= kubeadm-config.yaml
kube-controller-manager 标志 --node-cidr-mask-size-ipv4|--node-cidr-mask-size-ipv6
是使用默认值来设置的。参见配置 IPv4/IPv6 双协议栈 。
说明:
标志 --apiserver-advertise-address
不支持双协议栈。
向双协议栈集群添加节点
在添加节点之前,请确保该节点具有 IPv6 可路由的网络接口并且启用了 IPv6 转发。
下面的名为 kubeadm-config.yaml
的 kubeadm
配置文件
示例用于向集群中添加工作节点。
apiVersion : kubeadm.k8s.io/v1beta3
kind : JoinConfiguration
discovery :
bootstrapToken :
apiServerEndpoint : 10.100.0.1 :6443
token : "clvldh.vjjwg16ucnhp94qr"
caCertHashes :
- "sha256:a4863cde706cfc580a439f842cc65d5ef112b7b2be31628513a9881cf0d9fe0e"
# 请更改上面的认证信息,使之与你的集群中实际使用的令牌和 CA 证书匹配
nodeRegistration :
kubeletExtraArgs :
node-ip : 10.100.0.3 ,fd00:1:2:3::3
下面的名为 kubeadm-config.yaml
的 kubeadm
配置文件
示例用于向集群中添加另一个控制面节点。
apiVersion : kubeadm.k8s.io/v1beta3
kind : JoinConfiguration
controlPlane :
localAPIEndpoint :
advertiseAddress : "10.100.0.2"
bindPort : 6443
discovery :
bootstrapToken :
apiServerEndpoint : 10.100.0.1 :6443
token : "clvldh.vjjwg16ucnhp94qr"
caCertHashes :
- "sha256:a4863cde706cfc580a439f842cc65d5ef112b7b2be31628513a9881cf0d9fe0e"
# 请更改上面的认证信息,使之与你的集群中实际使用的令牌和 CA 证书匹配
nodeRegistration :
kubeletExtraArgs :
node-ip : 10.100.0.4 ,fd00:1:2:3::4
JoinConfiguration.controlPlane 中的 advertiseAddress
设定 API 服务器将公告自身要监听的
IP 地址。advertiseAddress
的取值与 kubeadm join
的标志
--apiserver-advertise-address
的取值相同。
kubeadm join --config= kubeadm-config.yaml
创建单协议栈集群
说明:
双协议栈支持并不意味着你需要使用双协议栈来寻址。
你可以部署一个启用了双协议栈联网特性的单协议栈集群。
为了更便于理解,参看下面的名为 kubeadm-config.yaml
的 kubeadm
配置文件 示例,
该文件用于单协议栈控制面节点。
apiVersion : kubeadm.k8s.io/v1beta3
kind : ClusterConfiguration
networking :
podSubnet : 10.244.0.0 /16
serviceSubnet : 10.96.0.0 /16
接下来
2.3 - Turnkey 云解决方案
本页列示 Kubernetes 认证解决方案供应商。
在每一个供应商分页,你可以学习如何安装和设置生产就绪的集群。
3 - 最佳实践
3.1 - 大规模集群的注意事项
集群是运行 Kubernetes 代理的、
由控制平面 管理的一组
节点 (物理机或虚拟机)。
Kubernetes v1.29 单个集群支持的最大节点数为 5,000。
更具体地说,Kubernetes 旨在适应满足以下所有 标准的配置:
每个节点的 Pod 数量不超过 110
节点数不超过 5,000
Pod 总数不超过 150,000
容器总数不超过 300,000
你可以通过添加或删除节点来扩展集群。集群扩缩的方式取决于集群的部署方式。
云供应商资源配额
为避免遇到云供应商配额问题,在创建具有大规模节点的集群时,请考虑以下事项:
请求增加云资源的配额,例如:
计算实例
CPU
存储卷
使用中的 IP 地址
数据包过滤规则集
负载均衡数量
网络子网
日志流
由于某些云供应商限制了创建新实例的速度,因此通过分批启动新节点来控制集群扩展操作,并在各批之间有一个暂停。
控制面组件
对于大型集群,你需要一个具有足够计算能力和其他资源的控制平面。
通常,你将在每个故障区域运行一个或两个控制平面实例,
先垂直缩放这些实例,然后在到达下降点(垂直)后再水平缩放。
你应该在每个故障区域至少应运行一个实例,以提供容错能力。
Kubernetes 节点不会自动将流量引向相同故障区域中的控制平面端点。
但是,你的云供应商可能有自己的机制来执行此操作。
例如,使用托管的负载均衡器时,你可以配置负载均衡器发送源自故障区域 A 中的 kubelet 和 Pod 的流量,
并将该流量仅定向到也位于区域 A 中的控制平面主机。
如果单个控制平面主机或端点故障区域 A 脱机,则意味着区域 A 中的节点的所有控制平面流量现在都在区域之间发送。
在每个区域中运行多个控制平面主机能降低出现这种结果的可能性。
etcd 存储
为了提高大规模集群的性能,你可以将事件对象存储在单独的专用 etcd 实例中。
在创建集群时,你可以(使用自定义工具):
启动并配置额外的 etcd 实例
配置 API 服务器 ,将它用于存储事件
有关为大型集群配置和管理 etcd 的详细信息,
请参阅为 Kubernetes 运行 etcd 集群
和使用 kubeadm 创建一个高可用 etcd 集群 。
插件资源
Kubernetes 资源限制
有助于最大程度地减少内存泄漏的影响以及 Pod 和容器可能对其他组件的其他方式的影响。
这些资源限制适用于插件 资源,
就像它们适用于应用程序工作负载一样。
例如,你可以对日志组件设置 CPU 和内存限制:
...
containers :
- name : fluentd-cloud-logging
image : fluent/fluentd-kubernetes-daemonset:v1
resources :
limits :
cpu : 100m
memory : 200Mi
插件的默认限制通常基于从中小规模 Kubernetes 集群上运行每个插件的经验收集的数据。
插件在大规模集群上运行时,某些资源消耗常常比其默认限制更多。
如果在不调整这些值的情况下部署了大规模集群,则插件可能会不断被杀死,因为它们不断达到内存限制。
或者,插件可能会运行,但由于 CPU 时间片的限制而导致性能不佳。
为避免遇到集群插件资源问题,在创建大规模集群时,请考虑以下事项:
部分垂直扩展插件 —— 总有一个插件副本服务于整个集群或服务于整个故障区域。
对于这些附加组件,请在扩大集群时加大资源请求和资源限制。
许多水平扩展插件 —— 你可以通过运行更多的 Pod 来增加容量——但是在大规模集群下,
可能还需要稍微提高 CPU 或内存限制。
VerticalPodAutoscaler 可以在 recommender 模式下运行,
以提供有关请求和限制的建议数字。
一些插件在每个节点上运行一个副本,并由 DaemonSet 控制:
例如,节点级日志聚合器。与水平扩展插件的情况类似,
你可能还需要稍微提高 CPU 或内存限制。
接下来
3.2 - 运行于多可用区环境
本页描述如何跨多个区(Zone)运行集群。
背景
Kubernetes 从设计上允许同一个 Kubernetes 集群跨多个失效区来运行,
通常这些区位于某个称作 区域(Region) 逻辑分组中。
主要的云提供商都将区域定义为一组失效区的集合(也称作 可用区(Availability Zones )),
能够提供一组一致的功能特性:每个区域内,各个可用区提供相同的 API 和服务。
典型的云体系结构都会尝试降低某个区中的失效影响到其他区中服务的概率。
控制面行为
所有的控制面组件
都支持以一组可相互替换的资源池的形式来运行,每个组件都有多个副本。
当你部署集群控制面时,应将控制面组件的副本跨多个失效区来部署。
如果可用性是一个很重要的指标,应该选择至少三个失效区,
并将每个控制面组件(API 服务器、调度器、etcd、控制器管理器)复制多个副本,
跨至少三个失效区来部署。如果你在运行云控制器管理器,
则也应该将该组件跨所选的三个失效区来部署。
说明:
Kubernetes 并不会为 API 服务器端点提供跨失效区的弹性。
你可以为集群 API 服务器使用多种技术来提升其可用性,包括使用
DNS 轮转、SRV 记录或者带健康检查的第三方负载均衡解决方案等等。
节点行为
Kubernetes 自动为负载资源(如 Deployment
或 StatefulSet )
跨集群中不同节点来部署其 Pod。
这种分布逻辑有助于降低失效带来的影响。
节点启动时,每个节点上的 kubelet 会向 Kubernetes API 中代表该 kubelet 的 Node
对象添加标签 。
这些标签可能包含区信息 。
如果你的集群跨了多个可用区或者地理区域,你可以使用节点标签,结合
Pod 拓扑分布约束
来控制如何在你的集群中多个失效域之间分布 Pod。这里的失效域可以是地理区域、可用区甚至是特定节点。
这些提示信息使得调度器 能够更好地调度
Pod,以实现更好的可用性,降低因为某种失效给整个工作负载带来的风险。
例如,你可以设置一种约束,确保某个 StatefulSet 中的 3 个副本都运行在不同的可用区中,
只要其他条件允许。你可以通过声明的方式来定义这种约束,
而不需要显式指定每个工作负载使用哪些可用区。
跨多个区分布节点
Kubernetes 的核心逻辑并不会帮你创建节点,你需要自行完成此操作,或者使用类似
Cluster API 这类工具来替你管理节点。
使用类似 Cluster API 这类工具,你可以跨多个失效域来定义一组用做你的集群工作节点的机器,
以及当整个区的服务出现中断时如何自动治愈集群的策略。
为 Pod 手动指定区
你可以应用节点选择算符约束 到你所创建的
Pod 上,或者为 Deployment、StatefulSet 或 Job 这类工作负载资源中的 Pod 模板设置此类约束。
跨区的存储访问
当创建持久卷时,Kubernetes 会自动向那些链接到特定区的 PersistentVolume 添加区标签。
调度器 通过其
NoVolumeZoneConflict
断言确保申领给定 PersistentVolume 的 Pod
只会被调度到该卷所在的可用区。
请注意,添加区标签的方法可能取决于你的云提供商和存储制备器。
请参阅具体的环境文档,确保配置正确。
请注意,添加区标签的方法可能会根据你所使用的云提供商和存储制备器而有所不同。
为确保配置正确,请始终参阅你的环境的特定文档。
你可以为 PersistentVolumeClaim 指定
StorageClass
以设置该类中的存储可以使用的失效域(区)。
要了解如何配置能够感知失效域或区的 StorageClass,
请参阅可用的拓扑逻辑 。
网络
Kubernetes 自身不提供与可用区相关的联网配置。
你可以使用网络插件
来配置集群的联网,该网络解决方案可能拥有一些与可用区相关的元素。
例如,如果你的云提供商支持 type=LoadBalancer
的 Service,
则负载均衡器可能仅会将请求流量发送到运行在负责处理给定连接的负载均衡器组件所在的区。
请查阅云提供商的文档了解详细信息。
对于自定义的或本地集群部署,也可以考虑这些因素。
Service 和
Ingress 的行为,
包括处理不同失效区的方法,在很大程度上取决于你的集群是如何搭建的。
失效恢复
在搭建集群时,你可能需要考虑当某区域中的所有失效区都同时掉线时,是否以及如何恢复服务。
例如,你是否要求在某个区中至少有一个节点能够运行 Pod?
请确保任何对集群很关键的修复工作都不要指望集群中至少有一个健康节点。
例如:当所有节点都不健康时,你可能需要运行某个修复性的 Job,
该 Job 要设置特定的容忍度 ,
以便修复操作能够至少将一个节点恢复为可用状态。
Kubernetes 对这类问题没有现成的解决方案;不过这也是要考虑的因素之一。
接下来
要了解调度器如何在集群中放置 Pod 并遵从所配置的约束,
可参阅调度与驱逐 。
3.3 - 校验节点设置
节点一致性测试 是一个容器化的测试框架,提供了针对节点的系统验证和功能测试。
测试验证节点是否满足 Kubernetes 的最低要求;通过测试的节点有资格加入 Kubernetes 集群。
该测试主要检测节点是否满足 Kubernetes 的最低要求,通过检测的节点有资格加入 Kubernetes 集群。
节点的前提条件
要运行节点一致性测试,节点必须满足与标准 Kubernetes 节点相同的前提条件。节点至少应安装以下守护程序:
与 CRI 兼容的容器运行时,例如 Docker、Containerd 和 CRI-O
Kubelet
要运行节点一致性测试,请执行以下步骤:
得出 kubelet 的 --kubeconfig
的值;例如:--kubeconfig=/var/lib/kubelet/config.yaml
。
由于测试框架启动了本地控制平面来测试 kubelet,因此使用 http://localhost:8080
作为API 服务器的 URL。
一些其他的 kubelet 命令行参数可能会被用到:
--cloud-provider
:如果使用 --cloud-provider=gce
,需要移除这个参数来运行测试。
使用以下命令运行节点一致性测试:
# $CONFIG_DIR 是你 Kubelet 的 pod manifest 路径。
# $LOG_DIR 是测试的输出路径。
sudo docker run -it --rm --privileged --net= host \
-v /:/rootfs -v $CONFIG_DIR :$CONFIG_DIR -v $LOG_DIR :/var/result \
registry.k8s.io/node-test:0.2
Kubernetes 也为其他硬件体系结构的系统提供了节点一致性测试的 Docker 镜像:
架构
镜像
amd64
node-test-amd64
arm
node-test-arm
arm64
node-test-arm64
运行特定的测试
要运行特定测试,请使用你希望运行的测试的特定表达式覆盖环境变量 FOCUS
。
sudo docker run -it --rm --privileged --net= host \
-v /:/rootfs:ro -v $CONFIG_DIR :$CONFIG_DIR -v $LOG_DIR :/var/result \
-e FOCUS = MirrorPod \ # Only run MirrorPod test
registry.k8s.io/node-test:0.2
要跳过特定的测试,请使用你希望跳过的测试的常规表达式覆盖环境变量 SKIP
。
sudo docker run -it --rm --privileged --net= host \
-v /:/rootfs:ro -v $CONFIG_DIR :$CONFIG_DIR -v $LOG_DIR :/var/result \
-e SKIP = MirrorPod \ # 运行除 MirrorPod 测试外的所有一致性测试内容
registry.k8s.io/node-test:0.2
节点一致性测试是节点端到端测试 的容器化版本。
默认情况下,它会运行所有一致性测试。
理论上,只要合理地配置容器和挂载所需的卷,就可以运行任何的节点端到端测试用例。但是这里强烈建议只运行一致性测试 ,因为运行非一致性测试需要很多复杂的配置。
注意事项
测试会在节点上遗留一些 Docker 镜像,包括节点一致性测试本身的镜像和功能测试相关的镜像。
测试会在节点上遗留一些死的容器。这些容器是在功能测试的过程中创建的。
3.4 - 强制实施 Pod 安全性标准
本页提供实施 Pod 安全标准(Pod Security Standards)
时的一些最佳实践。
使用内置的 Pod 安全性准入控制器
特性状态: Kubernetes v1.25 [stable]
Pod 安全性准入控制器
尝试替换已被废弃的 PodSecurityPolicies。
完全未经配置的名字空间应该被视为集群安全模型中的重大缺陷。
我们建议花一些时间来分析在每个名字空间中执行的负载的类型,
并通过引用 Pod 安全性标准来确定每个负载的合适级别。
未设置标签的名字空间应该视为尚未被评估。
针对所有名字空间中的所有负载都具有相同的安全性需求的场景,
我们提供了一个示例
用来展示如何批量应用 Pod 安全性标签。
拥抱最小特权原则
在一个理想环境中,每个名字空间中的每个 Pod 都会满足 restricted
策略的需求。
不过,这既不可能也不现实,某些负载会因为合理的原因而需要特权上的提升。
允许 privileged
负载的名字空间需要建立并实施适当的访问控制机制。
对于运行在特权宽松的名字空间中的负载,需要维护其独特安全性需求的文档。
如果可能的话,要考虑如何进一步约束这些需求。
采用多种模式的策略
Pod 安全性标准准入控制器的 audit
和 warn
模式(mode)
能够在不影响现有负载的前提下,让该控制器更方便地收集关于 Pod 的重要的安全信息。
针对所有名字空间启用这些模式是一种好的实践,将它们设置为你最终打算 enforce
的
期望的 级别和版本。这一阶段中所生成的警告和审计注解信息可以帮助你到达这一状态。
如果你期望负载的作者能够作出变更以便适应期望的级别,可以启用 warn
模式。
如果你希望使用审计日志了监控和驱动变更,以便负载能够适应期望的级别,可以启用 audit
模式。
当你将 enforce
模式设置为期望的取值时,这些模式在不同的场合下仍然是有用的:
通过将 warn
设置为 enforce
相同的级别,客户可以在尝试创建无法通过合法检查的 Pod
(或者包含 Pod 模板的资源)时收到警告信息。这些信息会帮助于更新资源使其合规。
在将 enforce
锁定到特定的非最新版本的名字空间中,将 audit
和 warn
模式设置为 enforce
一样的级别而非 latest
版本,
这样可以方便看到之前版本所允许但当前最佳实践中被禁止的设置。
第三方替代方案
说明:  本部分链接到提供 Kubernetes 所需功能的第三方项目。Kubernetes 项目作者不负责这些项目。此页面遵循
CNCF 网站指南 ,按字母顺序列出项目。要将项目添加到此列表中,请在提交更改之前阅读
内容指南 。
Kubernetes 生态系统中也有一些其他强制实施安全设置的替代方案处于开发状态中:
采用 内置的 方案(例如 PodSecurity 准入控制器)还是第三方工具,
这一决策完全取决于你自己的情况。在评估任何解决方案时,对供应链的信任都是至关重要的。
最终,使用前述方案中的 任何 一种都好过放任自流。
3.5 - PKI 证书和要求
Kubernetes 需要 PKI 证书才能进行基于 TLS 的身份验证。如果你是使用
kubeadm 安装的 Kubernetes,
则会自动生成集群所需的证书。你还可以生成自己的证书。
例如,不将私钥存储在 API 服务器上,可以让私钥更加安全。此页面说明了集群必需的证书。
集群是如何使用证书的
Kubernetes 需要 PKI 才能执行以下操作:
Kubelet 的客户端证书,用于 API 服务器身份验证
Kubelet 服务端证书 ,
用于 API 服务器与 Kubelet 的会话
API 服务器端点的证书
集群管理员的客户端证书,用于 API 服务器身份认证
API 服务器的客户端证书,用于和 Kubelet 的会话
API 服务器的客户端证书,用于和 etcd 的会话
控制器管理器的客户端证书或 kubeconfig,用于和 API 服务器的会话
调度器的客户端证书或 kubeconfig,用于和 API 服务器的会话
前端代理 的客户端及服务端证书
说明:
只有当你运行 kube-proxy
并要支持扩展 API 服务器 时,
才需要 front-proxy
证书。
etcd 还实现了双向 TLS 来对客户端和对其他对等节点进行身份验证。
证书存储位置
假如你通过 kubeadm 安装 Kubernetes,大多数证书会被存储在 /etc/kubernetes/pki
中。
本文档中的所有路径都是相对于该目录的,但用户账号证书除外,kubeadm 将其放在 /etc/kubernetes
中。
如果你不想通过 kubeadm 生成所需证书,你可以使用一个单根 CA 来创建这些证书,或者直接提供所有证书。
参见证书 以进一步了解如何创建自己的证书授权机构。
更多关于管理证书的信息,请参阅使用 kubeadm 进行证书管理 。
单根 CA
你可以创建由管理员控制的单根 CA。这个根 CA 可以创建多个中间 CA,
并将所有进一步的创建委托给 Kubernetes 本身。
需要这些 CA:
路径
默认 CN
描述
ca.crt,key
kubernetes-ca
Kubernetes 通用 CA
etcd/ca.crt,key
etcd-ca
与 etcd 相关的所有功能
front-proxy-ca.crt,key
kubernetes-front-proxy-ca
用于前端代理
上面的 CA 之外,还需要获取用于服务账号管理的密钥对,也就是 sa.key
和 sa.pub
。
下面的例子说明了上表中所示的 CA 密钥和证书文件。
/etc/kubernetes/pki/ca.crt
/etc/kubernetes/pki/ca.key
/etc/kubernetes/pki/etcd/ca.crt
/etc/kubernetes/pki/etcd/ca.key
/etc/kubernetes/pki/front-proxy-ca.crt
/etc/kubernetes/pki/front-proxy-ca.key
所有的证书
如果你不想将 CA 的私钥拷贝至你的集群中,你也可以自己生成全部的证书。
需要这些证书:
默认 CN
父级 CA
O(位于 Subject 中)
kind
主机 (SAN)
kube-etcd
etcd-ca
server, client
<hostname>
, <Host_IP>
, localhost
, 127.0.0.1
kube-etcd-peer
etcd-ca
server, client
<hostname>
, <Host_IP>
, localhost
, 127.0.0.1
kube-etcd-healthcheck-client
etcd-ca
client
kube-apiserver-etcd-client
etcd-ca
client
kube-apiserver
kubernetes-ca
server
<hostname>
, <Host_IP>
, <advertise_IP>
, [1]
kube-apiserver-kubelet-client
kubernetes-ca
system:masters
client
front-proxy-client
kubernetes-front-proxy-ca
client
说明:
不使用超级用户组 system:masters
来控制 kube-apiserver-kubelet-client
,
可以使用一个权限较低的组。kubeadm 使用 kubeadm:cluster-admins
组来达到这个目的。
[1]: 用来连接到集群的不同 IP 或 DNS 名称
(就像 kubeadm 为负载均衡所使用的固定
IP 或 DNS 名称:kubernetes
、kubernetes.default
、kubernetes.default.svc
、
kubernetes.default.svc.cluster
、kubernetes.default.svc.cluster.local
)。
其中 kind
对应一种或多种类型的 x509 密钥用途,也可记录在
CertificateSigningRequest
类型的 .spec.usages
中:
kind
密钥用途
server
数字签名、密钥加密、服务端认证
client
数字签名、密钥加密、客户端认证
说明:
上面列出的 Host/SAN 是获取工作集群的推荐配置方式;
如果需要特殊安装,则可以在所有服务器证书上添加其他 SAN。
说明:
对于 kubeadm 用户:
不使用私钥并将证书复制到集群 CA 的方案,在 kubeadm 文档中将这种方案称为外部 CA。
如果将上表与 kubeadm 生成的 PKI 进行比较,你会注意到,如果使用外部 etcd,则不会生成
kube-etcd
、kube-etcd-peer
和 kube-etcd-healthcheck-client
证书。
证书路径
证书应放置在建议的路径中(以便 kubeadm
使用)。无论使用什么位置,都应使用给定的参数指定路径。
默认 CN
建议的密钥路径
建议的证书路径
命令
密钥参数
证书参数
etcd-ca
etcd/ca.key
etcd/ca.crt
kube-apiserver
--etcd-cafile
kube-apiserver-etcd-client
apiserver-etcd-client.key
apiserver-etcd-client.crt
kube-apiserver
--etcd-keyfile
--etcd-certfile
kubernetes-ca
ca.key
ca.crt
kube-apiserver
--client-ca-file
kubernetes-ca
ca.key
ca.crt
kube-controller-manager
--cluster-signing-key-file
--client-ca-file, --root-ca-file, --cluster-signing-cert-file
kube-apiserver
apiserver.key
apiserver.crt
kube-apiserver
--tls-private-key-file
--tls-cert-file
kube-apiserver-kubelet-client
apiserver-kubelet-client.key
apiserver-kubelet-client.crt
kube-apiserver
--kubelet-client-key
--kubelet-client-certificate
front-proxy-ca
front-proxy-ca.key
front-proxy-ca.crt
kube-apiserver
--requestheader-client-ca-file
front-proxy-ca
front-proxy-ca.key
front-proxy-ca.crt
kube-controller-manager
--requestheader-client-ca-file
front-proxy-client
front-proxy-client.key
front-proxy-client.crt
kube-apiserver
--proxy-client-key-file
--proxy-client-cert-file
etcd-ca
etcd/ca.key
etcd/ca.crt
etcd
--trusted-ca-file, --peer-trusted-ca-file
kube-etcd
etcd/server.key
etcd/server.crt
etcd
--key-file
--cert-file
kube-etcd-peer
etcd/peer.key
etcd/peer.crt
etcd
--peer-key-file
--peer-cert-file
etcd-ca
etcd/ca.crt
etcdctl
--cacert
kube-etcd-healthcheck-client
etcd/healthcheck-client.key
etcd/healthcheck-client.crt
etcdctl
--key
--cert
注意事项同样适用于服务账号密钥对:
私钥路径
公钥路径
命令
参数
sa.key
kube-controller-manager
--service-account-private-key-file
sa.pub
kube-apiserver
--service-account-key-file
下面的例子展示了自行生成所有密钥和证书时所需要提供的文件路径。
这些路径基于前面的表格 。
/etc/kubernetes/pki/etcd/ca.key
/etc/kubernetes/pki/etcd/ca.crt
/etc/kubernetes/pki/apiserver-etcd-client.key
/etc/kubernetes/pki/apiserver-etcd-client.crt
/etc/kubernetes/pki/ca.key
/etc/kubernetes/pki/ca.crt
/etc/kubernetes/pki/apiserver.key
/etc/kubernetes/pki/apiserver.crt
/etc/kubernetes/pki/apiserver-kubelet-client.key
/etc/kubernetes/pki/apiserver-kubelet-client.crt
/etc/kubernetes/pki/front-proxy-ca.key
/etc/kubernetes/pki/front-proxy-ca.crt
/etc/kubernetes/pki/front-proxy-client.key
/etc/kubernetes/pki/front-proxy-client.crt
/etc/kubernetes/pki/etcd/server.key
/etc/kubernetes/pki/etcd/server.crt
/etc/kubernetes/pki/etcd/peer.key
/etc/kubernetes/pki/etcd/peer.crt
/etc/kubernetes/pki/etcd/healthcheck-client.key
/etc/kubernetes/pki/etcd/healthcheck-client.crt
/etc/kubernetes/pki/sa.key
/etc/kubernetes/pki/sa.pub
你必须手动配置以下管理员账号和服务账号:
文件名
凭据名称
默认 CN
O (位于 Subject 中)
admin.conf
default-admin
kubernetes-admin
<admin-group>
super-admin.conf
default-super-admin
kubernetes-super-admin
system:masters
kubelet.conf
default-auth
system:node:<nodeName>
(参阅注释)
system:nodes
controller-manager.conf
default-controller-manager
system:kube-controller-manager
scheduler.conf
default-scheduler
system:kube-scheduler
说明:
kubelet.conf
中 <nodeName>
的值 必须 与 kubelet 向 apiserver 注册时提供的节点名称的值完全匹配。
有关更多详细信息,请阅读节点授权 。
说明:
在上面的例子中,<admin-group>
是实现特定的。
一些工具在默认的 admin.conf
中签署证书,以成为 system:masters
组的一部分。
system:masters
是一个紧急情况下的超级用户组,可以绕过 Kubernetes 的授权层,如 RBAC。
另外,某些工具不会生成单独的 super-admin.conf
将证书绑定到这个超级用户组。
kubeadm 在 kubeconfig 文件中生成两个单独的管理员证书。
一个是在 admin.conf
中,带有 Subject: O = kubeadm:cluster-admins, CN = kubernetes-admin
。kubeadm:cluster-admins
是绑定到 cluster-admin
ClusterRole 的自定义组。
这个文件在所有由 kubeadm 管理的控制平面机器上生成。
另一个是在 super-admin.conf
中,具有 Subject: O = system:masters, CN = kubernetes-super-admin
。
这个文件只在调用了 kubeadm init
的节点上生成。
对于每个配置,请都使用给定的 CN 和 O 生成 x509 证书/密钥偶对。
为每个配置运行下面的 kubectl
命令:
KUBECONFIG=<filename> kubectl config set-cluster default-cluster --server=https://<host ip>:6443 --certificate-authority <path-to-kubernetes-ca> --embed-certs
KUBECONFIG=<filename> kubectl config set-credentials <credential-name> --client-key <path-to-key>.pem --client-certificate <path-to-cert>.pem --embed-certs
KUBECONFIG=<filename> kubectl config set-context default-system --cluster default-cluster --user <credential-name>
KUBECONFIG=<filename> kubectl config use-context default-system
这些文件用途如下:
文件名
命令
说明
admin.conf
kubectl
配置集群的管理员
super-admin.conf
kubectl
为集群配置超级管理员用户
kubelet.conf
kubelet
集群中的每个节点都需要一份
controller-manager.conf
kube-controller-manager
必须添加到 manifests/kube-controller-manager.yaml
清单中
scheduler.conf
kube-scheduler
必须添加到 manifests/kube-scheduler.yaml
清单中
下面是前表中所列文件的完整路径。
/etc/kubernetes/admin.conf
/etc/kubernetes/super-admin.conf
/etc/kubernetes/kubelet.conf
/etc/kubernetes/controller-manager.conf
/etc/kubernetes/scheduler.conf