kubernetes中pod资源的调度-创新互联

kubernetes简介

成都创新互联专业IDC数据服务器托管提供商,专业提供成都服务器托管,服务器租用,四川移动机房托管四川移动机房托管,成都多线服务器托管等服务器托管服务。

kubernetes,简称K8s,是用8代替8个字符“ubernete”而成的缩写。是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。

Pod简介

Pod是Kubernetes创建或部署的最小/最简单的基本单位,一个Pod代表集群上正在运行的一个进程。

一个Pod封装一个应用容器(也可以有多个容器),存储资源、一个独立的网络IP以及管理控制容器运行方式的策略选项。Pod代表部署的一个单位:Kubernetes中单个应用的实例,它可能由单个容器或多个容器共享组成的资源。

通常情况下,使用的都是k8s默认的调度调度方式,但是在有些情况下,我们需要将pod运行在具有特点的标签的node上才能都运行,这个时候,pod的调度策略就不能使用k8s默认的调度策略了,这个时候,就需要指定调度策略,告诉k8s需要将pod调度到那些node(节点)上。

nodeSelector
常规情况下,会直接使用nodeSelector这种调度策略。labels(标签) 是k8s里面用来编标记资源的一种常用的方式,我们可以给node标记特殊的标签,然后nodeSelector会将pod调度到带有指定labels的node上的。

下面看个示例:

首先,查看node的label信息,通过下面的命令查看的 node 的 label:

$ kubectl get nodes --show-labels
NAME    STATUS   ROLES   AGE    VERSION  LABELS
master   Ready   master   147d    v1.10.0  beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=master,node-role.kubernetes.io/master=
node02   Ready      67d    v1.10.0  beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,course=k8s,kubernetes.io/hostname=node02
node03   Ready      127d    v1.10.0  beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,jnlp=haimaxy,kubernetes.io/hostname=node03

然后,可以给node02节点新增一个label:

$ kubectl label nodes node02 com=yijiadashuju
node "node02" labeled

然后通过上面的--show-labels参数可以查看上述标签是否生效。当 node 被打上了相关标签后,在调度的时候就可以使用这些标签了,只需要在 Pod 的spec字段中添加nodeSelector字段,里面是我们需要被调度的节点的 label 即可。比如,要将 Pod 我们要强制调度到 node02 这个节点上去,可以使用 nodeSelector 来表示了:(pod-selector-demo.yaml)

apiVersion: v1
kind: Pod
metadata:
  labels:
   app: busybox-pod
  name: test-busybox
spec:
  containers:
  - command:
   - sleep
   - "3600"
   image: busybox
   imagePullPolicy: Always
   name: test-busybox
  nodeSelector:
   com: yijiadashuju

然后,执行pod-selector-demo.yaml文件后,可以通过下面的命令查看pod运行的节点信息

kubectl get pod -o wide -n default

也可以使用description命令查看pod被调度到哪个节点上:

$ kubectl create -f pod-selector-demo.yaml
pod "test-busybox" created
$ kubectl describe pod test-busybox
Name:     test-busybox
Namespace:   default
Node:     node02/10.151.30.63
......
QoS Class:    BestEffort
Node-Selectors:  com=youdianzhishi
Tolerations:   node.kubernetes.io/not-ready:NoExecute for 300s
         node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type   Reason         Age  From        Message
  ----   ------         ----  ----        -------
  Normal  SuccessfulMountVolume  55s  kubelet, node02   MountVolume.SetUp succeeded for volume "default-token-n9w2d"
  Normal  Scheduled        54s  default-scheduler  Successfully assigned test-busybox to node02
  Normal  Pulling         54s  kubelet, node02   pulling image "busybox"
  Normal  Pulled         40s  kubelet, node02   Successfully pulled image "busybox"
  Normal  Created         40s  kubelet, node02   Created container
  Normal  Started         40s  kubelet, node02   Started container

从上面的执行结果可以看出,pod 通过默认的 default-scheduler 调度器到了node02节点上。不过,这种调度方式属于强制性的。如果node02上的资源不足,那么pod的状态将会一直是pending状态。这就是nodeselector的用法了。

通过上面的介绍,可以看出nodeselector使用起来非常方便,但是还有很多的不足,那就是不够灵活,控制粒度偏大,在实际使用中还是有许多的不便。接下来一起看先亲和性和反亲和性调度。

亲和性和反亲和性调度

k8s的默认调度流程实际上是经过了两个阶段:predicates 和 priorities 。使用默认的调度流程的话,k8s会将pod调度到资源充裕的节点上,使用nodeselector的调度方法,又会将pod调度具有指定标签的pod上。然后在实际生产环ongoing境中,我们需要将pod调度到具有默些label的一组node才能满足实际需求,这个时候就需要nodeAffinity(节点亲和性)、podAffinity(pod 亲和性) 以及 podAntiAffinity(pod 反亲和性)。

亲和性可以分为具体可以细分为硬和软两种亲和性,

软亲和性:如果调度的时候,没有满足要求,也可以继续调度,即能满足最好,不能也无所谓
硬亲和性:是指调度的时候必须满足特定的要求,如果不满足,那么pod将不会被调度到当前node

规则可以设置:
软策略: preferredDuringSchedulingIgnoredDuringExecution

硬策略: requiredDuringSchedulingIgnoredDuringExecution

nodeAffinity 节点亲和性
节点亲和性主要是用来控制 pod 能部署在哪些节点上,以及不能部署在哪些节点上的。它可以进行一些简单的逻辑组合了,不只是简单的相等匹配。

接下来看一个示例,使用 Deployment 来管理3个 pod 副本,使用nodeAffinity控制 pod 的调度,如下例子:(node-affinity-demo.yaml)

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: affinity
  labels:
   app: affinity
spec:
  replicas: 3
  revisionHistoryLimit: 15
  template:
   metadata:
    labels:
     app: affinity
     role: test
   spec:
    containers:
    - name: nginx
     image: nginx:1.7.9
     ports:
     - containerPort: 80
      name: nginxweb
    affinity:
     nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:  # 硬策略
       nodeSelectorTerms:
       - matchExpressions:
        - key: kubernetes.io/hostname
         operator: NotIn
         values:
         - node03
      preferredDuringSchedulingIgnoredDuringExecution:  # 软策略
      - weight: 1
       preference:
        matchExpressions:
        - key: com
         operator: In
         values:
         - yijiadashuju

这个pod调度的时候,首先要求不能运行在node03节点上,但是如果有节点满足labels为com:yijiadashuju 的话,就会优先调度到这个节点上。

接下来看下节点信息:

$ kubectl get nodes --show-labels
NAME    STATUS   ROLES   AGE    VERSION  LABELS
master   Ready   master   154d    v1.10.0  beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=master,node-role.kubernetes.io/master=
node02   Ready      74d    v1.10.0  beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,com=yijiadashuju,course=k8s,kubernetes.io/hostname=node02
node03   Ready      134d    v1.10.0  beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,jnlp=haimaxy,kubernetes.io/hostname=node03

可以看到 node02 节点有com=yijiadashuju的 label,按要求会优先调度到这个节点,接下来创建 pod,然后使用descirbe命令查看调度情况。

$ kubectl create -f node-affinity-demo.yaml
deployment.apps "affinity" created
$ kubectl get pods -l app=affinity -o wide
NAME             READY   STATUS   RESTARTS  AGE    IP       NODE
affinity-7b4c946854-5gfln  1/1    Running  0      47s    10.244.4.214  node02
affinity-7b4c946854-l8b47  1/1    Running  0      47s    10.244.4.215  node02
affinity-7b4c946854-r86p5  1/1    Running  0      47s    10.244.4.213  node02

从结果可以看到 pod 均被部署到了 node02节点。

现在Kubernetes提供的操作符有下面的几种

In:label 的值在某个标签中
NotIn:label 的值不在某个标签中
Gt:label 的值大于某个值
Lt:label 的值小于某个值
Exists:某个 label 存在
DoesNotExist:某个 label 不存在

如果nodeSelectorTerms下面有多个选项的话,满足任何一个条件就可以了;如果matchExpressions有多个选项的话,则必须同时满足这些条件才能正常调度 POD。

podAffinity pod亲和性

pod的亲和性主要用来解决pod可以和哪些pod部署在同一个集群里面,即拓扑域(由node组成的集群)里面;而pod的反亲和性是为了解决pod不能和哪些pod部署在一起的问题,二者都是为了解决pod之间部署问题。需要注意的是,Pod 间亲和与反亲和需要大量的处理,这可能会显著减慢大规模集群中的调度,不建议在具有几百个节点的集群中使用,而且Pod 反亲和需要对节点进行一致的标记,即集群中的每个节点必须具有适当的标签能够匹配 topologyKey。如果某些或所有节点缺少指定的 topologyKey 标签,可能会导致意外行为。

下面是pod间亲和的示例:

pods/pod-with-pod-affinity.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
   podAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector:
      matchExpressions:
      - key: security
       operator: In
       values:
       - S1
     topologyKey: failure-domain.beta.kubernetes.io/zone
   podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
    - weight: 100
     podAffinityTerm:
      labelSelector:
       matchExpressions:
       - key: security
        operator: In
        values:
        - S2
      topologyKey: failure-domain.beta.kubernetes.io/zone
  containers:
  - name: with-pod-affinity
   image: k8s.gcr.io/pause:2.0

podAntiAffinity pod反亲和性

下面是一个pod反亲和yaml文件示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-cache
spec:
  selector:
   matchLabels:
    app: store
  replicas: 3
  template:
   metadata:
    labels:
     app: store
   spec:
    affinity:
     podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
        matchExpressions:
        - key: app
         operator: In
         values:
         - store
       topologyKey: "kubernetes.io/hostname"
    containers:
    - name: redis-server
     image: redis:3.2-alpine

另外有需要云服务器可以了解下创新互联cdcxhl.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


文章标题:kubernetes中pod资源的调度-创新互联
分享网址:http://scyanting.com/article/dpegse.html