网络研讨会系列:使用Helm的Kubernetes包管理和使用JenkinsX的CI/CD

来自菜鸟教程
跳转至:导航、​搜索

网络研讨会系列

本文补充了 使用 Kubernetes 进行 CI/CD 的网络研讨会系列。 该系列讨论了如何采用云原生方法来构建、测试和部署应用程序,涵盖发布管理、云原生工具、服务网格和可与 Kubernetes 一起使用的 CI/CD 工具。 它旨在帮助有兴趣将 CI/CD 最佳实践与 Kubernetes 集成到他们的工作流程中的开发人员和企业。

本教程包括本系列第二部分的概念和命令,使用 Helm 进行 Kubernetes 包管理和使用 Jenkins X 进行 CI/CD。


警告: 本教程中的过程仅用于演示目的。 因此,他们没有遵循生产就绪部署所需的最佳实践和安全措施。


观看 YouTube 视频

介绍

为了在部署应用程序时减少错误和组织复杂性,CI/CD 系统必须包括用于包管理/部署的强大工具和具有自动化测试的管道。 但在现代生产环境中,基于云的基础设施日益复杂,可能会给构建可靠的 CI/CD 环境带来问题。 为解决这个问题而开发的两个 Kubernetes 特定工具是 Helm 包管理器和 Jenkins X 管道自动化工具。

Helm 是专为 Kubernetes 设计的包管理器,由 Cloud Native Computing Foundation (CNCF) 与 Microsoft、Google、Bitnami 和 Helm 贡献者社区合作维护。 在高层次上,它实现了与 APT 或 YUM 等 Linux 系统包管理器相同的目标:在后台管理应用程序和依赖项的安装,并向用户隐藏复杂性。 但是对于 Kubernetes,对这种管理的需求更加明显:安装应用程序需要对 YAML 文件进行复杂而繁琐的编排,升级或回滚版本可能非常困难,甚至不可能。 为了解决这个问题,Helm 运行在 Kubernetes 之上,将应用程序打包成预先配置好的资源,称为 charts,用户可以通过简单的命令进行管理,使共享和管理应用程序的过程更加人性化。友好。

Jenkins X 是一个 CI/CD 工具,用于自动化 Kubernetes 的生产管道和环境。 使用 Docker 镜像、Helm 图表和 Jenkins 管道引擎,Jenkins X 可以自动管理发布和版本,并在 GitHub 上的环境之间推广应用程序。

CI/CD with Kubernetes 系列 的第二篇文章中,您将通过以下方式预览这两个工具:

  • 使用 Helm 管理、创建和部署 Kubernetes 包。
  • 使用 Jenkins X 构建 CI/CD 管道。

尽管各种 Kubernetes 平台都可以使用 Helm 和 Jenkins X,但在本教程中,您将运行在本地环境中设置的模拟 Kubernetes 集群。 为此,您将使用 Minikube,该程序允许您在自己的机器上试用 Kubernetes 工具,而无需设置真正的 Kubernetes 集群。

在本教程结束时,您将对这些 Kubernetes 原生工具如何帮助您为云应用程序实现 CI/CD 系统有一个基本的了解。

先决条件

要遵循本教程,您将需要:

  • 具有 16 GB RAM 或以上的 Ubuntu 16.04 服务器。 由于本教程仅用于演示目的,因此命令从 root 帐户运行。 请注意,此帐户的无限制权限不符合生产就绪的最佳实践,可能会影响您的系统。因此,建议在虚拟机或虚拟机等测试环境中执行这些步骤DigitalOcean Droplet
  • 一个 GitHub 帐户GitHub API 令牌。 请务必记录此 API 令牌,以便您可以在本教程的 Jenkins X 部分中输入它。
  • 熟悉 Kubernetes 概念。 详情请参考文章【X28X】Kubernetes简介【X61X】。

第 1 步 — 使用 Minikube 创建本地 Kubernetes 集群

在设置 Minikube 之前,您必须安装它的依赖项,包括 Kubernetes 命令行工具 kubectl、双向数据传输中继 socat 和容器程序 Docker[X222X ]。

首先,确保系统的包管理器可以使用 apt-transport-https 通过 HTTPS 访问包:

apt-get update
apt-get install apt-transport-https

接下来,为了确保 kubectl 下载有效,请将 Google 官方存储库的 GPG 密钥添加到您的系统中:

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -

添加 GPG 密钥后,通过在文本编辑器中打开文件来创建文件 /etc/apt/sources.list.d/kubernetes.list

nano /etc/apt/sources.list.d/kubernetes.list

打开此文件后,添加以下行:

/etc/apt/sources.list.d/kubernetes.list

deb http://apt.kubernetes.io/ kubernetes-xenial main

这将向您的系统显示下载 kubectl 的源。 添加该行后,保存并退出文件。 使用 nano 文本编辑器,您可以通过按 CTRL+X、键入 y 并按 ENTER 来执行此操作。

最后,更新 APT 的源列表并安装 kubectlsocatdocker.io

apt-get update
apt-get install -y kubectl socat docker.io

注意: Minikube 要模拟 Kubernetes 集群,您必须下载 docker.io 包,而不是较新的 docker-ce 版本。 对于生产就绪环境,docker-ce 将是更合适的选择,因为它在官方 Docker 存储库中得到更好的维护。


现在您已经安装了 kubectl,您可以继续 安装 Minikube。 首先,使用 curl 下载程序的二进制文件:

curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.28.0/minikube-linux-amd64

接下来,更改刚刚下载的文件的访问权限,以便您的系统可以执行它:

chmod +x minikube

最后,将 minikube 文件复制到 /usr/local/bin/ 的可执行路径并从主目录中删除原始文件:

cp minikube /usr/local/bin/
rm minikube

在您的机器上安装 Minikube 后,您现在可以启动该程序。 要创建 Minikube Kubernetes 集群,请使用以下命令:

minikube start --vm-driver none

标志 --vm-driver none 指示 Minikube 使用容器而不是虚拟机在本地主机上运行 Kubernetes。 以这种方式运行 Minikube 意味着您不需要下载 VM 驱动程序,但也意味着 Kubernetes API 服务器将以 root 身份运行不安全。

警告: 因为具有root权限的API服务器将无限制地访问本地主机,所以不建议在个人工作站上使用none驱动运行Minikube。


现在您已经启动了 Minikube,请检查以确保您的集群正在使用以下命令运行:

minikube status

您将收到以下输出,其中您的 IP 地址代替了 your_IP_address

minikube: Running
cluster: Running
kubectl: Correctly Configured: pointing to minikube-vm at your_IP_address

现在您已经使用 Minikube 设置了模拟 Kubernetes 集群,您可以通过在集群顶部安装和配置 Helm 包管理器来获得 Kubernetes 包管理的经验。

第 2 步 — 在集群上设置 Helm 包管理器

为了协调 Kubernetes 集群上应用程序的安装,您现在将安装 Helm 包管理器。 Helm 由一个在集群外运行的 helm 客户端和一个在集群内管理应用程序发布的 tiller 服务器组成。 您必须安装和配置两者才能在集群上成功运行 Helm。

安装 Helm 二进制文件,首先使用 curl 从官方 Helm GitHub 存储库下载以下 安装脚本 到名为 get_helm.sh 的新文件中:

curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get > get_helm.sh

由于此脚本需要 root 访问权限,因此更改 get_helm.sh 的权限,以便文件的所有者(在本例中为 root)可以读取、写入和执行它:

chmod 700 get_helm.sh

现在,执行脚本:

./get_helm.sh

脚本完成后,您将 helm 安装到 /usr/local/bin/helmtiller 安装到 /usr/local/bin/tiller

虽然现在安装了 tiller,但它还没有正确的角色和权限来访问 Kubernetes 集群中的必要资源。 要将这些角色和权限分配给 tiller,您必须创建一个名为 tiller服务帐户 。 在 Kubernetes 中,服务帐户代表在 pod 中运行的进程的身份。 进程通过服务帐户进行身份验证后,它可以联系 API 服务器并访问集群资源。 如果 pod 没有分配特定的服务帐户,它会获得默认服务帐户。 您还必须创建授权 tiller 服务帐户的 基于角色的访问控制 (RBAC) 规则。

在 Kubernetes RBAC API 中,role 包含确定一组权限的规则。 角色可以定义为 namespacecluster 的范围,并且只能授予对单个命名空间内资源的访问权限。 ClusterRole 可以在集群级别创建相同的权限,授予对集群范围资源(如节点)和命名空间资源(如 Pod)的访问权限。 要为 tiller 服务帐户分配正确的角色,请创建一个名为 rbac_helm.yaml 的 YAML 文件并在文本编辑器中打开它:

nano rbac_helm.yaml

将以下行添加到文件中以配置 tiller 服务帐户:

rbac_helm.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: tiller
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: tiller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: ServiceAccount
    name: tiller
    namespace: kube-system

  - kind: User
    name: "admin"
    apiGroup: rbac.authorization.k8s.io

  - kind: User
    name: "kubelet"
    apiGroup: rbac.authorization.k8s.io

  - kind: Group
    name: system:serviceaccounts
    apiGroup: rbac.authorization.k8s.io

在前面的文件中,ServiceAccount 允许 tiller 进程作为经过身份验证的服务帐户访问 apiserver。 ClusterRole 授予角色某些权限,ClusterRoleBinding 将该角色分配给 subjects 列表,包括 tiller 服务帐户、[ X153X] 和 kubelet 用户,以及 system:serviceaccounts 组。

接下来,使用以下命令在 rbac_helm.yaml 中部署配置:

kubectl apply -f rbac_helm.yaml 

部署了 tiller 配置后,您现在可以使用 --service-acount 标志初始化 Helm 以使用您刚刚设置的服务帐户:

helm init --service-account tiller 

您将收到以下输出,表示初始化成功:

OutputCreating /root/.helm
Creating /root/.helm/repository
Creating /root/.helm/repository/cache
Creating /root/.helm/repository/local
Creating /root/.helm/plugins
Creating /root/.helm/starters
Creating /root/.helm/cache/archive
Creating /root/.helm/repository/repositories.yaml
Adding stable repo with URL: https://kubernetes-charts.storage.googleapis.com
Adding local repo with URL: http://127.0.0.1:8879/charts
$HELM_HOME has been configured at /root/.helm.

Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.

Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
To prevent this, run `helm init` with the --tiller-tls-verify flag.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
Happy Helming!

这会在 kube-system 命名空间中创建一个 tiller pod。 它还在 $HOME 目录中创建 .helm 默认存储库,并在 https://kubernetes-charts.storage.googleapis.com 和本地 Helm 存储库 http://127.0.0.1:8879/charts 配置默认 Helm 稳定图表存储库。

要确保 tiller pod 正在 kube-system 命名空间中运行,请输入以下命令:

kubectl --namespace kube-system get pods

在您的 pod 列表中,将出现 tiller-deploy,如以下输出所示:

OutputNAME                                    READY   STATUS    RESTARTS   AGE
etcd-minikube                           1/1     Running   0          2h
kube-addon-manager-minikube             1/1     Running   0          2h
kube-apiserver-minikube                 1/1     Running   0          2h
kube-controller-manager-minikube        1/1     Running   0          2h
kube-dns-86f4d74b45-rjql8               3/3     Running   0          2h
kube-proxy-dv268                        1/1     Running   0          2h
kube-scheduler-minikube                 1/1     Running   0          2h
kubernetes-dashboard-5498ccf677-wktkl   1/1     Running   0          2h
storage-provisioner                     1/1     Running   0          2h
tiller-deploy-689d79895f-bggbk          1/1     Running   0          5m

如果 tiller pod 的状态为 Running,它现在可以代表 Helm 从集群内部管理 Kubernetes 应用程序。

要确保整个 Helm 应用程序正常工作,请在 Helm 包存储库中搜索 MongoDB 等应用程序:

helm search mongodb

在输出中,您将看到适合您的搜索词的可能应用程序列表:

OutputNAME                                    CHART VERSION   APP VERSION     DESCRIPTION
stable/mongodb                          5.4.0           4.0.6           NoSQL document-oriented database that stores JSON-like do...
stable/mongodb-replicaset               3.9.0           3.6             NoSQL document-oriented database that stores JSON-like do...
stable/prometheus-mongodb-exporter      1.0.0           v0.6.1          A Prometheus exporter for MongoDB metrics
stable/unifi                            0.3.1           5.9.29          Ubiquiti Network's Unifi Controller

现在您已经在 Kubernetes 集群上安装了 Helm,您可以通过创建示例 Helm 图表并从中部署应用程序来了解有关包管理器的更多信息。

第 3 步 — 创建图表并使用 Helm 部署应用程序

在 Helm 包管理器中,单个包称为 charts。 在图表中,一组文件定义了一个应用程序,该应用程序的复杂性可以从一个 pod 到一个结构化的全栈应用程序。 您可以从 Helm 存储库下载图表,也可以使用 helm create 命令创建自己的图表。

要测试 Helm 的功能,请使用以下命令创建一个名为 demo 的新 Helm 图表:

helm create demo

在您的主目录中,您将找到一个名为 demo 的新目录,您可以在其中创建和编辑自己的图表模板。

移动到 demo 目录并使用 ls 列出其内容:

cd demo
ls

您将在 demo 中找到以下文件和目录:

演示

charts  Chart.yaml  templates  values.yaml

使用文本编辑器打开 Chart.yaml 文件:

nano Chart.yaml

在里面,你会发现以下内容:

演示/Chart.yaml

apiVersion: v1
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: demo
version: 0.1.0

在这个 Chart.yaml 文件中,您会发现像 apiVersion 这样的字段,它必须始终是 v1,一个 description 提供有关 [ X155X] 是图表的 name,以及 Helm 用作发布标记的 version 编号。 检查完文件后,关闭文本编辑器。

接下来,打开 values.yaml 文件:

nano values.yaml

在此文件中,您将找到以下内容:

演示/values.yaml

# Default values for demo.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 1

image:
  repository: nginx
  tag: stable
  pullPolicy: IfNotPresent

nameOverride: ""
fullnameOverride: ""

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: false
  annotations: {}
    # kubernetes.io/ingress.class: nginx
    # kubernetes.io/tls-acme: "true"
  paths: []
  hosts:
    - chart-example.local
  tls: []
  #  - secretName: chart-example-tls
  #    hosts:
  #      - chart-example.local

resources: {}
  # We usually recommend not to specify default resources and to leave this as a conscious
  # choice for the user. This also increases chances charts run on environments with little
  # resources, such as Minikube. If you do want to specify resources, uncomment the following
  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
  # limits:
  #  cpu: 100m
  #  memory: 128Mi
  # requests:
  #  cpu: 100m
  #  memory: 128Mi

nodeSelector: {}

tolerations: []

affinity: {}

通过更改 values.yaml 的内容,图表开发人员可以为图表中定义的应用程序提供默认值,控制副本数、图像库、入口访问、秘密管理等。 图表用户可以使用 helm install 使用自定义 YAML 文件为这些参数提供自己的值。 当用户提供自定义值时,这些值将覆盖图表的 values.yaml 文件中的值。

关闭 values.yaml 文件并使用以下命令列出 templates 目录的内容:

ls templates

在这里,您将找到可以控制图表不同方面的各种文件的模板:

模板

deployment.yaml  _helpers.tpl  ingress.yaml  NOTES.txt  service.yaml  tests

现在您已经探索了 demo 图表,您可以通过安装 demo 来试验 Helm 图表安装。 使用以下命令返回您的主目录:

cd

使用 helm install 安装名为 webdemo Helm 图表:

helm install --name web ./demo

您将获得以下输出:

OutputNAME:   web
LAST DEPLOYED: Wed Feb 20 20:59:48 2019
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Service
NAME      TYPE       CLUSTER-IP     EXTERNAL-IP  PORT(S)  AGE
web-demo  ClusterIP  10.100.76.231  <none>       80/TCP   0s

==> v1/Deployment
NAME      DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
web-demo  1        0        0           0          0s

==> v1/Pod(related)
NAME                       READY  STATUS             RESTARTS  AGE
web-demo-5758d98fdd-x4mjs  0/1    ContainerCreating  0         0s


NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=demo,app.kubernetes.io/instance=web" -o jsonpath="{.items[0].metadata.name}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl port-forward $POD_NAME 8080:80

在此输出中,您将找到应用程序的 STATUS,以及集群中相关资源的列表。

接下来,使用以下命令列出由 demo Helm 图表创建的部署:

kubectl get deploy

这将产生列出您的活动部署的输出:

OutputNAME       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
web-demo   1         1         1            1           4m

使用命令 kubectl get pods 列出您的 pod 将显示正在运行您的 web 应用程序的 pod,如下所示:

OutputNAME                        READY   STATUS    RESTARTS   AGE
web-demo-5758d98fdd-nbkqd   1/1     Running   0          4m

要演示 Helm 图表中的更改如何发布应用程序的不同版本,请在文本编辑器中打开 demo/values.yaml 并将 replicaCount: 更改为 3image:tag:stablelatest。 在以下代码块中,您将看到 YAML 文件在完成修改后的样子,其中突出显示了更改:

演示/values.yaml

# Default values for demo.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 3

image:
  repository: nginx
  tag: latest
  pullPolicy: IfNotPresent

nameOverride: ""
fullnameOverride: ""

service:
  type: ClusterIP
  port: 80
. . .

保存并退出文件。

在部署 web 应用程序的这个新版本之前,请使用以下命令列出您的 Helm 版本,就像它们现在一样:

helm list

您将收到以下输出,其中包含您之前创建的一个部署:

OutputNAME    REVISION        UPDATED                         STATUS          CHART           APP VERSION     NAMESPACE
web     1               Wed Feb 20 20:59:48 2019        DEPLOYED        demo-0.1.0      1.0             default

请注意,REVISION 被列为 1,表明这是 web 应用程序的第一个版本。

要使用对 demo/values.yaml 所做的最新更改部署 web 应用程序,请使用以下命令升级应用程序:

helm upgrade web ./demo

现在,再次列出 Helm 版本:

helm list

您将收到以下输出:

OutputNAME    REVISION        UPDATED                         STATUS          CHART           APP VERSION     NAMESPACE
web     2               Wed Feb 20 21:18:12 2019        DEPLOYED        demo-0.1.0      1.0             default

请注意,REVISION 已更改为 2,表示这是第二次修订。

要查找 web 的 Helm 版本历史记录,请使用以下命令:

helm history web

这将显示 web 应用程序的两个版本:

输出

REVISION        UPDATED                         STATUS          CHART           DESCRIPTION
1               Wed Feb 20 20:59:48 2019        SUPERSEDED      demo-0.1.0      Install complete
2               Wed Feb 20 21:18:12 2019        DEPLOYED        demo-0.1.0      Upgrade complete

要将您的应用程序回滚到修订版 1,请输入以下命令:

helm rollback web 1

这将产生以下输出:

OutputRollback was a success! Happy Helming!

现在,调出 Helm 发布历史:

helm history web

您将收到以下列表:

OutputREVISION        UPDATED                         STATUS          CHART           DESCRIPTION
1               Wed Feb 20 20:59:48 2019        SUPERSEDED      demo-0.1.0      Install complete
2               Wed Feb 20 21:18:12 2019        SUPERSEDED      demo-0.1.0      Upgrade complete
3               Wed Feb 20 21:28:48 2019        DEPLOYED        demo-0.1.0      Rollback to 1

通过回滚 web 应用程序,您创建了与修订 1 具有相同设置的第三修订。 请记住,您始终可以通过在 STATUS 下找到 DEPLOYED 项来判断哪个版本处于活动状态。

为了准备下一部分,通过使用 helm delete 命令删除 web 版本来清理测试区域:

helm delete web

再次检查 Helm 发布历史:

helm history web

您将收到以下输出:

OutputREVISION        UPDATED                         STATUS          CHART           DESCRIPTION
1               Wed Feb 20 20:59:48 2019        SUPERSEDED      demo-0.1.0      Install complete
2               Wed Feb 20 21:18:12 2019        SUPERSEDED      demo-0.1.0      Upgrade complete
3               Wed Feb 20 21:28:48 2019        DELETED         demo-0.1.0      Deletion complete

REVISION 3STATUS变成了DELETED,说明你部署的web实例已经被删除。 但是,尽管这确实删除了该版本,但它并没有从存储中删除它。 为了完全删除版本,运行带有 --purge 标志的 helm delete 命令。

helm delete web --purge

在此步骤中,您已使用 Helm 在 Kubernetes 上管理应用程序发布。 如果您想进一步学习 Helm,请查看我们的 Helm 简介,Kubernetes 包管理器 教程,或查看官方 Helm 文档

接下来,您将使用 jx CLI 设置和测试管道自动化工具 Jenkins X,以创建一个 CI/CD 就绪的 Kubernetes 集群。

第 4 步 — 设置 Jenkins X 环境

使用 Jenkins X,您可以使用内置的管道自动化和 CI/CD 解决方案从头开始创建 Kubernetes 集群。 通过安装 jx CLI 工具,您将能够有效地管理应用程序发布、Docker 映像和 Helm 图表,此外还可以在 GitHub 中跨环境自动推广您的应用程序。

由于您将使用 jx 创建集群,因此您必须首先删除已有的 Minikube 集群。 为此,请使用以下命令:

minikube delete

这将删除本地模拟的 Kubernetes 集群,但不会删除您首次安装 Minikube 时创建的默认目录。 要清除机器上的这些,请使用以下命令:

rm -rf ~/.kube
rm -rf ~/.minikube
rm -rf /etc/kubernetes/*
rm -rf /var/lib/minikube/*

从机器上完全清除 Minikube 后,您可以继续安装 Jenkins X 二进制文件。

首先,使用 curl 命令从官方 Jenkins X GitHub 存储库 下载压缩的 jx 文件,然后使用 tar 命令解压:

curl -L https://github.com/jenkins-x/jx/releases/download/v1.3.781/jx-linux-amd64.tar.gz | tar xzv 

接下来,将下载的jx文件移动到/usr/local/bin处的可执行路径:

mv jx /usr/local/bin

Jenkins X 带有一个在 Kubernetes 集群中运行的 Docker Registry。 由于这是一个内部元素,因此自签名证书等安全措施可能会给程序带来麻烦。 要解决此问题,请将 Docker 设置为对本地 IP 范围使用不安全的注册表。 为此,创建文件 /etc/docker/daemon.json 并在文本编辑器中打开它:

nano /etc/docker/daemon.json

将以下内容添加到文件中:

/etc/docker/daemon.json

{
  "insecure-registries" : ["0.0.0.0/0"]
}

保存并退出文件。 要使这些更改生效,请使用以下命令重新启动 Docker 服务:

systemctl restart docker 

要验证您是否已使用不安全的注册表配置 Docker,请使用以下命令:

docker info

在输出的末尾,您应该看到以下突出显示的行:

OutputContainers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 15
Server Version: 18.06.1-ce
Storage Driver: overlay2
 Backing Filesystem: extfs
 Supports d_type: true
 Native Overlay Diff: true

. . .

Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
 0.0.0.0/0
 127.0.0.0/8
Live Restore Enabled: false

现在您已经下载了 Jenkins X 并配置了 Docker 注册表,使用 jx CLI 工具创建具有 CI/CD 功能的 Minikube Kubernetes 集群:

jx create cluster minikube --cpu=5 --default-admin-password=admin --vm-driver=none --memory=13314

在这里,您正在使用 Minikube 创建一个 Kubernetes 集群,使用标志 --cpu=5 设置 5 个 CPU 和 --memory=13314 为您的集群提供 13314 MB 内存。 由于 Jenkins X 是一个强大但大型的程序,这些规范将确保 Jenkins X 在此演示中正常工作。 此外,您正在使用 --default-admin-password=admin 将 Jenkins X 密码设置为 admin--vm-driver=none 以在本地设置集群,就像您在步骤 1 中所做的那样。

当 Jenkins X 启动您的集群时,您将在整个过程的不同时间收到各种提示,这些提示为您的集群设置参数并确定它将如何与 GitHub 通信以管理您的生产环境。

首先,您将收到以下提示:

Output? disk-size (MB) 150GB

ENTER 继续。 接下来,系统将提示您输入您希望与 git 一起使用的名称、您希望与 git 一起使用的电子邮件地址以及您的 GitHub 用户名。 出现提示时输入其中的每一个,然后按 ENTER

接下来,Jenkins X 会提示你输入你的 GitHub API 令牌:

OutputTo be able to create a repository on GitHub we need an API Token
Please click this URL https://github.com/settings/tokens/new?scopes=repo,read:user,read:org,user:email,write:repo_hook,delete_repo

Then COPY the token and enter in into the form below:

? API Token:

在此处输入您的令牌,或使用前面代码块中突出显示的 URL 创建具有适当权限的新令牌。

接下来,Jenkins X 会问:

Output? Do you wish to use GitHub as the pipelines Git server: (Y/n)

? Do you wish to use your_GitHub_username as the pipelines Git user for GitHub server: (Y/n)

两个问题都输入 Y

之后,Jenkins X 会提示你回答以下问题:

Output? Select Jenkins installation type:   [Use arrows to move, type to filter]
>Static Master Jenkins
  Serverless Jenkins

? Pick workload build pack:   [Use arrows to move, type to filter]
> Kubernetes Workloads: Automated CI+CD with GitOps Promotion
  Library Workloads: CI+Release but no CD

前者选择Static Master Jenkins,后者选择Kubernetes Workloads: Automated CI+CD with GitOps Promotion。 当提示为您的环境存储库选择组织时,请选择您的 GitHub 用户名。

最后,您将收到以下输出,验证安装成功并提供您的 Jenkins X 管理员密码。

OutputCreating GitHub webhook for your_GitHub_username/environment-horsehelix-production for url http://jenkins.jx.your_IP_address.nip.io/github-webhook/

Jenkins X installation completed successfully


        ********************************************************

             NOTE: Your admin password is: admin

        ********************************************************



Your Kubernetes context is now set to the namespace: jx
To switch back to your original namespace use: jx namespace default
For help on switching contexts see: https://jenkins-x.io/developing/kube-context/

To import existing projects into Jenkins:       jx import
To create a new Spring Boot microservice:       jx create spring -d web -d actuator
To create a new microservice from a quickstart: jx create quickstart

接下来,使用 jx get 命令接收显示应用程序信息的 URL 列表:

jx get urls

此命令将生成类似于以下内容的列表:

Name                      URL
jenkins                   http://jenkins.jx.your_IP_address.nip.io
jenkins-x-chartmuseum     http://chartmuseum.jx.your_IP_address.nip.io
jenkins-x-docker-registry http://docker-registry.jx.your_IP_address.nip.io
jenkins-x-monocular-api   http://monocular.jx.your_IP_address.nip.io
jenkins-x-monocular-ui    http://monocular.jx.your_IP_address.nip.io
nexus                     http://nexus.jx.your_IP_address.nip.io

您可以通过在浏览器中输入地址并输入您的用户名和密码,使用这些 URL 通过 UI 查看有关您的 CI/CD 环境的 Jenkins X 数据。 在这种情况下,这将是两者的“管理员”。

接下来,为了确保命名空间 jxjx-stagingjx-production 中的服务帐户具有管理员权限,请使用以下命令修改您的 RBAC 策略:

kubectl create clusterrolebinding jx-staging1 --clusterrole=cluster-admin --user=admin --user=expose --group=system:serviceaccounts --serviceaccount=jx-staging:expose --namespace=jx-staging
kubectl create clusterrolebinding jx-staging2 --clusterrole=cluster-admin --user=admin --user=expose --group=system:serviceaccounts --serviceaccount=jx-staging:default --namespace=jx-staging
kubectl create clusterrolebinding jx-production1 --clusterrole=cluster-admin --user=admin --user=expose --group=system:serviceaccounts --serviceaccount=jx-production:expose --namespace=jx-productions
kubectl create clusterrolebinding jx-production2 --clusterrole=cluster-admin --user=admin --user=expose --group=system:serviceaccounts --serviceaccount=jx-production:default --namespace=jx-productions
kubectl create clusterrolebinding jx-binding1 --clusterrole=cluster-admin --user=admin --user=expose --group=system:serviceaccounts --serviceaccount=jx:expose --namespace=jx
kubectl create clusterrolebinding jx-binding2 --clusterrole=cluster-admin --user=admin --user=expose --group=system:serviceaccounts --serviceaccount=jx:default --namespace=jx

现在您已经创建了内置 Jenkins X 功能的本地 Kubernetes 集群,您可以继续在平台上创建应用程序以测试其 CI/CD 功能并体验 Jenkins X 管道。

第 5 步 — 在您的 Jenkins X 环境中创建测试应用程序

在 Kubernetes 集群中设置 Jenkins X 环境后,您现在拥有可以帮助您自动化测试管道的 CI/CD 基础设施。 在此步骤中,您将通过在正常工作的 Jenkins X 管道中设置测试应用程序来尝试这一点。

出于演示目的,本教程将使用 CloudYuga 团队创建的示例 RSVP 应用程序。 您可以在 DO-Community GitHub 存储库 中找到此应用程序以及其他网络研讨会材料。

首先,使用以下命令从存储库中克隆示例应用程序:

git clone https://github.com/do-community/rsvpapp.git

克隆存储库后,进入 rsvpapp 目录并删除 git 文件:

cd rsvpapp
rm -r .git/

要为新应用初始化 git 存储库和 Jenkins X 项目,您可以使用 jx create 从头开始或模板,或 jx import 从本地项目或 git 导入现有应用存储库。 对于本教程,通过在应用程序的主目录中运行以下命令来导入示例 RSVP 应用程序:

jx import

Jenkins X 将提示您输入您的 GitHub 用户名、是否要初始化 git、提交消息、您的组织以及您想要的存储库名称。 回答“是”以初始化 git,然后向其余提示提供您的个人 GitHub 信息和偏好。 当 Jenkins X 导入应用程序时,它将在应用程序的主目录中创建 Helm 图表和 Jenkinsfile。 您可以根据需要修改这些图表和 Jenkinsfile。

由于示例 RSVP 应用程序在其容器的端口 5000 上运行,因此修改您的 charts/rsvpapp/values.yaml 文件以匹配此。 在文本编辑器中打开 charts/rsvpapp/values.yaml

nano charts/rsvpapp/values.yaml

在此 values.yaml 文件中,将 service:internalPort: 设置为 5000。 进行此更改后,您的文件应如下所示:

图表/rsvpapp/values.yaml

# Default values for python.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
  repository: draft
  tag: dev
  pullPolicy: IfNotPresent
service:
  name: rsvpapp
  type: ClusterIP
  externalPort: 80
  internalPort: 5000
  annotations:
    fabric8.io/expose: "true"
    fabric8.io/ingress.annotations: "kubernetes.io/ingress.class: nginx"
resources:
  limits:
    cpu: 100m
    memory: 128Mi
  requests:
    cpu: 100m
    memory: 128Mi
ingress:
  enabled: false

保存并退出您的文件。

接下来,更改 charts/preview/requirements.yaml 以适合您的应用程序。 requirements.yaml 是一个 YAML 文件,开发人员可以在其中声明图表依赖关系,以及图表的位置和所需的版本。 由于我们的示例应用程序将 MongoDB 用于数据库目的,因此您需要修改 charts/preview/requirements.yaml 文件以将 MongoDB 列为依赖项。 使用以下命令在文本编辑器中打开文件:

nano charts/preview/requirements.yaml

通过在 alias: cleanup 条目之后添加 mongodb-replicaset 条目来编辑文件,如以下代码块中突出显示的那样:

图表/预览/requirements.yaml

# !! File must end with empty line !!
dependencies:
- alias: expose
  name: exposecontroller
  repository: http://chartmuseum.jenkins-x.io
  version: 2.3.92
- alias: cleanup
  name: exposecontroller
  repository: http://chartmuseum.jenkins-x.io
  version: 2.3.92
- name: mongodb-replicaset
  repository: https://kubernetes-charts.storage.googleapis.com/
  version: 3.5.5

  # !! "alias: preview" must be last entry in dependencies array !!
  # !! Place custom dependencies above !!
- alias: preview
  name: rsvpapp
  repository: file://../rsvpapp

在这里,您已将 mongodb-replicaset 图表指定为 preview 图表的依赖项。

接下来,对您的 rsvpapp 图表重复此过程。 创建 charts/rsvpapp/requirements.yaml 文件并在文本编辑器中打开它:

nano charts/rsvpapp/requirements.yaml

打开文件后,添加以下内容,确保在填充的行之前和之后有一行空白:

图表/rsvpapp/requirements.yaml

dependencies:
- name: mongodb-replicaset
  repository: https://kubernetes-charts.storage.googleapis.com/
  version: 3.5.5

现在您已将 mongodb-replicaset 图表指定为 rsvpapp 图表的依赖项。

接下来,为了将示例 RSVP 应用程序的前端连接到 MongoDB 后端,请将 MONGODB_HOST 环境变量添加到 charts/rsvpapp/templates/ 中的 deployment.yaml 文件中。 在文本编辑器中打开此文件:

nano charts/rsvpapp/templates/deployment.yaml

除了文件顶部的一个空行和文件底部的两个空行之外,将以下突出显示的行添加到文件中。 请注意,YAML 文件需要这些空行才能正常工作:

图表/rsvpapp/templates/deployment.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: {{ template "fullname" . }}
  labels:
    draft: {{ default "draft-app" .Values.draft }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}"
spec:
  replicas: {{ .Values.replicaCount }}
  template:
    metadata:
      labels:
        draft: {{ default "draft-app" .Values.draft }}
        app: {{ template "fullname" . }}
{{- if .Values.podAnnotations }}
      annotations:
{{ toYaml .Values.podAnnotations | indent 8 }}
{{- end }}
    spec:
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        env:
        - name: MONGODB_HOST
          value: "mongodb://{{.Release.Name}}-mongodb-replicaset-0.{{.Release.Name}}-mongodb-replicaset,{{.Release.Name}}-mongodb-replicaset-1.{{.Release.Name}}-mongodb-replicaset,{{.Release.Name}}-mongodb-replicaset-2.{{.Release.Name}}-mongodb-replicaset:27017"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        ports:
        - containerPort: {{ .Values.service.internalPort }}
        resources:
{{ toYaml .Values.resources | indent 12 }}

通过这些更改,Helm 将能够使用 MongoDB 作为其数据库来部署您的应用程序。

接下来,通过打开应用程序主目录中的文件来检查 Jenkins X 生成的 Jenkinsfile

nano Jenkinsfile

这个 Jenkinsfile 定义了每次将应用程序版本提交到 GitHub 存储库时触发的管道。 如果您想自动化您的代码测试,以便在每次触发管道时触发测试,您可以将测试添加到此文档中。

为了演示这一点,添加自定义测试用例,将 Jenkinsfile 中的 stage('Build Release') 替换为以下突出显示的行:

/rsvpapp/Jenkinsfile

. . .
  stages {
    stage('CI Build and push snapshot') {
      when {
        branch 'PR-*'
      }
      environment {
        PREVIEW_VERSION = "0.0.0-SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER"
        PREVIEW_NAMESPACE = "$APP_NAME-$BRANCH_NAME".toLowerCase()
        HELM_RELEASE = "$PREVIEW_NAMESPACE".toLowerCase()
      }
      steps {
        container('python') {
          sh "pip install -r requirements.txt"
          sh "python -m pytest tests/test_rsvpapp.py"
          sh "export VERSION=$PREVIEW_VERSION && skaffold build -f skaffold.yaml"
          sh "jx step post build --image $DOCKER_REGISTRY/$ORG/$APP_NAME:$PREVIEW_VERSION"
          dir('./charts/preview') {
            sh "make preview"
            sh "jx preview --app $APP_NAME --dir ../.."
          }
        }
      }
    }
    stage('Build Release') {
      when {
        branch 'master'
      }
      steps {
        container('python') {

          // ensure we're not on a detached head
          sh "git checkout master"
          sh "git config --global credential.helper store"
          sh "jx step git credentials"

          // so we can retrieve the version in later steps
          sh "echo \$(jx-release-version) > VERSION"
          sh "jx step tag --version \$(cat VERSION)"
          sh "pip install -r requirements.txt"
          sh "python -m pytest tests/test_rsvpapp.py"
          sh "export VERSION=`cat VERSION` && skaffold build -f skaffold.yaml"
          sh "jx step post build --image $DOCKER_REGISTRY/$ORG/$APP_NAME:\$(cat VERSION)"
        }
      }
    }
. . .

通过添加的行,Jenkins X 管道将安装依赖项并在您提交对应用程序的更改时执行 Python 测试。

现在您已经更改了示例 RSVP 应用程序,使用以下命令将这些更改提交并推送到 GitHub:

git add *
git commit -m update
git push

当您将这些更改推送到 GitHub 时,您将触发应用程序的新构建。 如果您通过导航到 http://jenkins.jx.your_IP_address.nip.io 并输入“admin”作为您的用户名和密码来打开 Jenkins UI,您将找到有关您的新构建的信息。 如果您从页面左侧的菜单中单击“构建历史”,您应该会看到已提交构建的历史记录。 如果您单击构建旁边的蓝色图标,然后从左侧菜单中选择“控制台输出”,您将找到管道中自动化步骤的控制台输出。 滚动到此输出的末尾,您会发现以下消息:

Output. . .
Finished: SUCCESS

这意味着您的应用程序已经通过了您的自定义测试,并且现在已成功部署。

Jenkins X 构建应用发布后,会将应用推广到 staging 环境。 要验证您的应用程序是否正在运行,请使用以下命令列出在 Kubernetes 集群上运行的应用程序:

jx get app

您将收到类似于以下内容的输出:

OutputAPPLICATION STAGING PODS URL
rsvpapp     0.0.2   1/1  http://rsvpapp.jx-staging.your_IP_address.nip.io

从这里,您可以看到 Jenkins X 已将您的应用程序部署在您的 jx-staging 环境中,版本为 0.0.2。 输出还显示了可用于访问应用程序的 URL。 访问此 URL 将显示示例 RSVP 应用程序:

接下来,使用以下命令检查应用程序的活动:

jx get activity -f rsvpapp 

您将收到类似于以下内容的输出:

OutputSTEP                                        STARTED      AGO DURATION STATUS
your_GitHub_username/rsvpappv/master #1    3h42m23s    4m51s Succeeded Version: 0.0.1
  Checkout Source                          3h41m52s       6s Succeeded
  CI Build and push snapshot               3h41m46s          NotExecuted
  Build Release                            3h41m46s      56s Succeeded
  Promote to Environments                  3h40m50s    3m17s Succeeded
  Promote: staging                         3h40m29s    2m36s Succeeded
    PullRequest                            3h40m29s    1m16s Succeeded  PullRequest: https://github.com/your_GitHub_username/environment-horsehelix-staging/pull/1 Merge SHA: dc33d3747abdacd2524e8c22f0b5fbb2ac3f6fc7
    Update                                 3h39m13s    1m20s Succeeded  Status: Success at: http://jenkins.jx.your_IP_address.nip.io/job/your_GitHub_username/job/environment-horsehelix-staging/job/master/2/display/redirect
    Promoted                               3h39m13s    1m20s Succeeded  Application is at: http://rsvpapp.jx-staging.your_IP_address.nip.io
  Clean up                                 3h37m33s       1s Succeeded
your_GitHub_username/rsvpappv/master #2      28m37s    5m57s Succeeded Version: 0.0.2
  Checkout Source                            28m18s       4s Succeeded
  CI Build and push snapshot                 28m14s          NotExecuted
  Build Release                              28m14s      56s Succeeded
  Promote to Environments                    27m18s    4m38s Succeeded
  Promote: staging                           26m53s     4m0s Succeeded
    PullRequest                              26m53s     1m4s Succeeded  PullRequest: https://github.com/your_GitHub_username/environment-horsehelix-staging/pull/2 Merge SHA: 976bd5ad4172cf9fd79f0c6515f5006553ac6611
    Update                                   25m49s    2m56s Succeeded  Status: Success at: http://jenkins.jx.your_IP_address.nip.io/job/your_GitHub_username/job/environment-horsehelix-staging/job/master/3/display/redirect
    Promoted                                 25m49s    2m56s Succeeded  Application is at: http://rsvpapp.jx-staging.your_IP_address.nip.io
  Clean up                                   22m40s       0s Succeeded

在这里,您通过应用带有 -f rsvpapp 的过滤器来获取 RSVP 应用程序的 Jenkins X 活动。

接下来,使用以下命令列出在 jx-staging 命名空间中运行的 pod:

kubectl get pod -n jx-staging

您将收到类似于以下内容的输出:

NAME                                 READY     STATUS    RESTARTS   AGE
jx-staging-mongodb-replicaset-0      1/1       Running   0          6m
jx-staging-mongodb-replicaset-1      1/1       Running   0          6m
jx-staging-mongodb-replicaset-2      1/1       Running   0          5m
jx-staging-rsvpapp-c864c4844-4fw5z   1/1       Running   0          6m

此输出显示您的应用程序正在 jx-staging 命名空间中运行,以及后端 MongoDB 数据库的三个 pod,遵循您之前对 YAML 文件所做的更改。

现在您已经通过 Jenkins X 管道运行了一个测试应用程序,您可以尝试将此应用程序推广到生产环境。

第 6 步 — 将您的测试应用程序提升到不同的命名空间

为了完成这个演示,您将通过将示例 RSVP 应用程序提升到您的 jx-production 命名空间来完成 CI/CD 过程。

首先,在以下命令中使用 jx promote

jx promote rsvpapp --version=0.0.2 --env=production

这会将与 version=0.0.2 一起运行的 rsvpapp 应用程序提升到生产环境。 在整个构建过程中,Jenkins X 会提示你输入你的 GitHub 账户信息。 用您个人的回答来回答这些提示。

推广成功后,查看应用列表:

jx get app

您将收到类似于以下内容的输出:

OutputAPPLICATION STAGING PODS URL                                             PRODUCTION PODS URL
rsvpapp     0.0.2   1/1  http://rsvpapp.jx-staging.your_IP_address.nip.io 0.0.2      1/1  http://rsvpapp.jx-production.your_IP_address.nip.io

有了这个PRODUCTION信息,就可以确认Jenkins X已经将rsvpapp提升到生产环境了。 如需进一步验证,请在浏览器中访问生产 URL http://rsvpapp.jx-production.your_IP_address.nip.io。 您应该看到正在运行的应用程序,现在从“生产”运行:

最后,在 jx-production 命名空间中列出您的 pod。

kubectl get pod -n jx-production

您会发现 rsvpapp 和 MongoDB 后端 pod 正在此命名空间中运行:

NAME                                     READY     STATUS    RESTARTS   AGE
jx-production-mongodb-replicaset-0       1/1       Running   0          1m
jx-production-mongodb-replicaset-1       1/1       Running   0          1m
jx-production-mongodb-replicaset-2       1/1       Running   0          55s
jx-production-rsvpapp-54748d68bd-zjgv7   1/1       Running   0          1m 

这表明您已成功将 RSVP 示例应用程序提升到生产环境,在 CI/CD 管道末端模拟应用程序的生产就绪部署。

结论

在本教程中,您使用 Helm 管理模拟 Kubernetes 集群上的包,并自定义了 Helm 图表来打包和部署您自己的应用程序。 您还可以在 Kubernetes 集群上设置 Jenkins X 环境,并通过 CI/CD 管道从头到尾运行示例应用程序。

您现在已经拥有了在自己的 Kubernetes 集群上构建 CI/CD 系统时可以使用的这些工具的经验。 如果您想了解有关 Helm 的更多信息,请查看我们的 Helm 简介、Kubernetes 包管理器如何使用 Helm 包管理器在 Kubernetes 集群上安装软件 文章. 要进一步探索 Kubernetes 上的 CI/CD 工具,您可以在本网络研讨会系列的下一个教程中了解 Istio 服务网格。