LINUX学习------Linux自动化运维——Kubernetes的pod管理

一、Pod管理

Pods
Pod是可以创建和管理Kubernetes计算的最小可部署单元,一个Pod代表着集群中运行的一个进程,每个pod都有一个唯一的ip。

Pod (就像在鲸鱼荚或者豌豆荚中)是一组(一个或多个)容器; 这些容器共享存储、网络、以及怎样运行这些容器的声明。 Pod
中的内容总是并置(colocated)的并且一同调度,在共享的上下文中运行。 Pod
所建模的是特定于应用的“逻辑主机”,其中包含一个或多个应用容器, 这些容器是相对紧密的耦合在一起的。
在非云环境中,在相同的物理机或虚拟机上运行的应用类似于 在同一逻辑主机上运行的云应用。

LINUX学习------Linux自动化运维——Kubernetes的pod管理_第1张图片

通常你不需要直接创建 Pod,甚至单实例 Pod。 相反,你会使用诸如 Deployment 或 Job 这类工作负载资源 来创建 Pod。

Kubernetes 集群中的 Pod 主要有两种用法:

运行单个容器的 Pod。"每个 Pod 一个容器"模型是最常见的 Kubernetes 用例; 在这种情况下,可以将 Pod
看作单个容器的包装器,并且 Kubernetes 直接管理 Pod,而不是容器。

运行多个协同工作的容器的 Pod。 Pod 可能封装由多个紧密耦合且需要共享资源的共处容器组成的应用程序。
这些位于同一位置的容器可能形成单个内聚的服务单元 —— 一个容器将文件从共享卷提供给公众,
而另一个单独的“边车”(sidecar)容器则刷新或更新这些文件。 Pod 将这些容器和存储资源打包为一个可管理的实体。

每个 Pod 都旨在运行给定应用程序的单个实例。如果希望横向扩展应用程序(例如,运行多个实例 以提供更多的资源),则应该使用多个
Pod,每个实例使用一个 Pod。 在 Kubernetes 中,这通常被称为 副本(Replication)。
通常使用一种工作负载资源及其控制器来创建和管理一组 Pod 副本。

kubectl命令可以参考官方网站:Kubectl Reference Docs

1、Pod创建与使用

1、启动之前创建的k8s集群,这里注意一定要先启动仓库,因为集群创建pod时需要从私有仓库中拉取镜像,检查server1的harbor仓库是否启动
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第2张图片

2、server2集群Master端查看集群内各节点均处于就绪状态

kubectl get pod -n kube-system						##当启动时确保节点都是成功的

LINUX学习------Linux自动化运维——Kubernetes的pod管理_第3张图片

3、启动容器创建Pod应用,(当前版本的k8s)使用这种方式不可以指定Pod内副本个数,只能生成一个容器,使用describe参数可以查看指定Pod中容器的详细属性信息

LINUX学习------Linux自动化运维——Kubernetes的pod管理_第4张图片
4、查看Pod资源的额外信息如容器分配到的ip、调度到集群中的哪一台主机上, curl访问查询到的ip可以看到生成容器所使用的镜像的默认发布页面
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第5张图片
5、删除Pod,创建deployment控制器,这种方式可以使用–replicas参数指定创建副本的个数,集群会自动创建Pod,此时查看pod信息可以看到pod中有两个随机调度生成的容器副本
在这里插入图片描述
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第6张图片
查看pod中容器的标签
在这里插入图片描述
6、删除pod中的某个容器副本后,RS副本控制器自动检测到容器副本数量不足,会重新拉起一个容器副本
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第7张图片
7、暴露deployment控制器创建service,设定暴露端口,此时k8s集群会为pod自动分配一个仅集群内部可以访问的虚拟IP即vip,访问这一vip会轮询pod中的两个容器副本,实现自动负载均衡
(service是一个抽象概念,定义了一个服务的多个pod逻辑合集和访问pod的策略,一般把service称为微服务。)
在这里插入图片描述
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第8张图片
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第9张图片
查看service的详细属性信息可以看到其包含了两个访问后端
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第10张图片
8、删除pod中的某个容器副本,RS副本控制器重新拉起一个容器副本,可以看到新建容器分配到的ip改变,此时再次查看service的详细属性信息可以看到其包含的两个访问后端的ip也自动进行了更新,我们可以将其理解为另一种形式的健康检测
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第11张图片
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第12张图片

2、Pod扩容缩容

1、使用scale参数将已有pod中的容器副本数目扩容到指定数量
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第13张图片
2、查看service的详细属性信息可以看到service的虚拟vip及其所包含的6个访问后端
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第14张图片
3、访问service的虚拟vip会轮询pod中的多个容器副本,实现自动负载均衡
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第15张图片
4、使用scale参数将已有pod中的容器副本数目缩容到指定数量,缩容时是把最新创建的容器副本删掉,保留运行时间最长的容器副本
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第16张图片

3、Pod中镜像的滚动更新

1、使用deployment控制器更新pod中容器副本的镜像版本,可以看到原来的容器副本被删掉,创建了新镜像版本的容器副本
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第17张图片
2、查看Pod资源的额外信息得到容器分配到的ip, curl访问查询到的ip,从镜像默认发布页面可以看出生成容器所使用的镜像版本成功更新
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第18张图片
3、查看集群中所有已存在的资源可以发现,原来的RS副本控制器不会删掉,会创建新的RS控制器,这样便于镜像版本回滚,当pod中镜像回滚到原来的版本时,原来的控制器又会再次运行
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第19张图片
4、使用deployment控制器回滚pod中容器副本的镜像版本,查看Pod资源的额外信息得到容器分配到的ip, curl访问查询到的ip可以看到生成容器所使用的镜像版本已回滚,这里也可以通过访问service的虚拟vip看到生成容器所使用的镜像版本已回滚,原来的RS控制器再次运行,同理新的RS控制器不会删掉
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第20张图片

二、资源

1.1、资源分类

K8s中所有的内容都抽象为资源,资源实例化之后,叫做对象。集群资源分为:名称空间级别、集群级别、元数据型。

名称空间级别:

工作负载型资源:service,pod,Redeployment(控制器,我们很少直接操作pod,而是通过控制器来操作Pod)、ReplicaSet、StatefilSet、Job、Cronjob
服务发现及服务均衡资源型资源:Service、Ingress
配置与存储型资源:Volume、CSI(容器存储接口,可以扩展各种第三方的存储卷)、ConfigMap、Secret、DownwardAPI
特殊类型的存储卷:ConfigMap(当配置中心来使用的资源类型)、Secret(保存敏感数据)、DownwardAPI(把外部环境中的信息输出给容器)
集群级别:

集群级资源:Namespace、Node、Role、rolebinding、clusterrolebinding 元数据型:

元数据型资源:HPA、podtemplate、limitrange(限制资源的如cpu、内存等)

1.2、资源清单

在K8S中,一般使用yaml格式的文件来创建符合我们预期期望的pod,这样的yaml文件我们一般称为资源清单
资源清单中常见字段的解释:

参数名 字段类型 说明
version string 这里是指的是K8S API的版本,可以用”kubectl api-versions“命令查询
kind string 这是指的是yaml文件定义的资源类型和角色,比如:pod
metadata Object 元数据对象,固定值就写metedata
metadata.name string 元数据对象的名字,这里由我们编写,比如命名Pod的名字
metadata.namespace string 元数据对象的命名空间,由我们自身定义
Spec Object 详细定义对象,固定值就写Spec
spec.containers[] list 这里是Spec对象的容器列表定义,是个列表
spec.containers[].name string 这里定义容器的名字
spec.containers[].image string 这里定义要用到的镜像名称
spec.containers[].imagePullPolicy string 定义镜像拉取策略,有Always、Never、IfNotPresent三个值可选(1)Always:意思是每次都尝试重新拉取镜像(2)Never:表示仅适用本地镜像(3)IfNotPresent:如果本地有镜像就使用本地镜像,没有就拉取在线镜像。上面三个值都没设置的话,默认是Always。
spec.containers[].command[] list 指定容器启动命令,因为是数组可以指定多个,不指定则使用镜像打包时使用的启动命令
spec.containers[].args[] list 指定容器启动命令参数,因为是数组可以指定多个
spec.containers[].workingDir string 指定容器的工作目录
spec.containers[].volumeMounts[] list 指定容器内部的存储卷配置
spec.containers[].volumeMounts[].name string 指定可以被容器挂载的存储卷的名称
spec.containers[].volumeMounts[].mountPath string 指定可以被容器挂载的存储卷的路径
spec.containers[].volumeMounts[].readOnly string 设置存储卷路径的读写模式,ture或者false,默认是读写模式
spec.containers[].ports[] list 指定容器需要用到的端口列表
spec.containers[].ports[].name string 指定端口的名称
spec.containers[].ports[].containerPort string 指定容器需要监听的端口号
spec.containers[].ports[].hostPort string 指定容器所在主机需要监听的端口号,默认跟上面containerPort相同,注意设置了hostPort同一台主机无法启动该容器的相同副本(因为主机的端口号不能相同,这样会冲突)
spec.containers[].ports[].protocol string 指定端口协议,支持TCP和UDP,默认值为TCP
spec.containers[].env[] list 指定容器运行前需设置的环境变量列表
spec.containers[].env[].name string 指定环境变量名称
spec.containers[].env[].value string 指定环境变量值
spec.containers[].resources Object 指定资源限制和资源请求的值(这里开始就是设置容器的资源上限)
spec.containers[].resources.limits Object 指定设置容器运行时资源的运行上限
spec.containers[].resources.limits.cpu string 指定CPU的限制,单位为Core数,将用于docker run –cpu-shares参数
spec.containers[].resources.limits.memory string 指定mem内存的限制,单位为MIB、GiB
spec.containers[].resources.requests Object 指定容器启动和调度时的限制设置
spec.containers[].resources.requests.cpu string CPU请求,单位为core数,容器启动时初始化可用数量
spec.containers[].resources.requests.memory string 内存请求,单位为MIB、GiB,容器启动的初始化可用数量
spec.restartPolicy string 定义pod的重启策略,可选值为Always、OnFailure、Never,默认值为Always。 1.Always:pod一旦终止运行,则无论容器是如何终止的,kubelet服务都将重启它。2.OnFailure:只有pod以非零退出码终止时,kubelet才会重启该容器。如果容器正常结束(退出码为0),则kubectl将不会重启它。3.Never:Pod终止后,kubelet将退出码报告给master,不会重启该pod
spec.nodeSelector Object 定义Node的label过滤标签,以key:value格式指定
spec.imagePullSecrets Object 定义pull镜像时使用secret名称,以name:secretkey格式指定
spec.hostNetwork Boolean 定义是否使用主机网络模式,默认值为false。设置True表示使用宿主机网络,不使用docker网桥,同时设置了True将无法在同一台宿主机上启动第二个副本

2.1、构建资源清单

1、在编写资源清单文件时需要指明api资源属于哪个群组和版本,我们在编写前可以先进行查询

kubectl api-versions :查询命令

LINUX学习------Linux自动化运维——Kubernetes的pod管理_第21张图片
2、删除已有的pod,创建pod目录并在该目录下编写文件构建资源清单pod.yaml(.yaml文件与.yml文件无区别),应用资源清单,此时可以查看到生成的pod,其中包含了由myapp镜像生成的一个副本
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第22张图片
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第23张图片
3、在server1上搭建的Habbor私有仓库中上传busybox的镜像,修改并应用资源清单文件,利用私有仓库中的busybox镜像在生成的pod中新建一个副本,此时可以查看到pod中有两个容器副本就绪
在这里插入图片描述
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第24张图片
4、此时连接进入pod中busybox容器的bash环境,访问本地看到的是pod中myapp容器的发布页面,这是因为pod中所有的副本共享一个ip
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第25张图片

三、POD生命周期

Pod 遵循一个预定义的生命周期,起始于 Pending 阶段,如果至少其中有一个主要容器正常启动,则进入 Running,之后取决于
Pod 中是否有容器以失败状态结束而进入 Succeeded 或者 Failed 阶段。 Pod 在其生命周期中只会被调度一次。 一旦
Pod 被调度(分派)到某个节点,Pod 会一直在该节点运行,直到 Pod 停止或者 被终止。
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第26张图片

3.1、init容器

Pod 可以包含多个容器,应用运行在这些容器里面,同时 Pod 也可以有一个或多个先于应用容器启动的 Init 容器。
Init 容器与普通的容器非常像,除了如下两点:

它们总是运行到完成。
Init 容器不支持 Readiness,因为它们必须在 Pod 就绪之前运行完成,每个 Init 容器必须运行成功,下一个才能够运行。
如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止。然而,如果 Pod 对应的 restartPolicy 值为 Never,它不会重新启动。

3.2、init容器的作用

Init 容器可以包含一些安装过程中应用容器中不存在的实用工具或个性化代码。
Init 容器可以安全地运行这些工具,避免这些工具导致应用镜像的安全性降低。
应用镜像的创建者和部署者可以各自独立工作,而没有必要联合构建一个单独的应用镜像。
Init 容器能以不同于Pod内应用容器的文件系统视图运行。因此,Init容器可具有访问 Secrets 的权限,而应用容器不能够访问。
由于 Init 容器必须在应用容器启动之前运行完成,因此 Init
容器提供了一种机制来阻塞或延迟应用容器的启动,直到满足了一组先决条件。一旦前置条件满足,Pod内的所有的应用容器会并行启动。

3.3、init初始化容器

初始化容器,在容器运行之前进行初始化,故初始化容器不包括readiness就绪探针。

初始化可以包括一些安装过程中应用容器中不存在的实用工具或服务,定义初始化服务后,必须要添加服务,初始化才能完成。

vim init.yaml

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busyboxplus
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busyboxplus
    command: ['sh', '-c', "until nslookup myservice.default.svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busyboxplus
    command: ['sh', '-c', "until nslookup mydb.default.svc.cluster.local; do echo waiting for mydb; sleep 2; done"]


2、读取资源清单创建pod,查看Pod信息可以在状态中看到两个初始化容器都未成功运行,每个init初始化容器必须成功运行并退出后,主容器才能成功运行,因此pod一直未就绪。编辑资源清单文件init.yaml,为两个init初始化容器构建资源模块

apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9377

LINUX学习------Linux自动化运维——Kubernetes的pod管理_第27张图片

4、探针

探针 是由 kubelet 对容器执行的定期诊断:

ExecAction:在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
TCPSocketAction:对指定端口上的容器的 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的。
HTTPGetAction:对指定的端口和路径上的容器的 IP 地址执行 HTTP Get
请求。如果响应的状态码大于等于200且小于400,则诊断被认为是成功的。 每次探测都将获得以下三种结果之一:

成功:容器通过了诊断。
失败:容器未通过诊断。
未知:诊断失败,因此不会采取任何行动。

4.1、livenessProbe存活探针

livenessProbe存活探针: 指示容器是否正在运行。如果存活探测失败,则 kubelet 会杀死容器,并且容器将受到其
重启策略的影响。如果容器不提供存活探针,则默认状态为 Success。

1、编辑资源清单文件pod.yaml,设置在生成pod时使用存活探针探测容器的8080端口是否开放,从而指示容器是否正在运行
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第28张图片
2、读取资源清单创建pod,查看Pod信息可以在状态中看到新建的容器无法成功运行,这是因为我们在文件中指定使用myapp镜像创建容器,myapp容器默认开放的是80端口,8080端口不处于侦听状态,存活探针探测到后认为容器未在运行,k8s会杀死容器,并且容器将受到其重启策略的影响
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第29张图片
3、编辑资源清单文件pod.yaml,设置在生成pod时使用存活探针探测容器的80端口是否开放
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第30张图片
4、删除已有的pod,此时读取资源清单重新创建pod,查看Pod信息可以在状态中看到pod就绪并成功运行
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第31张图片
查看pod的详细描述信息可以看到80端口开放

Kubectl describe pod pod-example

在这里插入图片描述

4.2、readinessProbe就绪探针

readinessProbe就绪探针: 指示容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与 Pod 匹配的所有
Service的端点中删除该 Pod 的 IP 地址。初始延迟之前的就绪状态默认为 Failure。如果容器不提供就绪探针,则默认状态为
Success。

1、编辑资源清单文件pod.yaml,设置在生成pod时使用就绪探针检测容器默认发布路径下是否有指定test.html文件,从而指示容器是否准备好服务请求
在这里插入图片描述
2、删除已有的pod,此时读取资源清单重新创建pod,查看Pod信息可以在状态中看到pod一直未就绪,但curl访问容器分配到的ip可以看到生成容器所使用的镜像的默认发布页面,这说明容器实际上已就绪

LINUX学习------Linux自动化运维——Kubernetes的pod管理_第32张图片
3、删除已有的pod,编辑资源清单文件pod.yaml,设置pod的标签labels为myapp,读取资源清单重新创建pod,查看标签设置成功
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第33张图片
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第34张图片
4、新建编辑服务资源清单svc.yaml,设置创建的服务为标签为myapp的Pod提供统一的对外访问接口,应用服务资源清单svc.yaml,service创建成功,但此时查看服务的详细信息发现该服务无后端pod,这是因为就绪探针持续运行,当容器没有就绪,svc不会暴露出去,没有能够提供访问的后端
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第35张图片
5、连接进入pod,在容器默认发布路径下创建指定test.html文件,就绪探针检测到后指示容器就绪,此时查看服务的详细信息发现该服务有了后端pod
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第36张图片
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第37张图片
6、连接进入pod,在容器默认发布路径下删除test.html文件,查看Pod信息可以看到pod未就绪,再次查看服务的详细信息发现该服务无后端pod

LINUX学习------Linux自动化运维——Kubernetes的pod管理_第38张图片
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第39张图片
当同时设置存活探针、就绪探针,先判断容器是否存活,再看是否就绪

4.3、startupProbe启动探针

startupProbe启动探针: 指示容器中的应用是否已经启动。如果提供了启动探测(startup
probe),则禁用所有其他探测,直到它成功为止。如果启动探测失败,kubelet
将杀死容器,容器服从其重启策略进行重启。如果容器没有提供启动探测,则默认状态为成功Success。

实际中,为了防止存活探针误杀正在启动的容器,一般可以给容器配置一个启动探针,启动探针检测成功后才能继续执行存活检测。
比如可以进行如下配置:

startupProbe:
  httpGet:
    path: /test.html
    port: 80
  failureThreshold: 30
  periodSeconds: 10

该启动探针会每10s检测一次容器80端口,最多检测30次,若某次检测成功,则允许存活探针接管检测;若30次都没有检测成功,则重启容器。

四、控制器

一、控制器简介

自主POD调度绑定至节点若主程序崩溃则节点kubelet能够自动重启容器,但若是非主进程崩溃类的容器kubelet无从感知。这便需要依赖于POD对象定义的存活探测,以便kubelet能够探知到此类故障,但若pod被删除或者工作节点自身发生故障(工作节点上都有kubelet,kubelet不可用,因此其健康状态便无法保证),则便需要控制器来处理相应的容器重启和配置。
Kubernetes 中内建了很多 controller(控制器),这些相当于一个状态机,用来控制 Pod 的具体状态和行为。

Pod 的分类:

自主式 Pod:Pod 退出后不会被创建
控制器管理的 Pod:在控制器的生命周期里,始终要维持 Pod 的副本数目 控制器类型:

ReplicationController和ReplicaSet
Deployment
DaemonSet
StatefulSet
Job
CronJob HPA全称Horizontal Pod Autoscaler

二、各控制器示例

本篇给出了ReplicaSet和Deployment控制器的实例用法

2.1、ReplicaSet控制器

ReplicaSet 是下一代的 Replication Controller,官方推荐使用ReplicaSet。 ReplicaSet 和Replication Controller 的唯一区别是选择器的支持,ReplicaSet 支持新的基于集合的选择器需求。
ReplicaSet 确保任何时间都有指定数量的 Pod 副本在运行 虽然 ReplicaSets
可以独立使用,但今天它主要被Deployments 用作协调 Pod 创建、删除和更新的机制。

1、删除已有的pod,编辑ReplicaSet控制器清单文件rs.yaml,读取该文件新建pod
在这里插入图片描述
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第40张图片
2、查看pod信息可以看到由RS控制器管理的三个pod副本成功创建,查看RS控制器信息可以看到由rs.yaml文件创建的控制器
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第41张图片
3、编辑ReplicaSet控制器清单文件rs.yaml,指定运行的Pod 副本数量为6
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第42张图片
4、读取应用该文件,查看pod信息可以看到由RS控制器管理的pod副本数量变为6个,更改其中任意副本的标签,再次查看pod信息可以看到由RS控制器新建了一个pod副本,其管理的pod副本数量仍为6个
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第43张图片
5、此时删除更改过标签的副本,RS控制器管理的副本无变化,删除未修改过标签的副本,查看pod信息可以看到RS控制器新拉起一个pod副本,其管理的pod副本数量始终为6个
这是因为ReplicaSet 控制器是通过标签控制在任何时间都有指定数量的 Pod 副本在运行

LINUX学习------Linux自动化运维——Kubernetes的pod管理_第44张图片

2.2、Deployment控制器

Deployment 为 Pod 和 ReplicaSet 提供了一个申明式的定义方法。

典型的应用场景:

用来创建Pod和ReplicaSet
滚动更新和回滚
扩容和缩容
暂停与恢复

1、编辑ReplicaSet控制器清单文件rs.yaml,缩小运行的Pod 副本数量为3(3个副本够实验使用),设定RS控制器生成的副本使用v1版本的myapp镜像
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第45张图片
2、读取应用该文件,查看pod信息可以看到由RS控制器管理的pod副本数量变为3个,curl访问任一pod副本分配到的ip,是nginx容器的默认发布页面,这说明RS副本控制器只通过标签控制副本数量,不能实现pod副本镜像版本的迭代更新
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第46张图片
3、pod副本镜像版本的迭代更新需要与deployment控制器结合,读取rs.yaml文件删除生成的pod副本及控制器,编辑deployment控制器清单文件deployment.yaml,设定deployment控制器生成的三个副本使用nginx镜像(不进行设定时deployment控制器默认副本数为1)
在这里插入图片描述
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第47张图片

4、读取应用该文件,查看pod资源额外信息可以得到生成的pod副本的ip,curl访问任一pod副本分配到的ip,是nginx容器的默认发布页面
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第48张图片
5、编辑deployment.yaml,设定deployment控制器生成的副本使用v1版本的myapp镜像,读取应用该文件
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第49张图片
在这里插入图片描述
6、再次查看pod资源额外信息可以得到生成的pod副本的ip,curl访问任一pod副本分配到的ip,是myapp:v1容器的默认发布页面,pod副本镜像版本迭代更新成功
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第50张图片
7、查看RS控制器信息可以看到,deployment控制器生成时会同时生成RS控制器来协调 Pod 创建、删除和更新,由于我们进行了镜像版本更新,所以会有两个RS控制器,即原有的RS控制器不会删除,便于镜像版本的回滚
在这里插入图片描述

2.3、DaemonSet控制器

DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。当有节点加入集群时, 也会为他们新增一个 Pod。当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。

DaemonSet 的典型用法:

在每个节点上运行集群存储 DaemonSet,例如 glusterd、ceph。
在每个节点上运行日志收集 DaemonSet,例如 fluentd、logstash。
在每个节点上运行监控 DaemonSet,例如 Prometheus Node Exporter、zabbix agent等
一个简单的用法是在所有的节点上都启动一个 DaemonSet,将被作为每种类型的 daemon 使用。 一个稍微复杂的用法是单独对每种 daemon 类型使用多个 DaemonSet,但具有不同的标志,并且对不同硬件类型具有不同的内存、CPU 要求。

$ vim daemonset-example.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
 name: daemonset-example
 labels:
   k8s-app: zabbix-agent
spec:
 selector:
   matchLabels:
     name: zabbix-agent
 template:
   metadata:
     labels:
       name: zabbix-agent
   spec:
     containers:
     - name: zabbix-agent
       image: zabbix/zabbix-agent

2.4、StatefulSet控制器

StatefulSet 是用来管理有状态应用的工作负载 API对象。实例之间有不对等关系,以及实例对外部数据有依赖关系的应用,称为“有状态应用”
StatefulSet 用来管理 Deployment和扩展一组 Pod,并且能为这些 Pod 提供序号和唯一性保证。
StatefulSets对于需要满足以下一个或多个需求的应用程序很有价值:

稳定的、唯一的网络标识符。
稳定的、持久的存储。
有序的、优雅的部署和缩放。
有序的、自动的滚动更新。

2.5、Job控制器

执行批处理任务,仅执行一次任务,保证任务的一个或多个Pod成功结束。

$ vim job-example.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
  spec:
    containers:
    - name: pi
      image: perl
      command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
    restartPolicy: Never
 backoffLimit: 4
$ kubectlapply -f job-example.yaml
$ kubectl get pod
NAME      READY   STATUS      RESTARTS  AGE
pi-6phk8  0/1     Completed   0         2m22s
$ kubectl logspi-6phk8
$ kubectldelete job pi

2.6、CronJob控制器

Cron Job 创建基于时间调度的 Jobs。 一个 CronJob 对象就像 crontab (cron table)文件中的一行,它用 Cron 格式进行编写,并周期性地在给定的调度时间执行 Job。

$ vim cronjob-example.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
 name: cronjob-example
spec:
 schedule: "* * * * *"
 jobTemplate:
   spec:
     template:
       spec:
         containers:
         - name: cronjob
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; echo Hello from k8s cluster
         restartPolicy: OnFailure
         
$ kubectlapply -f cronjob-example.yaml
$ kubectl get cronjob
NAME              SCHEDULE    SUSPEND  ACTIVE   LAST SCHEDULE   AGE
cronjob-example  * * * * *   False     0       38s             8m22s 
$ kubectl get job -w
NAME                         COMPLETIONS   DURATION  AGE
cronjob-example-1581873180   1/1          1s         3m
cronjob-example-1581873240   1/1          1s         2m
$ kubectl get pod
NAME                               READY   STATUS     RESTARTS   AGE
cronjob-example-1581873240-r644w   0/1    Completed   0          2m51s
cronjob-example-1581873300-p89rc   0/1    Completed   0          111s
$ kubectl logs cronjob-example-1581873240-r644w
Sun Feb 16 17:14:06 UTC 2020
Hello from k8s cluster
$ kubectldelete  cronjob  cronjob-example
cronjob.batch"cronjob-example" deleted

2.7、HPA控制器

Horizontal Pod Autoscaler(HPA)HPA可作为KubernetesAPI资源的控制实现,它基于采集到得资源指标数据来调整控制器的行为,HPA获取资源指标数据是通过Heapster和REST客户端接口获取。目前HPA有两个版本分别是HPA和HPAv1。

工作流程:

1.创建HPA资源,设定目标CPU使用率限额,以及最大、最小实例数, 一定要设置Pod的资源限制参数: request, 否则HPA不会工作。
2.控制管理器每隔30s(可以通过–horizontal-pod-autoscaler-sync-period修改)查询metrics的资源使用情况
3.然后与创建时设定的值和指标做对比(平均值之和/限额),求出目标调整的实例个数
4.目标调整的实例数不能超过1中设定的最大、最小实例数,如果没有超过,则扩容;超过,则扩容至最大的实例个数 然后就是重复2-4步

自动伸缩算法: HPA
Controller会通过调整副本数量使得CPU使用率尽量向期望值靠近,而且不是完全相等.另外,官方考虑到自动扩展的决策可能需要一段时间才会生效:例如当pod所需要的CPU负荷过大,从而在创建一个新pod的过程中,系统的CPU使用量可能会同样在有一个攀升的过程。所以,在每一次作出决策后的一段时间内,将不再进行扩展决策。对于扩容而言,这个时间段为3分钟,缩容为5分钟(可以通过–horizontal-pod-autoscaler-downscale-delay, --horizontal-pod-autoscaler-upscale-delay进行调整)。

HPA
Controller中有一个tolerance(容忍力)的概念,它允许一定范围内的使用量的不稳定,现在默认为0.1,这也是出于维护系统稳定性的考虑。例如,设定HPA调度策略为cpu使用率高于50%触发扩容,那么只有当使用率大于55%或者小于45%才会触发伸缩活动,HPA会尽力把Pod的使用率控制在这个范围之间。

具体的每次扩容或者缩容的多少Pod的算法为: Ceil(前采集到的使用率 / 用户自定义的使用率) * Pod数量)
每次最大扩容pod数量不会超过当前副本数量的2倍

五、service

一、service简介

Service可以看作是一组提供相同服务的Pod对外的访问接口。借助Service,应 用可以方便地实现服务发现和负载均衡。
Service默认只支持4层负载均衡能力,没有7层功能。(可以通过Ingress实现)

Service的类型:

ClusterIP:默认值,k8s系统给service自动分配的虚拟IP,只能在集群内部访问。
NodePort:将Service通过指定的Node上的端口暴露给外部,访问任意一个
NodeIP:nodePort都将路由到ClusterIP。 LoadBalancer:在 NodePort 的基础上,借助 cloud
provider 创建一个外部的负 载均衡器,并将请求转发:NodePort,此模式只能在云服务器上使用。
ExternalName:将服务通过 DNS CNAME 记录方式转发到指定的域名(通过 spec.externlName 设定)

二、IPVS模式的service

Service 是由 kube-proxy 组件,加上 iptables 来共同实现的. kube-proxy 通过 iptables 处理
Service 的过程,需要在宿主机上设置相当多的iptables 规则,如果宿主机有大量的Pod,不断刷新iptables规则,会消耗大量的CPU资源。
IPVS模式的service,可以使K8s集群支持更多量级的Pod。

所有节点都先安装IPVS

yum install -y ipvsadm //所有节点安装
lsmod |grep ip_vs  //查看IP VS模式

LINUX学习------Linux自动化运维——Kubernetes的pod管理_第51张图片

kubectl -n kube-system get cm   ## 查看配置信息

LINUX学习------Linux自动化运维——Kubernetes的pod管理_第52张图片

kubectl -n kube-system edit cm kube-proxy    ##编辑配置信息,指定使用 ipvs 的模式,不写时默认用的是 iptables

LINUX学习------Linux自动化运维——Kubernetes的pod管理_第53张图片
需要重启服务生效

kubectl get pod -n kube-system |grep kube-proxy | awk '{system("kubectl delete pod "$1" -n kube-system")}'
ipvsadm -ln

LINUX学习------Linux自动化运维——Kubernetes的pod管理_第54张图片
编辑deployment.yaml,将副本数置为3
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第55张图片
读取应用该文件,现在有3个pod
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第56张图片
查看mysvc的详细内容,可以看到后端pod有3个
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第57张图片
再次查看当前连接情况,可以看到现在mysvc有3个pod
kube-proxy通过linux的IPVS模块,以rr轮询方式调度service中的Pod。
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第58张图片
测试访问该服务n次LINUX学习------Linux自动化运维——Kubernetes的pod管理_第59张图片
可以看到每次访问以轮询的方式分配给每一个pod,因为每个pod的权值相同,所以分别响应了2次
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第60张图片

三、实现外部访问

3.1、NodePort方式

LINUX学习------Linux自动化运维——Kubernetes的pod管理_第61张图片
server2查看mysvc详细信息,并测试访问
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第62张图片
编译mysvc的配置文件,修改类型为NodePort
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第63张图片

可以看到修改成功,开放的端口是30017
在这里插入图片描述
node节点也可以看到该端口处于监听状态
在这里插入图片描述
在这里插入图片描述

使用真实主机访问服务,可以看到来自三个后端轮询应答
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第64张图片
查看pod列表,可以发现轮询应答正是来自这3个pod
在这里插入图片描述
进入容器中并查看mysvc服务的dns解析
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第65张图片
显示kube-system的pod,看到两个coredns
查看kube-system的svc,服务端口为53
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第66张图片
查看kube-dns服务详细信息,有两个后端pod,对比一下ip可以发现,就是刚才的两个coredns
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第67张图片
LINUX学习------Linux自动化运维——Kubernetes的pod管理_第68张图片

3.2、Headless无头模式

以DNS记录的方式解析出被代理Pod的IP地址,不需要通过Ip地址访问,可直接访问服务名称

查看所有的pod并显示标签
vim headless.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  ports:
    - name: http
      port: 80
      targetPort: 80
  selector:
      app: myapp
  clusterIP: None

拉起容器,查看svc信息

kubectl apply -f headless.yaml
kubectl get svc

LINUX学习------Linux自动化运维——Kubernetes的pod管理_第69张图片

3.3、LoadBalancer模式

适用于公有云上的Kubernetes 服务。
可以指定一个 LoadBalancer 类型的Service,在service提交后,Kubernetes就会调用 CloudProvider 在公有云上为你创建一个负载均衡服务,并且把被代理的 Pod 的 IP地址配置给负载均衡服务做后端。

3.4、ExternalName方式

externalName Service是k8s中一个特殊的service类型,它不需要指定selector去选择哪些pods实例提供服务,而是使用DNS CNAME机制把自己CNAME到你指定的另外一个域名上,可以提供集群内的名字,也可以指定外部真实域名。

清理之前的lb-svc.yml配置文件,可以看到lb-svc服务已经删除

你可能感兴趣的:(kubernetes,运维,linux)