三、K8s详解-Pod、Pod控制器、Service详解

一、Pod详解

1、pod定义

下面包括了pod的常用特性配置,让我们一一解答吧。

apiVersion: v1     #必选,版本号,例如v1
kind: Pod         #必选,资源类型,例如 Pod
metadata:         #必选,元数据
  name: string     #必选,Pod名称
  namespace: string  #Pod所属的命名空间,默认为"default"
  labels:           #自定义标签列表
    - name: string                 
spec:  #必选,Pod中容器的详细定义
  containers:  #必选,Pod中容器列表
  - name: string   #必选,容器名称
    image: string  #必选,容器的镜像名称
    imagePullPolicy: [ Always|Never|IfNotPresent ]  #获取镜像的策略 
    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    #端口协议,支持TCPUDP,默认TCP
    env:   #容器运行前需设置的环境变量列表
    - name: string  #环境变量名称
      value: string #环境变量的值
    resources: #资源限制和请求的设置
      limits:  #资源限制的设置
        cpu: string     #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
        memory: string  #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
      requests: #资源请求的设置
        cpu: string    #Cpu请求,容器启动的初始可用数量
        memory: string #内存请求,容器启动的初始可用数量
    lifecycle: #生命周期钩子
        postStart: #容器启动后立即执行此钩子,如果执行失败,会根据重启策略进行重启
        preStop: #容器终止前执行此钩子,无论结果如何,容器都会终止
    livenessProbe:  #对Pod内各容器健康检查的设置,当探测无响应几次后将自动重启该容器
      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          #对容器健康检查探测等待响应的超时时间,单位秒,默认1periodSeconds: 0           #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
       successThreshold: 0
       failureThreshold: 0
       securityContext:
         privileged: false
  restartPolicy: [Always | Never | OnFailure]  #Pod的重启策略
  nodeName: <string> #设置NodeName表示将该Pod调度到指定到名称的node节点上
  nodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上
  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的存储卷,挂载集群与定义的secret对象到容器内部
      scretname: string  
      items:     
      - key: string
        path: string
    configMap:         #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
      name: string
      items:
      - key: string
        path: string

2、pod配置

1、pod基本配置

下面定义了一个比较简单Pod的配置,里面有一个nginx容器。

apiVersion: v1
kind: Pod
metadata:
  name: pod-base
  namespace: dev
  labels:
    user: zhanggang
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1

2、pod镜像拉取策略

imagePullPolicy,用于设置镜像拉取策略,k8s支持配置三种拉取策略:

  • 1、Always:总是从远程仓库拉取镜像(一直远程下载)
  • 2、IfNotPresent:本地有则使用本地镜像,本地没有则从远程仓库拉取镜像(本地有就本地 本地没远程下载)
  • 3、Never:只使用本地镜像,从不去远程仓库拉取,本地没有就报错 (一直使用本地)

镜像拉取策略默认值说明

1、如果镜像tag为具体版本号, 默认策略是:IfNotPresent
2、如果镜像tag为:latest(最新版本) ,默认策略是always

3、pod启动命令

command,用于在pod中的容器初始化完毕之后运行一个命令。

command: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3; done;"]


"/bin/sh","-c", 使用sh执行命令

touch /tmp/hello.txt; 创建一个/tmp/hello.txt 文件

while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3; done; 每隔3秒向文件中写入当前时间

3、pod环境变量

env,环境变量,用于在pod中的容器设置环境变量。
这种方式不是很推荐,推荐将这些配置单独存储在配置文件中,这种方式将在后面介绍。

apiVersion: v1
kind: Pod
metadata:
  name: pod-env
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
    command: ["/bin/sh","-c","while true;do /bin/echo $(date +%T);sleep 60; done;"]
    env: # 设置环境变量列表
    - name: "username"
      value: "admin"
    - name: "password"
      value: "123456"

4、pod容器端口设置

容器的端口,也就是设置该容器暴露的端口。

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

5、pod容器资源配额

容器中的程序要运行,肯定是要占用一定资源的,比如cpu和内存等,如果不对某个容器的资源做限制,那么它就可能吃掉大量资源,导致其它容器无法运行。针对这种情况,kubernetes提供了对内存和cpu的资源进行配额的机制,这种机制主要通过resources选项实现。

limits:用于限制运行时容器的最大占用资源,当容器占用资源超过limits时会被终止,并进行重启。
requests :用于设置容器需要的最小资源,如果环境资源不够,容器将无法启动。
cpu:core数,可以为整数或小数。
memory: 内存大小,可以使用Gi、Mi、G、M等形式。

apiVersion: v1
kind: Pod
metadata:
  name: pod-resources
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
    resources: # 资源配额
      limits:  # 限制资源(上限)
        cpu: "2" # CPU限制,单位是core数
        memory: "10Gi" # 内存限制
      requests: # 请求资源(下限)
        cpu: "1"  # CPU限制,单位是core数
        memory: "10Mi"  # 内存限制

2、Pod生命周期

我们一般将pod对象从创建至终的这段时间范围称为pod的生命周期,它主要包含下面的过程:

容器启动后钩子(post start)、容器终止前钩子(pre stop)。
容器的存活性探测(liveness probe)、就绪性探测(readiness probe)。

在这里插入图片描述

在整个生命周期中,Pod会出现5种状态(相位),分别如下:

1、挂起(Pending):apiserver已经创建了pod资源对象,但它尚未被调度完成或者仍处于下载镜像的过程中
2、运行中(Running):pod已经被调度至某节点,并且所有容器都已经被kubelet创建完成
3、成功(Succeeded):pod中的所有容器都已经成功终止并且不会被重启
4、失败(Failed):所有容器都已经终止,但至少有一个容器终止失败,即容器返回了非0值的退出状态
5、未知(Unknown):apiserver无法正常获取到pod对象的状态信息,通常由网络通信失败所导致

1、pod的创建过程

1、用户通过kubectl或其他api客户端提交需要创建的pod信息给apiServer

2、apiServer开始生成pod对象的信息,并将信息存入etcd,然后返回确认信息至客户端

3、apiServer开始反映etcd中的pod对象的变化,其它组件使用watch机制来跟踪检查apiServer上的变动

4、scheduler发现有新的pod对象要创建,开始为Pod分配主机并将结果信息更新至apiServer

5、node节点上的kubelet发现有pod调度过来,尝试调用docker启动容器,并将结果回送至apiServer

6、apiServer将接收到的pod状态信息存入etcd中

在这里插入图片描述

2、pod的终止过程

1、用户向apiServer发送删除pod对象的命令
2、apiServcer中的pod对象信息会随着时间的推移而更新,在宽限期内(默认30s),pod被视为dead
3、将pod标记为terminating状态
4、kubelet在监控到pod对象转为terminating状态的同时启动pod关闭过程
5、端点控制器监控到pod对象的关闭行为时将其从所有匹配到此端点的service资源的端点列表中移除
6、如果当前pod对象定义了preStop钩子处理器,则在其标记为terminating后即会以同步的方式启动执行
7、pod对象中的容器进程收到停止信号
8、宽限期结束后,若pod中还存在仍在运行的进程,那么pod对象会收到立即终止的信号
9、kubelet请求apiServer将此pod资源的宽限期设置为0从而完成删除操作,此时pod对于用户已不可见

3、初始化容器

pod中引入了初始化容器概念,初始化容器是在pod的主容器启动之前要运行的容器,主要是做一些主容器的前置工作,它具有两大特征:
1、初始化容器必须运行完成直至结束,若某初始化容器运行失败,那么kubernetes需要重启它直到成功完成
2、初始化容器必须按照定义的顺序执行,当且仅当前一个成功之后,后面的一个才能运行

列举初始化容器使用场景:
1、提供主容器镜像中不具备的工具程序或自定义代码
2、初始化容器要先于应用容器串行启动并运行完成,因此可用于延后应用容器的启动直至其依赖的条件得到满足。


初始化容器案例

假设要以主容器来运行nginx,但是要求在运行nginx之前先要能够连接上mysql和redis所在服务器。
创建pod-initcontainer.yaml,内容如下:
下面两个初始化容器所连接的IP都不存在,可以发现Pod是起不来的。

apiVersion: v1
kind: Pod
metadata:
  name: pod-initcontainer
  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', 'until ping 192.168.90.14 -c 1 ; do echo waiting for mysql...; sleep 2; done;']
  - name: test-redis
    image: busybox:1.30
    command: ['sh', '-c', 'until ping 192.168.90.15 -c 1 ; do echo waiting for reids...; sleep 2; done;']

4、钩子函数

什么是钩子函数呢?就是在主容器的启动之后和停止之前提供的两个函数。

  • post start:容器创建之后执行,如果失败了会重启容器 。
  • pre stop :容器终止之前执行,执行完成之后容器将成功终止,在其完成之前会阻塞删除容器的操作。

钩子处理器支持使用下面三种方式定义动作:

1、Exec命令:在容器内执行一次命令

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

2、TCPSocket:在当前容器尝试访问指定的socket

  lifecycle:
    postStart:
      tcpSocket:
        port: 8080

3、HTTPGet:在当前容器中向某url发起http请求

  lifecycle:
    postStart:
      httpGet:
        path: / #URI地址
        port: 80 #端口号
        host: 127.0.0.1 #主机地址
        scheme: HTTP #支持的协议,http或者https

接下来,以exec方式为例,演示下钩子函数的使用,创建pod-hook-exec.yaml文件,内容如下:

apiVersion: v1
kind: Pod
metadata:
  name: pod-hook-exec
  namespace: dev
spec:
  containers:
  - name: main-container
    image: nginx:1.17.1
    ports:
    - name: nginx-port
      containerPort: 80
    lifecycle:
      postStart: 
        exec: # 在容器启动的时候执行一个命令,修改掉nginx的默认首页内容
          command: ["/bin/sh", "-c", "echo postStart... > /usr/share/nginx/html/index.html"]
      preStop:
        exec: # 在容器停止之前停止nginx服务
          command: ["/usr/sbin/nginx","-s","quit"]

5、容器探测

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

1、liveness probes: 存活性探针,用于检测应用实例当前是否处于正常运行状态,如果不是,k8s会重启容器。
2、readiness probes: 就绪性探针,用于检测应用实例当前是否可以接收请求,如果不能,k8s不会转发流量。

区别:livenessProbe 决定是否重启容器,readinessProbe 决定是否将请求转发给容器。

上面两种探针目前均支持下面三种探测方式:

1、Exec命令:在容器内执行一次命令,如果命令执行的退出码为0,则认为程序正常,否则不正常。

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

2、TCPSocket:将会尝试访问一个用户容器的端口,如果能够建立这条连接,则认为程序正常,否则不正常。

  livenessProbe:
    tcpSocket:
      port: 8080

3、HTTPGet:调用容器内Web应用的URL,如果返回的状态码在200和399之间,则认为程序正常,否则不正常。

  livenessProbe:
    httpGet:
      path: / #URI地址
      port: 80 #端口号
      host: 127.0.0.1 #主机地址
      scheme: HTTP #支持的协议,http或者https

举例探测失败重启

apiVersion: v1
kind: Pod
metadata:
  name: pod-liveness-httpget
  namespace: default
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      httpGet:  # 其实就是访问http://127.0.0.1:80/hello  
        scheme: HTTP #支持的协议,http或者https
        port: 80 #端口号
        path: /hello #URI地址
      initialDelaySeconds: 30 # 容器启动后30s开始探测
      timeoutSeconds: 5 # 探测超时时间为5s

创建pod,观察效果

发现pod一直在重启,说明接口http://127.0.0.1:80/hello 是不存在的。在这里插入图片描述
kubectl describe pod pod-liveness-httpget
查看pod的详细信息,发现报的是livenessprobe失败,访问404找不到接口。
在这里插入图片描述

6、重启策略

在上面容器探测出现了问题,kubernetes就会对容器所在的Pod进行重启,其实这是由pod的重启策略决定的,pod的重启策略有 3 种,分别如下:

  • Always :容器失效时,自动重启该容器,这也是默认值。
  • OnFailure : 容器终止运行且退出码不为0时重启
  • Never : 不论状态为何,都不重启该容器

重启策略适用于pod对象中的所有容器,首次需要重启的容器,将在其需要时立即进行重启,随后再次需要重启的操作将由kubelet延迟一段时间后进行,且反复的重启操作的延迟时长以此为10s、20s、40s、80s、160s和300s,300s是最大延迟时长。

创建pod-restartpolicy.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: pod-restartpolicy
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      httpGet:
        scheme: HTTP
        port: 80
        path: /hello
  restartPolicy: Never # 设置重启策略为Never

二、Pod控制器

1、Pod控制器简介

Pod是k8s的最小管理单元,在k8s中,按照pod的创建方式可以将其分为两类:
1、自主式pod:kubernetes直接创建出来的Pod,这种pod删除后就没有了,也不会重建。
2、控制器创建的pod:kubernetes通过控制器创建的pod,这种pod删除了之后还会自动重建。项目中基本都用第二种。


什么是Pod控制器?
Pod控制器是管理pod的中间层,使用Pod控制器之后,只需要告诉Pod控制器,想要多少个什么样的Pod就可以了,它会创建出满足条件的Pod并确保每一个Pod资源处于用户期望的目标状态。如果Pod资源在运行中出现故障,它会基于指定策略重新编排Pod。


在k8s中,有很多类型的pod控制器,每种都有自己的适合的场景,常见的有下面这些:
1、ReplicationController:比较原始的pod控制器,已经被废弃,由ReplicaSet替代
2、ReplicaSet:保证副本数量一直维持在期望值,并支持pod数量扩缩容,镜像版本升级
3、Deployment:通过控制ReplicaSet来控制Pod,并支持滚动升级、回退版本
4、Horizontal Pod Autoscaler:可以根据集群负载自动水平调整Pod的数量,实现削峰填谷
5、DaemonSet:在集群中的指定Node上运行且仅运行一个副本,一般用于守护进程类的任务
6、Job:它创建出来的pod只要完成任务就立即退出,不需要重启或重建,用于执行一次性任务
7、Cronjob:它创建的Pod负责周期性任务控制,不需要持续后台运行
8、StatefulSet:管理有状态应用。

项目中经常用的控制器是Deployment。

2、Deployment

为了更好的解决服务编排的问题,k8s在V1.2版本开始,引入了Deployment控制器。值得一提的是,这种控制器并不直接管理pod,而是通过管理ReplicaSet来简介管理Pod,即:Deployment管理ReplicaSet,ReplicaSet管理Pod。所以Deployment比ReplicaSet功能更加强大。

Deployment主要功能有下面几个:
1、支持ReplicaSet的所有功能
2、支持发布的停止、继续
3、支持滚动升级和回滚版本。


1、创建deploy

创建pc-deployment.yaml,内容如下:

apiVersion: apps/v1
kind: Deployment      
metadata:
  name: pc-deployment
  namespace: default
spec: 
  replicas: 3
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1

2、扩缩容

//介绍两种扩缩容的方式
//如果指定namespace的话,需要加-n 参数
1、直接命令修改
kubectl scale deploy deploy名称 --replicas=5
2、编辑deployment的副本数量,修改spec:replicas即可
kubectl edit deploy deploy名称

3、镜像更新策略

deployment支持两种更新策略:重建更新和滚动更新,可以通过strategy指定策略类型,支持两个属性:


strategy:指定新的Pod替换旧的Pod的策略, 支持两个属性:
  type:指定策略类型,支持两种策略
    Recreate:在创建出新的Pod之前会先杀掉所有已存在的Pod
    RollingUpdate:滚动更新,就是杀死一部分,就启动一部分,在更新过程中,存在两个版本Pod
  rollingUpdate:当type为RollingUpdate时生效,用于为RollingUpdate设置参数,支持两个属性:
    maxUnavailable:用来指定在升级过程中不可用Pod的最大数量,默认为25%。
    max违规词汇: 用来指定在升级过程中可以超过期望的Pod的最大数量,默认为25%。

只需要在deploy的yaml文件中加入下面配置即可

spec:
  strategy: # 策略
    type: RollingUpdate # 滚动更新策略
    rollingUpdate:
      max违规词汇: 25% 
      maxUnavailable: 25%

4、版本回退

5、金丝雀发布

Deployment控制器支持控制更新过程中的控制,如“暂停(pause)”或“继续(resume)”更新操作。

比如有一批新的Pod资源创建完成后立即暂停更新过程,此时,仅存在一部分新版本的应用,主体部分还是旧的版本。然后,再筛选一小部分的用户请求路由到新版本的Pod应用,继续观察能否稳定地按期望的方式运行。确定没问题之后再继续完成余下的Pod资源滚动更新,否则立即回滚更新操作。这就是所谓的金丝雀发布,我们平常基本用不到金丝雀发布,就不在这举例了。

三、service详解

在k8s中,pod是应用程序的载体,我们可以通过pod的ip来访问应用程序,但是pod的ip地址不是固定的,这也就意味着不方便直接采用pod的ip对服务进行访问。

为了解决这个问题,kubernetes提供了Service资源,Service会对提供同一个服务的多个pod进行聚合,并且提供一个统一的入口地址。通过访问Service的入口地址就能访问到后面的pod服务。

1、创建service


apiVersion: v1
kind: Service
metadata:
  name: service-clusterip
  namespace: dev
spec:
  selector:
    app: nginx-pod
  clusterIP: 10.97.97.97 # service的ip地址,如果不写,默认会生成一个
  type: ClusterIP
  ports:
  - port: 80  # Service端口       
    targetPort: 80 # pod端口

对于yaml中的port、targetPort、nodePort和containerPort等理解,大家看port、targetPort、nodePort和containerPort区别。

2、clusterIP、NodePort详解

clusterIP 创建的Service的ip地址只有集群内部才可以访问

NodePort 就是将service的端口映射到Node的一个端口上,然后就可以通过NodeIp:NodePort来访问service。


apiVersion: v1
kind: Service
metadata:
  name: service-nodeport
  namespace: dev
spec:
  selector:
    app: nginx-pod
  type: NodePort # service类型
  ports:
  - port: 80
    nodePort: 30002 # 指定绑定的node的端口(默认的取值范围是:30000-32767), 如果不指定,会默认分配
    targetPort: 80

四、k8s学习链接

k8s学习链接:
一、Kubernetes详解-(对k8s里面概念和名词的解释理解)

二、Kubernetes详解-(对k8s里namespace、pod、deployment、service的简单使用)

三、K8s详解-Pod、Pod控制器、Service特性详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北漂IT民工_程序员_ZG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值