一:Pod介绍

pod资源的各种配置和原理

关于很多yaml文件的编写,都是基于配置引出来的

1:pod的结构和定义

 每个Pod中都可以包含一个或者多个容器,这些容器可以分为2大类:

  1:用户所在的容器,数量可多可少(用户容器)

  2:pause容器,这是每个pod都会有的一个跟容器,作用有2个

    1、可以以它为根据,评估整个pod的健康状态

    2、可以在根容器上面设置ip地址,其他容器都以此ip,实现Pod内部的网络通信

      这里的Pod内部通讯是,pod之间采用二层网络技术来实现

      ;其他容器都共享这个根容器的ip地址,外界访问这个根容器ip地址+端口即可

2:pod定义

pod的资源清单:

属性,依次类推的进行查找

[root@master /]# kubectl  explain pod
#查看二级属性
[root@master /]# kubectl  explain pod.metadata

 

介绍

apiVersion 版本
#查看所有的版本
[root@master /]# kubectl  api-versions
admissionregistration.k8s.io/v1
apiextensions.k8s.io/v1
apiregistration.k8s.io/v1
apps/v1
authentication.k8s.io/v1
authorization.k8s.io/v1
autoscaling/v1
autoscaling/v2
batch/v1
certificates.k8s.io/v1
coordination.k8s.io/v1
discovery.k8s.io/v1
events.k8s.io/v1
flowcontrol.apiserver.k8s.io/v1beta2
flowcontrol.apiserver.k8s.io/v1beta3
networking.k8s.io/v1
node.k8s.io/v1
policy/v1
rbac.authorization.k8s.io/v1
scheduling.k8s.io/v1
storage.k8s.io/v1
v1

kind 类型
#查看资源的类型
[root@master /]# kubectl  api-resources 

metadata  元数据,资源的名字,标签等等
[root@master /]# kubectl  explain  pod.metadata 

status   状态信息,自动的进行生成,不需要自己定义
[root@master /]# kubectl  get pods -o yaml

spec  定义资源的详细信息,
下面的子属性
containers:object  容器列表,用于定义容器的详细信息
nodename:string   根据nodename的值将pod的调度到指定的node节点,pod部署在哪个Pod上面
nodeselector:pod标签选择器,可以将pod调度到包含这些label的Node上
hostnetwork:默认是false,k8s自动的分配一个ip地址,如果设置为true,就使用宿主机的ip
volumes:存储卷,用于定义pod上面挂载的存储信息
restartpolicy:重启策略,表示pod在遇到故障的时候处理的策略

3:pod配置

主要关于pod.spec.containers属性

里面有的是数组,就是可以选择多个值,在里面的话,有的只是一个值,看情况进行区分

[root@master /]# kubectl  explain pod.spec.containers
KIND:       Pod
VERSION:    v1

name:容器名称
image:容器需要的镜像地址
imagePullPolicy:镜像拉取策略  本地的还是远程的
command:容器的启动命令列表,如不指定,使用打包时使用的启动命令  string
args:容器的启动命令需要的参数列表,也就是上面的列表的命令   string
env:容器环境变量的配置   object
ports:容器需要暴露的端口列表   object
resources:资源限制和资源请求的设置   object

1、基本配置

[root@master ~]# cat pod-base.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-base
  namespace: dev
  labels:
    user: qqqq
spec:
   containers:
     - name: nginx
       image: nginx:1.17.1
     - name: busybox
       image: busybox:1.30

简单的Pod的配置,里面有2个容器
nginx轻量级的web软件
busybox:就是一个小巧的Linux命令集合

[root@master ~]# kubectl create  -f pod-base.yaml 
pod/pod-base created

#查看Pod状态,
ready:只有里面有2个容器,但是只有一个是准备就绪的,还有一个没有启动
restarts:重启的次数,因为有一个容器故障了,Pod一直重启试图恢复它
[root@master ~]# kubectl get pods -n dev
NAME       READY   STATUS             RESTARTS      AGE
pod-base   1/2     CrashLoopBackOff   4 (29s ago)   2m36s

#可以查看pod详情
[root@master ~]# kubectl describe  pods pod-base -n dev
Events:
  Type     Reason     Age                   From               Message
  ----     ------     ----                  ----               -------
  Normal   Scheduled  4m51s                 default-scheduler  Successfully assigned dev/pod-base to node2
  Normal   Pulling    4m51s                 kubelet            Pulling image "nginx:1.17.1"
  Normal   Pulled     4m17s                 kubelet            Successfully pulled image "nginx:1.17.1" in 33.75s (33.75s including waiting)
  Normal   Created    4m17s                 kubelet            Created container nginx
  Normal   Started    4m17s                 kubelet            Started container nginx
  Normal   Pulling    4m17s                 kubelet            Pulling image "busybox:1.30"
  Normal   Pulled     4m9s                  kubelet            Successfully pulled image "busybox:1.30" in 8.356s (8.356s including waiting)
  Normal   Created    3m27s (x4 over 4m9s)  kubelet            Created container busybox
  Normal   Started    3m27s (x4 over 4m9s)  kubelet            Started container busybox
  Warning  BackOff    2m59s (x7 over 4m7s)  kubelet            Back-off restarting failed container busybox in pod pod-base_dev(2e9aeb3f-2bec-4af5-853e-2d8473e115a7)
  Normal   Pulled     2m44s (x4 over 4m8s)  kubelet            Container image "busybox:1.30" already present on machine  

之后再来进行解决

2、镜像拉取

imagePullPolicy

就是pod里面有个容器,一个有本地镜像,一个没有,可以使用这个参数来进行控制是本地还是远程的

imagePullPolicy的值,

  Always:总是从远程仓库进行拉取镜像(一直用远程下载)

  ifNotPresent:本地有则使用本地的镜像,本地没有则使用从远程仓库拉取镜像

  Never:一直使用本地的,不使用远程下载

如果镜像的tag为具体的版本号:默认值是ifNotPresent,

 如果是latest:默认策略是always

[root@master ~]# cat pod-policy.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-imagepullpolicy
  namespace: dev
  labels:
    user: qqqq
spec:
   containers:
     - name: nginx
       image: nginx:1.17.2
       imagePullPolicy: Never
     - name: busybox
       image: busybox:1.30

[root@master ~]# kubectl create -f pod-policy.yaml 
pod/pod-imagepullpolicy created

#查看pods状态
[root@master ~]# kubectl get pods -n dev
NAME                  READY   STATUS             RESTARTS        AGE
pod-base              1/2     CrashLoopBackOff   9 (3m59s ago)   25m
pod-imagepullpolicy   0/2     CrashLoopBackOff   1 (9s ago)      19s

#查看详细的信息
[root@master ~]# kubectl describe  pods pod-imagepullpolicy -n dev 
Events:
  Type     Reason             Age                From               Message
  ----     ------             ----               ----               -------
  Normal   Scheduled          64s                default-scheduler  Successfully assigned dev/pod-imagepullpolicy to node1
  Normal   Pulling            64s                kubelet            Pulling image "busybox:1.30"
  Normal   Pulled             56s                kubelet            Successfully pulled image "busybox:1.30" in 8.097s (8.097s including waiting)
  Normal   Created            39s (x3 over 56s)  kubelet            Created container busybox
  Normal   Started            39s (x3 over 56s)  kubelet            Started container busybox
  Normal   Pulled             39s (x2 over 55s)  kubelet            Container image "busybox:1.30" already present on machine
  Warning  ErrImageNeverPull  38s (x6 over 64s)  kubelet            Container image "nginx:1.17.2" is not present with pull policy of Never
  Warning  Failed             38s (x6 over 64s)  kubelet            Error: ErrImageNeverPull
  Warning  BackOff            38s (x3 over 54s)  kubelet            Back-off restarting failed container busybox in pod pod-imagepullpolicy_dev(38d5d2ff-6155-4ff3-ad7c-8b7f4a370107)

#直接报了一个错误,就是镜像拉取失败了

#解决的措施,修改里面的策略为ifnotpresent即可
[root@master ~]# kubectl  delete  -f pod-policy.yaml 
[root@master ~]# kubectl  apply  -f pod-policy.yaml 
[root@master ~]# kubectl  get pods -n dev
[root@master ~]# kubectl  get pods -n dev
NAME                  READY   STATUS             RESTARTS         AGE
pod-base              1/2     CrashLoopBackOff   11 (2m34s ago)   34m
pod-imagepullpolicy   1/2     CrashLoopBackOff   4 (63s ago)      2m55s
这样就拉取成功了

3、启动命令

command:容器启动的命令列表,如果不指定的话,使用打包时使用的启动命令

args:容器的启动命令需要的参数列表

为什么没有busybox运行了,busybox并不是一个程序,而是类似于一个工具类的集合,他会自动的进行关闭,解决的方法就是让其一直的运行,这就要使用command命令了

[root@master ~]# cat command.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-command
  namespace: dev
spec:
   containers:
     - name: nginx
       image: nginx:1.17.1
     - name: busybox
       image: busybox:1.30
       command: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hell0.txt;sleep 3;done;"]


#/bin/sh  命令行脚本
-c  之后的字符串作为一个命令来执行
向这个文件里面执行时间,然后执行结束后,休息3秒钟,这个就是一个进程一直在运行

[root@master ~]# kubectl  create -f command.yaml 
pod/pod-command created

#这样就好了,都启动了
[root@master ~]# kubectl get pods -n dev
NAME          READY   STATUS    RESTARTS   AGE
pod-command   2/2     Running   0          6s

#进入这个容器
[root@master ~]# kubectl  exec pod-command -n dev -it -c busybox /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # 

这样就成功的进入里面去了
/ # cat /tmp/hell0.txt ,因为有这个进程的存在,就不是关闭掉

  

说明:发现command已经完成启动命令后和传递参数后的功能,为什么还需要提供一个args的选项了,用于传递参数呢,这其实跟docker有点关系,整个个就是覆盖dockerfile中的entrypoint的功能

k8s拉取镜像的时候,里面有一个dockerfile来构建镜像,然后k8s的command和args会替换

情况:

  1,如果command和args没有写,那么用dockerfile的配置

  2、如果command写了,但是args没有写,那么用dockerfile默认配置会被忽略,执行输入的command命令

  3、如果command没写,但是args写了,那么dockerfile中的配置的entrypoint命令会被执行,使用当前的args的参数

  4、如果都写了,那么dockerfile的配置被忽略,执行command并追上args参数

 4、环境变量(了解即可)

env向容器里面传入环境变量,object类型的数组

键值对,就是一个键加上一个值即可

[root@master ~]# cat pod-env.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-command
  namespace: dev
spec:
   containers:
     - name: nginx
       image: nginx:1.17.1
     - name: busybox
       image: busybox:1.30
       command: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hell0.txt;sleep 3;done;"]
       env:
       - name: "username"
          vaule : "admin"
       - name: "password"
         vaule: "123456"


#创建Pod
[root@master ~]# kubectl create -f pod-env.yaml 
pod/pod-command created
[root@master ~]# kubectl get pods -n dev
NAME          READY   STATUS    RESTARTS   AGE
pod-command   2/2     Running   0          47s


#进入容器里面
-c选项,只有一个容器的话,可以省略掉即可
[root@master ~]# kubectl  exec -ti pod-command -n dev -c busybox /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # echo $username
admin
/ # echo password
password

5、端口设置(ports)

查看端口一些选项  

[root@master ~]# kubectl  explain  pod.spec.containers.ports
ports 
   name:端口的名称,必须是在Pod中是唯一的
   containerport 容器要监听的端口
   hostport 容器要在主机上公开的端口,如果设置,主机上只能运行容器的一个副本,会有冲突,多个Pod会占用一个端口
   hostip  要将外部端口绑定到主机的Ip(一般省略了)
   protocol  端口协议,默认是TCP,UTP,SCTP
   

 

案例:

[root@master ~]# cat pod-port.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-ports
  namespace: dev
spec:
   containers:
   - name: nginx
     image: nginx:1.17.1
     ports:
     - name: nginx-port
       containerPort: 80
       protocol: TCP

kubectl create -f pod-port.yaml 
[root@master ~]# kubectl get pod -n dev -o wide
NAME          READY   STATUS    RESTARTS   AGE     IP           NODE    NOMINATED NODE   READINESS GATES
pod-command   2/2     Running   0          27m     10.244.1.2   node2   <none>           <none>
pod-ports     1/1     Running   0          2m58s   10.244.2.2   node1   <none>           <none>

#访问容器里面的程序的话,需要使用Pod的ip加上容器的端口即可,进行访问
[root@master ~]# curl 10.244.2.2:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

6、资源限制(resources)

因为容器的运行需要占用一些资源,就是对某些容器进行资源的限制,如果某个资源突然大量的值内存的话,其他的容器就不能正常的工作了,就会出现问题

就是规定A容器只需要600M内存,如果大于的话,就出现了问题,进行重启容器的操作

有2个字选项:

limits:用于限制运行时容器的最大占用资源,当容器占用的资源超过了limits会被终止,并就进行重启(上限)

requests:用于设置容器需要的最小资源,如果环境资源不够的话,容器无法进行启动(下限)  

  作用:

    1、只针对cpu,内存

案例:

[root@master ~]# cat pod-r.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-resources
  namespace: dev
spec:
   containers:
   - name: nginx
     image: nginx:1.17.1
     resources:
        limits:
           cpu: "2"
           memory: "10Gi"
        requests:
            cpu: "1"
            memory: "10Mi"

kubectl create -f pod-r.yaml 
[root@master ~]# kubectl get pods -n dev
NAME            READY   STATUS    RESTARTS   AGE
pod-command     2/2     Running   0          41m
pod-ports       1/1     Running   0          16m
pod-resources   1/1     Running   0          113s


#规定最少需要10G才能启动容器,但是不会进行启动
[root@master ~]# cat pod-r.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-resources
  namespace: dev
spec:
   containers:
   - name: nginx
     image: nginx:1.17.1
     resources:
        limits:
           cpu: "2"
           memory: "10Gi"
        requests:
            cpu: "1"
            memory: "10G"
[root@master ~]# kubectl create -f pod-r.yaml 
pod/pod-resources created

#查找状态
[root@master ~]# kubectl get pods -n dev
NAME            READY   STATUS    RESTARTS   AGE
pod-command     2/2     Running   0          44m
pod-ports       1/1     Running   0          19m
pod-resources   0/1     Pending   0          89s

#查看详细的信息
[root@master ~]# kubectl  describe  pods pod-resources -n dev

cpu和内存的单位
cpu为整数
内存为Gi Mi  G M等形式

二:pod生命周期    

 1:概念

一般是指Pod对象从创建至终的时间范围称为pod的生命周期,主要包含一下过程

  1、pod创建过程

  2、运行初始化容器过程,它是容器的一种,可多可少,一定在主容器运行之前执行

  3、运行主容器过程

    容器启动后钩子,容器终止前钩子,就是启动之后的一些命令,2个特殊的点

    容器的存活性探测,就绪性探测

  4、pod终止过程

在整个生命周期中,pod会出现5中状态

挂起(pending):apiserver,已经创建了pod资源对象,但它尚未被调度,或者仍然处于下载镜像的过程中;创建一个pod,里面有容器,需要拉取

运行中(running):pod已经被调度至某一个节点,并且所有的容器都已经被kubelet创建完成

成功(succeeded):Pod中的所有容器都已经被成功终止,并且不会被重启;就是运行一个容器,30秒后,打印,然后退出

失败(failed):所有容器都已经被终止,但至少有一个容器终止失败,即容器返回非0的退出状态

未知(unknown):apiserver无法正常的获取到pod对象的状态信息,通常由网络通信失败所导致的

2:pod创建和终止

pod的创建过程:

都监听到apiserver上面了 

开始创建就已经返回一个信息了,给etcd了,

scheduler:开始为pod分配主机,将结果告诉apiserver

node节点上面发现有pod调度过来,调用docker启动容器,并将结果告诉apiserver

apiserver将接收的信息pod状态信息存入etcd中

pod的终止过程:

service就是Pod的代理,访问pod通过service即可

 向apiserver发送一个请求,apiserver更新pod的状态,将pod标记为terminating状态,kubelet监听到为terminating,就启动关闭pod过程

3:初始化容器

主要做的就是主容器的前置工作(环境的准备),2个特点

  1、初始化容器必须运行在完成直至结束,若某初始化容器运行失败了,那么k8s需要重启它知道成功完成

  2、初始化容器必须按照定义的顺序执行,当且仅当前一个成功了,后面的一个才能运行,否则不运行

初始化容器应用场景:

  提供主容器进行不具备工具程序或自定义代码

  初始化容器需要先于应用容器串行启动并运行成功,因此,可应用容器的启动直至依赖的条件得到满足

      nginx,mysql,redis,  先连mysql,不成功,则会一直处于连接, 一直连成功了,就会去连接redis,这2个条件都满足了,nginx这个主容器就会启动了

测试:

规定mysql 192.168.109.201  redis 192.168.109.202

 

[root@master ~]# cat pod-init.yaml 
apiVersion: v1
kind: Pod
metadata:
   name: pod-init
   namespace: dev
spec:
   containers:
   - name: main-container
     image: nginx:1.17.1
     ports:
     - name: nginx-port
       containerPort: 80
   initContainers:
   - name: test-mysql
     image: busybox:1.30
     command: ['sh','-c','util ping 192.168.109.201 -c 1;do echo waiting for mysql;sleep 2;done;']
   - name: test-redis
     image: busybox:1.30
     command: ['sh','-c','util ping 192.168.109.202 -c 1;di echo waiting for redis;sleep 2;done']
#由于没有地址,所以的话,初始化失败
[root@master ~]# kubectl get pods -n dev
NAME       READY   STATUS                  RESTARTS      AGE
pod-init   0/1     Init:CrashLoopBackOff   3 (27s ago)   83s

#添加地址,第一个初始化容器就能运行了
[root@master ~]# ifconfig  ens33:1 192.168.109.201 netmask 255.255.255.0 up

#再次添加地址,第二个初始化容器也能运行了
[root@master ~]# ifconfig  ens33:2 192.168.109.202 netmask 255.255.255.0 up
[root@master ~]# kubectl get pods -n dev -w
NAME       READY   STATUS     RESTARTS   AGE
pod-init   0/1     Init:0/2   0          6s
pod-init   0/1     Init:1/2   0          13s
pod-init   0/1     Init:1/2   0          14s
pod-init   0/1     PodInitializing   0          27s
pod-init   1/1     Running           0          28s

主容器就运行成功了

4:主容器钩子函数

就是主容器上面的一些点,能够允许用户使用一些代码

2个点  

post start:容器启动后钩子,容器启动之后会立即的执行,成功了,则启动,否则,会重启

prestop:容器终止前钩子,容器在删除之前执行,就是terming状态,会阻塞容器删除,执行成功了,就会删除

1、钩子处理器(三种方式定义动作)

exec命令:在容器内执行一次命令

用的最多的exec方式

lifecycle:
   podstart:
     exec:
       command:
        - cat
        - /tmp/healthy 

tcpsocket:在当前容器内尝试访问指定socket,在容器内部访问8080端口

lifecycle:
   podstart:
      tcpsocket:
         port:8080   #会尝试连接8080端口  

httpget:在当前容器中向某url发起http请求

lifecycle:
   poststart:
    httpGet:
     path: url地址
     port:   80
     host: 主机地址
     schme: HTTP 支持的协议  

案例:

apiVersion: v1
kind: Pod
metadata:
   name: pod-exec
   namespace: dev
spec:
   containers:
   - name: main-container
     image: nginx:1.17.1
     ports:
     - name: nginx-port
       containerPort: 80  #容器内部的端口,一般是service将公开pod端口,将pod端口映射到主机上面
     lifecycle:
       postStart:
         exec:   ###在启动的时候,执行一个命令,修改默认网页内容
            command: ["/bin/sh","-c","echo poststart > /usr/share/nginx/html/index.html"]
       preStop:
          exec:    ###停止容器的时候,-s传入一个参数,优雅的停止nginx服务
             command: ["/usr/sbin/nginx","-s","quit"]

[root@master ~]# kubectl create -f pod-exec.yaml 
pod/pod-exec created
[root@master ~]# kubectl get pods -n dev -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP           NODE    NOMINATED NODE   READINESS GATES
pod-exec   1/1     Running   0          53s   10.244.1.7   node1   <none>           <none>
pod-init   1/1     Running   0          27m   10.244.1.6   node1   <none>           <none>

访问一下pod里面容器的服务即可
格式为pod的ip+容器的端口
[root@master ~]# curl 10.244.1.7:80
poststart

5:容器探测  

主容器探测:用于检测容器中的应用实例是否正常的工作,是保障业务可用性的一种传统机制,如果经过了探测,实例的状态不符合预期,那么k8s就会把问题的实例摘除,不承担业务的流量,k8s提供了2种探针来实现容器探测,

分别是:

  liveness probes:存活性探针,用于检测应用实例,是否处于正常的运行状态,如果不是,k8s会重启容器;用于决定是否重启容器

  readiness probes:就绪性探针,用于检测应用实例是否可以接受请求,如果不能,k8s不会转发流量;nginx需要读取很多的web文件,在读取的过程中,service认为nginx已经成功了,如果有个请求的话,那么就无法提供了服务;所以就不会将请求转发到这里了

就是一个service来代理许多的pod,请求来到了pod,如果有一个pod出现了问题,如果没有了探针的话,就会出现了问题

作用

  1、找出这些出了问题的pod

  2、服务是否已经准备成功了

三种探测方式:

exec:退出码为0,则正常

livenessProbe
   exec:
     command:
       - cat
       - /tmp/healthy

tcpsocket:

livenessProbe:
    tcpSocket:
       port: 8080

httpget:

返回的状态码在200个399之间,则认为程序正常,否则不正常

livenessProbe:
    httpGet:
      path: /  url地址
       port:80  主机端口
       host:主机地址
       scheme:http
      

案例:

exec案例:

[root@master ~]# cat pod-live-exec.yaml 
apiVersion: v1
kind: Pod
metadata:
   name: pod-liveness-exec
   namespace: dev
spec:
   containers:
   - name: main-container
     image: nginx:1.17.1
     ports:
     - name: nginx-port
       containerPort: 80
     livenessProbe:
        exec:
          command: ["/bin/cat","/tmp/hello.txt"]   #由于没有这个文件,所以就会一直进行重启

#出现了问题,就会处于一直重启的状态
[root@master ~]# kubectl get pods -n dev
NAME                READY   STATUS    RESTARTS      AGE
pod-exec            1/1     Running   0             38m
pod-init            1/1     Running   0             65m
pod-liveness-exec   1/1     Running   2 (27s ago)   97s

#查看pod的详细信息
[root@master ~]# kubectl describe  pod -n dev pod-liveness-exec 
Events:
  Type     Reason     Age                 From               Message
  ----     ------     ----                ----               -------
  Normal   Scheduled  2m13s               default-scheduler  Successfully assigned dev/pod-liveness-exec to node2
  Normal   Pulling    2m12s               kubelet            Pulling image "nginx:1.17.1"
  Normal   Pulled     2m                  kubelet            Successfully pulled image "nginx:1.17.1" in 12.606s (12.606s including waiting)
  Normal   Created    33s (x4 over 2m)    kubelet            Created container main-container
  Normal   Started    33s (x4 over 2m)    kubelet            Started container main-container
  Warning  Unhealthy  33s (x9 over 113s)  kubelet            Liveness probe failed: /bin/cat: /tmp/hello.txt: No such file or directory
  Normal   Killing    33s (x3 over 93s)   kubelet            Container main-container failed liveness probe, will be restarted
  Normal   Pulled     33s (x3 over 93s)   kubelet            Container image "nginx:1.17.1" already present on machine

#一直在重启
[root@master ~]# kubectl get pods -n dev
NAME                READY   STATUS             RESTARTS      AGE
pod-exec            1/1     Running            0             39m
pod-init            1/1     Running            0             66m
pod-liveness-exec   0/1     CrashLoopBackOff   4 (17s ago)   2m57s


#一个正常的案例
[root@master ~]# cat pod-live-exec.yaml 
apiVersion: v1
kind: Pod
metadata:
   name: pod-liveness-exec
   namespace: dev
spec:
   containers:
   - name: main-container
     image: nginx:1.17.1
     ports:
     - name: nginx-port
       containerPort: 80
     livenessProbe:
        exec:
          command: ["/bin/ls","/tmp/"]
[root@master ~]# kubectl create -f pod-live-exec.yaml 
pod/pod-liveness-exec created

#就不会一直重启了
[root@master ~]# kubectl get pods -n dev
NAME                READY   STATUS    RESTARTS   AGE
pod-exec            1/1     Running   0          42m
pod-init            1/1     Running   0          69m
pod-liveness-exec   1/1     Running   0          56s

#查看详细的信息,发现没有错误

  

tcpsocket:  

[root@master ~]# cat tcp.yaml 
apiVersion: v1
kind: Pod
metadata:
   name: pod-liveness-tcp
   namespace: dev
spec:
   containers:
   - name: main-container
     image: nginx:1.17.1
     ports:
     - name: nginx-port
       containerPort: 80
     livenessProbe:
        tcpSocket:
           port: 8080    访问容器的8080端口


kubectl create -f tcp.yaml
#发现一直在进行重启,没有访问到8080端口
[root@master ~]# kubectl get pods -n dev
NAME               READY   STATUS    RESTARTS      AGE
pod-liveness-tcp   1/1     Running   5 (72s ago)   3m43s

#查看详细的信息
[root@master ~]# kubectl describe  pod -n dev pod-liveness-tcp  
Events:
  Type     Reason     Age                    From               Message
  ----     ------     ----                   ----               -------
  Normal   Scheduled  3m22s                  default-scheduler  Successfully assigned dev/pod-liveness-tcp to node2
  Normal   Pulled     112s (x4 over 3m22s)   kubelet            Container image "nginx:1.17.1" already present on machine
  Normal   Created    112s (x4 over 3m22s)   kubelet            Created container main-container
  Normal   Started    112s (x4 over 3m22s)   kubelet            Started container main-container
  Normal   Killing    112s (x3 over 2m52s)   kubelet            Container main-container failed liveness probe, will be restarted
  Warning  Unhealthy  102s (x10 over 3m12s)  kubelet            Liveness probe failed: dial tcp 1

正常的案例:

[root@master ~]# cat tcp.yaml 
apiVersion: v1
kind: Pod
metadata:
   name: pod-liveness-tcp
   namespace: dev
spec:
   containers:
   - name: main-container
     image: nginx:1.17.1
     ports:
     - name: nginx-port
       containerPort: 80
     livenessProbe:
        tcpSocket:
           port: 80 

#查看效果,没有任何的问题
[root@master ~]# kubectl describe  pods -n dev  pod-liveness-tcp 
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  27s   default-scheduler  Successfully assigned dev/pod-liveness-tcp to node2
  Normal  Pulled     28s   kubelet            Container image "nginx:1.17.1" already present on machine
  Normal  Created    28s   kubelet            Created container main-container
  Normal  Started    28s   kubelet            Started container main-container

httpget

[root@master ~]# cat tcp.yaml 
apiVersion: v1
kind: Pod
metadata:
   name: pod-liveness-http
   namespace: dev
spec:
   containers:
   - name: main-container
     image: nginx:1.17.1
     ports:
     - name: nginx-port
       containerPort: 80
     livenessProbe:
        httpGet:
           scheme: HTTP
           port: 80
           path: /hello   # http://127.0.0.1:80/hello


#发现一直在进行重启的操作
[root@master ~]# kubectl describe pod  -n dev  pod-liveness-http 
[root@master ~]# kubectl get pods -n dev
NAME                READY   STATUS    RESTARTS      AGE
pod-liveness-http   1/1     Running   1 (17s ago)   48s
pod-liveness-tcp    1/1     Running   0             4m21s

#正常的情况
[root@master ~]# cat tcp.yaml 
apiVersion: v1
kind: Pod
metadata:
   name: pod-liveness-http
   namespace: dev
spec:
   containers:
   - name: main-container
     image: nginx:1.17.1
     ports:
     - name: nginx-port
       containerPort: 80
     livenessProbe:
        httpGet:
           scheme: HTTP
           port: 80
           path: /
[root@master ~]# kubectl describe  pods -n dev pod-liveness-http 
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  21s   default-scheduler  Successfully assigned dev/pod-liveness-http to node1
  Normal  Pulled     22s   kubelet            Container image "nginx:1.17.1" already present on machine
  Normal  Created    22s   kubelet            Created container main-container
  Normal  Started    22s   kubelet            Started container main-container

容器探测补充

[root@master ~]# kubectl explain pod.spec.containers.livenessProbe
initialDelaySeconds	<integer>  容器启动后等待多少秒执行第一次探测
timeoutSeconds	<integer>   探测超时时间,默认是1秒,最小1秒
periodSeconds	<integer>   执行探测的频率,默认是10秒,最小是1秒
failureThreshold	<integer>    连续探测失败多少次后才被认为失败,默认是3,最小值是1
successThreshold	<integer>  连续探测成功多少次后才被认定为成功,默认是1

案例:

6:重启策略

就是容器探测出现了问题,k8s就会对容器所在的Pod进行重启,这个由pod的重启策略决定的,pod的重启策略有三种

  always:容器失效时,自动重启该容器,默认值

  onfailure:容器终止运行且退出码不为0时重启,异常终止

  never:不论状态为何,都不重启该容器

重启策略适用于Pod对象中的所有容器,首次需要重启的容器,将在需要时立即重启,随后再次需要重启的操作由kubelet延迟一段时间进行,且反复的重启操作的延迟时长为10S,20S,300s为最大的延迟时长

案例:

apiVersion: v1
kind: Pod
metadata:
   name: restart-pod
   namespace: dev
spec:
   containers:
   - name: main-container
     image: nginx:1.17.1
     ports:
     - name: nginx-port
       containerPort: 80
     livenessProbe:
        httpGet:
           scheme: HTTP
           port: 80
           path: /hello   # http://127.0.0.1:80/hello
   restartPolicy: Always

#会一直进行重启

#改为Never
容器监听失败了,就不会进行重启,直接停止了
状态是完成的状态,
[root@master ~]# kubectl get pods -n dev
NAME                READY   STATUS      RESTARTS      AGE
pod-liveness-http   1/1     Running     1 (16h ago)   16h
pod-liveness-tcp    1/1     Running     1 (22m ago)   16h
restart-pod         0/1     Completed   0             41s

[root@master ~]# kubectl describe  pod -n dev  restart-pod 

Events:
  Type     Reason     Age                From               Message
  ----     ------     ----               ----               -------
  Normal   Scheduled  84s                default-scheduler  Successfully assigned dev/restart-pod to node1
  Normal   Pulled     84s                kubelet            Container image "nginx:1.17.1" already present on machine
  Normal   Created    84s                kubelet            Created container main-container
  Normal   Started    84s                kubelet            Started container main-container
  Warning  Unhealthy  55s (x3 over 75s)  kubelet            Liveness probe failed: HTTP probe failed with statuscode: 404
  Normal   Killing    55s                kubelet            Stopping container main-container

三:pod调度

默认的情况下,一个Pod在哪个节点上面运行,是有scheduler组件采用相应的算法计算出来,这个过程是不受人工控制的,但是在实际中,这不满足需求,需要控制pod在哪个节点上面运行,这个就需要调度的规则了,四大类调度的方式

自动调度:经过算法自动的调度

定向调度:通过nodename属性(node的名字),nodeselector(标签)

亲和性调度:nodeAffinity(node的亲和性),podAffinity(pod的亲和性),podANtiAffinity(这个就是跟Pod的亲和性差,所以就去相反的一侧)

污点(容忍调度):站在node节点上面完成的,有一个污点,别人就不能在;容忍站在pod上面来说的,可以在node上面的污点进行就是容忍调度

1:定向调度

指定的是pod声明nodename,或者nodeselector,依次将pod调度到指定的node节点上面,这个是强制性的,即使node不存在,也会被调度,只不过是pod运行失败而已

1、nodename

强制的调度,直接跳过了scheduler的调度逻辑,直接将pod调度到指定的节点上面

[root@master ~]# cat pod-nodename.yaml 
apiVersion: v1
kind: Pod
metadata:
   name: pod-nodename
   namespace: dev
spec:
   containers:
   - name: main-container
     image: nginx:1.17.1
     ports:
   nodeName: node1

[root@master ~]# kubectl create  -f pod-nodename.yaml 
pod/pod-nodename created
#运行在node1上面运行
[root@master ~]# kubectl get pods -n dev -o wide
NAME                READY   STATUS    RESTARTS      AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pod-liveness-http   1/1     Running   1 (16h ago)   17h   10.244.2.8    node1   <none>           <none>
pod-liveness-tcp    1/1     Running   1 (42m ago)   17h   10.244.1.7    node2   <none>           <none>
pod-nodename        1/1     Running   0             41s   10.244.2.10   node1   <none>           <none>

#将节点改为不存在的,pod会失败而已
[root@master ~]# kubectl get pods -n dev -o wide
NAME                READY   STATUS    RESTARTS      AGE   IP           NODE    NOMINATED NODE   READINESS GATES
pod-liveness-http   1/1     Running   1 (16h ago)   17h   10.244.2.8   node1   <none>           <none>
pod-liveness-tcp    1/1     Running   1 (43m ago)   17h   10.244.1.7   node2   <none>           <none>
pod-nodename        0/1     Pending   0             9s    <none>       node3   <none>           <none>  

2、nodeselector

看的就是节点上面的标签,标签选择器,强制性的

[root@master ~]# kubectl label  nodes node1 nodeenv=pro
node/node1 labeled
[root@master ~]# kubectl label  nodes node2 nodeenv=test
node/node2 labeled
[root@master ~]# cat pod-selector.yaml 
apiVersion: v1
kind: Pod
metadata:
   name: pod-select
   namespace: dev
spec:
   containers:
   - name: main-container
     image: nginx:1.17.1
   nodeSelector:
       nodeenv: pro

[root@master ~]# kubectl get pods -n dev -o wide
NAME                READY   STATUS    RESTARTS      AGE     IP            NODE    NOMINATED NODE   READINESS GATES
pod-liveness-http   1/1     Running   1 (17h ago)   17h     10.244.2.8    node1   <none>           <none>
pod-liveness-tcp    1/1     Running   1 (51m ago)   17h     10.244.1.7    node2   <none>           <none>
pod-select          1/1     Running   0             2m16s   10.244.2.11   node1   <none>           <none>

#不存在的标签
改为pr1,调度失败
[root@master ~]# kubectl get pods -n dev
NAME                READY   STATUS    RESTARTS      AGE
pod-liveness-http   1/1     Running   1 (17h ago)   17h
pod-liveness-tcp    1/1     Running   1 (51m ago)   17h
pod-select          0/1     Pending   0             5s

2:亲和性调度

上面的问题,就是强制性的调度,就是如果没有节点的话,Pod就会调度失败

就是声明一个调度的节点,如果找到了,就调度,否则,找其他的;这个就是亲和性

  nodeAffinity:node的亲和性,以node为目标,主要就是标签()

  podAffinity:pod的亲和性,以pod为目标,就是以正在运行的pod为目标,就是一个web的pod需要和一个mysql的pod在一起,向其中一个打个标签,另外一个就会来找他

  podAntAffinity:pod的反亲和性,以pod为目标,讨厌和谁在一起,就选择其他的

 

场景的说明:

如果2个应用时频繁交互,那么就有必要利用亲和性让2个应用尽可能的靠近,这样就能减少因为网络通信带来的性能损耗了,调度到了pod1上面就都在一个节点上面,通信的性能就损耗减少了

 

反亲和性的应用:

当应用的采用多副本部署时,有必要采用反亲和性让各个应用实列打散分布在各个node上面,这样就能提高服务的高可用性

应用的功能是相同的,使用反亲和性,都分布在不同的节点上面,高可用性,就是坏了一个节点,其他的节点也能正常的提供工作

参数:

[root@master ~]# kubectl explain pod.spec.affinity.nodeAffinity

requiredDuringSchedulingIgnoredDuringExecution  node节点必须满足的指定的所有规划才可以,相当于硬限制
   nodeSelectorTerms:节点选择列表
       matchFields:按节点字段列出的节点选择器要求列表
       matchExpressions  按节点标签列出的节点选择器要求列表(标签)
         key:
         vaules:
         operator:关系符,支持in, not exists

如果有符合的条件,就调度,没有符合的条件就调度失败

preferredDuringSchedulingIgnoredDuringExecution 	<NodeSelector>  软限制,优先找这些满足的节点
    preference    一个节点选择器,以相应的权重相关联
            matchFields:按节点字段列出的节点选择器要求列表
            matchExpressions  按节点标签列出的节点选择器要求列表  
                 key:键
                 vaules:
                 operator:
    weight:倾向权重,1~100  ##就是倾向调度   
 

如果找不到的话,就从其他的节点调度上去

关系符
 - key:nodedev   匹配存在标签的key为noddev的节点
    operator: exists  
- key:  nodedev   匹配标签的key为nodedev,且vaule是xxx或者yyy的节点
   operator:in
   vaules:['xxx','yyy']    

  

1、nodeAffinity

node的亲和性,2大类,硬限制,软限制,节点上面的标签作为选择

[root@master ~]# cat pod-aff-re.yaml 
apiVersion: v1
kind: Pod
metadata:
   name: pod-aff
   namespace: dev
spec:
   containers:
   - name: main-container
     image: nginx:1.17.1
   affinity:
       nodeAffinity:   ##亲和性设置
          requiredDuringSchedulingIgnoredDuringExecution:  #设置node亲和性,硬限制
             nodeSelectorTerms:     
                  matchExpressions:     匹配nodeenv的值在[xxx,yyy]中的标签
                    - key: nodeenv
                      operator: In
                      vaules: ["xxx","yyy"] 
[root@master ~]# kubectl create -f pod-aff-re.yaml 
pod/pod-aff created
[root@master ~]# kubectl get pod -n dev
NAME                READY   STATUS    RESTARTS      AGE
pod-aff             0/1     Pending   0             23s
pod-liveness-http   1/1     Running   1 (17h ago)   18h
pod-liveness-tcp    1/1     Running   1 (94m ago)   18h
pod-select          0/1     Pending   0             43m

#调度失败

#值改为pro,就能在node1上面调度了
[root@master ~]# kubectl create -f pod-aff-re.yaml 
pod/pod-aff created
[root@master ~]# kubectl get pods -n dev
NAME                READY   STATUS    RESTARTS      AGE
pod-aff             1/1     Running   0             5s
pod-liveness-http   1/1     Running   1 (17h ago)   18h
pod-liveness-tcp    1/1     Running   1 (96m ago)   18h
pod-select          0/1     Pending   0             45m

  

软限制

#软限制
[root@master ~]# cat pod-aff-re.yaml 
apiVersion: v1
kind: Pod
metadata:
   name: pod-aff
   namespace: dev
spec:
   containers:
   - name: main-container
     image: nginx:1.17.1
   affinity:
     nodeAffinity:
       preferredDuringSchedulingIgnoredDuringExecution:   #软限制
       - weight: 1    
         preference:
            matchExpressions:
            - key: nodeenv
              operator: In
              values: ["xxx","yyy"] 

#直接调度在node2上面了
[root@master ~]# kubectl get pods -n dev -o wide
NAME                READY   STATUS    RESTARTS       AGE   IP           NODE     NOMINATED NODE   READINESS GATES
pod-aff             1/1     Running   0              41s   10.244.1.9   node2    <none>           <none>
pod-liveness-http   1/1     Running   1 (17h ago)    18h   10.244.2.8   node1    <none>           <none>
pod-liveness-tcp    1/1     Running   1 (102m ago)   18h   10.244.1.7   node2    <none>           <none>
pod-select          0/1     Pending   0              50m   <none>       <none>   <none>           <none>

 

注意:

如果同时定义了nodeSelector和nodeAffinity,那么必须满足这2个条件,pod才能在指定的node上面运行
如果nodeaffinity指定了多个nodeSelectorTerms,那么只要有一个能够匹配成功即可
如果一个nodeSelectorTerms中有多个matchExpressions,则一个节点必须满足所有的才能匹配成功
如果一个Pod所在node在pod运行期间标签发生了改变,不符合该pod的节点亲和性需求,则系统将忽略此变化

 这个调度就是只在调度的时候生效,所以的话,就是如果调度成功后,标签发生了变化,不会对这个pod进行什么样的变化

2、podAffinitly

就是以正在运行的pod为参照,硬限制和软限制

kubectl explain pod.spec.affinity.podAffinity

requiredDuringSchedulingIgnoredDuringExecution   硬限制
    namespace:指定参照pod的名称空间,如果不指定的话,默认的参照物pod就跟pod一眼的
    topologkey:调度的作用域,靠近到节点上,还是网段上面,操作系统了
                        ###hostname的话,就是以node节点为区分的范围,调度到node1的节点上面
                                os的话,就是以操作系统为区分的,调度到跟pod1操作系统上一样的
     labeSelector:标签选择器
          matchExpressions: 按节点列出的节点选择器要求列表
               key:
               vaules:
               operator:
          matchLbales:   指多个matchExpressions映射的内容
preferredDuringSchedulingIgnoredDuringExecution  软限制
    namespace:指定参照pod的名称空间,如果不指定的话,默认的参照物pod就跟pod一眼的
    topologkey:调度的作用域,靠近到节点上,还是网段上面,操作系统了
                        ###hostname的话,就是以node节点为区分的范围,调度到node1的节点上面
                                os的话,就是以操作系统为区分的,调度到跟pod1操作系统上一样的
     labeSelector:标签选择器
          matchExpressions: 按节点列出的节点选择器要求列表
               key:
               vaules:
               operator:
          matchLbales:   指多个matchExpressions映射的内容
    weight:倾向权重1~100

 

案例:

软亲和性:

apiVersion: v1
kind: Pod
metadata:   #元数据的信息
   name: pods-1   #pod的名字
   namespace: dev   #名称空间
spec:   
  containers:   #容器
    - name: my-tomcat   #镜像的名字
      image: tomcat    #拉取的镜像
      imagePullPolicy: IfNotPresent   #策略为远程和本地都有
  affinity:
     podAffinity:   #pod的亲和性
       preferredDuringSchedulingIgnoredDuringExecution:   #软限制
       - weight: 1    #权重为1
         podAffinityTerm:    #定义了具体的pod亲和性的条件
          labelSelector:    #标签选择器
             matchExpressions:   #一个或者多个标签匹配式
                 - key: user   #标签的键
                   operator: In   
                   values:    #标签的值
                      - "qqqq"
          topologyKey: kubernetes.io/hostname   #按照主机进行区分


就是这个pod会被调度到节点上面有pod,并且标签为user=qqqq这个节点上面去

 

硬亲和性:

apiVersion: v1
kind: Pod
metadata:
   name: pod-5
   namespace: dev
spec:
  containers:
    - name: my-tomcat
      image: tomcat
      imagePullPolicy: IfNotPresent
  affinity:
     podAffinity:
       requiredDuringSchedulingIgnoredDuringExecution:  #软限制
         - labelSelector:   #标签选择器
             matchExpressions:    #匹配列表
                 - key: user   
                   operator: In
                   values: ["qqqq"]   
           topologyKey: kubernetes.io/hostname    #按照主机来进行划分

  

  

3、反亲和性

就是不在这个pod上面进行调度,在另外的一个pod上面进行调度即可

案例:

[root@master mnt]# cat podaff.yaml 
apiVersion: v1
kind: Pod
metadata:
   name: podaff
   namespace: dev
spec:
   containers:
   - name: main-container
     image: nginx:1.17.1
   affinity:
     podAntiAffinity:
       requiredDuringSchedulingIgnoredDuringExecution:
       - labelSelector:
           matchExpressions:
           - key: podenv
             operator: In
             values: ["pro"]
         topologyKey: kubernets.io/hostname

发现在node2节点上面创建了
[root@master mnt]# kubectl get pods -n dev -o wide
NAME         READY   STATUS    RESTARTS   AGE     IP            NODE    NOMINATED NODE   READINESS GATES
pod-podaff   1/1     Running   0          61m     10.244.2.14   node1   <none>           <none>
podaff       1/1     Running   0          2m57s   10.244.1.12   node2   <none>           <none>

 3:污点(taints)

 前面都是站在pod的角度上面来进行配置的属性,那么就是可以站在node的节点上面,是否允许这些pod调度过来,这些在node上面的信息就是被称为了污点

就是一个拒绝的策略

污点作用:

  可以将拒绝Pod调度过来

  甚至还可以将已经存在的pod赶出去

污点的格式:

key=value:effect

key和value:是污点的标签,effect描述污点的作用

effect三种的选项为:

  PreferNoSchedule:k8s尽量避免把Pod调度到具有该污点的node上面,除非没有其他的节点可以调度了

  NoSchedule:k8s不会把pod调度到该具有污点node上面,但不会影响当前node上已经存在的pod

  NoExecue:k8s将不会把Pod调度该具有污点的node上面,同时也会将node已经存在的Pod驱离,一个pod也没有了

 设置污点:

#设置污点
[root@master mnt]# kubectl taint  nodes node1 key=vaule:effect

#去除污点
[root@master mnt]# kubectl taint  nodes node1 key:effect-

#去除所有的污点
[root@master mnt]# kubectl taint  nodes node1 key-

  

案例:

准备节点node1,先暂时停止node2节点
为node1节点一个污点,tag=heima:PreferNoSchedule;  然后创建pod1
修改node1节点设置一个污点;tag=heima:NoSchedule: 然后创建pod2,不在接收新的pod,原来的也不会离开
修改node1节点设置一个污点;tag=heima:NoExecute;然后创建pod3,pod3也不会被创建,都没有了pod了

#关掉node2节点即可

#设置node1污点
[root@master mnt]# kubectl taint  nodes node1 tag=heima:PreferNoSchedule
node/node1 tainted
#查看污点
[root@master mnt]# kubectl describe  nodes -n dev node1| grep heima
Taints:             tag=heima:PreferNoSchedule

#第一个pod可以进行运行
[root@master mnt]# kubectl run taint1 --image=nginx:1.17.1 -n dev
pod/taint1 created
[root@master mnt]# kubectl  get pods -n dev 
NAME         READY   STATUS        RESTARTS   AGE
pod-podaff   1/1     Running       0          90m
podaff       1/1     Terminating   0          31m
taint1       1/1     Running       0          6s

#修改node1的污点
[root@master mnt]# kubectl taint  nodes node1 tag=heima:PreferNoSchedule-
node/node1 untainted

[root@master mnt]# kubectl taint  nodes node1 tag=heima:NoSchedule
node/node1 tainted

#第一个正常的运行,第二个运行不了
[root@master mnt]# kubectl run taint2 --image=nginx:1.17.1 -n dev
pod/taint2 created
[root@master mnt]# kubectl get pods -n dev
NAME         READY   STATUS        RESTARTS   AGE
pod-podaff   1/1     Running       0          94m
podaff       1/1     Terminating   0          35m
taint1       1/1     Running       0          3m35s
taint2       0/1     Pending       0          3s

#第三种污点的级别
[root@master mnt]# kubectl taint  nodes node1 tag=heima:NoSchedule-
node/node1 untainted
设置级别
[root@master mnt]# kubectl taint  nodes node1 tag=heima:NoExecute
node/node1 tainted
#新的pod也会不能创建了
[root@master mnt]# kubectl run taint3 --image=nginx:1.17.1 -n dev
pod/taint3 created
[root@master mnt]# kubectl get pods -n dev
NAME     READY   STATUS        RESTARTS   AGE
podaff   1/1     Terminating   0          39m
taint3   0/1     Pending       0          4s

  

为什么创建pod的时候,不能往master节点上面进行调度了,因为有污点的作用

4、容忍

 容忍就是忽略,node上面有污点,但是pod上面有容忍,进行忽略,可以进行调度

 案例:

apiVersion: v1
kind: Pod
metadata:
   name: pod-aff
   namespace: dev
spec:
   containers:    
   - name: main-container
     image: nginx:1.17.1
   tolerations:     #添加容忍
   - key: "tag"    #要容忍的key
     operator: "Equal"     #操作符
     values: "heima"            #容忍的污点
     effect: "NoExecute"    #添加容忍的规划,这里必须和标记的污点规则相同

#首先创建一个没有容忍的pod,看能不能进行创建
#无法进行创建
[root@master mnt]# kubectl get pods -n dev
NAME      READY   STATUS        RESTARTS   AGE
pod-aff   0/1     Pending       0          6s
podaff    1/1     Terminating   0          55m

#有容忍的创建
[root@master mnt]# kubectl create -f to.yaml 
pod/pod-aff created
[root@master mnt]# kubectl get pods -n dev
NAME      READY   STATUS        RESTARTS   AGE
pod-aff   1/1     Running       0          3s
podaff    1/1     Terminating   0          57m

  

容忍的详细信息

Key:对应的容忍的污点的值,空意味着匹配的所有的键
value:对应着容忍的污点的值
operator:key-value的运算符,支持Equal和Exists(默认),对于所有的键进行操作,跟值就没有关系了
effect:对应的污点的effect,空意味着匹配所有的影响
tolerationSeconds    容忍的时间,当effect为NoExecute时生效,表示pod在node上停留的时间

  

 四:pod控制器

1、pod的控制器的介绍

1:pod的分类:

  自主式pod,k8s直接创建出来的pod,这种pod删除后就没有了。也不会重建

  控制器创建的pod,通过控制器创建的Pod,这种pod删除后,还会自动重建

作用

 pod控制器管理pod的中间层,使用了pod控制器后,我们需要告诉pod控制器,想要多少个pod即可,他会创建满足条件的pod并确保pod处于用户期望的状态,如果pod运行中出现了故障,控制器会基于策略重启或者重建pod

 

2:控制器类型

replicaSet:保证指定数量的pod运行支持数量变更

deployment:通过控制replicaSet来控制pod,支持滚动升级,版本回退的功能

horizontal pod autoscaler:可以根据集群负载均衡自动调整pod的数量

 

 2:控制器的详细介绍

replicaSet(rs)

:创建的数量的Pod能够正常的运行,会持续监听pod的运行状态

支持对pod数量的扩容缩容,

案例:副本数量

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: pc-replicaset   #pod控制器的名字
  namespace: dev  
spec:
   replicas: 3   #创建的pod的数量,
   selector:   #pod标签选择器规则,选择app=nginx-pod的pod的标签用来进行管理,用来管理pod上面有相同的标签
     matchLabels:    #标签选择器规则
      app: nginx-pod  
   template:   副本,也就是创建pod的模版
     metadata:    #pod元数据的信息
       labels:    #pod上面的标签
         app: nginx-pod    
     spec:    
       containers:   #容器里面的名字
         - name: nginx   
           image: nginx:1.17.1  


#查看控制器
[root@master ~]# kubectl get rs -n dev
NAME            DESIRED   CURRENT   READY   AGE
pc-replicaset   3         3         3       70s
RESIRED 期望的pod数量
CURRENT:当前有几个
READY:准备好提供服务的有多少

#查看pod
[root@master ~]# kubectl get rs,pods -n dev
NAME                            DESIRED   CURRENT   READY   AGE
replicaset.apps/pc-replicaset   3         3         3       2m31s

NAME                      READY   STATUS    RESTARTS      AGE
pod/pc-replicaset-448tq   1/1     Running   0             2m31s
pod/pc-replicaset-9tdhd   1/1     Running   0             2m31s
pod/pc-replicaset-9z64w   1/1     Running   0             2m31s
pod/pod-pod-affinity      1/1     Running   1 (47m ago)   12h  

案例2:实现扩缩容的pod

#编辑yaml文件 edit
[root@master ~]# kubectl edit rs -n dev pc-replicaset 
replicaset.apps/pc-replicaset edited
[root@master ~]# kubectl get pods -n dev
NAME                  READY   STATUS    RESTARTS      AGE
pc-replicaset-448tq   1/1     Running   0             10m
pc-replicaset-9tdhd   1/1     Running   0             10m
pc-replicaset-9z64w   1/1     Running   0             10m
pc-replicaset-q6ps9   1/1     Running   0             94s
pc-replicaset-w5krn   1/1     Running   0             94s
pc-replicaset-zx8gw   1/1     Running   0             94s
pod-pod-affinity      1/1     Running   1 (55m ago)   12h
[root@master ~]# kubectl get rs -n dev
NAME            DESIRED   CURRENT   READY   AGE
pc-replicaset   6         6         6       10m


#第二种方式
[root@master ~]# kubectl scale  rs -n dev pc-replicaset --replicas=2 -n dev
replicaset.apps/pc-replicaset scaled
[root@master ~]# kubectl get rs,pod -n dev 
NAME                            DESIRED   CURRENT   READY   AGE
replicaset.apps/pc-replicaset   2         2         2       12m

NAME                      READY   STATUS    RESTARTS      AGE
pod/pc-replicaset-448tq   1/1     Running   0             12m
pod/pc-replicaset-9tdhd   1/1     Running   0             12m
pod/pod-pod-affinity      1/1     Running   1 (57m ago)   12h

 

案例3、镜像的版本的升级

#编辑镜像的版本
[root@master ~]# kubectl edit rs -n dev pc-replicaset 
replicaset.apps/pc-replicaset edited
[root@master ~]# kubectl get rs -n dev pc-replicaset -o wide
NAME            DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES         SELECTOR
pc-replicaset   2         2         2       15m   nginx        nginx:1.17.2   app=nginx-pod

#命令来进行编辑,但是一般使用edit来进行编辑即可
[root@master ~]# kubectl get rs -n dev -o wide
NAME            DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES         SELECTOR
pc-replicaset   2         2         2       17m   nginx        nginx:1.17.1   app=nginx-pod

  

案例4、删除replicaSet

就是先删除pod再来删除控制器

#文件来进行删除
root@master ~]# kubectl delete -f replicas.yaml 
replicaset.apps "pc-replicaset" deleted
[root@master ~]# kubectl get rs -n dev
No resources found in dev namespace.

#命令来进行删除
[root@master ~]# kubectl delete rs -n dev pc-replicaset 
replicaset.apps "pc-replicaset" deleted
[root@master ~]# kubectl get rs -n dev
No resources found in dev namespace.  

deployment(deploy)  

支持所有的RS的功能

 

 

保留历史的版本,就是可以进行回退版本

滚动更新的策略

 更新策略:

案例:创建deployment

[root@master ~]# cat deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
   name: pc-deployment
   namespace: dev
spec:
   replicas: 3
   selector:
      matchLabels:
       app: nginx-pod
   template:
      metadata:
         labels:
           app: nginx-pod
      spec:
        containers:
        - name: nginx
          image: nginx:1.17.1
[root@master ~]# kubectl get deploy -n dev
NAME            READY   UP-TO-DATE   AVAILABLE   AGE
pc-deployment   3/3     3            3           53s

update:最新版本的pod数量
available:当前可用的pod的数量

#所以也会创建一个rs出来
[root@master ~]# kubectl get rs -n dev
NAME                       DESIRED   CURRENT   READY   AGE
pc-deployment-6cb555c765   3         3         3       2m9s  
扩缩容:

基本上和之前的一样的操作

#命令来进行编辑
[root@master ~]# kubectl scale deployment -n dev pc-deployment --replicas=5 
deployment.apps/pc-deployment scaled
[root@master ~]# kubectl get pods -n dev
NAME                             READY   STATUS    RESTARTS      AGE
pc-deployment-6cb555c765-8qc9g   1/1     Running   0             4m52s
pc-deployment-6cb555c765-8xss6   1/1     Running   0             4m52s
pc-deployment-6cb555c765-m7wdf   1/1     Running   0             4s
pc-deployment-6cb555c765-plkbf   1/1     Running   0             4m52s
pc-deployment-6cb555c765-qh6gk   1/1     Running   0             4s
pod-pod-affinity                 1/1     Running   1 (81m ago)   13h

#编辑文件
[root@master ~]# kubectl edit deployments.apps -n dev pc-deployment 
deployment.apps/pc-deployment edited
[root@master ~]# kubectl get pods -n dev
NAME                             READY   STATUS    RESTARTS      AGE
pc-deployment-6cb555c765-8qc9g   1/1     Running   0             5m41s
pc-deployment-6cb555c765-8xss6   1/1     Running   0             5m41s
pc-deployment-6cb555c765-plkbf   1/1     Running   0             5m41s
pod-pod-affinity                 1/1     Running   1 (82m ago)   13h

 

镜像更新

分为重建更新,滚动更新

重建更新

一次性删除所有的来老版本的pod,然后再来创建新版本的pod

滚动更新:(默认)

先删除一部分的内容,进行更新,老的版本越来越少,新的版本越来越多

 

#重建策略
#先创建pod,实时观看
[root@master ~]# cat deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
   name: pc-deployment
   namespace: dev
spec:
   strategy:
     type: Recreate
   replicas: 3
   selector:
      matchLabels:
       app: nginx-pod
   template:
      metadata:
         labels:
           app: nginx-pod
      spec:
        containers:
        - name: nginx
          image: nginx:1.17.1

[root@master ~]# kubectl get pods -n dev -w

#然后更新镜像的版本
[root@master ~]# kubectl set image deploy pc-deployment nginx=nginx:1.17.2 -n dev

#查看
pc-deployment-6cb555c765-m92t8   0/1     Terminating   0             60s
pc-deployment-6cb555c765-m92t8   0/1     Terminating   0             60s
pc-deployment-6cb555c765-m92t8   0/1     Terminating   0             60s
pc-deployment-5967bb44bb-bbkzz   0/1     Pending       0             0s
pc-deployment-5967bb44bb-bbkzz   0/1     Pending       0             0s
pc-deployment-5967bb44bb-kxrn5   0/1     Pending       0             0s
pc-deployment-5967bb44bb-zxfwl   0/1     Pending       0             0s
pc-deployment-5967bb44bb-kxrn5   0/1     Pending       0             0s
pc-deployment-5967bb44bb-zxfwl   0/1     Pending       0             0s
pc-deployment-5967bb44bb-bbkzz   0/1     ContainerCreating   0             0s
pc-deployment-5967bb44bb-kxrn5   0/1     ContainerCreating   0             0s
pc-deployment-5967bb44bb-zxfwl   0/1     ContainerCreating   0             0s
pc-deployment-5967bb44bb-kxrn5   1/1     Running             0             1s

  

滚动更新:

[root@master ~]# cat deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
   name: pc-deployment
   namespace: dev
spec:
   strategy:
     type: RollingUpdate
     rollingUpdate:
        maxUnavailable: 25%
        maxSurge: 25%
   replicas: 3
   selector:
      matchLabels:
       app: nginx-pod
   template:
      metadata:
         labels:
           app: nginx-pod
      spec:
        containers:
        - name: nginx
          image: nginx:1.17.1

#更新
[root@master ~]# kubectl set image deploy pc-deployment nginx=nginx:1.17.3 -n dev
deployment.apps/pc-deployment image updated

#就会更新
[root@master ~]# kubectl set image deploy pc-deployment nginx=nginx:1.17.3 -n dev
deployment.apps/pc-deployment image updated

 

 

总结:

镜像版本更新的话,会先创建一个新的RS,老RS也会存在,pod会在新的RS里面,老RS就会删除一个,到最后老的rs里面没有了pod,新的rs里面就会有pod了

留这个老的rs的作用的话,就是版本回退作用

 

版本回退:

 

undo回滚到上一个版本

#记录整个更新的deployment过程
[root@master ~]# kubectl create -f deploy.yaml --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/pc-deployment created
#更新版本就会有历史记录
[root@master ~]# kubectl edit deployments.apps  -n dev pc-deployment 
deployment.apps/pc-deployment edited

[root@master ~]# kubectl rollout history deployment -n dev pc-deployment 
deployment.apps/pc-deployment 
REVISION  CHANGE-CAUSE
1         kubectl create --filename=deploy.yaml --record=true
2         kubectl create --filename=deploy.yaml --record=true
3         kubectl create --filename=deploy.yaml --record=true

#直接回退到到指定的版本,如果不指定的话,默认是上一个版本

[root@master ~]# kubectl rollout undo deployment  -n dev  pc-deployment --to-revision=1
deployment.apps/pc-deployment rolled back   
#rs也发生了变化,pod回到了老的rs里面了
[root@master ~]# kubectl get rs -n dev
NAME                       DESIRED   CURRENT   READY   AGE
pc-deployment-5967bb44bb   0         0         0       4m11s
pc-deployment-6478867647   0         0         0       3m38s
pc-deployment-6cb555c765   3         3         3       5m28s
[root@master ~]# kubectl rollout  history deployment -n dev 
deployment.apps/pc-deployment 
REVISION  CHANGE-CAUSE
2         kubectl create --filename=deploy.yaml --record=true
3         kubectl create --filename=deploy.yaml --record=true
4         kubectl create --filename=deploy.yaml --record=true   #这个就相当于是1了

   

金丝雀发布:

deployment支持更新过程中的控制,暂停,继续更新操作

就是在更新的过程中,仅存在一部分的更新的应用,主机部分是一些旧的版本,将这些请求发送到新的应用上面,不能接收请求就赶紧回退,能接受请求,就继续更新,这个就被称为金丝雀发布

#更新,并且立刻暂停
[root@master ~]# kubectl set image deploy pc-deployment nginx=nginx:1.17.2 -n dev && kubectl rollout pause deployment  -n dev pc-deployment 
deployment.apps/pc-deployment image updated
deployment.apps/pc-deployment paused

#rs的变化
[root@master ~]# kubectl get rs -n dev
NAME                       DESIRED   CURRENT   READY   AGE
pc-deployment-5967bb44bb   1         1         1       21m
pc-deployment-6478867647   0         0         0       20m
pc-deployment-6cb555c765   3         3         3       22m

#有一个已经更新完毕了
[root@master ~]# kubectl rollout  status  deployment  -n dev
Waiting for deployment "pc-deployment" rollout to finish: 1 out of 3 new replicas have been updated...

#发送一个请求

#继续更新
[root@master ~]# kubectl rollout  resume deployment  -n dev pc-deployment 
deployment.apps/pc-deployment resumed

#查看状态
[root@master ~]# kubectl rollout  status  deployment  -n dev
Waiting for deployment "pc-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment spec update to be observed...
Waiting for deployment spec update to be observed...
Waiting for deployment "pc-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "pc-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "pc-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "pc-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "pc-deployment" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "pc-deployment" rollout to finish: 1 old replicas are pending termination...
deployment "pc-deployment" successfully rolled out

#查看rs
[root@master ~]# kubectl get rs -n dev
NAME                       DESIRED   CURRENT   READY   AGE
pc-deployment-5967bb44bb   3         3         3       24m
pc-deployment-6478867647   0         0         0       24m
pc-deployment-6cb555c765   0         0         0       26m  

 hpa控制器

 

 

总的来说就是,就是获取每个pod的利用率,与pod上面的hpa定义的指标进行比较,如果大于的话,就直接自动的增加pod,当访问量减少了话,会删除增加的pod

通过监控pod负载均衡的情况,实现pod数量的扩缩容

安装一个软件,拿到pod的负载

metries-server可以用来收集集群中的资源使用情况。pod。node都可以以进行监控

# 下载最新版配置软件包
wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.6.3/components.yaml

#到每台服务器上系在阿里云版本的相关版本
ctr image pull registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server:v0.6.3

#修改配置文件
containers:
- args:
  - --cert-dir=/tmp
  - --secure-port=4443
  - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
  - --kubelet-use-node-status-port
  - --metric-resolution=15s
  - --kubelet-insecure-tls  #增加证书忽略
  image: registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server:v0.6.3 #修改image为阿里云下载的这个

#应用下配置文件
kubectl apply -f   components.yaml

#查看执行结果
[root@master ~]# kubectl get pod -n kube-system 
NAME                              READY   STATUS    RESTARTS       AGE
coredns-66f779496c-88c5b          1/1     Running   33 (55m ago)   10d
coredns-66f779496c-hcpp5          1/1     Running   33 (55m ago)   10d
etcd-master                       1/1     Running   14 (55m ago)   10d
kube-apiserver-master             1/1     Running   14 (55m ago)   10d
kube-controller-manager-master    1/1     Running   14 (55m ago)   10d
kube-proxy-95x52                  1/1     Running   14 (55m ago)   10d
kube-proxy-h2qrf                  1/1     Running   14 (55m ago)   10d
kube-proxy-lh446                  1/1     Running   15 (55m ago)   10d
kube-scheduler-master             1/1     Running   14 (55m ago)   10d
metrics-server-6779c94dff-dflh2   1/1     Running   0              2m6s

 

查看资源的使用情况

#查看node的使用情况信息
[root@master ~]# kubectl top nodes
NAME     CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
master   104m         5%     1099Mi          58%       
node1    21m          1%     335Mi           17%       
node2    22m          1%     305Mi           16%       
#查看pod的使用情况
[root@master ~]# kubectl top pods -n dev
NAME        CPU(cores)   MEMORY(bytes)   
pod-aff     3m           83Mi            
pod-label   0m           1Mi     

 

实现这个hpa的操作,就是pod上面要有资源的限制才可以,

然后使用命令即可

 

测试:

 

[root@master ~]# cat deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
   name: nginx
   namespace: dev
spec:
   replicas: 1   #一个副本数量
   selector:
      matchLabels:
       app: nginx-pod    #标签选择器
   template:
      metadata:
         labels:
           app: nginx-pod
      spec:
        containers:
        - name: nginx
          image: nginx:1.17.1
          resources:
             requests:
               cpu: 100m   #最少需要100毫核才能启动


#创建deployment
kubectl create  -f deploy.yaml 
#创建service
kubectl expose deployment  nginx --type=NodePort --port=80 -n dev

#创建一个hpa
[root@master ~]# cat hpa.yaml 
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
   name: pc-hpa
   namespace: dev
spec:
   minReplicas: 1
   maxReplicas: 10
   targetCPUUtilizationPercentage: 3   #cpu的指标为%3,方便测试用的
   scaleTargetRef:  #选择的控制器
      apiVersion: apps/v1
      kind: Deployment   #deploy控制器
      name: nginx


#查看hpa控制器
[root@master ~]# kubectl get hpa -n dev
NAME     REFERENCE          TARGETS        MINPODS   MAXPODS   REPLICAS   AGE
pc-hpa   Deployment/nginx   <unknown>/3%   1         10        0          5s
[root@master ~]# kubectl get hpa -n dev
NAME     REFERENCE          TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
pc-hpa   Deployment/nginx   0%/3%     1         10        1          114s


#进行压力测试,就是超过%3
[root@master ~]# cat f.sh 
while `true`:
do
	curl 192.168.109.100:30843 &> /dev/null
done

[root@master ~]# kubectl get hpa -n dev -w
pc-hpa   Deployment/nginx   1%/3%     1         10        1          22m
pc-hpa   Deployment/nginx   0%/3%     1         10        1          22m
pc-hpa   Deployment/nginx   42%/3%    1         10        1          25m
pc-hpa   Deployment/nginx   92%/3%    1         10        4          25m
pc-hpa   Deployment/nginx   23%/3%    1         10        8          25m
pc-hpa   Deployment/nginx   0%/3%     1         10        10         26m

[root@master ~]# kubectl get deployment -n dev -w
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   1/1     1            1           39m
nginx   1/4     1            1           60m
nginx   1/4     1            1           60m
nginx   1/4     1            1           60m
nginx   1/4     4            1           60m
nginx   2/4     4            2           60m
nginx   3/4     4            3           60m
nginx   4/4     4            4           60m
nginx   4/8     4            4           60m
nginx   4/8     4            4           60m
nginx   4/8     4            4           60m
nginx   4/8     8            4           60m
nginx   5/8     8            5           60m
nginx   6/8     8            6           60m
nginx   7/8     8            7           60m
nginx   8/8     8            8           60m
nginx   8/10    8            8           61m
nginx   8/10    8            8           61m
nginx   8/10    8            8           61m
nginx   8/10    10           8           61m
nginx   9/10    10           9           61m
nginx   10/10   10           10          61m

[root@master ~]# kubectl get pod-n dev -w
nginx-7f89875f58-gt67w   0/1     Pending             0          0s
nginx-7f89875f58-gt67w   0/1     Pending             0          0s
nginx-7f89875f58-545rj   0/1     Pending             0          0s
nginx-7f89875f58-gt67w   0/1     ContainerCreating   0          0s
nginx-7f89875f58-545rj   0/1     Pending             0          0s
nginx-7f89875f58-545rj   0/1     ContainerCreating   0          0s
nginx-7f89875f58-545rj   1/1     Running             0          1s
nginx-7f89875f58-gt67w   1/1     Running             0          1s

#当访问量减少的时候,这个pod里面自动的减少,只不过需要一点时间  

daemonset(DS)控制器

 在每个节点上面创建一个副本(并且只能有一个),就是节点级别的,一般用于日志收集,节点监控等

当节点移除的话,自然Pod也就没有了

 

案例:

[root@master ~]# cat daemonset.yaml 
apiVersion: apps/v1
kind: DaemonSet
metadata:
   name: daemon
   namespace: dev
spec:
   selector:
      matchLabels:
        app: nginx-pod
   template:
        metadata:
          labels:
             app: nginx-pod
        spec:
          containers:
          - name: nginx
            image: nginx:1.17.1

[root@master ~]# kubectl get pod -n dev -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP             NODE    NOMINATED NODE   READINESS GATES
daemon-g8b4v             1/1     Running   0          2m30s   10.244.1.102   node2   <none>           <none>
daemon-t5tmd             1/1     Running   0          2m30s   10.244.2.89    node1   <none>           <none>
nginx-7f89875f58-prf9c   1/1     Running   0          79m     10.244.2.84    node1   <none>           <none>

#每个副本上面都有一个pod

  

job控制器

 批量处理(依次处理指定数量的任务),一次性任务(每个任务仅运行一次就结束)

由job创建的pod执行成功时,job会记录成功结束的Pod数量

当成功结束的pod达到指定的数量时,job将完成执行

里面的job都是存放的一次性文件

重启策略:在这里不能设置为always,因为这个是一次性任务,结束了,都要进行重启

只能设置为onfailure和never才行

onfailure:pod出现故障时,重启容器,不是创建pod,failed次数不变

never:出现故障,并且故障的pod不会消失也不会重启,failed次数=1

 

案例:

[root@master ~]# cat jod.yaml 
apiVersion: batch/v1
kind: Job
metadata:
   name: pc-job
   namespace: dev
spec:
   manualSelector: true
   completions: 6  #一次性创建6个pod
   parallelism: 3   #允许三个一起执行,2轮就结束了
   selector:
      matchLabels:
        app: counter-pod
   template:
        metadata:
          labels:
             app: counter-pod
        spec:
          restartPolicy: Never
          containers:
          - name: busybox
            image: busybox:1.30
            command: ["/bin/sh","-c","for i in 1 2 3 4 5 6 7 8 9;do echo $i;sleep 3;done"]

[root@master ~]# kubectl get job -n dev -w
NAME     COMPLETIONS   DURATION   AGE
pc-job   0/6                      0s
pc-job   0/6           0s         0s
pc-job   0/6           2s         2s
pc-job   0/6           29s        29s
pc-job   0/6           30s        30s
pc-job   3/6           30s        30s
pc-job   3/6           31s        31s
pc-job   3/6           32s        32s
pc-job   3/6           59s        59s
pc-job   3/6           60s        60s
pc-job   6/6           60s        60s
[root@master ~]# kubectl get pod -n dev -w
NAME                     READY   STATUS    RESTARTS   AGE
daemon-g8b4v             1/1     Running   0          20m
daemon-t5tmd             1/1     Running   0          20m
nginx-7f89875f58-prf9c   1/1     Running   0          97m
pc-job-z2gmb             0/1     Pending   0          0s
pc-job-z2gmb             0/1     Pending   0          0s
pc-job-z2gmb             0/1     ContainerCreating   0          0s
pc-job-z2gmb             1/1     Running             0          1s
pc-job-z2gmb             0/1     Completed           0          28s
pc-job-z2gmb             0/1     Completed           0          29s
pc-job-z2gmb             0/1     Completed           0          30s
pc-job-z2gmb             0/1     Completed           0          30s

cronjob控制器(cj)

 就是指定时间的周期执行job任务

 

案例:

[root@master ~]# cat cronjob.yaml 
apiVersion: batch/v1
kind: CronJob
metadata:
   name: pc-cronjob
   namespace: dev
   labels:
       controller: cronjob
spec:
    schedule: "*/1 * * * *"
    jobTemplate:
        metadata:
          name: pc-cronjob
          labels:
             controller: cronjob
        spec:
          template:
              spec:
                restartPolicy: Never
                containers:
                - name: counter
                  image: busybox:1.30
                  command: ["/bin/sh","-c","for i in 1 2 3 4 5 6 7 8 9;do echo$i;sleep 3;done"]

[root@master ~]# kubectl get job -n dev -w
NAME                  COMPLETIONS   DURATION   AGE
pc-cronjob-28604363   0/1           21s        21s
pc-job                6/6           60s        33m
pc-cronjob-28604363   0/1           28s        28s
pc-cronjob-28604363   0/1           29s        29s
pc-cronjob-28604363   1/1           29s        29s
pc-cronjob-28604364   0/1                      0s
pc-cronjob-28604364   0/1           0s         0s
pc-cronjob-28604364   0/1           1s         1s
pc-cronjob-28604364   0/1           29s        29s
pc-cronjob-28604364   0/1           30s        30s
pc-cronjob-28604364   1/1           30s        30s
^C[root@master ~]# 

[root@master ~]# kubectl get pod -n dev -w
NAME                     READY   STATUS      RESTARTS   AGE
daemon-g8b4v             1/1     Running     0          57m
daemon-t5tmd             1/1     Running     0          57m
nginx-7f89875f58-prf9c   1/1     Running     0          134m
pc-job-2p6p6             0/1     Completed   0          32m
pc-job-62z2d             0/1     Completed   0          32m
pc-job-6sm97             0/1     Completed   0          32m
pc-job-97j4j             0/1     Completed   0          31m
pc-job-lsjz5             0/1     Completed   0          31m
pc-job-pt28s             0/1     Completed   0          31m


[root@master ~]# kubectl get pod -n dev -w
pc-cronjob-28604363-fcnvr   0/1     Pending     0          0s
pc-cronjob-28604363-fcnvr   0/1     Pending     0          0s
pc-cronjob-28604363-fcnvr   0/1     ContainerCreating   0          0s
pc-cronjob-28604363-fcnvr   1/1     Running             0          0s
pc-cronjob-28604363-fcnvr   0/1     Completed           0          27s
pc-cronjob-28604363-fcnvr   0/1     Completed           0          29s
pc-cronjob-28604363-fcnvr   0/1     Completed           0          29s

#就是这个job执行结束后,每隔1分钟再去执行 

四:service详解

 流量负载组件service和ingress

serverice用于四层的负载ingress用于七层负载

1、service介绍

 pod有一个ip地址,但是不是固定的,所以的话,service就是一部分的pod的代理,有一个ip地址,可以通过这个地址来进行访问pod

service就是一个标签选择器的机制

 kube-proxy代理

 核心就是kube-proxy机制发生的作用,当创建service时,api-server向etcd存储service相关的信息,kube-proxy监听到发生了变化,就会将service相关的信息转换为访问规则

查看规则

 

kube-proxy支持的三种模式

userspace模式:用户空间模式

 kube-proxy会为每一个service创建一个监听的端口,发给service的ip的请求会被iptables规则重定向到kube-proxy监听的端口上,kube-proxy根据算法选择一个提供服务的pod并建立连接,以将请求转发到pod上

kube-proxy相当于一个负载均衡器的样子

 缺点:效率比较低,进行转发处理时,增加内核和用户空间

 

iptables模式

 

当请求来的时候,不经过了kube-proxy了,经过clusterip(规则即可),然后进行轮询(随机)转发到pod上面

缺点:没有负载均衡,一但又问题,用户拿到的就是错误的页面

 

ipvs模式:

 

 

 

 开启ipvs模块

编辑里面的配置文件为mode为ipvs
[root@master /]# kubectl edit cm kube-proxy -n kube-system 
#删除里面的pod,带有标签的
[root@master /]# kubectl delete pod -l k8s-app=kube-proxy -n kube-system
root@master /]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  172.17.0.1:30203 rr  轮询的规则,就是将地址转发到这里面去即可
  -> 10.244.2.103:80              Masq    1      0          0         
TCP  192.168.109.100:30203 rr
  -> 10.244.2.103:80              Masq    1      0          0         
TCP  10.96.0.1:443 rr
  -> 192.168.109.100:6443         Masq    1      0          0         
TCP  10.96.0.10:53 rr
  -> 10.244.0.44:53               Masq    1      0          0         
  -> 10.244.0.45:53               Masq    1      0          0         
TCP  10.96.0.10:9153 rr
  -> 10.244.0.44:9153             Masq    1      0          0         
  -> 10.244.0.45:9153             Masq    1      0          0         
TCP  10.100.248.78:80 rr
  -> 10.244.2.103:80              Masq    1      0          0         
TCP  10.110.118.76:443 rr
  -> 10.244.1.108:10250           Masq    1      0          0         
  -> 10.244.2.102:10250           Masq    1      0          0         
TCP  10.244.0.0:30203 rr

2:service类型

标签选择器只是一个表象,本质就是规则,通过标签,来进行确定里面的pod的ip

session亲和性,如果不配置的话,请求会将轮询到每一个pod上面,特殊的情况下,将多个请求发送到同一个pod上面,就需要session亲和性 

type:就是service类型

  ClusterIP:默认值,k8s自动分配的虚拟ip,只能在集群内部访问

  NodePort:将service通过指定的node上面端口暴露给外部,可以实现集群外面访问服务,节点上面的端口暴露给外部

  LoadBalancer:使用外接负载均衡器完成到服务的负载分发,注意此模式需要外部云环境

  ExternalName:把集合外部的服务引入集群内部,直接使用

 

1、环境准备

 

三个pod。deploy控制器来创建,  

[root@master ~]# cat service-example.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
   name: pc-deployment
   namespace: dev
spec:
   replicas: 3
   selector:
       matchLabels:
          app: nginx-pod
   template:
       metadata:
         labels:
           app: nginx-pod
       spec:
          containers:
          - name: nginx
            image: nginx:1.17.1
            ports:
            - containerPort: 80
[root@master ~]# kubectl get pod -n dev -o wide
NAME                             READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
pc-deployment-5cb65f68db-959hm   1/1     Running   0          62s   10.244.2.104   node1   <none>           <none>
pc-deployment-5cb65f68db-h6v8r   1/1     Running   0          62s   10.244.1.110   node2   <none>           <none>
pc-deployment-5cb65f68db-z4k2f   1/1     Running   0          62s   10.244.2.105   node1   <none>           <none>
#访问pod的ip和容器里面的端口
[root@master ~]# curl 10.244.2.104:80

修改里面的网页文件,观察请求发送到哪一个节点上面去了,依次修改网页文件即可
[root@master ~]# kubectl exec -ti -n dev pc-deployment-5cb65f68db-h6v8r  /bin/bash
root@pc-deployment-5cb65f68db-z4k2f:/# echo 10.244.2.10 > /usr/share/nginx/html/index.html  

 2、ClusterIP类型的service

 service的端口可以随便写

[root@master ~]# cat ClusterIP.yaml 
apiVersion: v1
kind: Service
metadata:
   name: service-clusterip
   namespace: dev
spec:
   selector:   #service标签选择器
     app: nginx-pod
   clusterIP: 10.96.0.100   #不写的话,默认生成一个ip地址
   type: ClusterIP
   ports:
   - port: 80  #service端口
     targetPort: 80  #pod的端口

[root@master ~]# kubectl create -f ClusterIP.yaml 
service/service-clusterip created

[root@master ~]# kubectl get svc -n dev
NAME                TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
service-clusterip   ClusterIP   10.96.0.100   <none>        80/TCP    2m7s
#查看service的详细的信息,
[root@master ~]# kubectl describe svc service-clusterip -n dev
Name:              service-clusterip
Namespace:         dev
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx-pod
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.96.0.100
IPs:               10.96.0.100
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.110:80,10.244.2.104:80,10.244.2.105:80   #建立pod和service的关联,主要是标签选择器,里面都是记录的Pod的访问地址,实际端点服务的集合
Session Affinity:  None
Events:            <none>
[root@master ~]# kubectl get pod -n dev -o wide
NAME                             READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
pc-deployment-5cb65f68db-959hm   1/1     Running   0          25m   10.244.2.104   node1   <none>           <none>
pc-deployment-5cb65f68db-h6v8r   1/1     Running   0          25m   10.244.1.110   node2   <none>           <none>
pc-deployment-5cb65f68db-z4k2f   1/1     Running   0          25m   10.244.2.105   node1   <none>           <none>

[root@master ~]# kubectl get endpoints -n dev
NAME                ENDPOINTS                                         AGE
service-clusterip   10.244.1.110:80,10.244.2.104:80,10.244.2.105:80   4m48s

真正起作用的就是kube-proxy,创建service的时,会创建对应的规则
[root@master ~]# ipvsadm -Ln
TCP  10.96.0.100:80 rr
  -> 10.244.1.110:80              Masq    1      0          0         
  -> 10.244.2.104:80              Masq    1      0          0         
  -> 10.244.2.105:80              Masq    1      0          0     

#发送一个请求,测试是谁接收了,循环访问,发现是轮询环的状态
[root@master ~]# while true;do curl 10.96.0.100:80; sleep 5;done;
10.244.2.105
10.244.2.104
 10.244.1.110
10.244.2.105
10.244.2.104
 10.244.1.110 

访问service的ip和主机端口

负载分发策略:(session亲和性)

默认的话,访问就是轮询或者随机

有设置的话,就是多个请求到同一个pod里面上面,就不会轮训或者随机

#设置session亲和性
[root@master ~]# cat ClusterIP.yaml 
apiVersion: v1
kind: Service
metadata:
   name: service-clusterip
   namespace: dev
spec:
   sessionAffinity: ClientIP   #就是通过哟个请求到同一个节点上面
   selector:
     app: nginx-pod
   clusterIP: 10.96.0.100
   type: ClusterIP
   ports:
   - port: 80
     targetPort: 80

[root@master ~]# kubectl get svc -n dev
NAME                TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
service-clusterip   ClusterIP   10.96.0.100   <none>        80/TCP    78s
[root@master ~]# ipvsadm -Ln
TCP  10.96.0.100:80 rr persistent 10800   持久化
  -> 10.244.1.112:80              Masq    1      0          0         
  -> 10.244.2.107:80              Masq    1      0          0         
  -> 10.244.2.108:80              Masq    1      0          0         

这种类型的service,只能通过集群节点来进行访问,就是内部进行访问,自己的电脑访问不了这个ip
[root@master ~]# curl 10.96.0.100:80
10.244.2.108
[root@master ~]# curl 10.96.0.100:80
10.244.2.108
[root@master ~]# curl 10.96.0.100:80
10.244.2.108

3、headliness类型的service

Cluster类型的service,默认是随机的负载均衡分发策略,希望自己来控制这个策略,使用headliness类型的service,不会分发Clusterip。想要访问service,只能通过service的域名来进行访问

[root@master ~]# cat headliness.yaml 
apiVersion: v1
kind: Service
metadata:
   name: service-headliness
   namespace: dev
spec:
   selector:
     app: nginx-pod
   clusterIP: None   #设置为None,就能生成headliness类型的service
   type: ClusterIP
   ports:
   - port: 80
     targetPort: 80
[root@master ~]# kubectl get svc -n dev
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service-headliness   ClusterIP   None         <none>        80/TCP    4s

#查看域名
[root@master ~]# kubectl exec -ti -n dev pc-deployment-5cb65f68db-959hm /bin/bash
root@pc-deployment-5cb65f68db-959hm:/# cat /etc/resolv.conf 
search dev.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.96.0.10
options ndots:5


#访问headliness类型的service
#格式为dns服务器,加上service的名字,名称空间,等;; ANSWER SECTION:
[root@master ~]# dig @10.96.0.10 service-headliness.dev.svc.cluster.local 
service-headliness.dev.svc.cluster.local. 30 IN	A 10.244.2.108
service-headliness.dev.svc.cluster.local. 30 IN	A 10.244.1.112
service-headliness.dev.svc.cluster.local. 30 IN	A 10.244.2.107

4、NodePort类型的service

 就是将service的port映射到node节点上面,通过nodeip+node端口来实现访问service

 请求来到node的端口上面时,会将请求发送到service的端口上面,再来发送到pod上面的端口,实现访问

就将service暴露到外部了

测试:

[root@master ~]# cat nodeport.yaml 
apiVersion: v1
kind: Service
metadata:
   name: service-clusterip
   namespace: dev
spec:
   selector:
     app: nginx-pod
   type: NodePort   #NodePort类型的service
   ports:
   - port: 80    #service端口
     targetPort: 80   #pod端口
     nodePort: 30002   默认在一个·1范围内
[root@master ~]# kubectl create -f nodeport.yaml 
service/service-clusterip created
[root@master ~]# kubectl get svc -n dev
NAME                TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service-clusterip   NodePort   10.106.183.217   <none>        80:30002/TCP   4s

#访问节点ip+端口就能映射到Clusterip+端口了
[root@master ~]# curl 192.168.109.100:30002
10.244.2.108
[root@master ~]# curl 192.168.109.101:30002
10.244.2.108
[root@master ~]# curl 192.168.109.102:30002
10.244.2.108

就能实现访问了service,以及内部了pod了 

5、LoadBalancer类型的service

 就是在nodeport的基础上面添加了一个负载均衡的设备,经过计算后得出

6、ExternalName类型的service 

 将这个这个服务引入www.baidu.com这个服务

[root@master ~]# cat service-external.yaml 
apiVersion: v1
kind: Service
metadata:
   name: service-externalname
   namespace: dev
spec:
   type: ExternalName
   externalName: www.baidu.com
[root@master ~]# kubectl create -f service-external.yaml 
service/service-externalname created
[root@master ~]# kubectl get svc -n dev
NAME                   TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)        AGE
service-clusterip      NodePort       10.106.183.217   <none>          80:30002/TCP   17m
service-externalname   ExternalName   <none>           www.baidu.com   <none>         7s

#访问service
[root@master ~]# dig @10.96.0.10 service-externalname.dev.svc.cluster.local
service-externalname.dev.svc.cluster.local. 30 IN CNAME	www.baidu.com.
www.baidu.com.		30	IN	CNAME	www.a.shifen.com.
www.a.shifen.com.	30	IN	A	180.101.50.188
www.a.shifen.com.	30	IN	A	180.101.50.242

#这样就能解析到了

 3:Ingress介绍

service对外暴露服务主要就是2种类型的,NodePort和LoadBalancer

缺点:

  NodePort暴露的是主机的端口,当集群服务很多的时候,这个端口就会更多

  LB方式就是每一个service都需要LB,浪费

 

 

 用户定义这个请求到service的规则,然后ingress控制器感知将其转换为nginx配置文件,然后动态更新到nginx-proxy里面去即可,这个过程是动态的

1、环境的准备

#下载yaml文件
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.1/deploy/static/provider/cloud/deploy.yaml

[root@master ingress-example]# kubectl get pod,svc -n ingress-nginx 
NAME                                           READY   STATUS      RESTARTS   AGE
pod/ingress-nginx-admission-create-jv5n5       0/1     Completed   0          77s
pod/ingress-nginx-admission-patch-tpfv6        0/1     Completed   0          77s
pod/ingress-nginx-controller-597dc6d68-rww45   1/1     Running     0          77s

NAME                                         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
service/ingress-nginx-controller             NodePort    10.97.10.122   <none>        80:30395/TCP,443:32541/TCP   78s
service/ingress-nginx-controller-admission   ClusterIP   10.96.17.67    <none>        443/TCP

  

service和deployment文件,创建2个service和6个pod

[root@master ~]# cat deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
   name: nginx-deployment
   namespace: dev
spec:
   replicas: 3
   selector:
      matchLabels:
       app: nginx-pod
   template:
      metadata:
         labels:
           app: nginx-pod
      spec:
        containers:
        - name: nginx
          image: nginx:1.17.1
          ports:
          - containerPort: 80
---

apiVersion: apps/v1
kind: Deployment
metadata:
   name: tomcat-deployment
   namespace: dev
spec:
   replicas: 3
   selector:
      matchLabels:
       app: tocmat-pod
   template:
      metadata:
         labels:
           app: tocmat-pod
      spec:
        containers:
        - name: tomcat
          image: tomcat:8.5-jre10-slim
          ports:
          - containerPort: 8080
---

apiVersion: v1
kind: Service
metadata:
   name: nginx-service
   namespace: dev
spec:
   selector:
     app: nginx-pod
   clusterIP: None
   type: ClusterIP
   ports:
   - port: 80
     targetPort: 80
---


apiVersion: v1
kind: Service
metadata:
   name: tomcat-service
   namespace: dev
spec:
   selector:
     app: tomcat-pod
   type: ClusterIP
   clusterIP: None
   ports:
   - port: 8080
     targetPort: 8080

[root@master ~]# kubectl get deployments.apps,pod -n dev
NAME                                READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment    3/3     3            3           86s
deployment.apps/tomcat-deployment   3/3     3            3           86s

NAME                                     READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-5cb65f68db-5lzpb    1/1     Running   0          86s
pod/nginx-deployment-5cb65f68db-75h4m    1/1     Running   0          86s
pod/nginx-deployment-5cb65f68db-nc8pj    1/1     Running   0          86s
pod/tomcat-deployment-5dbff496f4-6msb2   1/1     Running   0          86s
pod/tomcat-deployment-5dbff496f4-7wjc9   1/1     Running   0          86s
pod/tomcat-deployment-5dbff496f4-wlgmm   1/1     Running   0          86s

2、http代理 

 创建一个yaml文件就是里面,

 

 访问的就是域名+path 如果path是/xxx的话,访问要带上域名/xxx

 访问的时候,就会将其转发到对应的service加上端口上面即可

3、https代理

 密钥要提前的生成