k8s-Pod编排与调度

一、无状态负载 (Deployment)

1.1 背景

Pod是K8s调度的最小单元,但是Pod可能因为资源不足、集群崩溃等被驱逐。Controller Manage会管理Pod,完成Pod自愈、滚动升级等操作,通过Deployment这种资源完成Pod维护。

k8s-Pod编排与调度_第1张图片

一个Deployment可以包含一个或多个Pod副本,每个Pod副本的角色相同,所以系统会自动为Deployment的多个Pod副本分发请求。

Deployment集成了上线部署、滚动升级、创建副本、恢复上线的功能,在某种程度上,Deployment实现无人值守的上线,大大降低了上线过程的复杂性和操作风险。

Deployment关注的是应用的部署和管理,负责创建和更新Pod。

Service关注的是网络访问和服务的发现,提供统一的网络入口和负载均衡

在实际应用中,通常先创建Deployment来定义应用的需求,然后创建Service来暴露应用的服务。

1.2 创建

示例:创建一个名为nginx的Deployment负载,使用nginx:latest镜像创建两个Pod,每个Pod占用100m core CPU、200Mi内存。k8s-Pod编排与调度_第2张图片

从这个定义中可以看到
Deployment的名称为nginx;
spec.replicas定义了Pod的数量,即这个Deployment控制2个Pod;
spec.selector是Label Selector(标签选择器),表示这个Deployment会选择Label为app=nginx的Pod;
spec.template是Pod的定义,内容与Pod中的定义完全一致。
将上面Deployment的定义保存到deployment.yaml文件中,使用kubectl创建这个Deployment。
使用kubectl get查看Deployment和Pod,可以看到READY值为2/2,前一个2表示当前有2个Pod运行,后一个2表示期望有2个Pod,AVAILABLE为2表示有2个Pod是可用的。 

$ kubectl create -f deployment.yaml
deployment.apps/nginx created

$ kubectl get deploy
NAME           READY     UP-TO-DATE   AVAILABLE   AGE
nginx                  2/2                 2                   2             4m5s

1.3 如何控制Pod

k8s-Pod编排与调度_第3张图片

删除Pod后,Deployment会重新拉起一个新的Pod。

k8s-Pod编排与调度_第4张图片

1.4 ReplicaSet

两个后缀中前面一部分是相同的,都是7f98958cdf,这是因为Deployment不是直接控制Pod的,Deployment是通过ReplicaSet的控制器控制Pod,通过命令可以查询ReplicaSet,其中rs是ReplicaSet的缩写。

ReplicaSet的名称为nginx-7f98958cdf,后缀-7f98958cdf也是随机生成的。
Deployment控制ReplicaSet,ReplicaSet控制Pod。

k8s-Pod编排与调度_第5张图片

通过Describe也可以查询到ReplicaSet信息。

k8s-Pod编排与调度_第6张图片1.5 升级 

Deployment的两种升级策略:

  • RollingUpdate:滚动升级,即逐步创建新Pod再删除旧Pod,为默认策略。
  • Recreate:替换升级,即先把当前Pod删掉再重新创建Pod。

Deployment可以通过maxSurge和maxUnavailable两个参数控制升级过程中同时重新创建Pod的比例,这在很多时候是非常有用,配置如下所示。

spec:
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate 

  • maxSurge:与Deployment中spec.replicas相比最多可存在多少个Pod(默认125%,定义4个最多增加到5个),可以有多少个Pod存在,默认值是25%,比如spec.replicas为 4,那升级过程中就不能超过5个Pod存在,即按1个的步伐升级,实际升级过程中会换算成数字,且换算会向上取整。这个值也可以直接设置成数字。(最多有多少个Pod)
  • maxUnavailable:与Deployment中spec.replicas相比,可以有多少个Pod失效,也就是删除的比例,默认值是25%,比如spec.replicas为4,那升级过程中就至少有3个Pod存在,即删除Pod的步伐是1。同样这个值也可以设置成数字。(最少有多少个Pod)

1.6 回滚

     回滚也称为回退,即当发现升级出现问题时,让应用回到老的版本。Deployment可以非常方便的回滚到老版本。

Deployment之所以能如此容易的做到回滚,是因为Deployment是通过ReplicaSet控制Pod的,升级后之前ReplicaSet都一直存在,Deployment回滚做的就是使用之前的ReplicaSet再次把Pod创建出来。Deployment保存ReplicaSet的数量可使用revisionHistoryLimit参数限制,默认值10

二、有状态负载 (stateful)

2.0 有状态和无状态

无状态就是每个服务状态信息一致,有状态就是服务信息不一致,请求需要路由到某一个特定的服务器,应用中每个部分的角色不同(即分工不同),比如数据库有主备、Pod之间有依赖。

2.1 介绍

在Kubernetes中部署有状态应用对Pod有如下要求:

  • Pod能够被别的Pod找到,要求Pod有固定的标识。
  • 每个Pod有单独存储,Pod被删除恢复后,必须读取原来的数据,否则状态就会不一致。

Kubernetes提供了StatefulSet来解决这个问题,其具体如下:

  1. StatefulSet给每个Pod提供固定名称,Pod名称增加从0-N的固定后缀,Pod重新调度后Pod名称和HostName不变。
  2. StatefulSet通过Headless Service给每个Pod提供固定的访问域名。
  3. StatefulSet通过创建固定标识的PVC保证Pod重新调度后还是能访问到相同的持久化数据。

k8s-Pod编排与调度_第7张图片

2.2 创建Headless Service

2.2.0 Headless Service 和 Service的区别

headless不分配clusterIP
解析service的DNS,返回所有Pod的地址和DNS(statefulSet部署的Pod才有DNS)
普通的service,只能通过解析service的DNS返回service的ClusterIP

创建Statefulset需要一个Headless Service用于Pod访问。

  • spec.clusterIP:必须设置为None,表示Headless Service。
  • spec.ports.port:Pod间通信端口号。
  • spec.ports.name:Pod间通信端口名称。

k8s-Pod编排与调度_第8张图片

执行如下命令创建Headless Service。

创建完成后可以查询Service。

 2.3 创建statefulSet

  • 指定Headless Service:serviceName指定了Statefulset使用哪个Headless Service,需要填写Headless Service的名称。
  • 指定持久化声明:volumeClaimTemplates是用来申请持久化声明PVC ,这里定义了一个名为data的模板,它会为每个Pod创建一个PVC,storageClassName指定了持久化存储的类型,在PV、PVC和StorageClass会详细介绍;volumeMounts是为Pod挂载存储。当然如果不需要存储的话可以删除volumeClaimTemplates和volumeMounts字段。
  • k8s-Pod编排与调度_第9张图片

执行创建命令  

命令执行后,查询一下StatefulSet和Pod,可以看到Pod的名称后缀从0开始到2,逐个递增。

 k8s-Pod编排与调度_第10张图片

此时如果手动删除nginx-1这个Pod,然后再次查询Pod,可以看到StatefulSet重新创建了一个名称相同的Pod,通过创建时间5s可以看出nginx-1是刚刚创建的。

 k8s-Pod编排与调度_第11张图片

进入容器查看容器的hostname,可以看到同样是nginx-0、nginx-1和nginx-2。

 k8s-Pod编排与调度_第12张图片

同时可以看一下StatefulSet创建的PVC,可以看到这些PVC,都以“PVC名称-StatefulSet名称-编号”的方式命名,并且处于Bound状态。

2.4 StatefulSet的网络标识

Headless Service使用DNS,给每个Pod固定域名,即使ip变化也不影响访问。

2.5 StatefulSet存储状态

使用pvc做持久化存储。

图1 StatefulSet的Pod重建过程

k8s-Pod编排与调度_第13张图片

2.6 普通任务和定时任务 

        批量处理短暂的一次性任务,仅执行一次任务,保证一个或多个Pod结束。Job管理的Pod根据用户设置成功的任务完成就自动退出。

2.6.1 创建Job

        计算π到2000位并打印输出。Job结束需要运行50个Pod,这个示例中就是打印π 50次,并行运行5个Pod,Pod如果失败最多重试5次。

k8s-Pod编排与调度_第14张图片

根据completions和parallelism的设置,可以将Job划分为以下几种类型。

 k8s-Pod编排与调度_第15张图片

 2.6.2 创建CronJob

k8s-Pod编排与调度_第16张图片

CronJob的格式从前到后就是:

  • Minute
  • Hour
  • Day of month
  • Month
  • Day of week

如 "0,15,30,45 * * * * " ,前面逗号隔开的是分钟,后面第一个* 表示每小时,第二个 * 表示每个月的哪天,第三个表示每月,第四个表示每周的哪天。

如果您想要每个月的第一天里面每半个小时执行一次,那就可以设置为" 0,30 * 1 * * " 如果您想每个星期天的3am执行一次任务,那就可以设置为 "0 3 * * 0"。

三、守护进程集(DaemonSet)

3.1 守护进程集(DaemonSet)

        运行在节点上,有且仅有一个Pod,非常适合一些系统层面的应用,例如日志收集、资源监控等,这类应用需要每个节点都运行,且不需要太多实例。

k8s-Pod编排与调度_第17张图片

3.2 创建DaemonSet

k8s-Pod编排与调度_第18张图片

Deployment或StatefulSet中的replicas参数,因为是每个节点固定一个。nodeSelector,指定了只在有“daemon=need”的节点上才创建Pod,如下图所示,DaemonSet只在指定标签的节点上创建Pod。如果需要在每一个节点上创建Pod可以删除该标签。

k8s-Pod编排与调度_第19张图片 

创建DaemonSet

查询发现nginx-daemonset没有Pod创建。

k8s-Pod编排与调度_第20张图片

这是因为节点上没有daemon=need这个标签,使用如下命令可以查询节点的标签。

 

你可能感兴趣的:(kubernetes,容器,云原生)