脚本宝典收集整理的这篇文章主要介绍了Kubernetes-Pod介绍(三)-Pod调度,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
本篇是Kubernetes第六篇,大家一定要把环境搭建起来,看是解决不了问题的,必须实战。
在Kubernetes中我们很少直接创建一个Pod,大多数情况下会通过Replication Controller、deployment、Daemonset、Job等控制器完成一组Pod的创建、调度以及生命周期的管理。这是因为单个Pod不能满足我们提出的高可用、高并发的概念,除此之外在真实的生产环境下还有些行行色色的需求:
Deployment和Replication Controller主要功能就是自动部署一个容器应用的多份副本以及控制副本的数量,在集群内部始终控制指定的副本的数量。
#删除podkubectl delete -f nginx-deployment.yaml
#编辑nginx-deployment.yamlapiVersion: apps/v1kind: Deployment#创建名为nginx-deployment的Deployment资源对象metadata: name: nginx-deploymentspec: selector: #通过标签查找pod matchLabels: app: nginx #副本个数 replicas: 3 template: #pod打标签 metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest resources: limITs: memory: "128Mi" cpu: "128m" ports: - containerPort: 80
kubectl apply -f nginx-deployment.yaml
#获取deployment对象信息kubectl get deployment#获取pod信息kubectl get pod#获取rs信息kubectl get rs
注意:在定义Deployment资源的时候,matchLables和template.labels时必须成对出现的,名字也必须相同;
在Kubernetes中Pod的调度由kube-scheduler完成,最终实现Pod调度到最佳的节点上,这个过程都是自动完成的,我们是无法预计Pod最终被分配到那个节点上的,在实际的情况我们可能需要将Pod调度到指定的节点上,这个时候我们可以通过Node的Lable与Pod的NodeSelector的属性匹配完成节点的定向调度。
#删除podkubectl delete -f nginx-deployment.yaml#查看node节点kubectl get nodes
#查看节点详情kubectl get nodes#给节点打标签kubectl label nodes demo-work-1 zone=hangzhou#查看节点标签kubectl get node --show-labels
apiVersion: apps/v1kind: Deploymentmetadata: name: nginx-deploymentspec: selector: matchLabels: app: nginx replicas: 3 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest resources: limits: memory: "128Mi" cpu: "128m" ports: - containerPort: 80 #node选择器 nodeSelector: zone: hangzhou
kubectl apply -f nginx-deployment.yaml
#查看pod更多的节点信息kubectl get pods -o wide
注意:如果我们指定Pod的NodeSelector条件的时候,如果集群上不存在包含相同标签Node,Pod是无法调度成功的,也包含正在运行的Pod。
NodeSelector通过标签的方式,完成将节点的定向调度,这种亲和性的调度机制极大提升的Pod调度能力,帮助Kubernetes更好的去完成我们需求,但是NodeSelector调度方式还是过于简单,因此Kubernetes还提供NodeAffinity和PodAffinity两种维度亲和调度功能。
NodeAffinity翻译过来是Node亲和性调度,目的是为了替换NodeSelector,NodeAffinity目前有两种亲和性的表达方式:
IgnoredDuringExecution的意思是,Pod所在节点在运行期间发生变更,不在符合Pod节点的亲和性规则,系统不会影响已经在节点上运行的Pod。
#删除podkubectl delete -f nginx-deployment.yaml#打上海标签kubectl label nodes demo-work-2 zone=shanghai#看看Node标签kubectl get node --show-labels
apiVersion: apps/v1kind: Deploymentmetadata: name: nginx-deploymentspec: selector: matchLabels: app: nginx replicas: 10 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest resources: limits: memory: "128Mi" cpu: "128m" ports: - containerPort: 80 affinity: nodeAffinity: #优先匹配hangzhou的节点 其次匹配shanghai preferredDuringSchedulingIgnoredDuringExecution: - weight: 80 preference: matchExPressions: - key: zone operator: In values: - hangzhou - weight: 20 preference: matchExpressions: - key: zone operator: In values: - shanghai
kubectl apply -f nginx-deployment.yaml
#查看pod更多的节点信息kubectl get pods -o wide
在配置中我们看到可以使用操作符,操作符类型有以下几种:
In:表示所有信息都要在value的列表里面;
NotIn: 标签的值不在某个列表里面;
Exists: 存在某个标签;
DoesNotExist: 某个标签不存在;
Gt: 标签的值大于某个值;
Lt: 标签的值小于某个值;
注意点:
如果同时设置nodeSelector和nodeAffinity则必须同时满足两个条件,Pod才会运行到最终的节点上:
如果同时指定多个nodeSelectorTerms,只要满足其中一个就可以匹配成功;
如果nodeSelectorTerms有多个matchExpressions,则必须满足所有matchExpressions才可以运行Pod;
在生产环境中存在一类Pod,他们Pod之间相互依赖,要求尽可能被部署到相同的Node节点上,比如将应用的前端和后端部署在一起,减少访问延迟,或者为了避免Pod之间相互竞争,要求某些Pod相互远离,这就是Pod之间的亲和性或者互斥性。Pod亲和同样有requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution两种规则。
#删除podkubectl delete -f nginx-deployment.yaml
apiVersion: apps/v1kind: Deploymentmetadata: name: nginx-deploymentspec: selector: matchLabels: app: backend replicas: 3 template: metadata: labels: app: backend spec: containers: - name: nginx image: nginx:latest resources: limits: memory: "128Mi" cpu: "128m" ports: - containerPort: 80 affinity: nodeAffinity: #优先匹配hangzhou的节点 其次匹配shanghai preferredDuringSchedulingIgnoredDuringExecution: - weight: 80 preference: matchExpressions: - key: zone operator: In values: - hangzhou - weight: 20 preference: matchExpressions: - key: zone operator: In values: - shanghai
apiVersion: apps/v1kind: Deploymentmetadata: name: podaffinitydemospec: selector: matchLabels: app: frontend replicas: 3 template: metadata: labels: app: frontend spec: containers: - name: nginx image: nginx:latest resources: limits: memory: "128Mi" cpu: "128m" ports: - containerPort: 80 affinity: #亲和 podAffinity: requiredDuringSchedulingIgnoredDuringExecution: #选择标签键为zone - topoLOGyKey: zone labelSelector: #必须匹配到zone=hangzhou app=backend matchExpressions: - key: app operator: In values: - backend
kubectl apply -f nginx-deployment.yamlkubectl apply -f podAffinity-deployment.yaml
#查看pod更多的节点信息kubectl get pods -o wide
PodAntiAffinity就是反亲和性,可以和PodAffinity一起出现在配置文件中,与节点亲和类似,在Pod亲和中也可以使用操作符,相比于节点亲和多了一个必须的值topologyKey,对于topologyKey使用有以下注意:
对于requiredDuringSchedulingIgnoredDuringExecution的Pod的反亲和性和Pod的亲和性必须出现topologyKey;
对于requiredDuringSchedulingIgnoredDuringExecution的Pod反亲和性,引入LimitPodHardAntiAffinityTopology准入控制器来限制 topologyKey 只能是 kubernetes.io/hostname。如果要使用自定义拓扑域,则可以修改准入控制器,或者直接禁用它;
对于 preferredDuringSchedulingIgnoredDuringExecution 的 Pod 反亲和性,空的 topologyKey 表示所有拓扑域。所有拓扑域还只能是 kubernetes.io/hostname、failure-domain.beta.kubernetes.io/zone 和 failure-domain.beta.kubernetes.io/region 的组合;
除上述情况外,topologyKey 可以是任何合法的标签 key;
除了 labelSelector 和 topologyKey,也可以指定命名空间,labelSelector 也可以匹配它。 如果忽略或者为空,则默认为 Pod 亲和性/反亲和性的定义所在的命名空间。
亲和性可以帮助Pod调度到指定的节点,但是在复杂的生产环境中,当你某个节点出现问题的时候,我们不希望再有Pod被调度到该节点,这里的问题并不是节点挂掉了,而是磁盘爆满、CPU、内存不足等等情况,这时候我们可以将节点标记Taint,Pod就不会调度到该节点上。还有一种特殊情况有时候我们仍然需要将Pod调度到被标记Taint的节点上,这个时候我们为Pod设置Toleration属性来满足Taint节点。
#给demo-work-1标记污点 键名是 notRam,键值是 true,效果是NoSchedulekubectl taint nodes demo-work-1 notRam=true:NoSchedule#给demo-work-2标记污点 键名是 haha,键值是 true,效果是NoSchedulekubectl taint nodes demo-work-2 haha=true:NoSchedule#移除污点kubectl taint nodes demo-work-1 notRam=true:NoSchedule-
apiVersion: v1kind: Podmetadata: name: nginx labels: env: testspec: containers: - name: nginx image: nginx:latest imagePullpolicy: IfNotPresent #设置Toleration tolerations: - key: "notRam" operator: "Equal" value: "true" effect: "NoSchedule"
kubectl apply -f toleration-pod.yaml
#查看pod更多的节点信息kubectl get pods -o wide
对于operator取值有两种:
系统允许同一个Node设置多个Taint标签,也允许Pod设置设置多个Toleration属性。Kubernetes 处理多个Taint和Toleration的过程就像一个过滤器:首先列出所有Taint,忽略掉 Pod 中匹配的Taint。剩下的Taint有以下三种情况:
如果剩余的Taint中存在effect=NoSchedule, 则调度器不会将 Pod 分配到该节点;
如果剩余的Taint中不存在NoSchedule,但是存在PreferNoSchedule的污点, 则调度器会尝试不将 Pod 分配到该节点;
如果剩余的Taint中存在NoExecute,如果有Pod运行在该节点上,则会被驱逐;如果没有在该节点运行,则也不会调度到该节点;
对于是设置NoExecute的Taint,会对正在运行的Pod有驱逐策略:
没有设置Toleration的Pod会马上被驱逐;
配置Toleration的Pod,如果没有设置tolerationSeconds,则一种运行在节点上;
配置Toleration的Pod并且设置tolerationSeconds,则会在指定的时间后被驱逐,注意节点故障的情况下,系统会按照限速的模式逐步给Node添加Taint,避免特定情况下大量的Pod被驱逐;
Kubernetes默然情况下会给Pod添加以下两种Toleration:
自动添加的容忍度意味着在其中一种问题被检测到时 Pod 默认能够继续停留在当前节点运行 5 分钟,而不是立即被驱逐,避免系统产生波动。
Kubernetes从1.6版本开始引入两个Taint相关的新特性TaintNodesByCondition以及TaintBasedEvictions,用来改进Pod调度和驱逐问题,改造以后流程如下:
不断检查所有Node状态,设置对应的Condition;
不断的根据Node Condition设置对应的Taint;
不断的更加Taint驱逐Node上的Pod;
其中,检查Node的状态并且设置Node的Taint就是TaintNodesByCondition的特性,在满足以下情况的时候会自动给Node添加Taint:
node.kubernetes.io/unreachable: 节点不可触达,对应NodeCondition Ready为Unknown情况;
node.kubernetes.io/not-ready: 节点未就绪,对应NodeCondition Ready为False情况;
node.kubernetes.io/disk-pressure: 节点磁盘已满;
node.kubernetes.io/network-unavailable:节点网络不可用;
node.kubernetes.io/unschedulable(1.10 或更高版本): 节点不可调度;
Kubernetes从1.13以上两个特性会默认开启,TaintNodesByCondition只会为节点设置NoSchedule的添加Taint;TaintBasedEvictions只会为节点添加NoExecute添加Taint,该特性被开启之后,调度器会在有资源压力的时候给对应的Node添加NoExecute的Taint,如果没有设置对应的Toleration,则Pod会立即被驱逐,用此来保证Node不会崩溃。
当集群资源不足的时候,当我们需要创建Pod的时候,这个时候Pod会一致处于Pending状态,即使该Pod是一个特别重要的Pod,我们也需要等待调度器释放掉其他资源,才可以调用成功。针对这种情况,Kubernetes在1.8引入优先级调度的Pod,当资源不足的时候有优先级比较高的Pod需要调度的时候,会尝试释放一些优先级比较低的资源,来满足优先级高的资源的调度,在1.14的版本中正式Release。
apiVersion: scheduling.k8s.io/v1kind: PriorityClassmetadata: name: high-priorityvalue: 1000000globalDefault: falsedescription: "用于优先级调用"
apiVersion: v1kind: Podmetadata: name: nginx labels: env: testspec: containers: - name: nginx image: nginx:latest imagePullPolicy: IfNotPresent priorityclassname: high-priority
#创建优先级调度资源kubectl apply -f prioritydemo.yaml#创建podkubectl apply -f priority-pod.yaml
PriorityClass 是一个无名称空间对象,它定义了从优先级类名称到优先级整数值的映射,值越大,优先级越高。 PriorityClass 对象的名称必须是有效的 DNS 子域名, 并且它不能以 System- 为前缀。
关于使用PriorityClass注意:
如果你升级一个已经存在的但尚未使用优先级调度的集群,该集群中已经存在的 Pod 的优先级等效于0;
添加一个将 globalDefault 设置为 true 的 PriorityClass 不会改变现有 Pod 的优先级。 此类 PriorityClass 的值仅用于添加 PriorityClass 后创建的 Pod;
如果你删除了某个 PriorityClass 对象,则使用被删除的 PriorityClass 名称的现有 Pod 保持不变, 但是不能再创建使用已删除的 PriorityClass 名称的 Pod;
注意点,使用优先级抢占式的调度策略会导致某些Pod永远无法被调度。优先级调度不仅增加系统复杂性,还会带来很多不稳定的因素,建议在资源紧张的时候优先采用扩容手段。
DeamonSet确保节点上运行一个 Pod 的副本。 当有节点加入集群时, 也会为他们新增一个 Pod 。 当有节点从集群移除时,Pod也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。DeamonSet调度策略与RC类似,除了内置算法保证在Node上进行调度,也可以在Pod定义NodeSelector和NodeAffinity来满足指定条件的节点进行调度。
kubectl delete -f priority-pod.yaml
apiVersion: apps/v1kind: DaemonSetmetadata: name: fluentd-elasticseArchspec: selector: matchLabels: name: fluentd-elasticsearch template: metadata: labels: name: fluentd-elasticsearch spec: containers: - name: fluentd-elasticsearch image: fluentd:latest resources: limits: memory: 200Mi requests: cpu: 100m memory: 200Mi volumemounts: - name: varlog mountPath: /var/log - name: varlibdockercontainers mountPath: /var/lib/docker/containers readOnly: true terminationGracePeriodSeconds: 30 volumes: - name: varlog hostPath: path: /var/log - name: varlibdockercontainers hostPath: path: /var/lib/docker/containers
kubectl apply -f fluentd-deamonset.yaml
#查看pod更多的节点信息kubectl get pods -o wide
每个节点上运行集群守护进程;
每个节点上运行日志收集守护进程;
每个节点上运行监控守护进程;
经常会遇到这样的场景,有一批大量的数据需要计算,这个时候就需要我们批任务去处理,Kubernetes可以通过Job来定义启动批处理任务,批处理任务通常并行多个计算节点进行处理一个工作项,处理完成以后,整个批处理任务结束,按照实现方式不同可分为以下几种情况:
apiVersion: batch/v1kind: Jobmetadata: name: jobdemo labels: jobgroup: jobexamplespec: template: metadata: name: jobexample labels: jobgroup: jobexample spec: containers: - name: c image: busybox command: ["sh", "-c", "echo job demo && sleep 5"] restartPolicy: Never
kubectl apply -f busybox-job.yaml
kubectl get jobs -l jobgroup=jobexample
kubectl logs -f -l jobgroup=jobexample
在我们的日常需求中还有一种周期性任务,Kubernetes可以通过CronJobs 来创建周期性的任务,例如定期执行数据库备份,此外还可以使用CronJobs用来在指定时间来执行的独立任务,例如在集群状态空闲的时候执行某个Job。
apiVersion: batch/v1kind: CronJobmetadata: name: hellospec: schedule: "*/1 * * * *" joBTemplate: spec: template: spec: containers: - name: hello image: busybox imagePullPolicy: IfNotPresent command: - /bin/sh - -c - date; echo Hello Word restartPolicy: OnFailure
kubectl apply -f hello-cronjob.yaml
kubectl get cronJob hello
欢迎大家点点关注,点点赞!
以上是脚本宝典为你收集整理的Kubernetes-Pod介绍(三)-Pod调度全部内容,希望文章能够帮你解决Kubernetes-Pod介绍(三)-Pod调度所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。