查看原文
其他

在Kubernetes上部署和伸缩Jenkins

CALIN RUS RancherLabs 2019-03-29

在本教程中,我们将使用Rancher在Kubernetes上部署和伸缩Jenkins。按照本文的步骤一步步来,你将会使用到我们用来测试实际构建作业的master-agent体系结构,创建出功能齐全的Jenkins。


介  绍


Jenkins是一个开源的持续集成和持续交付工具,它可以用来自动构建、测试和部署软件。在全世界有超过一百万的用户在使用Jenkins,它是目前最流行的自动化服务器。Jenkins的优势包括:


  • 是一个拥有庞大社区支持的开源软件

  • 基于Java的代码库,使其可以移植到所有主要平台

  • 有超过1000个插件的丰富生态系统


Jenkins能够与主流的源代码管理系统(Git、SVN、Mercurial以及CVS)、主流的构建工具(Ant、Maven、Grunt)、shell脚本和Windows批处理命令、测试框架、报表生成器的都良好地协同工作。Jenkins的插件还提供了对Docker和Kubernetes的支持,Docker和Kubernetes能够创建、部署基于云的微服务环境,并且把它们投入到测试和生产部署中。


Jenkins支持master-agent体系结构(许多build agents/构建代理根据master服务器调度来完成任务),使其具有高度的可伸缩性。Master的工作是安排构建作业,将作业分发给代理实际执行,监视这些代理并获得构建的结果。除此之外,master服务器还可以直接执行构建作业。


代理的任务是构建从master服务器发送过来的作业。作业可以配置在指定类型的代理商运行,如果没有特别需求,Jenkins就简单地选择下一个可用代理。


Jenkins的可伸缩性可以带来许多便利:


  • 并行运行多个构建方案

  • 自动地挂载和移除代理,节约开销

  • 分配负载


当然,尽管Jenkins包含了这种开箱即用的可伸缩性特性,配置它的过程却并不是很简单。有许多能够扩展Jenkins的选择,而其中一种强大的选择就是使用Kubernetes。


Kubernetes是什么?


Kubernetes是一个开源的容器编排工具。它主要用来帮助操作人员部署、伸缩、更新和维护服务,以及提供服务发现机制来管理节点集群上的容器化应用程序。你可以查看官方文档,了解更多关于Kubernetes的内容和用途:

https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/


Kubernetes是管理可伸缩的、基于容器的工作负载的最佳工具之一。包括Jenkins在内的大多数应用程序都可以进行容器化,而这也使得Kubernetes成为了非常好的选择。



项目目标


在我们开始之前,先花一点时间描述一下我们将要构建的系统。


我们首先会将Jenkins master实例部署到Kubernetes集群上。我们将使用Jenkins的kubernetes插件。我们将使用Jenkins的kubernetes插件,通过提供动态代理来适配当前的工作负载,在集群上扩展Jenkins。该插件基于具体的Docker镜像启动代理,为每个构建创建一个Kubernetes pod。在构建完成后,Jenkins将删除pod来节省资源。代理则使用JNLP(Java Network Launch Protocol,Java网络启动协议)启动,因此容器能够在启动和运行之后自动连接到Jenkins master。


前期准备和安装


你需要准备这些东西来完成本教程:


Linux机器用于运行Rancher:我们还会使用它构建自定义的Jenkins镜像。可以按照Rancher安装入门指南在主机上安装Docker和Rancher:

https://rancher.com/quick-start/


Docker Hub账户:我们需要一个带有容器镜像仓库的账户,为Jenkins master和代理推送自定义镜像。


GCP账户:我们将在GCP上部署Kubernetes集群。谷歌云平台的free-tier应该能够完成这项工作。您实际使用其他公有云,操作也是一样的。


为Jenkins组件构建自定义的镜像


那么我们先从给Jenkins组件构建自定义镜像开始,将它们推送到Docker Hub。


登录到Linux服务器,在那里你就可以运行Rancher并构建镜像。如果还没有安装Docker和Rancher,请按照Rancher快速入门指南在主机上安装Docker和Rancher。主机准备好后,我们就可以准备dockerfile了。


编写Jenkins Master Dockerfile


我们先在当前文件夹下创建一个名为Dockerfile-jenkins-master的文件,来定义Jenkins master镜像:



在文件内部,加入下面Dockerfile构建命令。这些命令使用主Jenkins Docker镜像作为基础,配置我们用于部署到Kubernetes集群的插件:



完成后,保存并关闭文件


编写Jenkins代理的Dockerfiles


接下来,我们就可以为Jenkins代理创建Dockerfile文件了。我们将创建两个代理镜像,演示Jenkins如何正确识别为每个作业准备的正确代理。

 

在当前目录中创建一个空文件。我们将把它复制到镜像中作为正在构建的每个代理的标识符:



现在,为第一个代理镜像创建Dockerfile



该镜像将把空文件复制到一个唯一的名称,标记所使用的代理。



完成之后保存并关闭文件


最后,定义第二个代理。这个和前一个代理相同,不过使用了不同的文件标识符:



保存并关闭文件


现在你的工作目录看起来应该是这样的:



构建镜像并Push到Docker Hub


有了准备好的Dockerfile,我们现在就准备构建和push镜像到Docker Hub啦。


首先构建Jenkins master的镜像:


注意:下面的命令中,将 <dockerhub_user>替换成自己的Docker Hub账户名

[root@rancher-instance jenkins-kubernetes]# docker build -f Dockerfile-jenkins-master -t <dockerhub_user>/jenkins-master .



当命令的结果返回之后,查看新创建的镜像:



使用账户凭证登录到Docker Hub:

[root@rancher-instance jenkins-kubernetes]# docker loginLogin with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username: Password: Login Succeeded

现在,将镜像推送到Docker Hub:

注意:下面的命令中,同样注意替换成自己的Docker Hub账户



你可能还需要同样的命令来构建第二个镜像给Jenkins JNLP代理:


注意:下面的命令中,注意将<dockerhub_user>替换成自己的Docker Hub账户名



如果一切顺利,你就能在Docker Hub账户中看到下图这个状态:



使用Rancher部署集群


现在我们的镜像已经发布,就可以使用Rancher来帮助部署GKE集群了。如果您之前安装了Rancher,通过web浏览器访问服务器的ip地址就能登录到实例了。


接下来,创建新的GKE集群。这里为了创建具有访问权限的服务账户,你需要登录到谷歌云账户。使用其他的公有云服务所需的步骤也是相似的,具体可以参考文档学习如何创建服务账号,以及如何与Rancher一起部署集群:

https://rancher.com/docs/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/


在集群上部署Jenkins


在集群准备好之后,我们就可以部署Jenkins master和创建一些服务了。如果你对kubectl比较熟悉,你可以直接用命令行来实现;不过通过Rancher的UI,你也能很容易地部署所有需要的组件。


无论你选择何种方式将工作负载添加到集群上,都需要在本地计算机上创建下面的文件来定义需要创建的对象。


首先创建一个文件定义Jenkins部署:



在文件里粘贴下面的内容:


注意:下面的内容中将<dockerhub_user>替换成自己的Docker Hub账户名

apiVersion: extensions/v1beta1 kind: Deployment metadata:  name: jenkins spec:  replicas: 1  template:    metadata:      labels:        app: jenkins    spec:      containers:        - name: jenkins          image: <dockerhub_user>/jenkins-master          env:            - name: JAVA_OPTS              value: -Djenkins.install.runSetupWizard=false          ports:            - name: http-port              containerPort: 8080            - name: jnlp-port              containerPort: 50000          volumeMounts:            - name: jenkins-home              mountPath: /var/jenkins_home      volumes:        - name: jenkins-home          emptyDir: {}

下面,创建一个文件配置我们需要的两个服务。

一个是LoadBalancer服务,它将提供一个公开的IP地址便于我们在Internet上访问Jenkins。另一个是ClusterIP服务,用于在master和代理之间的内部通信,之后会用到该服务:



在文件内,复制下面的YAML结构:

apiVersion: v1 kind: Service metadata:  name: jenkins spec:  type: LoadBalancer  ports:    - port: 80      targetPort: 8080  selector:    app: jenkins --- apiVersion: v1 kind: Service metadata:  name: jenkins-jnlp spec:  type: ClusterIP  ports:    - port: 50000      targetPort: 50000  selector:    app: jenkins


在Rancher上,点击自己管理的集群(例子中名为jenkins)。在左上角的菜单中,选择Default项目,然后选择Workloads选项卡。



现在,点击Import YAML。在接下来的页面中,点击右上角的Read from a file按钮。选择在本地创建的deployment.yml文件并点击Import



Rancher将在集群上面部署一个基于你Jenkins master镜像的pod



接下来,我们需要在Jenkins master上配置访问UI的方式。


Load Balanced选项卡中,按照先前导入文件一样的操作。单击Import YAML按钮,接着点Read from a file按钮。然后从自己的电脑中选择service.yml文件,点击Import按钮。



Rancher会开始创建你的服务。部署负载均衡会花费一些时间。



在service状态成为Active后,你可以点击在负载均衡器行后侧的三个垂直点,选择View/Edit YAML来找到它的公共IP地址。在这里,向下滚动界面找到在status->loadBalancer->ingress->ip下的IP地址。



这样我们就可以通过该IP地址在web浏览器中访问Jenkins UI了。



配置动态的构建代理


有了Jenkins master启动运行后,我们可以进一步配置动态构建代理,以在必要的时候可以自动启动Pods。


禁用默认Master构建代理


Jenkins UI中左侧的Build Executor Status下,默认配置了两个Executor,等待执行构建作业,它们是由Jenkins master提供的。


主实例应该只负责调度构建作业、将作业分发给代理以供执行、监视代理并获取构建结果。因为我们不希望主实例执行构建,因此要禁用这些。


点击Manage Nodes之后的Manage Jenkins



单击与master行上的齿轮图标。



接下来的页面中,把# of executors设置成0,点击Save



这两个空闲的executors将从UI左侧的Build Executor Status中删除。


收集配置信息


为了在Kubernetes集群上自动部署构建代理,我们需要一些信息来配置Jenkins。我们需要三条来自GCP账户的信息以及一条来自ClusterIP服务中的信息。


在你的GCP账户中,选择Kubernetes Engine,接着是Clusters,然后点击集群的名称。在Detail列中,复制端点IP供之后使用。这是我们需要让Jenkins连接到集群的URL:



下一步,点击端点右侧的Show credentials。复制UsernamePassword



现在,切换到Rancher UI。在左上角菜单中,选择Jenkins集群上的Default项目。在上方的导航窗口中选择Workloads选项卡,然后单击页面上的Service Discovery选项卡:



点击jenkins-jnlp行上垂直的三个点,然后单击View/Edit YAML。复制spec > clusterIP以及spec > ports > port中的值备用。


配置Jenkins Kubernetes插件


返回主Jenkins仪表盘,点击Manage Jenkins,然后选择Manage Plugins



点击Installed选项卡并查看Kubernetes插件是否安装:



现在我们来配置插件。前往Manage Jenkins并选择Configure System



滑到页面底部的Cloud部分。点击Add a new cloud,选择Kubernetes



在下面的表单中,Kubernetes URL字段上输入https://,然后输入从GCP账户复制的集群端点IP地址。


Credentials下,点击Add按钮,选择Jenkins。在出现的表单上,输入从GCP账户复制的用户名和密码,单击底部的Add按钮。


返回到Kubernetes表单,从Credentials下拉菜单中选择刚才添加的凭据并单击Test Connection按钮。如果配置正确,则会显示“Connection test successful”。


现在,向下滚动到页面底部的Images部分,单击Add Pod Template按钮,然后选择Kubernetes Pod Template。 使用唯一值填写“Name”和“Labels”字段,以标识您的第一个代理。 我们将使用标签指定应该使用哪个代理镜像来运行每个构建。


接下来,在Jenkins tunnel字段中,输入你在Rancher UI中从jenkins-jnlp服务检索到的IP地址和端口,用冒号分隔:



现在,在Container字段中,单击Add Container按钮并选择Container Template,在弹出的内容中填写以下字段:


  • Name: jnlp(这是Jenkins代理需要的)

  • Docker image:<dockerhub_user>/Jenkins-slave-jnlp1(确保更改Docker Hub用户名)

  • Command to run:删除这里的值

  • Arguments to pass to the command:删除这里的值


其余字段保持原样。



接下来,单击Add Pod Template按钮,再次选择Kubernetes Pod Template。对创建的第二个代理镜像重复刚才的过程,需要注意的是,在需要的时候要修改那些对应于第二个镜像的值:



单击Save按钮保存修改并继续。


测试动态构建作业


现在我们已经完成了配置工作,我们可以创建一些构建作业,保证Jenkins能够在Kubernetes之上进行伸缩。这里我们将为每个Jenkins代理创建5个构建作业。


在Jenkins主页面,单击左侧的New Item,为第一个代理的第一个构建输入名称,选择Freestyle project并单击OK按钮。



在下一页的Label Expression字段中,输入你为第一个Jenkins代理镜像设置的标签,如果单击字段之外,会出现一条消息,提示标签由云提供服务。



向下滚动到Build Environment部分,检查Color ANSI Console Output。


在Build部分,单击Add build step并选择Execute shell。把下面的脚本粘贴进去。



完成之后单击Save



给第一个代理创建另外四个工作则是单击New Item,填写新名称并使用Copy from字段来从第一个构建中复制。你可以在无需对第一个构建作更改的情况下保存每个构建。


接下来,为第二个Jenkins代理配置第一个作业。单击New Item,给第二个代理的第一个作业选个名字,再一次从第一个代理中复制作业。这一次我们将在保存之前修改配置页面上的字段。


首先,修改Label Expression字段匹配第二个代理的标签。


接着,用下面的脚本替换掉Build部分文本框中的脚本:



完成后单击Save



同样按照刚刚我们的流程,为第二个代理创建另外四个构建。


现在,转回到主页面,单击每行最右边的图标,启动全部刚刚创建的10个作业。在启动之后,它们会按照Build Queue部分的指示排队等待执行:



大约几秒钟之后,会开始创建Pods来执行构建(你可以在Rancher的Workload选项卡中检验这一点)。Jenkins会为每个作业创建一个pod。在每个代理启动时,它连接到master并从队列中接收要执行的作业。



代理完成了自己的工作后,它就会自动从集群中删除:



要检查作业的状态,可以单击每个代理中的一项作业。从Build History中单击构建,然后点击Console Output。由第一个代理执行的作业应该指定使用了jenkins-slave1 Docker镜像,而由第二个代理执行的构建应该指定使用了jenkins-slave2镜像:




如果你得到了上面的输出,那么Jenkins的配置就是正确的,而且是按照预期的方式在运行的。现在你就可以开始定制自己的Kubernetes的构建系统,帮助自己的团队测试和发布软件啦。


结   论


在本文中,我们配置了Jenkins来按需自动部署构建代理,将其连接到了Rancher管理的Kubernetes集群。为此,我们完成了下面的步骤:


  • 使用Rancher创建了一个集群

  • 为Jenkins master和代理创建了自定义Docker镜像

  • 将Jenkins master和L4 LoadBalancer服务部署在Kubernetes集群上

  • 在集群上配置了Jenkins kubernetes插件,自动生成动态代理

  • 使用带有专用代理镜像的多个构建作业测试场景


本文着重展现了设置Jenkins master和代理体系结构的基本的必要配置。我们了解了Jenkins如何使用JNLP启动代理,以及容器如何自动连接到Jenkins master来接受指令。为了实现这一点,我们使用Rancher创建集群、部署工作负载并监控产生的Pods。在这之后,我们又依靠Jenkins Kubernetes插件将所有不同的组件连接在了一起。


拓展阅读

Kubernetes仪表盘和外部IP代理漏洞及应对之策

在Kubernetes中部署Elasticsearch

在Kubernetes集群上部署和管理JFrog Artifactory

About Rancher Labs



Rancher Labs由硅谷云计算泰斗、CloudStack之父梁胜创建,致力于打造创新的开源软件,帮助企业在生产环境中运行容器与Kubernetes。旗舰产品Rancher是一个开源的企业级Kubernetes平台,是业界首个且唯一可以管理所有云上、所有发行版、所有Kubernetes集群的平台。解决了生产环境中企业用户可能面临的基础设施不同的困境,改善Kubernetes原生UI易用性不佳以及学习曲线陡峭的问题,是企业落地Kubernetes的不二之选。


Rancher在全球拥有超过一亿的下载量,超过20000家企业客户。全球知名企业如中国人寿、华为、中国平安、民生银行、兴业银行、上汽集团、海尔、米其林、天合光能、丰田、本田、霍尼韦尔、金风科技、普华永道、海南航空、厦门航空、恒大人寿、中国太平、巴黎银行、美国银行、HSCIS恒生指数、中国水利、暴雪、CCTV等均是Rancher的付费客户。

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

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