文章目录
- 前言
- [一、Pod 定向部署到指定节点](#一、Pod 定向部署到指定节点)
-
- [🤔 配置解读](#🤔 配置解读)
- [🛠️ 完整实现步骤](#🛠️ 完整实现步骤)
-
- [步骤 1:为目标节点添加标签和污点](#步骤 1:为目标节点添加标签和污点)
- [步骤 2:部署应用 Pod](#步骤 2:部署应用 Pod)
- [💡 机制总结](#💡 机制总结)
- 工作负载Deployment的apiVersion
- service和deployment的标签选择器
-
- [🆚 核心区别对比表](#🆚 核心区别对比表)
- [🛠️ 语法结构差异详解](#🛠️ 语法结构差异详解)
-
- [1. Deployment 的选择器](#1. Deployment 的选择器)
- [2. Service 的选择器](#2. Service 的选择器)
- [💡 为什么会有这种设计差异?](#💡 为什么会有这种设计差异?)
- [🚀 总结建议](#🚀 总结建议)
前言
``
。
一、Pod 定向部署到指定节点
节点选择器 (nodeSelector) 和 污点与容忍 (Taints and Tolerations) 的结合使用。
这种组合策略非常有效,它通过"推拉结合"的方式,确保您的应用 Pod 能够精准且独占地运行在目标节点上。
yaml
nodeSelector: # 节点选择器
environment: uat-xc
tolerations: # 污点容忍
- effect: NoSchedule
key: environment
operator: Equal
value: uat-xc
🤔 配置解读
配置可以从两个方面来理解:
nodeSelector(拉取策略)
- 作用 :这是一个"吸引"规则。它告诉 Kubernetes 调度器:"请把这个 Pod 调度到拥有
environment: uat-xc标签的节点上。" - 前提 :目标节点必须已经打上了
environment: uat-xc这个标签。
tolerations(容忍策略)
- 作用:这是一个"通行证"或"免疫"规则。它允许 Pod "容忍"节点上的特定"污点"。
- 前提:为了让这个容忍生效,您需要在目标节点上添加一个对应的污点。
🛠️ 完整实现步骤
为了让配置完全生效,实现 Pod 定向部署到指定节点,需要完成以下两个步骤:
步骤 1:为目标节点添加标签和污点
假设目标节点名为 node-01,需要使用 kubectl 命令为其添加标签和污点。
-
添加标签 (匹配
nodeSelector)bashkubectl label nodes node-01 environment=uat-xc这条命令为
node-01节点添加了environment=uat-xc标签,满足了 Pod 中nodeSelector的要求。 -
添加污点 (匹配
tolerations)bashkubectl taint nodes node-01 environment=uat-xc:NoSchedule这条命令为
node-01节点添加了一个污点。这个污点会阻止所有没有对应容忍配置的 Pod 调度到该节点上。
步骤 2:部署应用 Pod
使用章节开头提供的 YAML 配置部署应用。这个 Pod 因为同时具备了 nodeSelector 和 tolerations,所以:
- 它只会 被调度到带有
environment=uat-xc标签的节点。 - 它能够 容忍
environment=uat-xc:NoSchedule这个污点。
因此,这个 Pod 最终会被精准地部署到 node-01 上,而其他没有对应容忍配置的普通 Pod 则无法进入该节点,从而实现了资源的独占。
💡 机制总结
| 机制 | 作用 | 配置位置 | 效果 |
|---|---|---|---|
| 节点选择器 (nodeSelector) | 吸引 Pod 到特定节点 | Pod 的 YAML 文件 | Pod 只能被调度到带有匹配标签的节点上。 |
| 污点与容忍 (Taints & Tolerations) | 排斥不匹配的 Pod | 污点在节点 上,容忍在Pod上 | 节点拒绝没有对应容忍的 Pod 调度。 |
通过结合使用这两种机制,您可以实现强大而灵活的调度策略,确保关键应用运行在专属的、经过优化的硬件资源上。
工作负载Deployment的apiVersion
在 Kubernetes 中,工作负载 Deployment 的 apiVersion 取决于你使用的 Kubernetes 集群版本。
目前主流且推荐使用的版本是 apps/v1。
- 📊 版本对照表
为了让你更直观地了解不同版本的对应关系,我整理了下表:
| Kubernetes 版本 | 推荐的 apiVersion | 状态 | 说明 |
|---|---|---|---|
| v1.9.0 及以后 | apps/v1 |
✅ 当前标准 | 生产环境的标准配置,稳定且长期支持。 |
| v1.6.0 - v1.8.0 | apps/v1beta2 |
⚠️ 已废弃 | 早期过渡版本,现已不再使用。 |
| v1.6.0 之前 | extensions/v1beta1 |
❌ 已移除 | 极早期的版本,在新版集群中已不可用。 |
- 📝 配置示例
在编写 Deployment 的 YAML 文件时,标准的头部配置如下:
yaml
apiVersion: apps/v1 # 这里指定 API 版本
kind: Deployment # 资源类型
metadata:
name: my-app-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: nginx:latest
- 💡 关键注意事项
selector 字段是必须的 :
在使用 apiVersion: apps/v1 时,必须 在 spec 下显式定义 selector 字段,且 matchLabels 必须与 template.metadata.labels 中的标签保持一致。这是 apps/v1 与旧版本的一个显著区别,旧版本有时允许隐式生成选择器。
如何确认你的集群版本 :
如果你不确定当前集群支持哪个版本,可以通过以下命令查看集群版本信息:
bash
kubectl version
或者直接尝试获取 Deployment 资源来验证 API 路径:
bash
kubectl explain deployment
总结 :除非你在维护非常古老的遗留系统,否则请始终使用 apiVersion: apps/v1。
service和deployment的标签选择器
在 Kubernetes 中,Service 和 Deployment 的标签选择器(Selector)虽然核心目的都是"根据标签找到 Pod",但它们在 YAML 语法结构 、强制程度 以及匹配逻辑上有着显著的区别。
简单来说:Deployment 的选择器更严格且语法嵌套更深,而 Service 的选择器更灵活且语法扁平。
以下是详细的对比分析:
🆚 核心区别对比表
| 特性 | Deployment 选择器 | Service 选择器 |
|---|---|---|
| YAML 语法路径 | spec.selector.matchLabels |
spec.selector |
| 语法结构 | 嵌套结构 :必须包含 matchLabels 或 matchExpressions 字段。 |
扁平结构 :直接写键值对,不需要 matchLabels 包装。 |
| 强制性 | 必填:必须显式定义,且必须与 Pod 模板标签匹配。 | 可选:如果不填,Service 依然可以创建(通常用于无头 Service 或手动管理 Endpoints)。 |
| 匹配逻辑 | 严格匹配:通常要求选择器是 Pod 标签的子集或完全一致。 | 超集匹配:只要 Pod 拥有选择器中指定的键值对即可,Pod 可以拥有额外标签。 |
| 主要作用 | 生命周期管理:决定 Deployment 管理哪些 Pod,负责创建、删除、更新。 | 流量路由:决定 Service 将流量转发给哪些 Pod(生成 Endpoints)。 |
🛠️ 语法结构差异详解
1. Deployment 的选择器
在 Deployment 中,选择器位于 spec.selector 下,并且必须 使用 matchLabels(或 matchExpressions)来包裹具体的标签。
- 关键点 :
spec.selector.matchLabels中的标签必须与spec.template.metadata.labels中的标签完全匹配(或者前者是后者的子集)。如果两者不一致,API Server 会直接报错拒绝创建。
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
selector: # 1. 定义选择器
matchLabels: # 2. 必须使用 matchLabels 包裹
app: my-app
version: v1
template:
metadata:
labels: # 3. Pod 模板的标签
app: my-app # 必须包含 selector 中的所有键值对
version: v1 # 必须包含 selector 中的所有键值对
env: prod # 可以包含额外的标签
spec:
containers:
- name: nginx
image: nginx
2. Service 的选择器
在 Service 中,选择器直接位于 spec.selector 下,直接 写键值对,不需要 matchLabels 这一层。
- 关键点 :Service 的匹配逻辑是"包含即匹配"。只要 Pod 身上贴了
app: my-app这个标签,不管 Pod 还有没有其他标签(比如env: prod),都会被这个 Service 选中并加入负载均衡池。
yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector: # 1. 直接写键值对,无需 matchLabels
app: my-app # 2. 只要 Pod 有这个标签就会被选中
ports:
- protocol: TCP
port: 80
targetPort: 8080
💡 为什么会有这种设计差异?
- Deployment (控制器) :它需要非常明确地知道"哪些 Pod 是我生的"以及"我要管理哪些 Pod"。使用
matchLabels这种显式的结构,配合严格的匹配检查,可以防止控制器误删或误管不属于它的 Pod,保证集群状态的稳定性。 - Service (网络抽象) :它的目标是"把流量送给符合条件的 Pod"。使用扁平的键值对结构更简洁,且支持"超集匹配"(即 Pod 标签是选择器的超集),这使得 Service 可以灵活地聚合不同类型的 Pod(例如,你可以创建一个选择器
app: backend,它同时选中了db和cache两种角色的 Pod,只要它们都有app: backend标签)。
🚀 总结建议
- 写 Deployment 时 :一定要检查
selector.matchLabels和template.metadata.labels是否一致,这是新手最容易报错的地方。 - 写 Service 时 :直接写
selector键值对即可,确保它能覆盖到你想要暴露的 Pod 标签。 - 排错技巧 :如果你发现 Service 没有流量,使用
kubectl get endpoints <service-name>查看是否有 IP。如果没有,通常是因为 Service 的selector写错了,或者 Pod 的标签没打对。
本文的引用仅限自我学习如有侵权,请联系作者删除。
参考知识
<>