✨✨ 欢迎大家来到景天科技苑✨✨
🎈🎈 养成好习惯,先赞后看哦~🎈🎈
🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生k8s,linux,shell脚本等实操经验,网站搭建,数据库等分享。所属的专栏:云原生K8S,零基础到进阶实战
景天的主页:景天科技苑
文章目录
- Kubernetes中关于污点、亲和性和容忍度的详细用法教程
- 一、污点(Taints)
- 1.1 污点的定义
- 1.2 设置污点
- 1.3 实战案例
- 二、容忍度(Tolerations)
- 2.1 容忍度的定义
- 2.2 设置容忍度
- 2.3 实战案例
- 三、亲和性(Affinity)
- 3.1 节点亲和性(Node Affinity)
- 示例YAML配置
- 3.2 Pod亲和性(Pod Affinity)和Pod反亲和性(Pod Anti-Affinity)
- Pod亲和性示例
- Pod反亲和性示例
- 四、综合实战案例
- 第一步:标记节点
- 第二步:配置数据库Pod
- 第三步:配置前端Pod和后端Pod的反亲和性
- 1. 资源限制(Resource Limits)
- 2. 存储配置(Storage Configuration)
- 3. 网络策略(Network Policies)
- 4. 容忍度(Tolerations)
- 5. 使用Deployment, StatefulSet或DaemonSet等控制器
- 6. 监控和日志
- 7. 备份和恢复策略
- 8. 更新和回滚策略
- 9. 安全性
Kubernetes中关于污点、亲和性和容忍度的详细用法教程
在Kubernetes中,污点(Taints)、亲和性(Affinity)和容忍度(Tolerations)是三个强大的工具,它们允许集群管理员精细控制Pod在节点上的调度。这些机制共同工作,确保Pod被调度到最适合它们的节点上,从而提高集群的效率和稳定性。本文将结合具体案例,详细介绍污点、亲和性和容忍度的用法。
一、污点(Taints)
污点是一种标记节点的机制,用于告诉Kubernetes调度器该节点上的Pod是有问题的,或者该节点应该被保留给特定的Pod使用。当节点被标记为污点时,除非Pod明确声明它可以容忍这个污点,否则调度器不会将新的Pod调度到这个节点上。
1.1 污点的定义
污点通常是一个键值对,并附加一个效果(Effect),用于指定污点的行为。污点的常见效果有三种:
- NoSchedule:如果节点上至少有一个未被忽略的NoSchedule污点生效,那么Kubernetes不会将新的Pod调度到这个节点上。已经存在的Pod不会受到影响,不会被驱逐或删除。
- PreferNoSchedule:如果节点上至少有一个不可容忍的PreferNoSchedule污点生效,Kubernetes将尽量避免在这个节点上调度新的Pod。但如果找不到其他合适的节点,还是会调度到这个节点上。
- NoExecute:如果节点上至少有一个未被忽略的NoExecute污点生效,那么已经存在的Pod会被驱逐(如果它们没有容忍这个污点),并且新的Pod不会被调度到这个节点上。
1.2 设置污点
使用kubectl taint
命令可以为节点添加污点。语法如下:
kubectl taint nodes <node-name> key=value:effect
例如,为名为node1
的节点添加一个污点,键为special-user
,值为yes
,效果为NoSchedule
:
kubectl taint nodes node1 special-user=yes:NoSchedule
1.3 实战案例
假设有一个名为node-special
的节点,我们想将其保留给特定用户或特定类型的Pod使用。首先,我们为这个节点添加一个污点:
kubectl taint nodes node-special dedicated=userA:NoSchedule
现在,除非Pod明确声明它可以容忍dedicated=userA:NoSchedule
这个污点,否则调度器不会将新的Pod调度到node-special
节点上。
二、容忍度(Tolerations)
容忍度是Pod的一个属性,用于指定Pod可以容忍哪些节点上的污点。只有当节点上存在被Pod容忍的污点时,该节点才会被考虑作为Pod的运行节点。
2.1 容忍度的定义
容忍度也是一个键值对,并附加一个效果(Effect),用于与节点的污点进行匹配。容忍度还支持操作符(Operator),用于指定匹配的方式。常见的操作符有Equal
和Exists
:
- Equal:容忍度与污点必须在key、value和effect三者完全匹配。
- Exists:容忍度与污点必须在key和effect二者完全匹配,容忍度中的value字段要使用空值。
2.2 设置容忍度
在Pod的YAML配置文件中,可以在spec.tolerations
字段下设置容忍度。例如:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
tolerations:
- key: "dedicated"
operator: "Equal"
value: "userA"
effect: "NoSchedule"
containers:
- name: my-container
image: my-app:v1
2.3 实战案例
现在,我们有一个Pod配置,它声明了可以容忍dedicated=userA:NoSchedule
这个污点。这个Pod的YAML配置文件如下:
apiVersion: v1
kind: Pod
metadata:
name: special-pod
spec:
tolerations:
- key: "dedicated"
operator: "Equal"
value: "userA"
effect: "NoSchedule"
containers:
- name: special-container
image: special-app:v1
当我们尝试部署这个Pod时,由于node-special
节点上有dedicated=userA:NoSchedule
这个污点,并且special-pod
Pod配置了相应的容忍度,因此special-pod
Pod会被调度到node-special
节点上。
三、亲和性(Affinity)
亲和性(Affinity)是另一种用于控制Pod调度的机制,它允许Pod根据节点的标签(Labels)或Pod的标签来选择调度目标。亲和性分为节点亲和性(Node Affinity)和Pod亲和性(Pod Affinity/Pod Anti-Affinity)。
3.1 节点亲和性(Node Affinity)
节点亲和性允许Pod根据节点的标签来选择调度目标。它可以是硬亲和性(requiredDuringSchedulingIgnoredDuringExecution)或软亲和性(preferredDuringSchedulingIgnoredDuringExecution)。
- 硬亲和性:调度器必须满足Pod的硬亲和性要求,否则Pod不会被调度。
- 软亲和性:调度器会尽量满足Pod的软亲和性要求,但如果无法满足,Pod仍然可以被调度。
示例YAML配置
apiVersion: v1
kind: Pod
metadata:
name: my-pod-with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: region
operator: In
values:
- us-west-1
containers:
- name: my-container
image: my-app:v1
在这个例子中,Pod要求必须调度到具有disktype=ssd
标签的节点上(硬亲和性),并且如果可能的话,也偏好调度到region=us-west-1
的节点上(软亲和性)。
3.2 Pod亲和性(Pod Affinity)和Pod反亲和性(Pod Anti-Affinity)
Pod亲和性允许Pod根据其他Pod的标签来选择调度目标,而Pod反亲和性则允许Pod避免与具有特定标签的Pod调度到同一个节点上。
Pod亲和性示例
apiVersion: v1
kind: Pod
metadata:
name: my-pod-with-pod-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: kubernetes.io/hostname
containers:
- name: my-container
image: my-app:v1
这个例子中,Pod要求必须调度到与具有security=S1
标签的Pod相同的节点上(基于kubernetes.io/hostname
标签)。
Pod反亲和性示例
apiVersion: v1
kind: Pod
metadata:
name: my-pod-with-pod-anti-affinity
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: kubernetes.io/hostname
containers:
- name: my-container
image: my-app:v1
这个例子中,Pod要求不能调度到与具有security=S1
标签的Pod相同的节点上,这有助于确保应用的高可用性。
四、综合实战案例
假设我们有一个Web应用,它由前端Pod和后端Pod组成。我们希望前端Pod和后端Pod能够尽可能地分散部署到不同的节点上,以提高应用的可用性。同时,我们还有一个特殊的数据库Pod,它应该只运行在具有storage=ssd
标签的节点上。
第一步:标记节点
首先,我们需要为存储SSD的节点添加storage=ssd
标签:
kubectl label nodes node-with-ssd storage=ssd
第二步:配置数据库Pod
apiVersion: v1
kind: Pod
metadata:
name: database-pod
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: storage
operator: In
values:
- ssd
containers:
- name: database-container
image: database-image:v1
第三步:配置前端Pod和后端Pod的反亲和性
# 前端Pod
apiVersion: v1
kind: Pod
metadata:
name: frontend-pod
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- backend
topologyKey: kubernetes.io/hostname
containers:
- name: frontend-container
image: frontend-image:v1
# 后端Pod
apiVersion: v1
kind: Pod
metadata:
name: backend-pod
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- frontend
topologyKey: kubernetes.io/hostname
containers:
- name: backend-container
image: backend-image:v1
labels:
app: backend
在这个例子中,前端Pod和后端Pod都配置了Pod反亲和性(Pod Anti-Affinity),使用preferredDuringSchedulingIgnoredDuringExecution
来指定调度时的偏好,但不是强制性的。weight
字段用于指定偏好的强度,这里都设置为100,表示尽可能分散部署。podAffinityTerm
中的labelSelector
用于选择具有特定标签的Pod(在这里是对方Pod的标签),而topologyKey
则设置为kubernetes.io/hostname
,表示调度器会尝试将Pod调度到与指定标签的Pod不在同一主机上的节点。
注意,虽然这里使用了preferredDuringSchedulingIgnoredDuringExecution
,即调度时的偏好,但它并不是强制性的。如果集群中没有足够的节点来满足这个偏好,Pod仍然会被调度到其他节点上。
另外,注意到后端Pod的YAML配置中添加了labels
字段,这是为了前端Pod能够通过标签选择器找到后端Pod。然而,在这个特定的反亲和性配置中,实际上并不需要后端Pod显式地给自己打上标签,因为前端Pod的反亲和性规则是基于后端Pod可能存在的标签来编写的。但在实践中,给Pod打上适当的标签通常是一个好习惯,因为它们可以用于多种用途,如服务发现、日志收集等。
最后,请注意,在实际部署时,您可能还需要考虑其他因素,如节点的资源限制、网络策略、存储配置等,这些都会影响到Pod的调度和部署。
当然,除了上述的Pod亲和性和反亲和性配置外,还有几个关键方面和最佳实践需要考虑,以确保Kubernetes集群中的Pod能够高效且可靠地运行。
1. 资源限制(Resource Limits)
为Pod设置资源请求(requests)和限制(limits)是非常重要的,这有助于确保Pod在运行时能够获得足够的资源,同时也防止单个Pod占用过多资源而影响其他Pod的性能。
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
containers:
- name: example-container
image: example-image:v1
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
2. 存储配置(Storage Configuration)
对于需要持久存储的Pod,可以使用PersistentVolumes(PV)和PersistentVolumeClaims(PVC)来管理存储资源。
# PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: example-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
# Pod中引用PVC
apiVersion: v1
kind: Pod
metadata:
name: example-pod-with-storage
spec:
containers:
- name: example-container
image: example-image:v1
volumeMounts:
- name: example-volume
mountPath: /data
volumes:
- name: example-volume
persistentVolumeClaim:
claimName: example-pvc
3. 网络策略(Network Policies)
网络策略允许您定义Pod之间的通信规则,从而增强集群的安全性。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: example-network-policy
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 3306
4. 容忍度(Tolerations)
容忍度允许Pod在具有特定污点(taints)的节点上运行。这可以用于确保只有特定的Pod可以运行在某些节点上,例如专用节点或具有特殊硬件的节点。
apiVersion: v1
kind: Pod
metadata:
name: example-pod-with-toleration
spec:
tolerations:
- key: "example-key"
operator: "Equal"
value: "special-value"
effect: "NoSchedule"
containers:
- name: example-container
image: example-image:v1
5. 使用Deployment, StatefulSet或DaemonSet等控制器
直接使用Pod进行部署通常不是最佳实践,因为Pod是单次运行的实例,不具备自动恢复、扩展或更新的能力。相反,您应该使用更高级的控制器,如Deployment、StatefulSet或DaemonSet,这些控制器提供了额外的功能和灵活性。
6. 监控和日志
确保您的Kubernetes集群和Pod都有适当的监控和日志记录解决方案。这有助于您及时发现并解决问题,优化集群性能,并确保应用的稳定运行。
7. 备份和恢复策略
对于关键数据和状态,确保有适当的备份和恢复策略。这可以包括定期备份PersistentVolume的内容,或者配置集群和应用的快照。
8. 更新和回滚策略
当更新应用时,考虑使用Deployment的滚动更新功能,并准备好在出现问题时回滚到旧版本的策略。
9. 安全性
确保您的Kubernetes集群和应用都遵循最佳安全实践,包括使用HTTPS、更新到最新版本、配置RBAC(基于角色的访问控制)等。
通过结合这些最佳实践和配置,您可以构建一个高效、可靠且安全的Kubernetes集群,以支持您的应用和服务。