在 Kubernetes Engine 上使用 Jenkins

本主题将向您介绍将 Jenkins 与 Google Kubernetes Engine 搭配使用的最佳做法。若要实现此解决方案,请参阅在 Kubernetes Engine 上设置 Jenkins

Jenkins 是一种开源自动化服务器,利用此服务器,您可以灵活地编排构建、测试和部署流水线。Kubernetes Engine 是 Kubernetes 的托管版本,是强大的集群管理器和容器编排系统。

当您需要设置持续交付 (CD) 流水线时,相对于基于虚拟机的标准部署,在 Kubernetes Engine 上部署 Jenkins 优势明显:

  • 当构建过程使用容器时,一个虚拟主机可以为不同的操作系统运行作业。

  • Kubernetes Engine 提供了临时构建执行程序,使每个构建都能够在与之前的构建相同的清洁环境中运行。

    • 作为短暂存在的构建执行程序的一部分,Kubernetes Engine 集群仅在构建正在运行时使用,从而使资源可用于批处理作业等其他集群任务。

    • 构建执行程序在几秒钟内启动。

  • Kubernetes Engine 利用 Google 全局负载平衡器将 Web 流量路由到您的实例。负载平衡器处理 SSL 终止服务并提供一个全局 IP 地址,该地址通过 Google 骨干网,沿一条最快路径将用户从与您的用户距离最近的接入点路由到 Web 前端。

如需深入了解 Kubernetes Engine 上的 Jenkins,请观看 YouTube上的 Next 2018 演讲:

DevOps 现状报告确定了可提高软件交付方面表现的功能。本主题将帮助您使用以下功能:

使用 Helm 部署 Jenkins 控制器

使用 HelmCharts 代码库部署 Jenkins。Helm 是一个软件包管理器,可用于配置和部署 Kubernetes 应用

下图介绍在多节点 Kubernetes 集群中部署 Jenkins 的架构。

Jenkins 和 Kubernetes 架构

将 Jenkins 控制器部署到 Kubernetes 集群内的单独命名空间中。命名空间可用于为 Jenkins 部署创建配额,以及从逻辑上将 Jenkins 与集群中的其他部署分开。

创建 Jenkins 服务

Jenkins 提供了两种集群需要访问的服务。请分别部署这些服务,以便对其进行单独的管理和命名。

  • 端口 8080 上的对外公开型 NodePort 服务,Pod 和外部用户可通过该服务访问 Jenkins 用户界面。这种类型的服务可通过 HTTP 负载平衡器实现负载平衡。

  • 端口 50000 上的内部私有 ClusterIP 服务,Jenkins 执行程序使用该服务从集群内部与 Jenkins 控制器通信。

以下部分显示了示例服务定义。(在定义中,控制器名为 master。)

---
  kind: Service
  apiVersion: v1
  metadata:
    name: jenkins-ui
    namespace: jenkins
  spec:
    type: NodePort
    selector:
      app: master
    ports:
      - protocol: TCP
        port: 8080
        targetPort: 8080
        name: ui
---
  kind: Service
  apiVersion: v1
  metadata:
    name: jenkins-discovery
    namespace: jenkins
  spec:
    selector:
      app: master
    ports:
      - protocol: TCP
        port: 50000
        targetPort: 50000
        name: slaves

创建 Jenkins 部署

将 Jenkins 控制器部署为副本计数为 1 的部署。这可以确保任何时候都有一个 Jenkins 控制器在集群中运行。如果 Jenkins 控制器 Pod 崩溃或其运行的节点关闭,Kubernetes 会在集群中的其他位置重启该 Pod。

务必将请求和限制作为 Helm 部署的一部分进行设置,这可以确保在调度之前,容器已占据一定数量的集群内部 CPU 和内存资源。否则,您的控制器可能因 CPU 或内存不足而停机。

Jenkins 主卷存储构成配置的 XML 配置文件和插件 JAR 文件。此数据存储在由 GKE 集群管理的永久性磁盘上,并且在重启 Jenkins 时会保留数据。如需更改永久性磁盘的大小,请在使用 Helm 安装 Jenkins 时修改 Persistence.Size 值。

连接到 Jenkins

创建完 Jenkins Pod 后,您可以创建负载平衡器端点,以便从 Cloud Platform 外部连接到该 Pod。请考虑以下最佳做法。

  • 使用 Kubernetes Ingress 资源,轻松配置带 SSL 终端的 L7 负载平衡器。

  • 使用 Kubernetes 密钥为负载平衡器提供 SSL 证书。 使用 tls.certtls.key 值,并在 Ingress 资源配置中引用这些值。

配置 Jenkins

保护 Jenkins

首次连接到 Jenkins 之后,请务必立即保护 Jenkins。对于利用内部用户数据库的简单程序,您可以按 Jenkins 标准安全设置教程中的说明操作。此设置不需要额外的基础架构,并可以锁定匿名用户。

安装插件

您可以安装以下插件来增强 Jenkins 与 Kubernetes Engine 之间的交互。

  • 可借助 Kubernetes 插件将 Kubernetes 服务帐号用于身份验证,并利用不同的基础映像创建已加标签的执行程序配置。此插件可在需要执行程序时创建一个 Pod,并在作业结束时销毁该 Pod。

  • 借助 Google Authenticated Source 插件,您可以在访问 Cloud Source Repositories 之类的 Cloud Platform 服务时使用服务帐号凭据。

如需使用 Helm Chart 添加其他插件,请修改传递给 Helm install 或 upgrade 命令的值文件中的插件列表

自定义 Jenkins 代理 Docker 映像

创建 Pod 模板时,您可以提供现有 Docker 映像,也可以创建装有大部分构建时间依赖项的自定义映像。使用自定义映像可以减少总构建时间并创建更一致的构建环境。

您的自定义 Docker 映像必须安装并配置 Jenkins JNLP 入站代理。JNLP 代理是与 Jenkins 控制器通信,进而协调运行 Jenkins 作业并报告作业状态的软件。

选项之一是向映像配置中添加 FROM jenkins/inbound-agent。 例如,如果应用构建过程依赖于 Go 运行时,则可以创建以下 Dockerfile,以通过自定义依赖项和构建工件扩展现有映像。

FROM jenkins/inbound-agent
RUN apt-get update && apt-get install -y golang

然后,通过运行以下命令构建映像并将其上传到项目的 Container Registry 代码库。

docker build -t gcr.io/[PROJECT]/my-jenkins-image .
gcloud auth configure-docker
docker push gcr.io/[PROJECT]/my-jenkins-image

创建 Pod 模板时,您可以将 Docker 映像字段设置为以下字符串,其中的 [PROJECT] 替换为项目名称,[IMAGE_NAME] 替换为映像名称。

gcr.io/[PROJECT]/[IMAGE_NAME]

以上示例确保 Jenkins 作业启动时已经预安装了 Go 语言运行时。

在 Jenkins 中构建 Docker 映像

您可以在 Jenkins 作业中使用 Cloud Build,以便构建 Docker 映像,而无需托管您自己的 Docker 守护进程。Jenkins 作业必须具有已被授予 cloudbuild.builds.editor 角色的可用服务帐号凭据。

如需查看 Jenkins Pipeline 文件示例,请参阅此 GitHub 代码库

Kaniko 是想要在集群内部构建容器的用户的另一个选项。Kaniko 不需要使用 Docker 守护进程就可以构建映像并将映像推送到远程注册表。

如需查看在 Jenkins 中使用 Kaniko 的示例,请参阅此 GitHub 代码库

后续步骤