Kubernetes系列(3)——工作负载

半日闲 2020年12月04日 71次浏览

前言

官方解释:工作负载就是运行在Kubernetes上的应用程序。
而我们的程序,也就是工作负载可以由单个组件构成,也可以由多个组件同时构成。

最小单位——Pod

Docker的操作单位是container,而Kubernetes的操作单位是Pod。从前一节容器的介绍中,我们知道容器实际上是一个进程,那么Pod是什么呢?“Pod (就像在鲸鱼荚或者豌豆荚中)是一组(一个或多个) 容器; 这些容器共享存储、网络、以及怎样运行这些容器的声明。 Pod 中的内容总是并置(colocated)的并且一同调度,在共享的上下文中运行。”——这是官网上的解释,因此我们知道了,Pod实际上是1个或者1组容器的集合。且Pod中的容器其生命周期是一致(即被Kubernetes同时调度)。
在通常情况下,每一个Pod中都应该只有1个业务容器,除非多个容器之间具有强依赖关系。
Pod的结构如下
image.png
同一个Pod中的container共享IPC,UTS,Network,因此它们之间可以自由相互通信。

资源

在Kubernetes中我们可以看到很多的概念,我们均可以称之为资源(resource),可以通过kubectl api-resources查看,如下
image.png
第1列,表示resource名称
第2列,表示该resource的简写
第3列,表示该resource所处的API Group
第4列,表示该resource的使用范围是否限制在namespace中
第5列,表示该resource的类别
Pod也可以算是资源的一部分,但是实际使用中,我们往往不会直接去创建或者升级某个Pod,而是使用处于Pod之上,更高级的控制器来操作Pod。
以下讲解一下常用的控制器

Deployment

简写deploy,官方也建议使用。
当我们创建1个deployment的时候,Kubernetes会自动的创建1个rs去控制Pod,而deployment只控制rs。Deployment相对于rs和rc来讲,可以提供更强大的操作功能,比如滚动升级,状态回滚等。
下面来看一个deploy的示例,如下

[root@a file-yaml]$ cat busybox-httpd-deploy-v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
## 定义该deployment的label
  labels:
    app: busybox-httpd
    version: v1
  name: busybox-httpd-v1
spec:
  replicas: 1
  ## 定义该deployment所选择的pod label
  selector:
    matchLabels:
      app: busybox-httpd
      version: v1
  template:
    metadata:
    ## 定义该Pod的label
      labels:
        app: busybox-httpd
        version: v1
    spec:
      containers:
      ## 定义pod中image
      - image: registry.cn-xxx.aliyuncs.com/xxx/busyboxhttpd:v1
      ## 定义image的pull策略
        imagePullPolicy: Always
        ## 定义container的名字
        name: busybox-httpd
        ## 定义container暴露的端口
        ports:
        - name: v1
          containerPort: 80

使用kubectl apply -f busybox-httpd-deploy-v1.yaml之后,就可以看到出现了3个resource,如下
image.png
如此,充分说明,deploy管理rs,而rs再操作pod。而且,也可以看到deploy,rs以及pod的label都包含我们定义的,除此之外,kubernetes还自动填写了1个hash的label。

StatefulSet

简写sts,使用deployment生成的pod都是无状态的,它们管理的pod的名字,IP,启停顺序都是随机,但是如果需要在Kubernetes部署一套zookeeper呢,那怎么办?我们可以使用statefulset来创建有状态的pod,使用statefulset所创建的pod,它们的ip都是固定的(即Pod在被删除后重新生成时,ip固定),名字也是有序的,
使用1个statefulset的yaml进行创建, statefuleset的yaml文件中必须要有serviceName字段,否则报错 
如下
image.png
可以看到pod的创建是依次从0号开始的,然后知道我们所需要的replica数
随机杀死1个pod后,statefulset生成的pod仍然是之前的ip,如下
image.png
我们杀死1个由deploy生成的pod,然后对比下生成的pod的ip,如下
image.png
可以看到,由statefulset产生的pod的ip在生命周期内是固定不变的,而由deploy产生的pod的ip则是随机分配的,pod杀死后,新pod的ip是全新的。

DaemonSet

简写ds,生产环境中,除了有状态的pod和无状态的pod之外,往往有些工作只能在本机进行,比如收集宿主机监控信息的agent这种,就必须固定运行某个节点上,那么对于这种情况,我们可以使用daemonset来应对。
由daemonset创建的pod会确保每个node节点上都有1个pod( 当然了,可以通过taint,node selector,Affinity,Toleration来限制ds的范围 ),当node移除集群后,该节点上的pod自动消亡。
我们创建1个ds来做验证, daemonset中定义的restartpolicy必须为always ,如下

[root@a test]$ cat busybox-httpd-ds-v1.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    app: busybox-httpd
  name: busybox-httpd
spec:
  selector:
    matchLabels:
      app: busybox-httpd
  template:
    metadata:
      labels:
        app: busybox-httpd
    spec:
      containers:
      - image: registry.cn-xx.aliyuncs.com/xx/busyboxhttpd:v1
        imagePullPolicy: Always
        name: busybox-httpd
        ports:
        - name: v1
          containerPort: 80
      imagePullSecrets:
      - name: regcred-test

使用kubectl apply -f创建该ds后,使用kubectl get po -o wide可以看到ds所产生的pod会在每个node节点上都会出现1个( 因为本次测试kubernetes集群只有1个节点,所以只会显示1个 )
image.png

Job和Cronjob

简写job,除了ds,sts,deploy常用之外,还有1个比较特别的,就是job。见名知义,此类控制器产生的pod是为了完成任务的,类似linux中的job和cronjob一样。

job

先来看一个job的yaml如下

[root@a test]$ cat busybox-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: busybox-pi
spec:
  template:
    spec:
      containers:
      - image: registry.cn-xx.aliyuncs.com/xxx/busyboxhttpd:v1
        name: busybox-pi
        ## 下面的command表示,计算pi的值,并且计算到小数点后1000位
        command: ["sh", "-c", "echo 'scale=1000; 4*a(1)' | bc -l "]
        ## 该job运行失败后,永远不会重新创建pod,避免了某些情况下job无法完成的
        ## 时候,就疯狂创建pod,导致node节点上资源枯竭
      restartPolicy: Never
      imagePullSecrets:
      - name: regcred-test

使用kubectl apply -f创建后,可以看到该job的创建过程
image.png
使用kubectl logs可以查看该job的输出日志
image.png
如上,确实看到了busybox镜像计算到了pi的第1000位,然后就结束了该pod的生命周期。

cronjob

再来看一下cronjob的
cronjob的定时任务写法和linux中的cronjob其实一样
其yaml文件如下

[root@a test]$ cat busybox-cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: busybox-hello
spec:
## 每1分钟运行1次
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - image: registry.cn-xx.aliyuncs.com/xx/busyboxhttpd:v1
            name: busybox-hello
            command: ["sh", "-c", "echo hello"]
          restartPolicy: Never
          imagePullSecrets:
          - name: regcred-test

使用kubectl apply -f只有,可以看到成功创建了job,且打印出了hello字段,如下
image.png

ReplicaSet

简写rs,是新一代的副本控制器,旧一代的副本控制器称之为ReplicaController(简写rc),相对于rc而严,rs所能支持的selector更复杂。

特殊Pod——StaticPod

在Kubernetes中,基本上所有的pod都会被各种控制器所管理,但是有1种pod不会被控制器管理,那就是static pod,这种pod由kubelet直接管理,且不会与api server通信,生命周期与kubernetes无关。

  1. 需要在kubelet的config文件中配置staticPodPath字段

image.png

  1. 在staticPodPath配置的目录下写入pod的yaml文件,如下
[root@a kubernetes]$ cat /etc/kubernetes/nginx-staticpod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: static-web
  labels:
    role: myrole
spec:
  containers:
    - name: web
      image: nginx
      ports:
        - name: web
          containerPort: 80
          protocol: TCP
  1. 重启kubelet,查看pod

image.png
可以看到,虽然可以使用kubectl命令来删除该pod,但是该pod会自动重启,即便是使用docker rm删除也会被自动重启

参考文档 Kubernetes官方文档