k8s之平滑升级

news2024/11/13 13:27:22

写在前面

通过POD 应用就有了存在的形式,通过deployment 保证了POD在一定的数量,通过service 可以实现一定数量的POD以负载均衡的方式对外提供服务。但,如果是程序开发了新功能,需要上线,该怎么办呢?对此k8s提供了平滑升级的解决方案,本文就一起来看下吧!

在这里插入图片描述

1:k8的版本是什么

在正式开始前,我们还需要看下什么是版本。在我们日常开发中完成一个功能后,一般都会在git上打一个tag,比如tag-v1.0,之后可能还会有其它版本,如下图:

在这里插入图片描述

这就是程序的版本,那么对于k8s来说版本是什么呢?当然肯定不是git这里的版本,而是yaml文件POD的template内容,但是yaml文件可能很大,总不能将其整个内容作为版本号吧,自然是不可以的,所以k8s采用的方案是将template部分执行hash得到一个一定长度的字符串,如下:

dongyunqi@mongodaddy:~/k8s$ kubectl get pod
NAME                      READY   STATUS    RESTARTS   AGE
ngx-dep-name-bfbb5f64b-ds78j   1/1     Running   0          6s
ngx-dep-name-bfbb5f64b-xr6gw   1/1     Running   0          6s

NAME列中的bfbb5f64b就是哈希template后的版本号了。

2:如何平滑升级

这里我们使用Nginx的镜像来测试,首先定义个ConfigMap,如下:

apiVersion: v1
kind: ConfigMap
metadata:
  name: ngx-conf

data:
  default.conf: |
    server {
      listen 80;
      location / {
        default_type text/plain;
        return 200
          'ver : $nginx_version\nsrv : $server_addr:$server_port\nhost: $hostname\n';
      }
    }

apply:

dongyunqi@mongodaddy:~/k8s$ kubectl apply -f smooth-upgrade-cm.yml 
configmap/ngx-conf created
dongyunqi@mongodaddy:~/k8s$ kubectl get cm
NAME               DATA   AGE
ngx-conf           1      8s

接着我们来创建deployment,yaml如下:

dongyunqi@mongodaddy:~/k8s$ cat smooth-upgrade-deployment.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: ngx-dep-app
  name: ngx-dep-name

spec:
  replicas: 3
  selector:
    matchLabels:
      app: ngx-dep-pod

  template:
    metadata:
      labels:
        app: ngx-dep-pod
    spec:
      volumes:
      - name: ngx-conf-vol
        configMap:
          name: ngx-conf

      containers:
      - image: nginx:alpine
        name: nginx
        ports:
        - containerPort: 80

        volumeMounts:
        - mountPath: /etc/nginx/conf.d
          name: ngx-conf-vol

apply后查看如下:

dongyunqi@mongodaddy:~/k8s$ kubectl apply -f smooth-upgrade-deployment.yml 
deployment.apps/ngx-dep-name created
dongyunqi@mongodaddy:~/k8s$ kubectl get deployment
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
ngx-dep-name   3/3     3            3           5s

看下POD:

dongyunqi@mongodaddy:~/k8s$ kubectl get pod -l app=ngx-dep-pod
NAME                           READY   STATUS    RESTARTS   AGE
ngx-dep-name-dcc8b7bfd-bhksq   1/1     Running   0          111s
ngx-dep-name-dcc8b7bfd-t96np   1/1     Running   0          111s
ngx-dep-name-dcc8b7bfd-tsvmc   1/1     Running   0          111s

可以看到此时的版本号是dcc8b7bfd,但此时我们还不能访问POD,需要继续定义service,yaml如下:

dongyunqi@mongodaddy:~/k8s$ cat smooth-upgrade-service.yml 
apiVersion: v1
kind: Service
metadata:
  name: ngx-svc
  
spec:
  selector:
    app: ngx-dep-pod # 查找app label为ngx-dep-pod的POD
    
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP

以上service的80端口映射到后端POD们的80端口。

apply后查看如下:

dongyunqi@mongodaddy:~/k8s$ kubectl apply -f smooth-upgrade-service.yml 
service/ngx-svc created
dongyunqi@mongodaddy:~/k8s$ kubectl get service
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   11d
ngx-svc      ClusterIP   10.99.187.192   <none>        80/TCP    6s
dongyunqi@mongodaddy:~/k8s$ kubect describe service ngx-svc
kubect: command not found
dongyunqi@mongodaddy:~/k8s$ kubectl describe service ngx-svc
Name:              ngx-svc
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=ngx-dep-pod
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.99.187.192
IPs:               10.99.187.192
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.10.4.10:80,10.10.4.11:80,10.10.4.12:80
Session Affinity:  None
Events:            <none>

接着为了能够在外部访问我们使用port-forward来转发Node的8080端口到service的80端口,如下:

dongyunqi@mongodaddy:~/k8s$ kubectl port-forward svc/ngx-svc 8080:80 &
[1] 115371
dongyunqi@mongodaddy:~/k8s$ Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80

然后就可以访问了,如下:

dongyunqi@mongodaddy:~/k8s$ curl 127.0.0.1:8080
Handling connection for 8080
ver : 1.21.5
srv : 127.0.0.1:80
host: ngx-dep-name-dcc8b7bfd-bhksq

可以看到此时Nginx的版本号是1.21.5,接着我们来修改Nginx的版本号为nginx:1.22-alpine模拟应用的升级,deployment的yaml修改后如下:

dongyunqi@mongodaddy:~/k8s$ cat smooth-upgrade-deploymentv2.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: ngx-dep-app
  name: ngx-dep-name

spec:
  minReadySeconds: 15      # 确认Pod就绪的等待时间 
  replicas: 3
  selector:
    matchLabels:
      app: ngx-dep-pod

  template:
    metadata:
      labels:
        app: ngx-dep-pod
    spec:
      volumes:
      - name: ngx-conf-vol
        configMap:
          name: ngx-conf

      containers:
      - image: nginx:1.22-alpine
        name: nginx
        ports:
        - containerPort: 80

        volumeMounts:
        - mountPath: /etc/nginx/conf.d
          name: ngx-conf-vol

这里增加了minReadySeconds: 15来增加POD创建的间隔时间,不然k8s升级POD过快,不方便看到整个平滑升级的过程,接着apply:

dongyunqi@mongodaddy:~/k8s$ kubectl apply -f smooth-upgrade-deploymentv2.yml 
deployment.apps/ngx-dep-name configured

然后通过命令kubectl rollout status deployment ngx-dep-name来查看升级的过程:

dongyunqi@mongodaddy:~/k8s$ kubectl rollout status deployment ngx-dep-name
Waiting for deployment "ngx-dep-name" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "ngx-dep-name" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "ngx-dep-name" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "ngx-dep-name" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "ngx-dep-name" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "ngx-dep-name" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "ngx-dep-name" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "ngx-dep-name" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "ngx-dep-name" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "ngx-dep-name" rollout to finish: 1 old replicas are pending termination...
deployment "ngx-dep-name" successfully rolled out

以上展示了新POD的升级和老POD的销毁过程,我们也可以通过命令kubectl describe deploy ngx-dep-name来查看整个升级的过程,如下:

dongyunqi@mongodaddy:~/k8s$ kubectl describe deploy ngx-dep-name
...
Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  33m    deployment-controller  Scaled up replica set ngx-dep-name-dcc8b7bfd to 3
  Normal  ScalingReplicaSet  11m    deployment-controller  Scaled up replica set ngx-dep-name-7cfd649b6 to 1
  Normal  ScalingReplicaSet  10m    deployment-controller  Scaled down replica set ngx-dep-name-dcc8b7bfd to 2
  Normal  ScalingReplicaSet  10m    deployment-controller  Scaled up replica set ngx-dep-name-7cfd649b6 to 2
  Normal  ScalingReplicaSet  10m    deployment-controller  Scaled down replica set ngx-dep-name-dcc8b7bfd to 1
  Normal  ScalingReplicaSet  10m    deployment-controller  Scaled up replica set ngx-dep-name-7cfd649b6 to 3
  Normal  ScalingReplicaSet  9m45s  deployment-controller  Scaled down replica set ngx-dep-name-dcc8b7bfd to 0

每一行的含义如下:

Scaled up replica set ngx-dep-name-dcc8b7bfd to 3
    老版本POD有3个
Scaled up replica set ngx-dep-name-7cfd649b6 to 1
    新版本POD增加到1个
Scaled down replica set ngx-dep-name-dcc8b7bfd to 2
    老版本POD减少到2个
Scaled up replica set ngx-dep-name-7cfd649b6 to 2    
    新版本POD增加到2个
Scaled down replica set ngx-dep-name-dcc8b7bfd to 1
    老版本POD减少到1个
Scaled up replica set ngx-dep-name-7cfd649b6 to 3
    新版本POD增加到3个
Scaled down replica set ngx-dep-name-dcc8b7bfd to 0
    老版本POD减少到0个

整个过程新POD的个数就好像滚雪球一样越来越多,所以这个过程也被称为滚动更新,整个过程用图展示的话如下:

在这里插入图片描述

接着我们可以查看新POD的版本信息:

dongyunqi@mongodaddy:~/k8s$ kubectl get pod -l app=ngx-dep-pod
NAME                           READY   STATUS    RESTARTS   AGE
ngx-dep-name-7cfd649b6-6ddnk   1/1     Running   0          5m23s
ngx-dep-name-7cfd649b6-fslcz   1/1     Running   0          3m45s
ngx-dep-name-7cfd649b6-pwd5r   1/1     Running   0          4m2s

可以看到此时版本变成了7cfd649b6,也可以访问确认Nginx升级是否成功:

dongyunqi@mongodaddy:~/k8s$ Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80

dongyunqi@mongodaddy:~/k8s$ curl 127.0.0.1:8080
Handling connection for 8080
ver : 1.22.1
srv : 127.0.0.1:80
host: ngx-dep-name-7cfd649b6-6ddnk

可以看到此时Nginx的版本号就变成了1.22.1了,说明Nginx就升级成功了。

3:更新历史维护

系统升级后并非万事大吉,因为可能会因为一个严重的bug需要我们将应用回退到之前的版本,k8s针对这种情况也提供了对应的解决方案,具体是使用命令kubectl rollout,如下查看更新历史:

dongyunqi@mongodaddy:~/k8s$ kubectl rollout history deploy ngx-dep-name
deployment.apps/ngx-dep-name 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

可以看到此时我们有1和2两个版本,但CHANGE-CAUSE<none>,就好像提交的代码没有comment一样,多少有些别扭,想要让该列有值需要在deployment的metadata中增加annotations: kubernetes.io/change-cause: 更新原因,为了测试,我们再来对Nginx进行一次升级,使用版本1.23.3,修改后yaml如下:

dongyunqi@mongodaddy:~/k8s$ cat smooth-upgrade-deploymentv3.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: ngx-dep-app
  name: ngx-dep-name
  annotations:
    kubernetes.io/change-cause: upgrade ngixn to 1.23.3  # ***

spec:
  replicas: 3
  selector:
    matchLabels:
      app: ngx-dep-pod

  template:
    metadata:
      labels:
        app: ngx-dep-pod
    spec:
      volumes:
      - name: ngx-conf-vol
        configMap:
          name: ngx-conf

      containers:
      - image: nginx:1.23.3 # ***
        name: nginx
        ports:
        - containerPort: 80

        volumeMounts:
        - mountPath: /etc/nginx/conf.d
          name: ngx-conf-vol

***为修改的行。apply后再来查看更新历史:

dongyunqi@mongodaddy:~/k8s$ kubectl rollout history deploy ngx-dep-name
deployment.apps/ngx-dep-name 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         upgrade ngixn to 1.23.3

可以看到此时CHANGE-CAUSE就有值了(看着舒服多了),有了这个更新历史之后,就可以使用命令 kubectl rollout undo,也可以加上参数 --to-revision 回退到任意一个历史版本,如下回退到最老的版本1:

dongyunqi@mongodaddy:~/k8s$ kubectl rollout undo deploy ngx-dep-name --to-revision=1
deployment.apps/ngx-dep-name rolled back

写在后面

小结

本文我们一起看了k8s的平滑升级方案,并分析了滚动更新的具体过程,查看了更新历史,以及如何回滚更新到指定版本等内容。希望本文能够帮助到你。

参考文章列表

k8s之Service 。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/182602.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

jvm相关,jvm内存模型,java程序运行流程及jvm各个分区的作用、对象的组成(针对hotspot虚拟机)--学习笔记

java程序运行时的运行模型 在jdk1.8之前的元空间&#xff0c;称为永久代并将元空间挪到了堆直接使用本地内存&#xff0c;不再占用堆空间 jvm内存结构划分 堆&#xff08;方法区&#xff09;和元空间是线程共有的&#xff0c;其他部分是线程私有的 每创建一个线程都会创建一个…

MYSQL中常见的知识问题(二)

1、B树和B树的区别&#xff0c;MYSQL为啥使用B树。 1.1、B树 目的&#xff1a;为了存储设备或者磁盘设计的一种平衡查找树。 定义&#xff08;M阶B树&#xff09;&#xff1a;a、树中的每个节点最多有m个孩子。 b、除了根节点和叶子节点外&#xff0c;其他节点最少含有m/2(取上…

08-网络管理-iptables基础(四表五链、禁止ping、防火墙规则添加/删除、自建链使用、SNAT\DNAT模式、FTP服务器防火墙规则)待发布

文章目录1. 概述1.1 四表1.2 五链1.3 四表五链的关系1.4 使用流程2. 语法和操作1.1 语法1.2 常用操作命令1.3 基本匹配条件1.4 基本动作1.5 常用命令示例- 设置默认值- 禁止80端口访问- 查看防火墙规则- 保存规则- 允许ssh- 禁止ping- 删除规则- 清除规则&#xff08;不包括默认…

HR软件如何识别保留优秀员工

在企业信息化的时代&#xff0c;越来越多的年轻员工开始追求他们的激情&#xff0c;辞掉那些乏味的工作&#xff0c;而选择加入重视员工生活质量的企业。他们不再追随那些以牺牲员工福利为代价追求利润的公司。 员工认可度有助于加强组织中的团队合作关系&#xff0c;反过来&a…

木马程序(病毒)

木马的由来 "特洛伊木马"&#xff08;trojan horse&#xff09;简称"木马"&#xff0c;据说这个名称来源于希腊神话《木马屠城记》。古希腊有大军围攻特洛伊城&#xff0c;久久无法攻下。于是有人献计制造一只高二丈的大木马&#xff0c;假装作战马神&…

实用技巧盘点:Python和Excel交互的常用操作

大家好&#xff0c;在以前&#xff0c;商业分析对应的英文单词是Business Analysis&#xff0c;大家用的分析工具是Excel&#xff0c;后来数据量大了&#xff0c;Excel应付不过来了&#xff08;Excel最大支持行数为1048576行&#xff09;&#xff0c;人们开始转向python和R这样…

【通信原理(含matlab程序)】实验六:模拟信号的数字化

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; 本人持续分享更多关于电子通信专业内容以及嵌入式和单片机的知识&#xff0c;如果大家喜欢&#xff0c;别忘点个赞加个关注哦&#xff0c;让我们一起共同进步~ &#x…

一文理解JVM虚拟机

一. JVM内存区域的划分 1.1 java虚拟机运行时数据区 java虚拟机运行时数据区分布图&#xff1a; JVM栈&#xff08;Java Virtual Machine Stacks&#xff09;&#xff1a; Java中一个线程就会相应有一个线程栈与之对应&#xff0c;因为不同的线程执行逻辑有所不同&#xff…

【JavaGuide面试总结】Java IO篇

【JavaGuide面试总结】Java IO篇1.有哪些常见的 IO 模型?2.Java 中 3 种常见 IO 模型BIO (Blocking I/O)NIO (Non-blocking/New I/O)AIO (Asynchronous I/O)1.有哪些常见的 IO 模型? UNIX 系统下&#xff0c; IO 模型一共有 5 种&#xff1a; 同步阻塞 I/O、同步非阻塞 I/O、…

浏览器兼容性 问题产生原因 厂商前缀 滚动条 css hack 渐近增强 和 优雅降级 caniuse

目录浏览器兼容性问题产生原因厂商前缀滚动条css hack渐近增强 和 优雅降级caniuse浏览器兼容性 问题产生原因 市场竞争标准版本的变化 厂商前缀 比如&#xff1a;box-sizing&#xff0c; 谷歌旧版本浏览器中使用-webkit-box-sizing:border-box 市场竞争&#xff0c;标准没有…

Java多线程案例之线程池

前言&#xff1a;在讲解线程池的概念之前&#xff0c;我们先来谈谈线程和进程&#xff0c;我们知道线程诞生的目的其实是因为进程太过重量了&#xff0c;导致系统在 销毁/创建 进程时比较低效&#xff08;具体指 内存资源的申请和释放&#xff09;。 而线程&#xff0c;其实做…

14岁初中生将免去四考,保送清华本硕博连读,乡亲们敲锣打鼓祝贺

导语&#xff1a; 很多学生在很小的时候&#xff0c;都曾有豪言壮语&#xff1a;“将来一定要考上清华北大”。可是真正接受教育&#xff0c;开始学习之后&#xff0c;学生们才能发现&#xff0c;原来学习这么难。不要说真的走进清华北大&#xff0c;即使是进入“985”大学&am…

C++ 智能指针(一) auto_ptr

文章目录前言 - 什么是智能指针&#xff1f;std::auto_ptrauto_ptr的使用常用成员方法&#xff1a;1. get()方法2. release()方法3. reset()方法4. operator()5. operator*() & operator->()auto_ptr的局限性前言 - 什么是智能指针&#xff1f; 在全文开始之前&#xf…

Redis事务的概述、设计与实现

1 Redis事务概述事务提供了一种“将多个命令打包&#xff0c; 然后一次性、按顺序地执行”的机制&#xff0c; 并且事务在执行的期间不会主动中断 —— 服务器在执行完事务中的所有命令之后&#xff0c; 才会继续处理其他客户端的其他命令。以下是一个事务的例子&#xff0c; 它…

mysql-事务以及锁原理讲解(二)

1、前言 众所周知&#xff0c;事务和锁是mysql中非常重要功能&#xff0c;同时也是面试的重点和难点。本文会详细介绍事务和锁的相关概念及其实现原理&#xff0c;相信大家看完之后&#xff0c;一定会对事务和锁有更加深入的理解。 2、什么是事务 在维基百科中&#xff0c;对事…

7 处理多维特征的输入

文章目录课程前提知识问题引入模型改进修改神经层的增加学习能力与超参数课本代码课程来源: 链接课程文本来源借鉴&#xff1a; 链接以及&#xff08;强烈推荐&#xff09;Birandaの课程前提知识 BCELoss - Binary CrossEntropyLoss BCELoss 是CrossEntropyLoss的一个特例&am…

JavaEE day7 初识JavaScript2

函数小结 1.可以赋值给变量(其实就是被变量所指向) 2.装入容器中作为元素存在 3.在函数调用的过程中&#xff0c;函数类型作为实参 4.函数作为另一个函数的返回值 可以直接return一个函数 5.和java不同&#xff0c;JS中允许在一个函数中定义另一个函数&#xff0c;也就是嵌…

介绍一个令强迫症讨厌的小红点组件

前言 在 App 的运营中,活跃度是一个重要的指标,日活/月活……为了提高活跃度,就发明了小红点,然后让强迫症用户“没法活”。 小红点虽然很讨厌,但是为了 KPI,程序员也不得不屈从运营同学的逼迫(讨好),得想办法实现。这一篇,来介绍一个徽标(Badge)组件,能够快速搞…

解决OpenEuler系统 Minimal BASH-like line editing is supported

2023年开工解决的第一个问题~呃&#xff0c;起因是这样的&#xff0c;由于业务需要&#xff0c;修改内核参数后重新打包内核&#xff0c;然后安装内核rpm包后&#xff0c;强制关机&#xff0c;结果就出现如上界面。网上搜索后绝大部分是因为安装了双系统后找不到grub系统引导文…

ELK_Elasticsearch基础介绍

目录 一、搜索是什么&#xff1f; 二、数据库做搜索的弊端 三、全文检索、倒排索引和Lucene 四、什么是Elasticsearch 1、Elasticsearch的功能 2、Elasticsearch的使用场景 3、Elasticsearch的特点 五、elasticsearch核心概念 一、搜索是什么&#xff1f; 概念&#x…