用Jenkins 实现Kubernetes零停机和蓝绿部署 | Kubernetes

标签: | 发表时间:2022-01-14 21:08 | 作者:
出处:https://kubernetes.io

自从我们将 Kubernetes Continuous DeployAzure Container Service插件添加到 Jenkins 更新中心后,“如何创建零停机部署”是我们最常见的问题之一。我们在 Azure 上创建了一个快速入门模板来演示零停机部署的样子。尽管我们的示例使用 Azure,但该概念很容易适用于所有 Kubernetes 安装。

滚动更新

Kubernetes 支持 RollingUpdate 策略,以逐步用新的 Pod 替换旧的 Pod,同时继续为客户端提供服务而不会导致停机。要执行 RollingUpdate 部署:

  • 设置 .spec.strategy.typeRollingUpdate(默认值)。
  • 设置 .spec.strategy.rollingUpdate.maxUnavailable.spec.strategy.rollingUpdate.maxSurge一些合理的值。
    • maxUnavailable:更新过程中不可用的最大 pod 数。这可以是副本计数的绝对数量或百分比;默认值为 25%。
    • maxSurge:可以在所需数量的 pod 上创建的最大 pod 数。同样,这可以是绝对数量或副本计数的百分比;默认值为 25%。
  • 为您的服务容器配置 readinessProbe以帮助 Kubernetes 确定 pod 的状态。Kubernetes 只会将客户端流量路由到具有健康活跃度探测的 Pod。

我们将使用官方 Tomcat 镜像的部署来演示这一点:

  apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: tomcat-deployment-rolling-update
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: tomcat
        role: rolling-update
    spec:
      containers:
      - name: tomcat-container
        image: tomcat:${TOMCAT_VERSION}
        ports:
        - containerPort: 8080
        readinessProbe:
          httpGet:
            path: /
            port: 8080
  strategy:
    type: RollingUpdate
    rollingUp      maxSurge: 50%

如果当前部署中运行的 Tomcat 是版本 7,我们可以替换 ${TOMCAT_VERSION}为 8 并将其应用到 Kubernetes 集群。使用 Kubernetes 持续部署Azure 容器服务插件,可以从简化部署过程的环境变量中获取值。

在幕后,Kubernetes 管理更新如下:

部署过程

  • 最初,所有 pod 都运行 Tomcat 7,前端服务将流量路由到这些 pod。
  • 在滚动更新期间,Kubernetes 会删除一些 Tomcat 7 pod,并创建相应的新 Tomcat 8 pod。它确保:
    • 期望 Pod 中的大多数 maxUnavailablepod 都不可用,也就是说,至少 (  replicasmaxUnavailable) 个 pod 应该为客户端流量提供服务,在我们的例子中是 2-1=1。
    • 在更新过程中最多可以创建 maxSurge 更多的 Pod,在我们的例子中是 2*50%=1。
  • 取下一个 Tomcat 7 pod,并创建一个 Tomcat 8 pod。 Kubernetes 不会将流量路由到其中任何一个,因为它们的就绪探测尚未成功。
  • 当就绪探针确定新的 Tomcat 8 pod 准备就绪时,Kubernetes 将开始将流量路由到它。这意味着在更新过程中,用户可能会同时看到旧服务和新服务。
  • 滚动更新继续通过删除 Tomcat 7 pod 并创建 Tomcat 8 pod,然后将流量路由到准备好的 pod。
  • 最后,所有 pod 都在 Tomcat 8 上。

滚动更新策略确保我们始终有一些就绪的后端 pod 服务于客户端请求,因此没有服务停机时间。但是,需要一些额外的注意:

  • 在更新期间,旧 pod 和新 pod 都可以为请求提供服务。如果服务层中没有明确定义的会话亲和性,用户可能会被路由到新的 Pod,然后再返回旧的 Pod。
  • 这还要求您为数据和 API 维护明确定义的向前和向后兼容性,这可能具有挑战性。
  • Pod 在启动后可能需要很长时间才能为流量做好准备。可能在很长一段时间内使用比平时更少的后端 pod 来提供流量。一般来说,这应该不是问题,因为我们倾向于在服务不太繁忙时进行生产升级。但这也会延长问题 1 的时间窗口。
  • 我们无法对正在创建的新 pod 进行全面测试。将应用程序更改从开发/质量保证环境转移到生产环境可能会带来破坏现有功能的持续风险。就绪探针可以做一些检查就绪的工作,但是它应该是一个可以定期运行的轻量级任务,不适合用作启动完整测试的入口点。

蓝/绿部署

引自 TechTarget 的蓝/绿部署

蓝/绿部署是发布软件代码的变更管理策略。蓝/绿部署(也称为 A/B 部署)需要两个完全相同的硬件环境,它们的配置方式完全相同。当一个环境处于活动状态并为最终用户提供服务时,另一个环境保持空闲状态。

容器技术提供了一个独立的环境来运行所需的服务,这使得创建蓝/绿部署所需的相同环境变得非常容易。松耦合的 Services - ReplicaSets,以及 Kubernetes 中基于标签/选择器的服务路由,使得在不同的后端环境之间切换变得很容易。使用这些技术,Kubernetes 中的蓝/绿部署可以完成如下:

  • 在部署之前,基础设施准备如下:
    • 准备蓝色部署和绿色部署, TOMCAT_VERSION=7分别 TARGET_ROLE设置为蓝色或绿色。
  apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: tomcat-deployment-${TARGET_ROLE}
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: tomcat
        role: ${TARGET_ROLE}
    spec:
      containers:
      - name: tomcat-container
        image: tomcat:${TOMCAT_VERSION}
        ports:
        - containerPort: 8080
        readinessProbe:
          httpGet:
            path: /
            port: 8080
  • 准备公共服务端点,该端点最初路由到后端环境之一,例如 TARGET_ROLE=blue.
  kind: Service
apiVersion: v1
metadata:
  name: tomcat-service
  labels:
    app: tomcat
    role: ${TARGET_ROLE}
    env: prod
spec:
  type: LoadBalancer
  selector:
    app: tomcat
    role: ${TARGET_ROLE}
  ports:
    - port: 80
      targetPort: 8080
  • 或者,准备一个测试端点,以便我们可以访问后端环境进行测试。它们类似于公共服务端点,但它们仅供开发/运营团队内部访问。
  kind: Service
apiVersion: v1
metadata:
  name: tomcat-test-${TARGET_ROLE}
  labels:
    app: tomcat
    role: test-${TARGET_ROLE}
spec:
  type: LoadBalancer
  selector:
    app: tomcat
    role: ${TARGET_ROLE}
  ports:
    - port: 80
      targetPort: 8080
  • 在非活动环境中更新应用程序,比如绿色环境。在部署配置中设置 TARGET_ROLE=green和更新绿色环境。 TOMCAT_VERSION=8
  • 通过测试端点测试部署, tomcat-test-green以确保绿色环境已准备好为客户端流量提供服务。
  • 通过更新服务配置,将前端服务路由切换到绿色环境 TARGET_ROLE=green
  • 在公共端点上运行其他测试以确保其正常工作。
  • 现在蓝色环境是空闲的,我们可以:
    • 将其保留在旧应用程序中,以便在新应用程序出现问题时我们可以回滚
    • 更新它以使其成为活动环境的热备份
    • 减少其副本数以节省占用的资源

资源

与滚动更新相比,蓝/绿向上*公共服务要么路由到旧应用程序,要么路由到新应用程序,但绝不会同时路由两者。

  • 新 Pod 准备就绪所需的时间不会影响公共服务质量,因为只有在所有新 Pod 都经过测试准备好后,流量才会被路由到新 Pod。
  • 我们可以在新环境服务于任何公共交通之前对其进行全面测试。请记住,这是在生产中,测试不应污染实时应用程序数据。

Jenkins 自动化

Jenkins 提供易于设置的工作流程来自动化您的部署。借助 Pipeline支持,可以灵活地构建零停机部署工作流,并可视化部署步骤。为了方便 Kubernetes 资源的部署过程,我们发布了 Kubernetes Continuous Deploy和基于 kubernetes-client构建的 Azure 容器服务插件 . 您可以将资源部署到 Azure Kubernetes 服务 (AKS) 或通用 Kubernetes 集群,而无需 kubectl,它支持资源配置中的变量替换,因此您可以将特定于环境的资源部署到集群,而无需更新资源配置。我们创建了一个 Jenkins 管道来演示 AKS 的蓝/绿部署。流程如下:

詹金斯管道

  • 预清洁:清洁工作区。
  • SCM:从源代码控制管理系统中提取代码。
  • 准备镜像:准备应用程序 docker 镜像并将它们上传到某个 Docker 存储库。
  • 检查Env:确定驱动以下部署的活动和非活动环境。
  • 部署:将新的应用资源配置部署到非活动环境。使用 Azure 容器服务插件,这可以通过以下方式完成:
  acsDeploy azureCredentialsId: 'stored-azure-credentials-id',
          configFilePaths: "glob/path/to/*/resource-config-*.yml",
          containerService: "aks-name | AKS",
          resourceGroupName: "resource-group-name",
          enableConfigSubstitution: true
  • 验证分阶段:验证部署到非活动环境以确保其正常工作。同样,请注意这是在生产环境中,因此请注意不要在测试期间污染实时应用程序数据。
  • 确认:(可选)发送电子邮件通知以供手动用户批准以继续进行实际环境切换。
  • Switch:将前端服务端点路由切换到非活动环境。这只是 AKS Kubernetes 集群的另一个服务部署。
  • 验证产品:验证前端服务端点在新环境中是否正常工作。
  • 后清理:对临时文件进行一些后清理。

对于滚动更新策略,只需将部署配置部署到 Kubernetes 集群,这是一个简单的一步。

放在一起

我们在 Azure 上构建了一个快速入门模板,以演示如何使用 Jenkins 对 AKS (Kubernetes) 进行零停机部署。转到 Kubernetes 上的 Jenkins 蓝绿部署,然后单击按钮部署到 Azure 以获取工作演示。该模板将提供:

  • 具有以下资源的 AKS 群集:
    • 代表环境“蓝色”和“绿色”的两个类似部署。两者最初都是使用 tomcat:7 图像设置的。
    • 两个测试端点服务( tomcat-test-bluetomcat-test-green),它们连接到相应的部署,可用于测试部署是否已准备好用于生产。
    • 一个生产服务端点 (  tomcat-service),它代表用户将访问的公共端点。最初它路由到“蓝色”环境。
  • 在 Ubuntu 16.04 VM 上运行的 Jenkins 主服务器,配置了 Azure 服务主体凭据。Jenkins 实例有两个示例作业:
    • AKS Kubernetes 滚动更新部署管道,用于演示到 AKS 的滚动更新部署。
    • AKS Kubernetes 蓝/绿部署管道,用于演示 AKS 的蓝/绿部署。
    • 我们没有在快速入门模板中包含电子邮件确认步骤。要添加它,您需要在 Jenkins 系统配置中配置电子邮件 SMTP 服务器详细信息,然后在 Switch 之前添加一个 Pipeline 阶段:
  stage('Confirm') {
    mail (to: '[email protected]',
        subject: "Job '${env.JOB_NAME}' (${env.BUILD_NUMBER}) is waiting for input",
        body: "Please go to ${env.BUILD_URL}.")
    input 'Ready to go?'
}

按照 步骤设置资源,您可以通过启动 Jenkins 构建作业进行尝试。

相关 [jenkins kubernetes kubernetes] 推荐:

用Jenkins 实现Kubernetes零停机和蓝绿部署 | Kubernetes

- -
自从我们将 Kubernetes Continuous Deploy和 Azure Container Service插件添加到 Jenkins 更新中心后,“如何创建零停机部署”是我们最常见的问题之一. 我们在 Azure 上创建了一个快速入门模板来演示零停机部署的样子. 尽管我们的示例使用 Azure,但该概念很容易适用于所有 Kubernetes 安装.

Kubernetes & Microservice

- - 午夜咖啡
这是前一段时间在一个微服务的 meetup 上的分享,整理成文章发布出来. 谈微服务之前,先澄清一下概念. 微服务这个词的准确定义很难,不同的人有不同的人的看法. 比如一个朋友是『微服务原教旨主义者』,坚持微服务一定是无状态的 http API 服务,其他的都是『邪魔歪道』,它和 SOA,RPC,分布式系统之间有明显的分界.

Kubernetes学习(Kubernetes踩坑记)

- - Z.S.K.'s Records
记录在使用Kubernetes中遇到的各种问题及解决方案, 好记性不如烂笔头. prometheus提示 /metrics/resource/v1alpha1 404. 原因: 这是因为[/metrics/resource/v1alpha1]是在v1.14中才新增的特性,而当前kubelet版本为1.13.

kubernetes移除Docker?

- -
两周前,Kubernetes在其最新的Changelog中宣布1.20之后将要弃用dockershime,也就说Kubernetes将不再使用Docker做为其容器运行时. 这一消息持续发酵,掀起了不小的波澜,毕竟Kubernetes+Docker的经典组合是被市场所认可的,大量企业都在使用. 看上去这个“弃用”的决定有点无厘头,那么为什么Kubernetes会做出这样的决定.

Kubernetes 完全教程

- - 午夜咖啡
经过一个阶段的准备,视频版本的 《Kubernetes 完全教程》出炉了. 课程一共分为七节,另外有一节 Docker 预备课,每节课大约一个多小时. 目标是让从没接触过 Kubernetes 的同学也能通过这个课程掌握 Kubernetes. 为什么要学习 Kubernetes. 在介绍课程之前,先说说为什么要学习 Kubernetes 以及什么人需要学习 Kubernetes.

Kubernetes 监控详解

- - DockOne.io
【编者的话】监控 Kubernetes 并不是件容易的事. 本文介绍了监控 Kubernetes 的难点、用例以及有关工具,希望可以帮助大家进一步了解监控 Kubernetes. 如果想要监控 Kubernetes,包括基础架构平台和正在运行的工作负载,传统的监控工具和流程可能还不够用. 就目前而言,监控 Kubernetes 并不是件容易的事.

Kubernetes 切换到 Containerd

- - bleem
由于 Kubernetes 新版本 Service 实现切换到 IPVS,所以需要确保内核加载了 IPVS modules;以下命令将设置系统启动自动加载 IPVS 相关模块,执行完成后需要重启. 重启完成后务必检查相关 module 加载以及内核参数设置:. 1.2、安装 Containerd. Containerd 在 Ubuntu 20 中已经在默认官方仓库中包含,所以只需要 apt 安装即可:.

喜大普奔:Spark on kubernetes

- - Zlatan Eevee
两个星期前(08/15/2017),spark社区提了一个新的SPIP(Spark Project Improvement Proposals): Spark on Kubernetes: Kubernetes as A Native Cluster Manager,即用k8s管理spark集群. 经过社区2个星期的投票,看上去很快要能合入了.

Kubernetes 日志收集方案

- - IT瘾-dev
Kubernetes 中的基本日志. Kubernetes 日志收集. 以 sidecar 容器收集日志. 用 sidecar 容器重新输出日志. 使用 sidecar 运行日志采集 agent. 前面的课程中和大家一起学习了 Kubernetes 集群中监控系统的搭建,除了对集群的监控报警之外,还有一项运维工作是非常重要的,那就是日志的收集.

Kubernetes 会不会“杀死” DevOps?

- - InfoQ推荐
DevOps 这个概念最早是在 2007 年提出的,那时云计算基础设施的概念也才刚刚提出没多久,而随着互联网的逐渐普及,应用软件的需求爆发式增长,软件开发的理念也逐渐从瀑布模型(waterfall)转向敏捷开发(agile). 传统的软件交付模式(应用开发人员专注于软件开发、IT 运维人员负责将软件部署到服务器运行),再也无法满足互联网软件快速迭代的需求.