1 Namespace

Namespace是kubernetes系统中的一种非常重要资源,它的主要作用是用来实现多套环境的资源隔离或者多租户的资源隔离
默认情况下,kubernetes集群中的所有的Pod都是可以相互访问的。但是在实际中,可能不想让两个Pod之间进行互相的访问,那此时就可以将两个Pod划分到不同的namespace下。kubernetes通过将集群内部的资源分配到不同的Namespace中,可以形成逻辑上的”组”,以方便不同的组的资源进行隔离使用和管理。

默认情况下,Kubernetes 会初始化四个名称空间:

  1. kubectl get ns
  2. 或者写成
  3. kubectl get namespace
  4. [root@k8s-master ~]# kubectl get namespace
  5. NAME STATUS AGE
  6. default Active 27h #所有未指定Namespace的对象都会被分配在default命名空间
  7. kube-node-lease Active 27h #集群节点之间的心跳维护,v1.13开始引入
  8. kube-public Active 27h #此命名空间下的资源可以被所有人访问(包括未认证用户),主要是为集群预留的,如:在某些情况中,某些 Kubernetes 对象应用应该能被所有集群用户访问到
  9. kube-system Active 27h #所有由Kubernetes系统创建的资源都处于这个命名空间

image.png

1.1 名称空间的操作

1.1.1 名称的查看

#1.查看所有的namespace
kubectl get ns
#2.查看指定的ns 命令:kubectl get ns ns名称
kubectl get ns default
#3.查看ns详情 命令:kubectl describe ns ns名称
kubectl describe ns default

1.1.2 创建和删除

方法一创建namespace

命令:kubectl create ns 需要创建的名称空间
kubectl create ns test

方法一删除名称空间

命令:kubectl create ns 需要删除名称空间的名字
kubectl delete ns test

方法二,yaml创建namespace,先新建一个yaml文件,内容如下

vim k8s-namespace-test.yaml
apiVersion: v1
kind: Namespace
metadata:
  name:  test1 # 名称空间的名字
spec: {}  
status: {}

创建名称空间

kubectl apply -f k8s-namespace-test.yaml

方法二删除名称空间

kubectl delete -f k8s-namespace-test.yaml

2 Pod

kubernetes在集群启动之后,集群中的各个组件也都是以Pod方式运行的。

2.1 pod操作

2.1.1 pod查看

#查看所有pod运行情况
kubectl get pods -A
#查看pod的详细信息
kubectl describe -n default pod nginx-65c4bffcb6-2t96r

2.1.2 命令行创建pod

#命令格式:kubectl run (pod控制器名称) [参数]
# --image  指定Pod的镜像
# --port   指定端口
# --namespace  指定namespace

kubectl run nginx --image=nginx:latest --port=80 --namespace test 
deployment.apps/nginx created

删除pod

kubectl delete -n test pod nginx
#我发现,显示删除Pod成功,但是再查询,发现又新产生了一个
#先查看当前namespace下的pod控制器
kubectl get deploy -n test
#接下来,删除此pod控制器
kubectl delete deploy nginx -n test
#稍等一下,发现pod被删除了
kubectl get pods -n test

2.1.3 yaml创建pod

vim pod-nginx.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: test
spec:
  containers:
  - image: nginx:latest
    name: pod
    ports:
    - name: nginx-port
      containerPort: 80
      protocol: TCP
      hostPort: 8081
创建:kubectl apply -f pod-nginx.yaml
删除:kubectl delete -f pod-nginx.yaml

2.2 pod生命周期

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

  • pod创建过程
  • 运行初始化容器(init container)过程
  • 运行主容器(main container)
    • 容器启动后钩子(post start)、容器终止前钩子(pre stop)
    • 容器的存活性探测(liveness probe)、就绪性探测(readiness probe)
  • pod终止过程

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

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

2.2.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中

image.png
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对于用户已不可见

2.2.2 初始化容器

初始化容器是在pod的主容器启动之前要运行的容器,主要是做一些主容器的前置工作,它具有两大特征:

  1. 初始化容器必须运行完成直至结束,若某初始化容器运行失败,那么kubernetes需要重启它直到成功完成
  2. 初始化容器必须按照定义的顺序执行,当且仅当前一个成功之后,后面的一个才能运行

初始化容器有很多的应用场景,下面列出的是最常见的几个:

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

测试

vi k8s-pod-life.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-life
  labels:
    app: pod-life
spec:
  volumes:
    - name: context-vol
      emptyDir: {}
  initContainers: # Pod 在启动 containers 之前,先要运行 initContainers 中的所有容器
    - name: nginx-init
      image: alpine # 必须有终结的那个时刻,一般不要用一直启动的镜像
      command: ["/bin/sh","-c","echo 2222 > /app/index.html;sleep 15;"]
      volumeMounts:
        - mountPath: /app
          name: context-vol
      securityContext:
        privileged: true # 使用特权模式运行容器,需要慎用!!!
  containers:
    - name: nginx
      image: nginx:1.20
      imagePullPolicy: IfNotPresent
      volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: context-vol
  restartPolicy: Always
kubectl apply -f k8s-pod-life.yaml

2.2.3 钩子函数

钩子函数能够感知自身生命周期中的事件,并在相应的时刻到来时运行用户指定的程序代码。

kubernetes在主容器的启动之后和停止之前提供了两个钩子函数:

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

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

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

    ……
    lifecycle:
      postStart: 
        exec:
          command:
          - cat
          - /tmp/healthy
    ……
    
  • TCPSocket:在当前容器尝试访问指定的socket

    ……      
    lifecycle:
      postStart:
        tcpSocket:
          port: 8080
    ……
    
  • HTTPGet:在当前容器中向某url发起http请求

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

    测试:

    vi pod-hook-exec.yaml
    
    apiVersion: v1
    kind: Pod
    metadata:
    name: pod-hook-exec
    namespace: test
    labels: pod-hook-exec
    spec:
    containers:
    - name: nginx-1.20
     image: nginx:1.20
     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"]
    
    kubectl apply -f pod-hook-exec.yaml
    

2.2.4 容器探测

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

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

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

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

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

    ……
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
    ……
    
  • TCPSocket:将会尝试访问一个用户容器的端口,如果能够建立这条连接,则认为程序正常,否则不正常

    ……      
    livenessProbe:
      tcpSocket:
        port: 8080
    ……
    
  • HTTPGet:调用容器内Web应用的URL,如果返回的状态码在200和399之间,则认为程序正常,否则不正常

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

    方式一:Exec

    vi pod-liveness-exec.yaml
    
    apiVersion: v1
    kind: Pod
    metadata:
    name: pod-liveness-exec
    namespace: test
    spec:
    containers:
    - name: nginx
      image: nginx:1.20
      ports: 
      - name: nginx-port
        containerPort: 80
      livenessProbe:
        exec:
          command: ["/bin/cat","/tmp/hello.txt"] # 执行一个查看文件的命令
    
    kubectl apply -f pod-liveness-exec.yaml
    

方式二:TCPSocket

vi pod-liveness-tcpsocket.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-liveness-tcpsocket
  namespace: test
spec:
  containers:
  - name: nginx
    image: nginx:1.20
    ports: 
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      tcpSocket:
        port: 8080 # 尝试访问8080端口
kubectl apply -f pod-liveness-tcpsocket.yaml

方式三:HTTPGet

vi pod-liveness-httpget.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-liveness-httpget
  namespace: test
spec:
  containers:
  - name: nginx
    image: nginx:1.20
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      httpGet:  # 其实就是访问http://127.0.0.1:80/hello  
        scheme: HTTP #支持的协议,http或者https
        port: 80 #端口号
        path: /hello #URI地址
kubectl apply -f pod-liveness-httpget.yaml

还有其他的配置

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

下面稍微配置两个,演示下效果即可:

[root@k8s-master ~]# more pod-liveness-httpget.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-liveness-httpget
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      httpGet:
        scheme: HTTP
        port: 80 
        path: /
      initialDelaySeconds: 30 # 容器启动后30s开始探测
      timeoutSeconds: 5 # 探测超时时间为5s

2.2.5 重启策略

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

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

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

测试:

vi pod-restartpolicy.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-restartpolicy
  namespace: test
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
#创建
kubectl apply -f pod-restartpolicy.yaml
#查看Pod详情,发现nginx容器失败
kubectl describe -n test pod pod-restartpolicy  
# 多等一会,再观察pod的重启次数,发现一直是0,并未重启
kubectl get -n test pod pod-restartpolicy

3 Pod控制器

3.1 Pod 控制器介绍

Pod是kubernetes的最小管理单元,在kubernetes中,按照pod的创建方式可以将其分为两类:

  • 自主式pod:kubernetes直接创建出来的Pod,这种pod删除后就没有了,也不会重建。
  • 控制器创建的pod:kubernetes通过控制器创建的pod,这种pod删除了之后还会自动重建。

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

常用pod控制器类型:

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

    3.2 ReplicaSet(RS)

    ReplicaSet的主要作用是保证一定数量的pod正常运行,它会持续监听这些Pod的运行状态,一旦Pod发生故障,就会重启或重建。同时它还支持对pod数量的扩缩容和镜像版本的升降级。

3.2.1 ReplicaSet 的资源清单文件:

apiVersion: apps/v1 # 版本号
kind: ReplicaSet # 类型       
metadata: # 元数据
  name: # rs名称 
  namespace: # 所属命名空间 
  labels: #标签
    controller: rs
spec: # 详情描述
  replicas: 3 # 副本数量
  selector: # 选择器,通过它指定该控制器管理哪些pod
    matchLabels:      # Labels匹配规则
      app: nginx-pod
    matchExpressions: # Expressions匹配规则
      - {key: app, operator: In, values: [nginx-pod]}
  template: # 模板,当副本数量不足时,会根据下面的模板创建pod副本
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
        ports:
        - containerPort: 80

3.2.2 创建ReplicaSet

vim k8s-rs-test.yaml
apiVersion: apps/v1 # 版本
kind: ReplicaSet # 类型
metadata: # 元数据
  name: nginx-rs-test # 名称
  namespace: dev
  labels: # 标签
    app: nginx
spec: # 规格,期望的状态
  replicas: 3 # 副本数量
  selector: # selector 选择器,通常而言,和 template 模板中的 labels 保持一致
    matchLabels:
      app: nginx
  template: # Pod 模板,原来怎么编写 Pod ,这里也怎么写。
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
#创建rs
kubectl apply -f k8s-rs-test.yaml

3.2.3 查看ReplicaSet

#查看rs
# DESIRED:期望副本数量  
# CURRENT:当前副本数量  
# READY:已经准备好提供服务的副本数量
[root@k8s-master ~]# kubectl get rs,pods -n dev
NAME                            DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-rs-test   3         3         3       70s

NAME                      READY   STATUS    RESTARTS   AGE
pod/nginx-rs-test-6rsbl   1/1     Running   0          70s
pod/nginx-rs-test-blqn6   1/1     Running   0          70s
pod/nginx-rs-test-vdbdh   1/1     Running   0          70s

3.2.4 扩缩容

#编辑rs的副本数量,修改spec:replicas: 4即可
kubectl edit rs nginx-rs-test -n dev

#查看pod数量
kubectl get pods -n dev

#也可使用scale命令实现扩缩容, 后面--replicas=n直接指定目标数量即可
kubectl scale rs nginx-rs-test --replicas=2 -n dev

#再次查看pod数量,发现nginx-rs-test已经变成2个了
kubectl get pods -n dev

3.2.5 镜像升级

# 编辑rs的容器镜像 - image: nginx:1.20
kubectl edit rs nginx-rs-test -n dev
#再次查看,发现镜像版本已经变更为nginx:1.20
[root@k8s-master ~]# kubectl get rs -n dev -owide
NAME            DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES       SELECTOR
nginx-rs-test   2         2         2       11m   nginx        nginx:1.20   app=nginx

#同样,我也可以用命令完成
#kubectl set image rs rs名称 容器=镜像版本 -n 名称空间
kubectl set image rs nginx-rs-test nginx=nginx:1.20.2 -n dev

#查看,镜像版本已变更为1.20.2
[root@k8s-master ~]# kubectl get rs -n dev -owide
NAME            DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES         SELECTOR
nginx-rs-test   2         2         2       14m   nginx        nginx:1.20.2   app=nginx

3.2.6 删除ReplicaSet

# 使用kubectl delete命令会删除此RS以及它管理的Pod
# 在kubernetes删除RS前,会将RS的replicasclear调整为0,等待所有的Pod被删除后,在执行RS对象的删除
kubectl delete rs nginx-rs-test -n dev
#查看是否删除
kubectl get rs -n dev -owide

#如果希望仅仅删除RS对象(保留Pod),可以使用kubectl delete命令时添加--cascade=false选项(不推荐)
kubectl delete rs nginx-rs-test -n dev --cascade=false

#也可直接通过yaml直接删除
kubectl delete -f k8s-rs-test.yaml

3.3 Deployment(Deploy)

3.3.1 deployment介绍

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

Deployment的特点

  • 支持ReplicaSet的所有功能
  • 支持发布的停止、继续
  • 支持滚动升级和回滚版本


3.3.2 Deployment的资源清单文件:

apiVersion: apps/v1 # 版本号
kind: Deployment # 类型       
metadata: # 元数据
  name: # rs名称 
  namespace: # 所属命名空间 
  labels: #标签
    controller: deploy
spec: # 详情描述
  replicas: 3 # 副本数量
  revisionHistoryLimit: 3 # 保留历史版本
  paused: false # 暂停部署,默认是false
  progressDeadlineSeconds: 600 # 部署超时时间(s),默认是600
  strategy: # 策略
    type: RollingUpdate # 滚动更新策略
    rollingUpdate: # 滚动更新
      maxSurge: 30% # 最大额外可以存在的副本数,可以为百分比,也可以为整数
      maxUnavailable: 30% # 最大不可用状态的 Pod 的最大值,可以为百分比,也可以为整数
  selector: # 选择器,通过它指定该控制器管理哪些pod
    matchLabels:      # Labels匹配规则
      app: nginx-pod
    matchExpressions: # Expressions匹配规则
      - {key: app, operator: In, values: [nginx-pod]}
  template: # 模板,当副本数量不足时,会根据下面的模板创建pod副本
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
        ports:
        - containerPort: 80

3.3.3 创建deployment

vim nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment      
metadata:
  name: nginx-deployment
  namespace: test
spec: 
  replicas: 3
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.20.2
#创建deployment
kubectl apply -f pc-deployment.yaml
#查看deployment
# UP-TO-DATE 最新版本的pod的数量
# AVAILABLE  当前可用的pod的数量
[root@k8s-master ~]# kubectl get deploy nginx-deployment -n test
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           94s

#查看rs
[root@k8s-master ~]# kubectl get rs -n test
NAME                       DESIRED   CURRENT   READY   AGE
nginx-deployment-b6c5fdf   3         3         3       2m15s

#查看pod
kubectl get pods -n test

3.3.4 扩缩容

#变更副本数量为4个
kubectl scale deploy nginx-deployment --replicas=3 -n test
#查看deployment
[root@k8s-master ~]# kubectl get deployment nginx-deployment -n test
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   4/4     4            4           11h
#查看pod
kubectl get pods -n test

3.3.5 镜像更新

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

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

3.2.6 重建更新

vim nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: test
  labels:
    app: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  revisionHistoryLimit: 15 # 旧副本集保留的数量,即可回滚的数量。默认为 10 。
  progressDeadlineSeconds: 600 # 处理的最终期限,如果超过了这个指定的时间就会给集群汇报错误。默认为 600s 。
  paused: false # 暂停更新,默认为 false 。
  strategy: # 更新策略
    type: Recreate # Recreate:在创建出新的Pod之前会先杀掉所有已经存在的Pod
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.17.1
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
kubectl apply -f nginx-deployment.yaml
#变更镜像,将镜像修改为1.20
kubectl set image deployment nginx-deployment nginx=nginx:1.20 -n test
#观察升级过程
kubectl get pods -n test -w

3.2.7 滚动更新

vim nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: test
  labels:
    app: nginx-deployment
spec:
  replicas: 4
  selector:
    matchLabels:
      app: nginx
  revisionHistoryLimit: 15 # 旧副本集保留的数量,即可回滚的数量。默认为 10 。
  progressDeadlineSeconds: 600 # 处理的最终期限,如果超过了这个指定的时间就会给集群汇报错误。默认为 600s 。
  paused: false # 暂停更新,默认为 false 。
  strategy: # 更新策略
    type: RollingUpdate # 滚动更新
    rollingUpdate:
      maxSurge: 25% # 最大增量:一次最多新建几个 Pod,可以写数字或百分比,maxUnavailable 为 0 的时候,maxSurge 不能为 0 。
      maxUnavailable: 25% # 最大不可用量:最大不可用的 Pod,可以写数字或百分比
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.20.2
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
kubectl apply -f nginx-deployment.yaml
#变更镜像版本
kubectl set image deployment nginx-deployment nginx=nginx:1.20 -n test
#观察升级过程
kubectl get pods -n test -w
#
kubectl get deploy,rs,pods -n test

3.2.8 版本回退

deployment支持版本升级过程中的暂停、继续功能以及版本回退等诸多功能。

kubectl rollout: 版本升级相关功能,支持下面的选项

  • status 显示当前升级状态
  • history 显示 升级历史记录
  • pause 暂停版本升级过程
  • resume 继续已经暂停的版本升级过程
  • restart 重启版本升级过程
  • undo 回滚到上一级版本(可以使用—to-revision回滚到指定版本) ```yaml

    查看当前升级版本的状态

    kubectl rollout status deploy nginx-deployment -n test

    查看升级历史记录

    kubectl rollout history deploy nginx-deployment -n test

    有几次版本记录,就说明完成过n-1次升级

版本回滚

这里直接使用—to-revision=1回滚到了1版本, 如果省略这个选项,就是回退到上个版本,就是2版本

kubectl rollout undo deployment nginx-deployment —to-revision=1 -n test

查看发现,通过nginx镜像版本可以发现到了第一版

查看rs,发现第一个rs中有4个pod运行,后面两个版本的rs中pod为运行

其实deployment之所以可是实现版本的回滚,就是通过记录下历史rs来实现的,

一旦想回滚到哪个版本,只需要将当前版本pod数量降为0,然后将回滚版本的pod提升为目标数量就可以了

kubectl get rs -n test

<a name="BRjXe"></a>
### 3.4 金丝雀发布
> Deployment控制器支持控制更新过程中的控制,如“暂停(pause)”或“继续(resume)”更新操作。
> 比如有一批新的Pod资源创建完成后立即暂停更新过程,此时,仅存在一部分新版本的应用,主体部分还是旧的版本。然后,再筛选一小部分的用户请求路由到新版本的Pod应用,继续观察能否稳定地按期望的方式运行。确定没问题之后再继续完成余下的Pod资源滚动更新,否则立即回滚更新操作。这就是所谓的金丝雀发布。

```yaml
#更新deployment的版本,并配置暂停deployment
kubectl set image deploy nginx-deployment nginx=nginx:1.21 -n test && kubectl rollout pause deployment nginx-deployment -n test

#观察更新状态
kubectl rollout status deploy nginx-deployment -n test

# 监控更新的过程,可以看到已经新增了一个资源,但是并未按照预期的状态去删除一个旧的资源,就是因为使用了pause暂停命令

kubectl get rs -n test -owide
kubectl get pods -n test
# 确保更新的pod没问题了,继续更新
kubectl rollout resume deploy nginx-deployment -n test
# 查看最后的更新情况
kubectl get rs -n test -o wide
kubectl get pods -n test

删除deployment

# 删除deployment,其下的rs和pod也将被删除
kubectl delete -f nginx-deployment.yaml

3.5 StatefulSet(sts)

3.5.1 statefulSet介绍

实例之间的不等关系以及实例对外数据有依赖关系的应用,就被称为”有状态应用”。 Deployment 部署的应用称为无状态应用,StatefulSet 部署的应用称为有状态应用

  • 无状态应用:网络可能会变(IP 地址)、存储可能会变(卷)、顺序可能会变(启动的顺序)。应用场景:业务代码,如:使用 SpringBoot 开发的商城应用的业务代码。
  • 有状态应用:网络不变、存储不变、顺序不变。应用场景:中间件,如:MySQL 集群、Zookeeper 集群、Redis 集群、MQ 集群

3.5.2 StatefulSet的功能

StatefulSet类似于ReplicaSet,不同之处在于它可以控制Pod的启动顺序,它为每个Pod设置唯一的标识。其具有一下功能:

  • 稳定的,唯一的网络标识符:即每个Pod有自己独有的域名,无论重启多少次都不会。
  • 稳定的,持久化存储:每个 Pod 始终对应各自的存储路径。
  • 有序的,优雅部署和缩放:按顺序地增加副本、减少副本,并在减少副本时执行清理。。
  • 有序的,自动滚动更新:按顺序自动地执行滚动更新。

3.5.3 Statefulset注意项

  • 需要定义pvc申请模板,每个pod使用不同的pvc。可以通过storageclass分配或者提前创建好pv。
  • 需要一个headless的service作为服务发现。
  • 如果需要删除statefulset,推荐将副本数置为0再删除。
  • 删除statefulset,并不会删除申请的pvc和pv。
  • 升级过程中,如果出现问题,可能需要人为干预。

3.5.4 部署StatefulSet

在创建StatefulSet之前先创建PV:

vi pv-nginx-statefulset.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv01
  labels:
    release: stable
spec:
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  hostPath:
    path: /tmp/data

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv02
  labels:
    release: stable
spec:
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  hostPath:
    path: /tmp/data
#创建pv
kubectl apply -f pv-nginx-statefulset.yaml
检查pv
kubectl get pv

创建statefulset的yaml文件

vi nginx-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx-statefulset
  namespace: test
spec:
  selector:
    matchLabels:
      app: sts-nginx
  serviceName: nginx-svc # 服务名称,这个字段需要和 service 的 metadata.name 相同
  replicas: 3 # 副本数
  template:
    metadata:
      labels:
        app: sts-nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.20
---
# 将 StatefulSet 加入service
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  namespace: test
spec:
  selector:
    app: sts-nginx
  type: ClusterIP
  clusterIP: None # 不分配 ClusterIP ,形成无头服务,整个集群的 Pod 能直接访问,但是浏览器不可以访问。
  ports:
    - name: nginx
      protocol: TCP
      port: 80
      targetPort: 80
kubectl apply -f nginx-statefulset.yaml

4 Lable

Label是kubernetes系统中的一个重要概念。它的作用就是在资源上添加标识,用来对它们进行区分和选择。

Label的特点:

  • 一个Label会以key/value键值对的形式附加到各种对象上,如Node、Pod、Service等等
  • 一个资源对象可以定义任意数量的Label ,同一个Label也可以被添加到任意数量的资源对象上去
  • Label通常在资源对象定义时确定,当然也可以在对象创建后动态添加或者删除

可以通过Label实现资源的多维度分组,以便灵活、方便地进行资源分配、调度、配置、部署等管理工作。

一些常用的Label 示例如下:

  • 版本标签:”version”:”release”, “version”:”stable”……
  • 环境标签:”environment”:”dev”,”environment”:”test”,”environment”:”pro”
  • 架构标签:”tier”:”frontend”,”tier”:”backend”

4.1 label的操作

4.1.1 label的查看

#显示所有pod的label的信息
[root@k8s-master ~]# kubectl get pods -n default --show-labels
NAME                     READY   STATUS    RESTARTS   AGE     LABELS
nginx-65c4bffcb6-2t96r   1/1     Running   0          37h     app=nginx,pod-template-hash=65c4bffcb6
nginx-pod                1/1     Running   0          2m48s   app=nginx,environment=prod

4.1.2 label添加

#为名称空间default下pod为nginx-pod添加一个hello=test的标签
kubectl label -n default pod nginx-pod hello=test

4.1.3 label更新

#为名称空间default下pod为nginx-pod的label修改为hello=test1
kubectl label -n default pod nginx-pod hello=test1 --overwrite

4.1.4 label删除

#将名称空间default下pod为nginx-pod的label删除
kubectl label -n default pod nginx-pod hello-

4.1.5 yaml方式操作label

vim label-pod-test.yaml
#为名称空间为test下的pod是nginx-test添加label为env=test,version=1.0
apiVersion: v1
kind: Pod
metadata:
  name: nginx-test
  namespace: test
  labels:
    version: "1.0" 
    env: "test"
spec:
  containers:
  - image: nginx:latest
    name: pod
    ports:
    - name: nginx-port
      containerPort: 80
      protocol: TCP
      hostPort: 8081
kubectl apply -f label-pod-test.yaml

5 工作负载Deployment

在kubernetes中,Pod是最小的控制单元,但是kubernetes很少直接控制Pod,一般都是通过Pod控制器来完成的。Pod控制器用于pod的管理,确保pod资源符合预期的状态,当pod的资源出现故障时,会尝试进行重启或重建pod。
在kubernetes中Pod控制器的种类有很多,本章节只介绍一种:Deployment

5.1 Deployment的操作

5.1.1 Deployment方式创建pod

# 命令格式: kubectl create deployment 名称  [参数] 
# --image  指定pod的镜像
# --port   指定端口
# --replicas  指定创建pod数量
# --namespace  指定namespace
kubectl run nginx --image=nginx:latest --port=80 --replicas=3 -n test \
deployment.apps/nginx created

5.1.2 查看创建的pod

#查看创建的Pod
kubectl get pods -n 
#查看deployment的信息
[root@k8s-master ~]# kubectl get deployment 
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   1/1     1            1           37h
# UP-TO-DATE:成功升级的副本数量
# AVAILABLE:可用副本的数量
kubectl describe deploy nginx -n test

5.1.3 删除

 kubectl delete deploy nginx -n test

5.1.4 yaml方式部署

vim deploy-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: dev
spec:
  replicas: 3
  selector:
    matchLabels:
      run: nginx
  template:
    metadata:
      labels:
        run: nginx
    spec:
      containers:
      - image: nginx:latest
        name: nginx
        ports:
        - containerPort: 80
          protocol: TCP
          hostPort: 8081
创建:kubectl create -f deploy-nginx.yaml

删除:kubectl delete -f deploy-nginx.yaml