查看原文
其他

Kubernetes+Helm+Jenkins 自动化发布项目

点击关注 👉 DevOps技术栈 2022-11-10
原文链接:https://hands-on-tech.github.io/2020/03/15/k8s-jenkins-example.html
让我们在 Kubernetes 上创建一个CI/CD(持续集成和持续部署)解决方案,使用 Jenkins 作为构建工具,并使用 Traefik 作为用于灵活应用程序部署和路由的入口。

目标

主要目标是在 Kubernetes 之上提供一种灵活的 CI/CD解决方案,并在每个环境中自动部署应用程序,定义主机和路由。为了使此过程易于理解,将详细介绍并描述以下步骤:
  1. 设置 Kubernetes 并了解其基本概念;
  2. 使用 Helm 安装 Traefik,Dashboard 和 Jenkins;
  3. 创建 Kotlin 应用程序以展示如何使用 CI/CD;
  4. 实施 Jenkins 管道以自动构建和部署应用程序。
为了完成上述步骤并验证提出的 CI/CD解决方案,提出了具有以下组件的体系结构:
  • Kubernetes:用于容器管理和编排;
  • Traefik:作为访问服务的代理和负载平衡器;
  • Kubernetes 仪表板:通过基于Web的界面管理Kubernetes;
  • Jenkins:作为自动化服务器来自动构建和部署应用程序;
  • GitHub:使用Git管理源代码;
  • DockerHub:作为用于使用示例应用程序管理Docker映像的注册表;
  • 应用程序说明:出于开发和测试目的的示例应用程序部署;
  • 应用程序生产:将在生产中使用的示例应用程序部署。
在幕后并作为支持工具,还使用了以下技术:
  • Docker:用于服务和应用程序容器化;
  • Helm:用于在Kubernetes上简化服务的部署和配置;
  • Kotlin:开发示例应用程序,它将自动构建并部署到Kubernetes
关于CI/CD解决方案,本文将重点介绍两个主要的交互工作流程,如下图所示:
  1. 构建和部署应用程序:签出最新的源代码版本以构建应用程序并将其部署在Kubernetes集群上;
  2. 访问应用程序:使用代理对特定主机名上的已部署应用程序进行标准化访问。

Kubernetes

Kubernetes,也称为K8s,是容器编排的当前标准解决方案,可以轻松地在云中以高可伸缩性,可用性和自动化级别部署和管理大规模应用程序。Kubernetes最初是由Google开发的,受到了开源社区的广泛关注。 
它是 Cloud Native Computing Foundation 的主要项目,一些最大的支持者也支持它,例如 Google,Amazon,Microsoft 和 IBM。
Kubernetes 目前是顶级的开源项目之一,也是 Linux 之前活动最多的项目。如今,已有多家公司提供了可用于生产的 Kubernetes 集群,例如亚马逊的 AWS,微软的 Azure 和 Google 的 GCE。Kubernetes文档中提供了现有云提供商的正式列表。

术语

为了理解如何部署应用程序,基本介绍一些核心概念,下面将对其进行介绍和简要介绍:
  • 命名空间:一个虚拟集群,可以位于同一物理集群硬件之上,从而使各个开发团队之间的关注点分离;
  • Pod:是最小的可部署单元,具有一组共享相同资源(例如内存,CPU和IP)的容器;
  • 副本集:确保在任何给定时间正在运行指定数量的Pod副本;
  • 部署:一组多个相同的Pod,定义如何运行应用程序的多个副本,如何自动替换任何失败或无响应的实例以及如何执行更新;
  • 服务:逻辑Pod集的抽象,这是其他应用程序用来与之交互的唯一接口;
  • 入口:管理如何提供对服务的外部访问;
  • 持久卷:用于在Pod生命周期内持久保存数据的一块存储。

架构

在开始安装和配置Kubernetes之前,了解正确设置集群所需的软件和硬件组件非常重要。下图总结了必需的组件体系结构,并简要描述了每个组件的角色:
  • Master:负责维护所需的群集状态,是管理员管理各个节点的入口点。以下软件组件在主机中运行:
    • API服务器:REST API,它公开了可以在群集上执行的所有操作,例如创建,配置和删除Pod和服务;
    • 调度程序:负责将任务分配给各个群集节点;
    • Controller-Manager:确保集群状态按预期运行,对整个集群中控制器触发的事件做出反应;
    • etcd:分布式键值存储,用于共享有关集群状态的信息,所有集群节点均可访问;
  • 节点:执行给定任务并运行以下组件的物理或虚拟机:
    • Docker:负责启动和管理容器的容器运行时;
    • Kubelet:跟踪Pod的状态,以确保所有容器都按预期运行;
    • Kube-proxy:路由从服务进入节点的流量;
  • UI:用于管理集群配置和应用程序的用户界面应用程序。Kubernetes仪表板将在本文中使用;
  • CLI:命令行界面,用于管理集群配置和应用程序。Kubectl将在本文中使用;

要了解有关 Kubernetes 体系结构和术语的更多信息,已经有几页提供了深入的描述,例如 Kubernetes 官方文档,Digital Ocean 的介绍和 Daniel Sanche 的术语介绍。

安装

由于安装和配置每个组件都可能是一项耗时的任务,因此有多个选项可以使安装Kubernetes 的过程更加简单。Ramit Surana 提供了此类安装程序的详尽列表。特别强调 kubeadm,kops,minikube 和 k3,它们一直受到开源社区的支持和更新。
由于我使用 MacOS 并想在单个节点上本地运行 Kubernetes,因此我决定利用 Docker Desktop,该桌面已经在单个工具中提供了 Docker 和 Kubernetes 的安装。安装后,可以检查系统托盘菜单,以确保 Kubernetes 按预期运行:

Kubectl

Kubectl是用于完全管理Kubernetes集群的官方CLI工具,可用于部署应用程序,检查和管理集群资源以及查看日志。由于Docker Desktop已经安装了kubectl,因此我们只需执行kubectl版本来检查其运行是否正常,该版本提供的输出类似于:
~ kubectl versionClient Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.5", GitCommit:"20c265fef0741dd71a66480e35bd69f18351daea", GitTreeState:"clean", BuildDate:"2019-10-15T19:16:51Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"darwin/amd64"}Server Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.5", GitCommit:"20c265fef0741dd71a66480e35bd69f18351daea", GitTreeState:"clean", BuildDate:"2019-10-15T19:07:57Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"linux/amd64"}
为了了解可用的命令和内在逻辑,我建议对官方的kubectl备忘单进行快速概述。例如,可以通过执行kubectl get pod来获取正在运行的列表pod。
最后但并非最不重要的一点是,如果您使用ZSH Shell,请记住使用kubectl插件,以便获得适当的突出显示和自动完成功能。为此,只需添加kubectl插件即可更改ZSH〜/ .zshrc初始化脚本:
plugins=(git kubectl)

Helm

Helm是Kubernetes的软件包管理器,它有助于创建模板,以准确描述如何安装应用程序。此类模板可以与社区共享,并可以针对特定安装进行自定义。每个模板称为舵图。检查Helm集线器以了解是否已经有想要运行的应用程序的图表。
如果您好奇并想了解图表的实现方式,则还可以检查带有正式稳定和孵化图表源代码的GitHub存储库。此外,如果您想拥有一个掌舵图表的存储库,则可以使用Harbor和JFrog Artifactory之类的解决方案来存储和提供自己的图表。
最后,要安装 Helm 并检查其是否正确安装,只需运行:
brew install helmhelm version
Which should give you something like:
~ helm versionversion.BuildInfo{Version:"v3.1.1", GitCommit:"afe70585407b420d0097d07b21c47dc511525ac8", GitTreeState:"clean", GoVersion:"go1.13.8"}

Traefik

Traefik是HTTP和TCP应用程序的一种广泛使用的代理和负载平衡器,本机兼容并针对基于云的解决方案进行了优化。总而言之,Traefik分析基础架构和服务配置,并自动发现每一项的正确配置,从而实现自动应用程序部署和路由。最重要的是,Traefik还支持收集详细的指标,日志和可追溯性。
Traefik提供了一个稳定且正式的Helm图表,可用于在Kubernetes上进行简单的安装和配置。以下配置值提供给图表,以便进行配置:
  • 使用管理员作为用户名和密码,通过域“ traefik.localhost”访问Traefik仪表板;
  • 对所有代理服务强制实施SSL,并自动为“ * .localhost”域生成通配符SSL证书。


将配置值保存在文件“ traefik-values.yml”中后,可以通过执行以下命令来安装Traefik:
helm install stable/traefik --name traefik --values traefik-values.yml
如果要删除Traefik,以下命令应有帮助:
Helm del --purge traefik
通过检查部署和Pod的状态来检查安装进度:
kubectl get deploymentskubectl get pods
当部署就绪状态为“ 1/1”(必须在1中准备1)时,访问http://traefik.localhost/以访问Traefik仪表板并使用先前定义的用户名和密码登录。在仪表板中,可以检查可用于访问已部署服务(后端)的入口点(前端)。

Kubernetes仪表板

Kubernetes Dashboard是一个开放源代码的Web界面,用于快速管理Kubernetes集群,并提供用户友好的功能来管理已部署的应用程序并进行故障排除。就个人而言,我更喜欢Portainer的界面和组织,但是它仍然不支持Kubernetes。因此,提供了以下配置以启用Traefik入口并通过http://dashboard.localhost使仪表板可用。

与Traefik相似,可以使用Kubernetes Dashboard Helm官方图表通过以下命令安装Dashboard:
helm install stable/kubernetes-dashboard --name dashboard --values dashboard-values.yml
为了登录,头盔图表已经创建了具有适当权限的服务帐户。使用这种服务帐户登录的令牌在kubernetes机密中可用。要获取可用机密列表,只需运行kubectl get secrets:
为了登录,头盔图表已经创建了具有适当权限的服务帐户。使用这种服务帐户登录的令牌在 kubernetes 机密中可用。要获取可用机密列表,只需运行kubectl get secrets
要获取机密值,请使用kubectl描述包含仪表板令牌的机密:kubectl describe secrets dashboard-kubernetes-dashboard-token-sk68z:
最后,转到http://dashboard.localhost,并使用先前的令牌值登录Kubernetes仪表板:

Jenkins

Jenkins 是使用最广泛的开源工具,可自动构建,测试和部署软件应用程序。因此,使用 Jenkins,我们可以指定一个处理管道,准确描述每次提交后如何自动构建和部署我们的应用程序。
要安装 Jenkins,我们将利用官方的 Jenkins Helm 图表,提供以下配置以指定登录凭据并安装插件以与 GitHub 和 Kubernetes 集成:


要执行安装,请执行以下命令并检查 kubectl get 部署的进度:
helm install stable/jenkins --name jenkins --values jenkins-values.yml

当所需的 Pod 运行时,请访问 http://jenkins.localhost 以访问 Jenkins 并使用先前提供的凭据登录:

应用

由于所有必需的工具都已成功安装并运行,因此我们现在可以创建要自动构建和部署的示例应用程序。此类应用程序将使用 Spring Boot 框架在 Kotlin 中开发。Spring Initializr 用于通过以下配置创建初始应用程序:
核心功能将在 GreetingController 中,后者仅提供 GET REST 端点即可根据输入参数,提供的环境变量和总体计数器提供问候,以区分不同的调用。

此外,请记住添加执行器依赖项以在 /actuator/health 上启用运行状况端点,该端点将用于向 Kubernetes 提供应用程序运行状况信息:

Dockerfile

要在 Kubernetes 中运行该应用程序,需要该应用程序的 Docker 映像,该映像可通过以下 Dockerfile 描述:

Helm chart

要为示例应用程序创建舵图,可以利用舵机CLI工具创建一个基准,使我们可以适应示例应用程序。可以通过在终端上运行helm create helm来创建这样的基准,helm create helm将创建必需的Kubernetes组件的模板以运行并正确配置应用程序。考虑到我们的目标,以下文件是最需要注意的文件:
  • Chart.yaml:图表属性,例如名称,描述和版本;
  • values.yaml:提供给图表的默认配置值;
  • template / deplyment.yaml:Kubernetes部署规范的模板,用于配置应用程序pod和复制特性;
  • template / service.yaml:Kubernetes服务规范的模板,用于配置其他应用程序的应用程序接口;
  • templates / ingress.yaml:Kubernetes入口规范的模板,以公开服务以供外部访问。
舵图使用{{}}
 用于模板,这意味着将解释内部的内容以提供输出值。官方指南中有关多个模板选项的更多详细信息。对于我们正在创建的模板,以下是最重要的示例:
  • {{.Values.replicaCount}}从提供的值文件中获取配置副本计数;
  • {{-toYaml. | nindent 8}}:将引用的Yaml树(点指向当前结构引用)复制到带有8个空格的缩进的结果中。
定义了以下值来配置应用程序,这些值将在图表模板中使用。重要的是要参考提供的docker映像参考,服务端口和入口配置以使用Traefik:

为了检查 Helm 图表是否正常工作,我们可以安装它并检查几个组件是否正确部署:
helm install example ./helmkubectl get deploymentkubectl get podkubectl get servicekubectl get ingress

Pipeline

目标是建立充分利用Kubernetes的管道,在按需执行的专用代理上构建所需的工件。这种方法为开发人员提供了高度的灵活性和独立性,他们可以完全控制他们的构建管道,并且不依赖于Jenkins主机上安装的任何软件。结果,Jenkins机器不会被许多不同的工具和版本污染。例如,如果一个团队需要Java 8,而另一个团队则需要Java 13,则Jenkins主机不需要同时安装两者,因为每个团队管道都将在自己的Jenkins代理上运行,并且每次运行都按需部署。为此,我们使用了Kubernetes Jenkins插件,该插件允许使用所需工具定义带有容器的容器。然后,我们仅需提及,我们想通过引用其名称在特定容器内运行特定步骤。
请记住,工作空间卷是自动创建的,并且在容器中的容器之间共享,这意味着工作空间上的任何更改将可用于其他容器。例如,如果我们使用maven容器创建打包的jar文件,则docker容器将可以使用它来创建docker映像。此外,为了加快构建过程,不要忘记为maven〜/ .m2文件夹创建一个卷,以便在作业运行之间共享下载的依赖项。
由于需要maven,docker和helm工具才能正确构建和部署示例应用程序,因此build.yaml文件中提供了以下pod规范:



对于管道,我决定使用声明性语法而不是脚本,这更适合简单的管道,并且更易于阅读和理解。但是,如果我们要执行更高级的任务,那么限制性更强的语法可能会成为限制。对于此类情况,可以在声明性管道中定义脚本块。总而言之,示例应用程序的CI / CD声明性管道将分为以下阶段:
  1. 构建:使用maven构建应用程序包;
  2. Docker Build:使用先前创建的Dockerfile构建docker镜像;
  3. Docker Publish:将构建的Docker映像发布到Docker Hub;
  4. Kubernetes部署:通过安装或升级相应的Kubernetes组件,使用先前创建的头盔图来部署应用程序。
在这些阶段的顶部,将创建两个不同的部署环境:生产(https://example.localhost)和登台(https://example-staging.localhost),它们分别与master和develop分支相关。因此,如果分支不是master或developer,则不会构建docker映像,并且不会将应用程序部署到Kubernetes。此外,所有应用程序工件都具有相同的版本,可以使用Pipeline Utility步骤Jenkins库从POM文件加载该版本。
在示例应用程序的Jenkins声明性管道下面找到该管道,该管道还使用build.yaml文件中所述的pod设置代理,并在每次运行作业时自动从GitHub签出源代码:


Job

最后,让我们创建 Jenkins 作业以使用示例应用程序源代码运行管道。为此,请转到Jenkins并使用以下配置创建一个新的 Multibranch Pipeline 作业:
保存 Jenkins 作业后,您应该能够在列表中看到它,浏览它的几个分支,并检查为每个分支执行的管道:

验证

现在所有部分都运行在一起,并且我们检查了核心功能,让我们验证该解决方案是否适合典型的GitFlow开发流程:
建立 Jenkins 的总行工作;
检查生产部署是否正在运行并提供期望的值:
~ curl -k -w '\n' --request GET 'https://example.localhost/greeting'{"id":1,"content":"Hello, World","env":"default_value"}
创建开发部门并建立各自的 Jenkins 工作;
检查暂存部署是否正常运行:
~ curl -k -w '\n' --request GET 'https://example-staging.localhost/greeting'{"id":1,"content":"Hello, World","env":"default_value"}
Checkout开发分支,并将问候语方法的默认名称参数值从“ World”更改为“ World!”;
提交并等待Jenkins作业完成,以更新登台部署;
检查分段部署上的默认值是否已更改:
~ curl -k -w '\n' --request GET 'https://example-staging.localhost/greeting'{"id":1,"content":"Hello, World!","env":"default_value"}
  • 将开发分支合并为主分支;
  • 等待Jenkins主工作完成并更新生产部署;
  • 检查生产部署是否正确更新:
    ~ curl -k -w '\n' --request GET 'https://example.localhost/greeting'{"id":1,"content":"Hello, World!","env":"default_value"}
是的,一切都在自动进行!

- END -

公众号后台回复「加群」加入一线高级工程师技术交流群,一起交流进步。

 推荐阅读 

让运维简单高效,轻松搞定运维管理平台 【图解】Kubernetes Deployment 故障排查指南备份和迁移 Kubernetes 利器:Velero搭建一套完整的企业级 K8s 集群(v1.20,二进制方式)Shell 脚本进阶,经典用法及其案例JAVA应用运维,线上故障排查全套路
5个面试的关键技巧,助你拿到想要的offer!



点亮,服务器三年不宕机

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存