台州宇洋台州网站建设,广告创意设计方案,瑞丽企业网站建设,上海公布最新情况在Kubernetes平台上#xff0c;我们很少会直接创建一个Pod#xff0c;在大多数情况下会通过控制器完成对一组Pod副本的创建、调度 及全生命周期的自动控制任务#xff0c;如#xff1a;RC、Deployment、DaemonSet、Job 等。本文主要举例常见的Pod调度。1全自动调度功能我们很少会直接创建一个Pod在大多数情况下会通过控制器完成对一组Pod副本的创建、调度 及全生命周期的自动控制任务如RC、Deployment、DaemonSet、Job 等。本文主要举例常见的Pod调度。1全自动调度功能Deployment或RC的主要功能之一就是自动部署一个容器应用的多份副本以及持续监控副本的数量在集群内始终维持用户指定的副本数量。举例使用配置文件可以创建一个ReplicaSet这个ReplicaSet会创建3个Nginx应用的Podapiversion: apps/v1kind: Deploymentmetadata: name: nginx-deploymentspec: selector: matchLabels: app: nginx replicas: 3 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80通过运行 kubectl get rs 和 kubectl get pods 可以查看已创建的ReplicaSet (RS)和Pod的信息从调度策略上来说这3个Nginx Pod由系统全自动完成调度。它们各自最终运行在哪个节点上完全由Master的Scheduler经过一系列算法计算得出用户无法干预调度过程和结果。2定向调度功能将Pod调度到指定的一些Node上通过Node的标签(Label)和Pod的nodeSelector属性相匹配。举例如果要实现定向调度首先的第一步就是要为Node节点搭上标签Label可以使用kubectl label命令kubectl label nodes node-namelabel-keylabel-value这里为k8s-node-1节点打上一个zonenorth标签表明它是“北方”的一个节点然后在Pod的定义中加上nodeSelector的设置以redis-master- controller.yaml为例:apiVersion: v1kind: ReplicationControllermetadata: name: redis-master labels: name: redis-masterspec: replicas: 1 selector: name: redis-master template: metadata: labels: name: redis-master spec: containers: - name: master image: kubeguide/redis-master ports: - containerPort: 6379 nodeSelector: zone: north运行kubectl create -f命令创建Podscheduler就会将该Pod调度到拥有 “zonenorth” 标签的Node上。使用kubectl get pods-o wide命令可以验证Pod所在的Node需要注意的是如果我们指定了Pod的nodeSelector条件且在集群中不存在包含相应标签的Node则即使在集群中还有其他可供使用的Node这个Pod也无法被成功调度。3Node亲和性调度功能目前有两种节点亲和性表达表达式含义RequiredDuringSchedulingIgnoredDuringExecution必须满足指定的规则才可以调度Pod到Node上功能与nodeSelector很像但是使用的是不同的语法)相当于限制PreferredDuringSchedulingIgnoredDuringExecution强调优先满足指定规则调度器会尝试调度Pod到Node上但并不强求相当于软限制举例有如下要求requiredDuringSchedulingIgnoredDuringExecution要求只运行在amd64的节点上(beta.kubernetes.io/arch In amd64)preferredDuringSchedulingIgnoredDuringExecution要求尽量运行在磁盘类型为ssd(disk-type In ssd)的节点上源文件定义如下apiVersion:vlkind:Podmetadata: name:with-node-affinityspec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms - matchExpressions: - key:beta.kubernetes.io/arch operator:In values: - amd64 preferredDuringSchedulingIgnoredDuringExecution: - weight:1 preference: matchExpressions: - key:disk-type operator:In values: - ssd containers: - name:with-node-affinity image:gcr.io/google containers/pause:2.0从上面的配置中可以看到 In操作符NodeAffinity语法支持的操作符包括In、NotIn、Exists、DoesNotExist、Gt、Lt。虽然没有节点排斥功能但是用NotIn 和DoesNotExist就可以实现排斥的功能了。4亲和性与互斥性调度功能亲和性与互斥性可以理解为就是相关联的两种或多种Pod是否可以在同一个拓扑域中共存或者互斥。举例首先创建一个名为pod-flag的Pod带有标签securityS1和appnginx后面的例子将使用pod-flag作为Pod亲和与互斥的目标Podapiversion:v1kind:Podmetadata: name:pod-flag labels: security:S1 app:nginxspec: containers: -name:nginx image:nginx下面创建第2个Pod来说明Pod的亲和性调度这里定义的亲和标签是 “securityS1”对应上面的Pod “pod-flag”topologyKey的值被设置为 “kubernetes.io/hostname“apiVersion:vlkind:Podmetadata: name:pod-affinityspec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key:security operator:In values: -S1 topologyKey:kubernetes.io/hostname containers: - name:with-pod-affinity image:gcr.io/google_containers/pause:2.0创建Pod之后使用kubectl get pods -o wide命令可以看到这两个Pod在同一个Node上运行。创建第3个Pod我们希望它不与目标Pod运行在同一个Node上apiversion:v1kind:Podmetadata: name:anti-affinityspec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key:security operator:In values: -S1 topologyKey:topology.kubernetes.io/zone podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key:app operator:In values: -nginx topologyKey:kubernetes.io/hostname containers: - name:anti-affinity image:gcr.io/google_containers/pause:2.0这里要求这个新Pod与securityS1的Pod为同一个zone但是不与appnginx 的Pod为同一个Node。创建Pod之后同样用kubectl get pods -o wide来查看会看到新的Pod被调度到了同一Zone内的不同Node上。5污点与容忍功能Taint污点 它让Node拒绝Pod的运行。简单地说被标记为Taint的节点就是存在问题的节点比 如磁盘要满、资源不足、存在安全隐患要进行升级维护希望新的Pod不会被调度过来。但被标记为Taint的节点并非故障节点仍是有效的工作节点所以仍需将某些Pod调度到这些节点上时可以通过使用Toleration属性来实现。举例Taint和Toleration是一种处理节点并且让Pod进行规避或者驱逐Pod的弹性处理方式下面列举一些常见的用例。举例一独占节点如果想要拿出一部分节点专门给一些特定应用使用则可以为节点添加这样Taintkubectl taint nodes nodename dedicatedgroupName:NoSchedule然后给这些应用的Pod加入对应的Toleration这样带有合适Toleration的Pod就会被允许同使用其他节点一样使用有Taint的节点。举例二具有特殊硬件设备的节点在集群里可能有一小部分节点安装了特殊的硬件设备如GPU芯片)用户自然会希望把不需要占用这类硬件的Pod排除在外以确保对这类硬件有需求的Pod能够被顺利调度到这些节点上。可以用下面的命令为节点设置Taintkubectl taint nodes nodename specialtrue:NoSchedule kubectl taint nodes nodename specialtrue:PreferNoSchedule6优先级调度功能提高资源利用率的常规做法是采用优先级方案即不同类型的负载对应不同的优先级同时允许集群中的所有负载所需的资源总量超过集群可提供的资源在这种情况下当发生资源不足的情况时系统可以选择释放一些不重要的负载优先级最低的)保障最重要的负载能够获取足够的资源稳定运行。举例首先由集群管理员创建PriorityClassPriorityClass不属于任何命名空间apiversion:scheduling.k8s.io/vlbetal kind:Priorityclassmetadata:name:high-priorityva1ue:1000000globalDefault:falsedescription:This priority class should be used for XYZ service pods only.上述YAML文件定义了一个名为high-priority的优先级类别优先级为 100000数字越大优先级越高超过一亿的数字被系统保留用于指派给系统组件。可以在任意Pod上引用上述Pod优先级类别apiVersion: v1kind: Podmetadata:name: nginx labels:env: testspec:containers:-name: nginximage: nginximagePullPolicy: IfNotPresent priorityclassName: high-priority如果发生了需要抢占的调度高优先级Pod就可能抢占节点N并将其低优先级Pod驱逐出节点N高优先级Pod的status信息中的nominatedNodeName字段会记录目标节点的名称。需要注意高优先级Pod仍然无法保证最终被调度到节点N上在节点N上低优先级Pod被驱逐的过程中如果有新的节点满足高优先级Pod的需求就会把它调度到新的Node上。而如果在等待低优先级的Pod退出的过程中又出现了优先级更高的Pod调度器就会调度这个更高优先级的Pod到节点N上并重新调度之前等待的高优先级Pod。7DaemonSet每个Node上只调度一个pod功能DaemonSet是 Kubernetes1.2 版本新增的一种资源对象用于管理在集群中的每个Node上仅运行一份Pod的副本实例。举例下面的例子定义了为在每个Node上都启动一个fluentd容器配置文件 fluentd-ds.yaml的内容如下 其中挂载了物理机的两个目录/var/log和 “/var/lib/docker/containers”:apiVersion: apps/v1kind: DaemonSetmetadata:name: fluentd-cloud-logging namespace: kube-system labels:k8s-app: fluentd-cloud-loggingspec:template:metadata:namespace: kube-system labels:k8s-app: fluentd-cloud-loggingspec:containers:-name: fluentd-cloud-loggingimage: gcr.io/google containers/fluentd-elasticsearch:1.17 resources:limits:cpu: 100mmemory: 200Mienv:-name: FLUENTD ARGS value: -qvolumeMounts-name: varlogmountPath: /var/logreadOnly: false-name: containersmountPath: /var/lib/docker/containers readonly: falsevolumes:-name: containershostPath:path: /var/lib/docker/containers -name: varloghostPath:path: /var/log查看创建好的DaemonSet和Pod可以看到在每个Node上都创建了一个Pod8批处理调度功能批处理任务通常并行或者串行 启动多个计算进程去处理一批工作项(Work item)处理完成后整个批处理任务结束。Kubernetes从1.2版本开始支持批处理类型的应用我们可以通过Kubernetes Job资源对象来定义并启动一个批处理任务。举例Job Template Expansion案例首先是Job Template Expansion模式由于在这种模式下每个Work item都对应一个Job实例所以这种模式首先定义一个Job模板模板里的主要参数是Work item的标识因为每个Job都处理不同的Work item。如下所示的Job模板文件名为job.yaml.txt)中的 $ITEM 可以作为任务项的标识apiVersion: batch/v1kind: Jobmetadata:name: process-item-$ITEM labels:jobgroup: jobexamplespec:template:metadata:name: jobexamplelabels:jobgroup: jobexamplespec:containers:-name: cimage: busyboxcommand: [sh,-c,echo Processing item $ITEM sleep 5] restartPolicy: Never通过下面的操作生成了3个对应的Job定义文件并创建Jobfor i in apple banana cherry do cat job.yaml.txt | sed s/\$ITEM/$i/ ./jobs/job-$i.yaml done# ls jobsjob-apple.yaml job-banana.yaml job-cherry.yaml # kubectl create -f jobsjob process-item-applecreated job process-item-bananacreated job process-item-cherrycreated观察Job的运行情况$ kubect1 get jobs -l jobgroupjobexampleNAME DESIRED SUCCESSFUL AGEprocess-item-apple 1 1 4mprocess-item-banana 1 1 4mprocess-item-cherry 1 1 4m举例Queue with Pod Per Work Item案例在这种模式下需要一个任务队列存放Work item比如RabbitMQ客户端程序先把要处理的任务变成Work item放入任务队列然后编写Worker程序、打包镜像并定义成为Job中的Work Pod。Worker程序的实现逻辑是从任务队列中拉取一个Work item并处理 在处理完成后结束进程。并行度为2的Demo如下图所示举例Queue with Variable Pod Count案例由于这种模式下Worker程序需要知道队列中是否还有等待处理的Work item如果有就取出来处理否则就认为所有工作完成并结束进程所以任务队列通常要采用Redis或者数据库来实现9定时任务功能Kubernetes从1.5版本开始增加了一种新类型的Job即类似Linux Cron的定时任务Cron Job。举例比如我们要每隔1min执行一次任务则Cron表达式如下 */1 * * * *编写一个Cron Job的配置文件cron.yamlapiversion: batch/vl beta kind: CronJobmetadata:name: hellospec:schedule: */1 * * * *jobTemplate:spec:template:spec:containers:-name:helloimage:busyboxargs:-/bin/sh--C-date;echo Hello from the Kubernetes cluster restartPolicy:OnFailure该例子定义了一个名为hello的Cron Job任务每隔1min执行一次运行的镜像是busybox运行的命令是Shell脚本脚本运行时会在控制台输出当前时间和字符串Hello from the Kubernetes cluster.然后每隔1min运行kubectl get cronjob hello查看任务状态发现的确每分钟调度了一次运行下面的命令可以更直观地了解Cron Job定期触发任务执行的历史和现状10容灾调度功能我们可以将Pod的各种常规调度策略认为是将整个集群视为一个整体然后进行 “打散或聚合” 的调度。当我们的集群是为了容灾而建设的跨区域的多中心多个Zone)集群即集群中的节点位于不同区域的机房时比如北京、上海、广 州、武汉要求每个中心的应用相互容灾备份又能同时提供服务此时最好的调度策略就是将需要容灾的应用均匀调度到各个中心当某个中心出现问题时 又自动调度到其他中心均匀分布举例假如我们的集群被划分为多个Zone我们有一个应用对应的Pod标签为 appfoo)需要在每个Zone均匀调度以实现容灾则可以定义YAML文件如下spec: topologySpreadConstraints: -maxSkew: 1whenUnsatisfiable: DoNotScheduletopologyKey: topology.kubernetes.io/zoneselector:matchLabels: app: foo在以上YAML定义中关键的参数是maxSkew用于指定Pod在各个Zone上调度时能容忍的最大不均衡数值越大表示能接受的不均衡调度越大值越小表示各个Zone的Pod数量分布越均匀。