K8S之Pod学习Ⅱ

命名空间

什么是命名空间?

Kubernetes 支持多个虚拟集群,它们底层依赖于同一个物理集群。 这些虚拟集群被称为命名空间。
命名空间namespace是k8s集群级别的资源,可以给不同的用户、租户、环境或项目创建对应的命名空间,例如,可以为test、devlopment、production环境分别创建各自的命名空间。

namespace应用场景

命名空间适用于存在很多跨多个团队或项目的用户的场景。对于只有几到几十个用户的集群,根本不需要创建或考虑命名空间。

1、查看名称空间及其资源对象
k8s集群默认提供了几个名称空间用于特定目的,例如,kube-system主要用于运行系统级资源,存放k8s一些组件的。而default则为那些未指定名称空间的资源操作提供一个默认值。

使用kubectl get namespace可以查看namespace资源,使用kubectl describe namespace $NAME可以查看特定的名称空间的详细信息。

2、管理namespace资源
namespace资源属性较少,通常只需要指定名称即可创建,如“kubectl create namespace qa”。namespace资源的名称仅能由字母、数字、下划线、连接线等字符组成。删除namespace资源会级联删除其包含的所有其他资源对象。

namespacs使用案例分享

#创建一个test命名空间

[root@kaivimaster1~]# kubectl create ns test

#切换命名空间

[root@kaivimaster1~]# kubectl  config set-context --current --namespace=kube-system

#切换命名空间后,kubectl get pods 如果不指定-n,查看的就是kube-system命名空间的资源了。

#查看哪些资源属于命名空间级别的

[root@kaivimaster1~]# kubectl api-resources --namespaced=true

namespace资源限额

namespace是命名空间,里面有很多资源,那么我们可以对命名空间资源做个限制,防止该命名空间部署的资源超过限制。
如何对namespace资源做限额呢?

[root@kaivimaster1~]# vim namespace-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: mem-cpu-quota
  namespace: test
spec:
  hard:
    requests.cpu: "2"
    requests.memory: 2Gi
    limits.cpu: "4"
    limits.memory: 4Gi

#创建的ResourceQuota对象将在test名字空间中添加以下限制:
每个容器必须设置内存请求(memory request),内存限额(memory limit),cpu请求(cpu request)和cpu限额(cpu limit)。
所有容器的内存请求总额不得超过2GiB。
所有容器的内存限额总额不得超过4 GiB。
所有容器的CPU请求总额不得超过2 CPU。
所有容器的CPU限额总额不得超过4CPU。

#创建pod时候必须设置资源限额,否则创建失败,如下:

[root@kaivimaster1 ~]# vim pod-test.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-test
  namespace: test
  labels:
    app: tomcat-pod-test
spec:
  containers:
  - name:  tomcat-test
    ports:
    - containerPort: 8080
    image: kaivi/tomcat-8.5-jre8:v1
    imagePullPolicy: IfNotPresent

[root@kaivimaster1 ~]# kubectl apply -f pod-test.yaml
配置文件中没有对创建pod设置资源限额

标签

什么是标签?

标签其实就一对 key/value ,被关联到对象上,比如Pod,标签的使用我们倾向于能够表示对象的特殊特点,就是一眼就看出了这个Pod是干什么的,标签可以用来划分特定的对象(比如版本,服务类型等),标签可以在创建一个对象的时候直接定义,也可以在后期随时修改,每一个对象可以拥有多个标签,但是,key值必须是唯一的。创建标签之后也可以方便我们对资源进行分组管理。如果对pod打标签,之后就可以使用标签来查看、删除指定的pod。
在k8s中,大部分资源都可以打标签。

给pod资源打标签

#对已经存在的pod打标签

[root@kaivimaster1~]# kubectl label pods pod-first  release=v1

查看标签是否打成功:

[root@kaivimaster1~]# kubectl get pods pod-first --show-labels

显示如下,显示如下,说明标签达成功了;

NAME         READY   STATUS    RESTARTS   AGE   LABELS
pod-first    1/1     Running   1          21h   release=v1, app=tomcat-pod-first

查看资源标签

#查看默认名称空间下所有pod资源的标签

[root@kaivimaster1~]# kubectl get pods --show-labels 

#查看默认名称空间下指定pod具有的所有标签

[root@kaivimaster1~]# kubectl get pods pod-first --show-labels

#列出默认名称空间下标签key是release的pod,不显示标签

[root@kaivimaster1~]# kubectl get pods -l release

#列出默认名称空间下标签key是release、值是v1的pod,不显示标签

[root@kaivimaster1~]# kubectl get pods -l release=v1

#列出默认名称空间下标签key是release的所有pod,并打印对应的标签值

[root@kaivimaster1~]# kubectl get pods -L release

#查看所有名称空间下的所有pod的标签

[root@kaivimaster1 ~]# kubectl get pods --all-namespace --show-labels
[root@kaivimaster1 ~]# kubectl get pods -l release=v1 -L release
NAME        READY   STATUS    RESTARTS   AGE   RELEASE
pod-first   1/1     Running   0          13h   v1

pod资源清单详细解读

apiVersion: v1       #版本号,例如v1
kind: Pod       #资源类型,如Pod
metadata:       #元数据
  name: string       # Pod名字
  namespace: string    # Pod所属的命名空间
  labels:      #自定义标签
    - name: string     #自定义标签名字
  annotations:       #自定义注释列表
    - name: string
spec:         # Pod中容器的详细定义
  containers:      # Pod中容器列表
  - name: string     #容器名称
    image: string    #容器的镜像名称
    imagePullPolicy: [Always | Never | IfNotPresent] #获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,否则下载镜像,Nerver表示仅使用本地镜像
    command: [string]    #容器的启动命令列表,如不指定,使用打包时使用的启动命令
    args: [string]     #容器的启动命令参数列表
    workingDir: string     #容器的工作目录
    volumeMounts:    #挂载到容器内部的存储卷配置
    - name: string     #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
      mountPath: string    #存储卷在容器内mount的绝对路径,应少于512字符
      readOnly: boolean    #是否为只读模式
    ports:       #需要暴露的端口库号
    - name: string     #端口号名称
      containerPort: int   #容器需要监听的端口号
      hostPort: int    #容器所在主机需要监听的端口号,默认与Container相同
      protocol: string     #端口协议,支持TCP和UDP,默认TCP
    env:       #容器运行前需设置的环境变量列表
    - name: string     #环境变量名称
      value: string    #环境变量的值
    resources:       #资源限制和请求的设置
      limits:      #资源限制的设置
        cpu: string    #cpu的限制,单位为core数
        memory: string     #内存限制,单位可以为Mib/Gib
      requests:      #资源请求的设置
        cpu: string    #cpu请求,容器启动的初始可用数量
        memory: string     #内存请求,容器启动的初始可用内存
    livenessProbe:     #对Pod内个容器健康检查的设置,当探测无响应几次后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法即可
      exec:      #对Pod容器内检查方式设置为exec方式
        command: [string]  #exec方式需要制定的命令或脚本
      httpGet:       #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
        path: string
        port: number
        host: string
        scheme: string
        HttpHeaders:
        - name: string
          value: string
      tcpSocket:     #对Pod内个容器健康检查方式设置为tcpSocket方式
         port: number
       initialDelaySeconds: 0  #容器启动完成后首次探测的时间,单位为秒
       timeoutSeconds: 0   #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
       periodSeconds: 0    #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
       successThreshold: 0
       failureThreshold: 0
       securityContext:
         privileged:false
    restartPolicy: [Always | Never | OnFailure]#Pod的重启策略,Always表示一旦不管以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示不再重启该Pod
    nodeSelector: obeject  #设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定
    imagePullSecrets:    #Pull镜像时使用的secret名称,以key:secretkey格式指定
    - name: string
    hostNetwork:false      #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
    volumes:       #在该pod上定义共享存储卷列表
    - name: string     #共享存储卷名称 (volumes类型有很多种)
      emptyDir: {}     #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
      hostPath: string     #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
        path: string     #Pod所在宿主机的目录,将被用于同期中mount的目录
      secret:      #类型为secret的存储卷,挂载集群与定义的secre对象到容器内部
        scretname: string  
        items:     
        - key: string
          path: string
      configMap:     #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
        name: string
        items:
        - key: string
          path: string

node节点选择器

我们在创建pod资源的时候,pod会根据schduler进行调度,那么默认会调度到随机的一个工作节点,如果我们想要pod调度到指定节点或者调度到一些具有相同特点的node节点,怎么办呢?

可以使用pod中的nodeName或者nodeSelector字段指定要调度到的node节点

1、nodeName:
指定pod节点运行在哪个具体node上

#把tomcat.tar.gz上传到kaivinode1和kaivinode2,手动解压:

[root@kaivinode1 ~]# docker load -i tomcat.tar.gz 
Loaded image: tomcat:8.5-jre8-alpine

[root@kaivinode2 ~]# docker load -i tomcat.tar.gz 
Loaded image: tomcat:8.5-jre8-alpine

#把busybox.tar.gz上传到kaivinode1和kaivinode2,手动解压:

[root@kaivinode1 ~]# docker load -i busybox.tar.gz

[root@kaivinode2 ~]# docker load -i busybox.tar.gz 
[root@kaivimaster1 ~]# cat pod-node.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
  namespace: default
  labels:
    app: myapp
    env: dev
spec:
  nodeName: kaivinode1
  containers:
  - name:  tomcat-pod-java
    ports:
    - containerPort: 8080
    image: tomcat:8.5-jre8-alpine
    imagePullPolicy: IfNotPresent
  - name: busybox
    image: busybox:latest
    command:
    - "/bin/sh"
    - "-c"
- "sleep 3600"
[root@kaivimaster1 ~]# kubectl apply -f pod-node.yaml

#查看pod调度到哪个节点
[root@kaivimaster1 ~]# kubectl get pods  -o wide
NAME             READY   STATUS    RESTARTS             
demo-pod        1/1     Running   0            kaivinode1  

2、nodeSelector:
指定pod调度到具有哪些标签的node节点上
#给node节点打标签,打个具有disk=ceph的标签

[root@kaivimaster1 ~]# kubectl label nodes kaivinode2 disk=ceph
node/kaivinode2 labeled

#定义pod的时候指定要调度到具有disk=ceph标签的node上

[root@kaivimaster1 ~]# cat pod-1.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: demo-pod-1
  namespace: default
  labels:
    app: myapp
    env: dev
spec:
  nodeSelector:            #node阶段选择器选择标签
    disk: ceph
  containers:
  - name:  tomcat-pod-java
    ports:
    - containerPort: 8080
    image: tomcat:8.5-jre8-alpine
    imagePullPolicy: IfNotPresent
[root@kaivimaster1 ~]# kubectl apply -f pod-1.yaml

#查看pod调度到哪个节点

[root@kaivimaster1 ~]# kubectl get pods  -o wide
NAME             READY   STATUS    RESTARTS             
demo-pod-1        1/1     Running   0            kaivinode2  

污点和容忍度

node节点亲和性

node节点亲和性调度:nodeAffinity

[root@kaivimaster1 ~]# kubectl explain pods.spec.affinity 
KIND:     Pod
VERSION:  v1
RESOURCE: affinity <Object>
DESCRIPTION:
     If specified, the pod's scheduling constraints
    Affinity is a group of affinity scheduling rules.
FIELDS:
   nodeAffinity	<Object>
   podAffinity	<Object>
   podAntiAffinity	<Object>
[root@kaivimaster1 ~]#  kubectl explain  pods.spec.affinity.nodeAffinity
KIND:     Pod
VERSION:  v1
RESOURCE: nodeAffinity <Object>
DESCRIPTION:
     Describes node affinity scheduling rules for the pod.
     Node affinity is a group of node affinity scheduling rules.
FIELDS:
   preferredDuringSchedulingIgnoredDuringExecution	<[]Object>
   requiredDuringSchedulingIgnoredDuringExecution	<Object>

prefered表示有节点尽量满足这个位置定义的亲和性,这不是一个必须的条件,软亲和性
require表示必须有节点满足这个位置定义的亲和性,这是个硬性条件,硬亲和性

[root@kaivimaster1 ~]# kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution
KIND:     Pod
VERSION:  v1
RESOURCE: requiredDuringSchedulingIgnoredDuringExecution <Object>
DESCRIPTION:
FIELDS:
   nodeSelectorTerms	<[]Object> -required-
     Required. A list of node selector terms. The terms are ORed.
[root@kaivimaster1 ~]# kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms
KIND:     Pod
VERSION:  v1
RESOURCE: nodeSelectorTerms <[]Object>
DESCRIPTION:
     Required. A list of node selector terms. The terms are ORed.
     A null or empty node selector term matches no objects. The requirements of
     them are ANDed. The TopologySelectorTerm type implements a subset of the
     NodeSelectorTerm.
FIELDS:
   matchExpressions	<[]Object>
   matchFields	<[]Object>
matchExpressions:匹配表达式的
matchFields: 匹配字段的
[root@kaivimaster1 ~]# kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchFields
KIND:     Pod
VERSION:  v1
RESOURCE: matchFields <[]Object>
DESCRIPTION:

FIELDS:
   key	<string> -required-
   values	<[]string>
[root@kaivimaster1 ~]# kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchExpressions
KIND:     Pod
VERSION:  v1
RESOURCE: matchExpressions <[]Object>
DESCRIPTION:
FIELDS:
   key	<string> -required-
   operator	<string> -required-
   values	<[]string>
key:检查label
operator:做等值选则还是不等值选则
values:给定值

例1:使用requiredDuringSchedulingIgnoredDuringExecution硬亲和性
#把myapp-v1.tar.gz上传到kaivinode2和kaivinode1上,手动解压:

[root@kaivinode1 ~]# docker load -i myapp-v1.tar.gz 
Loaded image: ikubernetes/myapp:v1
[root@kaivinode2 ~]# docker load -i myapp-v1.tar.gz 
Loaded image: ikubernetes/myapp:v1
[root@kaivimaster1 ~]# cat pod-nodeaffinity-demo.yaml 
apiVersion: v1
kind: Pod
metadata:
        name: pod-node-affinity-demo
        namespace: default
        labels:
            app: myapp
            tier: frontend
spec:
    containers:
    - name: myapp
      image: ikubernetes/myapp:v1
    affinity:
        nodeAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
                   nodeSelectorTerms:
                   - matchExpressions:
                     - key: zone
                       operator: In
                       values:
                       - foo
                       - bar

我们检查当前节点中有任意一个节点拥有zone标签的值是foo或者bar,就可以把pod调度到这个node节点的foo或者bar标签上的节点上

[root@kaivimaster1 ~]# kubectl apply -f pod-nodeaffinity-demo.yaml 
[root@kaivimaster1 ~]# kubectl get pods -o wide | grep pod-node
pod-node-affinity-demo             0/1     Pending     0   kaivinode1                       

status的状态是pending,上面说明没有完成调度,因为没有一个拥有zone的标签的值是foo或者bar,而且使用的是硬亲和性,必须满足条件才能完成调度

[root@kaivimaster1 ~]# kubectl label nodes kaivinode1 zone=foo

给这个kaivinode1节点打上标签zone=foo,在查看

[root@kaivimaster1 ~]#kubectl get pods -o wide 显示如下:
pod-node-affinity-demo             1/1     Running  0   kaivinode1

例2:使用preferredDuringSchedulingIgnoredDuringExecution软亲和性

[root@kaivimaster1 ~]# cat pod-nodeaffinity-demo-2.yaml 
apiVersion: v1
kind: Pod
metadata:
        name: pod-node-affinity-demo-2
        namespace: default
        labels:
            app: myapp
            tier: frontend
spec:
    containers:
    - name: myapp
      image: ikubernetes/myapp:v1
    affinity:
        nodeAffinity:
            preferredDuringSchedulingIgnoredDuringExecution:
            - preference:
               matchExpressions:
               - key: zone1
                 operator: In
                 values:
                 - foo1
                 - bar1
              weight: 60
[root@kaivimaster1 ~]# kubectl apply -f pod-nodeaffinity-demo-2.yaml

[root@kaivimaster1 ~]# kubectl get pods -o wide |grep demo-2
pod-node-affinity-demo-2           1/1     Running     0        kaivinode1

上面说明软亲和性是可以运行这个pod的,尽管没有运行这个pod的节点定义的zone1标签

Node节点亲和性针对的是pod和node的关系,Pod调度到node节点的时候匹配的条件

Pod节点亲和性

pod自身的亲和性调度有两种表示形式
podaffinity:pod和pod更倾向腻在一起,把相近的pod结合到相近的位置,如同一区域,同一机架,这样的话pod和pod之间更好通信,比方说有两个机房,这两个机房部署的集群有1000台主机,那么我们希望把nginx和tomcat都部署同一个地方的node节点上,可以提高通信效率;

podunaffinity:pod和pod更倾向不腻在一起,如果部署两套程序,那么这两套程序更倾向于反亲和性,这样相互之间不会有影响。

第一个pod随机选则一个节点,做为评判后续的pod能否到达这个pod所在的节点上的运行方式,这就称为pod亲和性;我们怎么判定哪些节点是相同位置的,哪些节点是不同位置的;我们在定义pod亲和性时需要有一个前提,哪些pod在同一个位置,哪些pod不在同一个位置,这个位置是怎么定义的,标准是什么?

以节点名称为标准,这个节点名称相同的表示是同一个位置,节点名称不相同的表示不是一个位置

[root@kaivimaster1 ~]# kubectl explain pods.spec.affinity.podAffinity
KIND:     Pod
VERSION:  v1
RESOURCE: podAffinity <Object>
DESCRIPTION:
     Describes pod affinity scheduling rules (e.g. co-locate this pod in the
     same node, zone, etc. as some other pod(s)).
     Pod affinity is a group of inter pod affinity scheduling rules.
FIELDS:
   preferredDuringSchedulingIgnoredDuringExecution	<[]Object>
   requiredDuringSchedulingIgnoredDuringExecution	<[]Object>
   
requiredDuringSchedulingIgnoredDuringExecution: 硬亲和性
preferredDuringSchedulingIgnoredDuringExecution:软亲和性
[root@kaivimaster1 ~]# kubectl explain pods.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution
KIND:     Pod
VERSION:  v1
RESOURCE: requiredDuringSchedulingIgnoredDuringExecution <[]Object>
DESCRIPTION:
FIELDS:
   labelSelector	<Object>
   namespaces	<[]string>
   topologyKey	<string> -required-

topologyKey:
位置拓扑的键,这个是必须字段
怎么判断是不是同一个位置:
rack=rack1
row=row1
使用rack的键是同一个位置
使用row的键是同一个位置
labelSelector:
我们要判断pod跟别的pod亲和,跟哪个pod亲和,需要靠labelSelector,通过labelSelector选则一组能作为亲和对象的pod资源
namespace:
labelSelector需要选则一组资源,那么这组资源是在哪个名称空间中呢,通过namespace指定,如果不指定namespaces,那么就是当前创建pod的名称空间

[root@kaivimaster1 ~]# kubectl explain pods.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution.labelSelector 
KIND:     Pod
VERSION:  v1
RESOURCE: labelSelector <Object>
DESCRIPTION:
     A label query over a set of resources, in this case pods.
     A label selector is a label query over a set of resources. The result of
     matchLabels and matchExpressions are ANDed. An empty label selector matches
     all objects. A null label selector matches no objects.
FIELDS:
   matchExpressions	<[]Object>
   matchLabels	<map[string]string>

例1:pod节点亲和性
定义两个pod,第一个pod做为基准,第二个pod跟着它走

[root@kaivimaster1]# kubectl delete pods pod-first
[root@kaivimaster1 ~]# cat pod-required-affinity-demo.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-first
  labels:
    app2: myapp2
    tier: frontend
spec:
    containers:
    - name: myapp
      image: ikubernetes/myapp:v1
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-second
  labels:
    app: backend
    tier: db
spec:
    containers:
    - name: busybox
      image: busybox:latest
      imagePullPolicy: IfNotPresent
      command: ["sh","-c","sleep 3600"]
    affinity:
      podAffinity:
         requiredDuringSchedulingIgnoredDuringExecution:
         - labelSelector:
              matchExpressions:
              - {key: app2, operator: In, values: ["myapp2"]}
           topologyKey: kubernetes.io/hostname

#上面表示创建的pod必须与拥有app=myapp标签的pod在一个节点上

[root@kaivimaster1 ~]# kubectl apply -f pod-required-affinity-demo.yaml 

kubectl get pods -o wide 显示如下:
pod-first              running        kaivinode1
pod-second             running        kaivinode1

上面说明第一个pod调度到哪,第二个pod也调度到哪,这就是pod节点亲和性

[root@kaivimaster1 ~]# kubectl delete -f pod-required-affinity-demo.yaml
[root@kaivimaster1 ~]# kubectl get nodes --show-labels

例2:pod节点反亲和性
定义两个pod,第一个pod做为基准,第二个pod跟它调度节点相反

[root@kaivimaster1 ~]# cat pod-required-anti-affinity-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-first
  labels:
    app1: myapp1
    tier: frontend
spec:
    containers:
    - name: myapp
      image: ikubernetes/myapp:v1
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-second
  labels:
    app: backend
    tier: db
spec:
    containers:
    - name: busybox
      image: busybox:latest
      imagePullPolicy: IfNotPresent
      command: ["sh","-c","sleep 3600"]
    affinity:
      podAntiAffinity:
         requiredDuringSchedulingIgnoredDuringExecution:
         - labelSelector:
              matchExpressions:
              - {key: app1, operator: In, values: ["myapp1"]}
           topologyKey: kubernetes.io/hostname
[root@kaivimaster1 ~]# kubectl apply -f pod-required-anti-affinity-demo.yaml
[root@kaivimaster1 ~]# kubectl get pods -o wide 显示两个pod不在一个node节点上,这就是pod节点反亲和性
pod-first            running        kaivinode1
pod-second           running        kaivinode2
[root@kaivimaster1 ~]# kubectl delete -f pod-required-anti-affinity-demo.yaml

例3:换一个topologykey

[root@kaivimaster1 ~]# kubectl label nodes  kaivinode2  zone=foo
[root@kaivimaster1 ~]# kubectl label nodes  kaivinode1  zone=foo --overwrite #覆盖
[root@kaivimaster1]# cat pod-first-required-anti-affinity-demo-1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-first
  labels:
    app3: myapp3
    tier: frontend
spec:
    containers:
    - name: myapp
      image: ikubernetes/myapp:v1

[root@kaivimaster1]# cat pod-second-required-anti-affinity-demo-1.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-second
  labels:
    app: backend
    tier: db
spec:
    containers:
    - name: busybox
      image: busybox:latest
      imagePullPolicy: IfNotPresent
      command: ["sh","-c","sleep 3600"]
    affinity:
      podAntiAffinity:
         requiredDuringSchedulingIgnoredDuringExecution:
         - labelSelector:
              matchExpressions:
              - {key: app3 ,operator: In, values: ["myapp3"]}
           topologyKey:  zone
[root@kaivimaster1 affinity]# kubectl apply -f pod-first-required-anti-affinity-demo-1.yaml

[root@kaivimaster1 affinity]# kubectl apply -f pod-second-required-anti-affinity-demo-1.yaml

[root@kaivimaster1 ~]#kubectl get pods -o wide 显示如下:
pod-first              running         kaivinode1
pod-second             pending         <none>

第二个节点现是pending,因为两个节点是同一个位置,现在没有不是同一个位置的了,而且我们要求反亲和性,所以就会处于pending状态,如果在反亲和性这个位置把required改成preferred,那么也会运行。
podaffinity:pod节点亲和性,pod倾向于哪个pod
nodeaffinity:node节点亲和性,pod倾向于哪个node

污点、容忍度

给了节点选则的主动权,我们给节点打一个污点,不容忍的pod就运行不上来,污点就是定义在节点上的键值属性数据,可以定决定拒绝那些pod;
taints是键值数据,用在节点上,定义污点;
tolerations是键值数据,用在pod上,定义容忍度,能容忍哪些污点
pod亲和性是pod属性;但是污点是节点的属性,污点定义在nodeSelector上

[root@kaivimaster1 affinity]# kubectl describe nodes kaivimaster1

Taints:             node-role.kubernetes.io/master:NoSchedule

[root@kaivimaster1 ~]# kubectl explain node.spec.taints
KIND:     Node
VERSION:  v1
RESOURCE: taints <[]Object>
DESCRIPTION:
     If specified, the node's taints.
     The node this Taint is attached to has the "effect" on any pod that does
     not tolerate the Taint.
FIELDS:
   effect	<string> -required-
   key	<string> -required-
   timeAdded	<string>
   value	<string>

taints的effect用来定义对pod对象的排斥等级(效果):

NoSchedule: 仅影响pod调度过程,当pod能容忍这个节点污点,就可以调度到当前节点,后来这个节点的污点改了,加了一个新的污点,使得之前调度的pod不能容忍了,那这个pod只会对新的pod进行排斥吃力,对现存的pod对象不产生影响

NoExecute: 既影响调度过程,又影响现存的pod对象,如果现存的pod不能容忍节点后来加的污点,这个pod就会被驱逐

PreferNoSchedule: 最好不,也可以,是NoSchedule的柔性版本

在pod对象定义容忍度的时候支持两种操作:
1.等值密钥:key和value上完全匹配

2.存在性判断:key和effect必须同时匹配,value可以是空

在pod上定义的容忍度可能不止一个,在节点上定义的污点可能多个,需要琢个检查容忍度和污点能否匹配,每一个污点都能被容忍,才能完成调度,如果不能容忍怎么办,那就需要看pod的容忍度了

[root@kaivimaster1 ~]# kubectl describe nodes kaivimaster1

查看master这个节点是否有污点,显示如下:

上面可以看到master这个节点的污点是Noschedule

所以我们创建的pod都不会调度到master上,因为我们创建的pod没有容忍度

[root@kaivimaster1 ~]# kubectl describe pods kube-apiserver-kaivimaster1 -n kube-system

显示如下:
在这里插入图片描述

可以看到这个pod的容忍度是NoExecute,则可以调度到kaivimaster1上

管理节点污点

[root@kaivimaster1]# kubectl taint –help

例1:把kaivinode2当成是生产环境专用的,其他node是测试的

[root@kaivimaster1 ~]# kubectl taint node kaivinode2 node-type=production:NoSchedule

给kaivinode2打污点,pod如果不能容忍就不会调度过来)

[root@kaivimaster1 ~]# cat pod-taint.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: taint-pod
  namespace: default
  labels:
    tomcat:  tomcat-pod
spec:
  containers:
  - name:  taint-pod
    ports:
    - containerPort: 8080
    image: tomcat:8.5-jre8-alpine
imagePullPolicy: IfNotPresent 
[root@kaivimaster1 ~]# kubectl apply -f pod-taint.yaml

[root@kaivimaster1 ~]# kubectl get pods -o wide 
显示如下:
taint-pod   running    kaivinode1

可以看到都被调度到kaivinode1上了,因为kaivinode2这个节点打了污点,而我们在创建pod的时候没有容忍度,所以kaivinode2上不会有pod调度上去的。

例2:给kaivinode1也打上污点

[root@kaivimaster1 ~]# kubectl delete -f pod-taint.yaml

[root@kaivimaster1 ~]#kubectl taint node kaivinode1 node-type=dev:NoExecute

[root@kaivimaster1 ~]#kubectl get pods -o wide 

显示如下:
taint-pod termaitering

[root@kaivimaster1 ~]# cat pod-demo-1.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: myapp-deploy
  namespace: default
  labels:
    app: myapp
    release: canary
spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - name: http
          containerPort: 80
      tolerations:
      - key: "node-type"
        operator: "Equal"
        value: "production"
        effect: "NoExecute"
        tolerationSeconds: 3600
[root@kaivimaster1 ~]# kubectl apply -f pod-demo-1.yaml
[root@kaivimaster1 ~]# kubectl get pods
myapp-deploy   1/1     Pending   0          11s  kaivinode2

还是显示pending,因为我们使用的是equal(等值匹配),所以key和value,effect必须和node节点定义的污点完全匹配才可以,把上面配置effect: "NoExecute"变成effect: "NoSchedule"成;
tolerationSeconds: 3600这行去掉

[root@kaivimaster1 ~]# kubectl delete -f pod-demo-1.yaml

[root@kaivimaster1 ~]# kubectl apply -f pod-demo-1.yaml

[root@kaivimaster1 ~]# kubectl get pods
myapp-deploy   1/1     running  0          11s  kaivinode2

上面就可以调度到kaivinode2上了,因为在pod中定义的容忍度能容忍node节点上的污点

例3:再次修改
修改如下部分:

tolerations:
- key: "node-type"
operator: "Exists"
value: ""
effect: "NoSchedule"

只要对应的键是存在的,exists,其值被自动定义成通配符

[root@kaivimaster1 ~]# kubectl delete -f pod-demo-1.yaml

[root@kaivimaster1 ~]# kubectl apply -f pod-demo-1.yaml

[root@kaivimaster1 ~]# kubectl get pods
发现还是调度到kaivinode2上
myapp-deploy   1/1     running  0          11s  kaivinode2

再次修改:

tolerations:
- key: "node-type"
operator: "Exists"
value: ""
effect: ""

有一个node-type的键,不管值是什么,不管是什么效果,都能容忍

[root@kaivimaster1 ~]# kubectl delete -f pod-demo-1.yaml

[root@kaivimaster1 ~]# kubectl apply -f pod-demo-1.yaml

[root@kaivimaster1 ~]#  kubectl get pods -o wide 显示如下:
myapp-deploy  running    kaivinode1

可以看到kaivinode2和kaivinode1节点上都有可能有pod被调度

删除污点:

[root@kaivimaster1 taint]# kubectl taint nodes kaivinode1 node-type:NoExecute-

[root@kaivimaster1 taint]# kubectl taint nodes kaivinode2 node-type-

你可能感兴趣的:(K8S,POD)