配置最佳实践
本文档突出并整合了在用户指南、入门文档和示例中介绍的配置最佳实践。
这是一份不断更新的文档。如果你想到此列表中没有包含但对其他人可能有用的内容,请不要犹豫提交一个问题或拉取请求。
通用配置技巧
在定义配置时,请指定最新的稳定 API 版本。
配置文件在推送到集群之前应存储在版本控制系统中。这样可以在需要时快速回滚配置变更。这也有助于集群重建和恢复。
使用 YAML 而不是 JSON 编写配置文件。虽然在几乎所有场景中这两种格式可以互换使用,但 YAML 通常更用户友好。
如果合理,将相关的对象组合到一个文件中。一个文件通常比多个文件更容易管理。请参阅 guestbook-all-in-one.yaml 文件,它是一个关于此语法的示例。
另请注意,许多
kubectl
命令可以作用于一个目录。例如,你可以对包含配置文件的目录运行kubectl apply
。不必要时,不要指定默认值:简单、最小化的配置会减少出错的可能性。
将对象描述放在注解中,以便更好地进行内省(introspection)。
注意
YAML 1.2 布尔值规范相对于 YAML 1.1 引入了一项破坏性变更。这是 Kubernetes 中一个已知的问题。YAML 1.2 仅将 true 和 false 视为有效的布尔值,而 YAML 1.1 也接受 yes、no、on 和 off 作为布尔值。然而,Kubernetes 使用的 YAML 解析器大多兼容 YAML 1.1,这意味着在 YAML 清单中使用 yes 或 no 而非 true 或 false 可能会导致意外错误或行为。为避免此问题,建议在 YAML 清单中布尔值始终使用 true 或 false,并引用任何可能与布尔值混淆的字符串,例如 "yes" 或 "no"。
除了布尔值,YAML 版本之间还有其他规范变更。请参考 YAML 规范变更文档以获得完整列表。
"裸 Pod" vs ReplicaSet, Deployment, 和 Job
如果可以避免,不要使用裸 Pod(即,不绑定到 ReplicaSet 或 Deployment 的 Pod)。裸 Pod 在节点发生故障时不会被重新调度。
Deployment 既会创建 ReplicaSet 以确保所需的 Pod 数量始终可用,又指定了替换 Pod 的策略(例如滚动更新),它几乎总是优于直接创建 Pod,除非是一些明确的
restartPolicy: Never
场景。Job 也可能适用。
Service
在创建 Service 对应的后端工作负载(Deployment 或 ReplicaSet)之前,以及在需要访问该 Service 的任何工作负载之前,先创建 Service。当 Kubernetes 启动一个容器时,它会提供指向该容器启动时所有正在运行的 Service 的环境变量。例如,如果存在一个名为
foo
的 Service,所有容器在其初始环境中都会获得以下变量:FOO_SERVICE_HOST=<the host the Service is running on> FOO_SERVICE_PORT=<the port the Service is running on>
这确实暗示了一个排序要求 - 任何 Pod 想要访问的
Service
都必须在Pod
本身之前创建,否则环境变量将不会被填充。DNS 没有这个限制。一个可选的(强烈推荐的)集群插件是 DNS 服务器。DNS 服务器会监听 Kubernetes API 中新的
Service
,并为每个 Service 创建一组 DNS 记录。如果整个集群中都启用了 DNS,那么所有Pod
都应该能够自动进行Service
的名称解析。除非绝对必要,否则不要为 Pod 指定
hostPort
。当你将 Pod 绑定到hostPort
时,这会限制 Pod 可以调度的位置数量,因为每个 <hostIP
,hostPort
,protocol
> 组合都必须是唯一的。如果你不明确指定hostIP
和protocol
,Kubernetes 将使用0.0.0.0
作为默认的hostIP
,并使用TCP
作为默认的protocol
。如果你只需要为了调试目的访问端口,可以使用apiserver 代理或
kubectl port-forward
。如果你明确需要在节点上暴露 Pod 的端口,在诉诸于
hostPort
之前,考虑使用 NodePort 类型的 Service。避免使用
hostNetwork
,原因与hostPort
相同。当你不需要
kube-proxy
的负载均衡功能时,使用无头 Service(即ClusterIP
为None
)进行服务发现。
使用标签
定义和使用 标签来标识应用程序或 Deployment 的语义属性,例如
{ app.kubernetes.io/name: MyApp, tier: frontend, phase: test, deployment: v3 }
。你可以使用这些标签来为其他资源选择合适的 Pod;例如,一个选择所有tier: frontend
Pod 的 Service,或者所有app.kubernetes.io/name: MyApp
的phase: test
组件。请参阅 guestbook 应用程序,了解此方法的示例。可以通过在其选择器中省略特定于发布的标签,使得一个 Service 能够跨越多个 Deployment。当需要在不停机的情况下更新正在运行的服务时,使用 Deployment。
一个对象的期望状态由 Deployment 描述,如果对其规范的更改被 应用,Deployment 控制器会以受控速率将实际状态更改为期望状态。
使用Kubernetes 常用标签来表示常用用例。这些标准化标签以一种使工具(包括
kubectl
和仪表盘)能够互操作的方式丰富了元数据。你可以为了调试目的修改标签。由于 Kubernetes 控制器(如 ReplicaSet)和 Service 使用选择器标签匹配 Pod,移除 Pod 的相关标签会使其不再被控制器考虑,也不再由 Service 提供流量。如果你移除现有 Pod 的标签,其控制器将创建一个新的 Pod 来替代它。这是在“隔离”环境中调试之前“活跃”的 Pod 的一种有用方法。要交互式地移除或添加标签,请使用
kubectl label
。
使用 kubectl
使用
kubectl apply -f <directory>
。这会在<directory>
中查找所有.yaml
、.yml
和.json
文件中的 Kubernetes 配置,并将其传递给apply
。使用
kubectl create deployment
和kubectl expose
快速创建单容器 Deployment 和 Service。有关示例,请参阅使用 Service 访问集群中的应用程序。