网络研讨会系列:使用Kubernetes进行CI/CD的构建块

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

网络研讨会系列

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

本教程包含本系列第一节“使用 Kubernetes 进行 CI/CD 的构建块”中的概念和命令。


观看 YouTube 视频

介绍

如果您开始使用 containers,您可能想知道如何自动化构建、测试和部署。 通过对这些流程采用 Cloud Native 方法,您可以利用正确的基础架构 API 以自动化方式打包和部署应用程序。

实现自动化的两个构建块包括 容器映像容器编排器 。 在过去一年左右的时间里,Kubernetes 已经成为容器编排的默认选择。 在 CI/CD with Kubernetes 系列的第一篇文章中,您将:

  • 使用 DockerBuildahKaniko 构建容器镜像。
  • 使用 Terraform 设置 Kubernetes 集群,并创建 DeploymentsServices
  • 使用 自定义资源 扩展 Kubernetes 集群的功能。

在本教程结束时,您将拥有使用 Docker、Buildah 和 Kaniko 构建的容器镜像,以及一个包含部署、服务和自定义资源的 Kubernetes 集群。

该系列的后续文章将涵盖相关主题:Kubernetes 的包管理、CI/CD 工具(如 Jenkins XSpinnaker)、服务网格和 GitOps。

先决条件

第 1 步 — 使用 Docker 和 Buildah 构建容器镜像

容器映像是一个自包含的实体,具有自己的应用程序代码、运行时和可用于创建和运行容器的依赖项。 您可以使用不同的工具来创建容器镜像,在此步骤中,您将使用其中两个工具构建容器:Docker 和 Buildah。

使用 Dockerfile 构建容器镜像

Docker 通过读取 Dockerfile 中的指令自动构建您的容器镜像,Dockerfile 是一个文本文件,其中包含组装容器镜像所需的命令。 使用 docker image build 命令,您可以创建一个自动构建,该构建将执行 Dockerfile 中提供的命令行指令。 构建镜像时,您还将通过 Dockerfile 传递 构建上下文 ,其中包含在容器镜像中创建环境和运行应用程序所需的文件集。

通常,您将为 Dockerfile 和构建上下文创建一个项目文件夹。 创建一个名为 demo 的文件夹开始:

mkdir demo
cd demo

接下来,在 demo 文件夹中创建一个 Dockerfile:

nano Dockerfile

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

~/demo/Dockerfile

FROM ubuntu:16.04

LABEL MAINTAINER neependra@cloudyuga.guru

RUN apt-get update \
    && apt-get install -y nginx \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
    && echo "daemon off;" >> /etc/nginx/nginx.conf

EXPOSE 80
CMD ["nginx"]

这个 Dockerfile 由一组指令组成,这些指令将构建一个运行 Nginx 的镜像。 在构建过程中,ubuntu:16.04 将作为基础镜像,并且将安装 nginx 包。 使用 CMD 指令,您还将 nginx 配置为容器启动时的默认命令。

接下来,您将使用 docker image build 命令构建容器映像,使用当前目录 (.) 作为构建上下文。 将 -t 选项传递给此命令,将图像命名为 nkhare/nginx:latest

sudo docker image build -t nkhare/nginx:latest .

您将看到以下输出:

OutputSending build context to Docker daemon  49.25MB
Step 1/5 : FROM ubuntu:16.04
 ---> 7aa3602ab41e
Step 2/5 : MAINTAINER neependra@cloudyuga.guru
 ---> Using cache
 ---> 552b90c2ff8d
Step 3/5 : RUN apt-get update     && apt-get install -y nginx     && apt-get clean     && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*     && echo "daemon off;" >> /etc/nginx/nginx.conf
 ---> Using cache
 ---> 6bea966278d8
Step 4/5 : EXPOSE 80
 ---> Using cache
 ---> 8f1c4281309e
Step 5/5 : CMD ["nginx"]
 ---> Using cache
 ---> f545da818f47
Successfully built f545da818f47
Successfully tagged nginx:latest

您的图像现在已构建。 您可以使用以下命令列出您的 Docker 映像:

docker image ls
OutputREPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nkhare/nginx        latest              4073540cbcec        3 seconds ago       171MB
ubuntu              16.04               7aa3602ab41e        11 days ago     

您现在可以使用 nkhare/nginx:latest 图像来创建容器。

使用 Project Atomic-Buildah 构建容器镜像

Buildah 是一个 CLI 工具,由 Project Atomic 开发,用于快速构建符合 Open Container Initiative (OCI) 标准的镜像。 OCI 为容器运行时和图像提供规范,以标准化行业最佳实践。

Buildah 可以从工作容器或 Dockerfile 创建映像。 它可以在没有 Docker 守护进程的情况下完全在用户空间构建镜像,并且可以执行 buildlistpushtag 等镜像操作。 在此步骤中,您将从源代码编译 Buildah,然后使用它来创建容器映像。

要安装 Buildah,您将需要所需的依赖项,包括使您能够管理包和包安全性的工具等。 运行以下命令来安装这些软件包:

 cd
 sudo apt-get install software-properties-common
 sudo add-apt-repository ppa:alexlarsson/flatpak
 sudo add-apt-repository ppa:gophers/archive
 sudo apt-add-repository ppa:projectatomic/ppa
 sudo apt-get update
 sudo apt-get install bats btrfs-tools git libapparmor-dev libdevmapper-dev libglib2.0-dev libgpgme11-dev libostree-dev libseccomp-dev libselinux1-dev skopeo-containers go-md2man

因为你将编译 buildah 源代码来创建它的包,你还需要安装 Go

sudo apt-get update
sudo curl -O https://storage.googleapis.com/golang/go1.8.linux-amd64.tar.gz
sudo tar -xvf go1.8.linux-amd64.tar.gz
sudo mv go /usr/local
sudo echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile
source ~/.profile
go version 

您将看到以下输出,表明安装成功:

Outputgo version go1.8 linux/amd64

您现在可以获得 buildah 源代码来创建它的包,以及 runc 二进制文件。 runcOCI 容器运行时的实现,您将使用它来运行 Buildah 容器。

运行以下命令安装 runcbuildah

mkdir ~/buildah
cd ~/buildah
export GOPATH=`pwd`
git clone https://github.com/containers/buildah ./src/github.com/containers/buildah
cd ./src/github.com/containers/buildah
make runc all TAGS="apparmor seccomp"
sudo cp ~/buildah/src/github.com/opencontainers/runc/runc /usr/bin/.
sudo apt install buildah 

接下来,创建 /etc/containers/registries.conf 文件来配置您的容器注册表:

sudo nano /etc/containers/registries.conf

将以下内容添加到文件中以指定您的注册表:

/etc/containers/registries.conf

# This is a system-wide configuration file used to
# keep track of registries for various container backends.
# It adheres to TOML format and does not support recursive
# lists of registries.

# The default location for this configuration file is /etc/containers/registries.conf.

# The only valid categories are: 'registries.search', 'registries.insecure',
# and 'registries.block'.

[registries.search]
registries = ['docker.io', 'registry.fedoraproject.org', 'quay.io', 'registry.access.redhat.com', 'registry.centos.org']

# If you need to access insecure registries, add the registry's fully-qualified name.
# An insecure registry is one that does not have a valid SSL certificate or only does HTTP.
[registries.insecure]
registries = []

# If you need to block pull access from a registry, uncomment the section below
# and add the registries fully-qualified name.
#
# Docker only
[registries.block]
registries = []

registries.conf 配置文件指定在完成不包含注册表或域部分的映像名称时应咨询哪些注册表。

现在运行以下命令来构建映像,使用 https://github.com/do-community/rsvpapp-webinar1 存储库作为构建上下文。 此存储库还包含相关的 Dockerfile:

sudo buildah build-using-dockerfile -t rsvpapp:buildah github.com/do-community/rsvpapp-webinar1 

此命令从 https://github.com/do-community/rsvpapp-webinar1 存储库中可用的 Dockerfille 创建一个名为 rsvpapp:buildah 的映像。

要列出图像,请使用以下命令:

sudo buildah images

您将看到以下输出:

OutputIMAGE ID             IMAGE NAME                                               CREATED AT             SIZE
b0c552b8cf64         docker.io/teamcloudyuga/python:alpine                    Sep 30, 2016 04:39     95.3 MB
22121fd251df         localhost/rsvpapp:buildah                                Sep 11, 2018 14:34     114 MB

这些图像之一是您刚刚创建的 localhost/rsvpapp:buildah。 另一个,docker.io/teamcloudyuga/python:alpine,是来自 Dockerfile 的基础镜像。

构建映像后,您可以将其推送到 Docker Hub。 这将允许您存储它以备将来使用。 您首先需要从命令行登录到您的 Docker Hub 帐户:

docker login -u your-dockerhub-username -p your-dockerhub-password

登录成功后,您将获得一个文件 ~/.docker/config.json,其中包含您的 Docker Hub 凭据。 然后,您可以使用该文件和 buildah 将图像推送到 Docker Hub。

例如,如果要推送刚刚创建的镜像,可以运行以下命令,引用 authfile 和要推送的镜像:

sudo buildah push --authfile ~/.docker/config.json rsvpapp:buildah docker://your-dockerhub-username/rsvpapp:buildah

您还可以使用以下命令将生成的图像推送到本地 Docker 守护程序:

sudo buildah push rsvpapp:buildah docker-daemon:rsvpapp:buildah

最后,看看你创建的 Docker 镜像:

sudo docker image ls
OutputREPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
rsvpapp             buildah             22121fd251df        4 minutes ago       108MB
nkhare/nginx        latest              01f0982d91b8        17 minutes ago      172MB
ubuntu              16.04               b9e15a5d1e1a        5 days ago          115MB

正如预期的那样,您现在应该看到一个新图像 rsvpapp:buildah,它是使用 buildah 导出的。

您现在拥有使用 Docker 和 Buildah 这两种不同工具构建容器映像的经验。 让我们继续讨论如何使用 Kubernetes 设置容器集群。

第 2 步 — 使用 kubeadm 和 Terraform 在 DigitalOcean 上设置 Kubernetes 集群

在 DigitalOcean 上设置 Kubernetes 有多种方法。 要了解有关如何使用 kubeadm 设置 Kubernetes 的更多信息,例如,您可以查看 如何在 Ubuntu 18.04 上使用 Kubeadm 创建 Kubernetes 集群。

由于本教程系列讨论了采用云原生方法进行应用程序开发,因此我们将在设置集群时应用此方法。 具体来说,我们将使用 kubeadm 和 Terraform 自动化我们的集群创建,这是一种简化创建和更改基础设施的工具。

使用您的个人访问令牌,您将使用 Terraform 连接到 DigitalOcean 以配置 3 个服务器。 您将在这些 VM 中运行 kubeadm 命令来创建一个包含一个主节点和两个工作节点的 3 节点 Kubernetes 集群。

在您的 Ubuntu 服务器上,创建一对 SSH 密钥 ,这将允许无密码登录到您的虚拟机:

ssh-keygen -t rsa

您将看到以下输出:

OutputGenerating public/private rsa key pair.
Enter file in which to save the key (~/.ssh/id_rsa): 

ENTER 将密钥对保存在您的主目录下的 ~/.ssh 目录中,或输入其他目的地。

接下来,您将看到以下提示:

OutputEnter passphrase (empty for no passphrase): 

在这种情况下,无需密码按 ENTER 即可启用无密码登录到您的节点。

您将看到确认您的密钥对已创建:

OutputYour identification has been saved in ~/.ssh/id_rsa.
Your public key has been saved in ~/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:lCVaexVBIwHo++NlIxccMW5b6QAJa+ZEr9ogAElUFyY root@3b9a273f18b5
The key's randomart image is:
+---[RSA 2048]----+
|++.E ++o=o*o*o   |
|o   +..=.B = o   |
|.    .* = * o    |
| .   =.o + *     |
|  . . o.S + .    |
|   . +.    .     |
|    . ... =      |
|        o= .     |
|       ...       |
+----[SHA256]-----+

通过运行以下命令获取您的公钥,该命令将在您的终端中显示它:

cat ~/.ssh/id_rsa.pub

按照 这些说明 将此密钥添加到您的 DigitalOcean 帐户。

接下来,安装 Terraform:

sudo apt-get update
sudo apt-get install unzip
wget https://releases.hashicorp.com/terraform/0.11.7/terraform_0.11.7_linux_amd64.zip
unzip terraform_0.11.7_linux_amd64.zip
sudo mv terraform /usr/bin/.
terraform version

您将看到确认您的 Terraform 安装的输出:

OutputTerraform v0.11.7

接下来,运行以下命令来安装 kubectl,一个将与您的 Kubernetes 集群通信的 CLI 工具,并在您的用户的主目录中创建一个 ~/.kube 目录:

sudo apt-get install apt-transport-https
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo touch /etc/apt/sources.list.d/kubernetes.list 
echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install kubectl
mkdir -p ~/.kube

创建 ~/.kube 目录将使您能够将配置文件复制到此位置。 在本节后面运行 Kubernetes 设置脚本后,您将执行此操作。 默认情况下,kubectl CLI 会在 ~/.kube 目录中查找配置文件以访问集群。

接下来,克隆本教程的示例项目存储库,其中包含用于设置基础架构的 Terraform 脚本:

git clone https://github.com/do-community/k8s-cicd-webinars.git

进入 Terrafrom 脚本目录:

cd k8s-cicd-webinars/webinar1/2-kubernetes/1-Terraform/

获取 SSH 公钥的指纹:

ssh-keygen -E md5 -lf ~/.ssh/id_rsa.pub | awk '{print $2}'

您将看到如下输出,突出显示的部分代表您的密钥:

OutputMD5:dd:d1:b7:0f:6d:30:c0:be:ed:ae:c7:b9:b8:4a:df:5e

请记住,您的密钥将与此处显示的不同。

将指纹保存到环境变量中,以便 Terraform 可以使用它:

export FINGERPRINT=dd:d1:b7:0f:6d:30:c0:be:ed:ae:c7:b9:b8:4a:df:5e

接下来,导出您的 DO 个人访问令牌:

export TOKEN=your-do-access-token

现在看一下~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terraform/项目目录:

ls
Outputcluster.tf  destroy.sh  files outputs.tf  provider.tf  script.sh

此文件夹包含使用 Terraform 部署 Kubernetes 集群所需的脚本和配置文件。

执行 script.sh 脚本触发 Kubernetes 集群设置:

./script.sh

脚本执行完成后,kubectl 将被配置为使用您创建的 Kubernetes 集群。

使用 kubectl get nodes 列出集群节点:

kubectl get nodes
OutputNAME                STATUS    ROLES     AGE       VERSION
k8s-master-node     Ready     master    2m        v1.10.0
k8s-worker-node-1   Ready     <none>    1m        v1.10.0
k8s-worker-node-2   Ready     <none>    57s       v1.10.0

您现在有一个主节点和两个工作节点处于 Ready 状态。

设置 Kubernetes 集群后,您现在可以探索构建容器映像的另一个选项:来自 Google Kaniko。

第 3 步 — 使用 Kaniko 构建容器镜像

在本教程的前面部分,您使用 Dockerfiles 和 Buildah 构建了容器映像。 但是如果你可以直接在 Kubernetes 上构建容器镜像呢? 有多种方法可以在 Kubernetes 内部运行 docker image build 命令,但这不是原生 Kubernetes 工具。 您必须依赖 Docker 守护程序来构建映像,并且它需要在集群中的 Pods 之一上运行。

一个名为 Kaniko 的工具允许您在现有 Kubernetes 集群上使用 Dockerfile 构建容器镜像。 在此步骤中,您将使用 Kaniko 使用 Dockerfile 构建容器映像。 然后,您将把这个镜像推送到 Docker Hub。

为了将您的图像推送到 Docker Hub,您需要将 Docker Hub 凭据传递给 Kaniko。 在上一步中,您登录到 Docker Hub 并使用您的登录凭据创建了一个 ~/.docker/config.json 文件。 让我们使用这个配置文件来创建一个 Kubernetes ConfigMap 对象来将凭证存储在 Kubernetes 集群中。 ConfigMap 对象用于存储配置参数,将它们与您的应用程序分离。

要使用 ~/.docker/config.json 文件创建名为 docker-config 的 ConfigMap,请运行以下命令:

sudo kubectl create configmap docker-config --from-file=$HOME/.docker/config.json

接下来,您可以在 ~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terraform/ 目录中创建一个名为 pod-kaniko.yml 的 Pod 定义文件(尽管它可以放在任何地方)。

首先,确保您在 ~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terraform/ 目录中:

cd ~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terraform/

创建 pod-kaniko.yml 文件:

nano pod-kaniko.yml

将以下内容添加到文件中,以指定部署 Pod 时会发生什么。 请务必将 Pod 的 args 字段中的 your-dockerhub-username 替换为您自己的 Docker Hub 用户名:

~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terraform/pod-kaniko.yaml

apiVersion: v1
kind: Pod
metadata:
  name: kaniko
spec:
  containers:
  - name: kaniko
    image: gcr.io/kaniko-project/executor:latest
    args: ["--dockerfile=./Dockerfile",
            "--context=/tmp/rsvpapp/",
            "--destination=docker.io/your-dockerhub-username/rsvpapp:kaniko",
            "--force" ]
    volumeMounts:
      - name: docker-config
        mountPath: /root/.docker/
      - name: demo
        mountPath: /tmp/rsvpapp
  restartPolicy: Never
  initContainers:
    - image: python
      name: demo
      command: ["/bin/sh"]
      args: ["-c", "git clone https://github.com/do-community/rsvpapp-webinar1.git /tmp/rsvpapp"] 
      volumeMounts:
      - name: demo
        mountPath: /tmp/rsvpapp
  restartPolicy: Never
  volumes:
    - name: docker-config
      configMap:
        name: docker-config
    - name: demo
      emptyDir: {}

此配置文件描述了部署 Pod 时会发生什么。 首先,Init 容器 将使用 Dockerfile https://github.com/do-community/rsvpapp-webinar1.git 将 Git 存储库克隆到名为 demo 的共享卷中。 Init 容器在应用程序容器之前运行,可用于运行不希望从应用程序容器运行的实用程序或其他任务。 然后,您的应用程序容器 kaniko 将使用 Dockerfile 构建映像,并使用您传递给 ConfigMap 卷 docker-config 的凭据将生成的映像推送到 Docker Hub。

要部署 kaniko pod,请运行以下命令:

kubectl apply -f pod-kaniko.yml 

您将看到以下确认信息:

Outputpod/kaniko created

获取 pod 列表:

kubectl get pods

您将看到以下列表:

OutputNAME      READY     STATUS     RESTARTS   AGE
kaniko    0/1       Init:0/1   0          47s

等待几秒钟,然后再次运行 kubectl get pods 以更新状态:

kubectl get pods

您将看到以下内容:

OutputNAME      READY     STATUS    RESTARTS   AGE
kaniko    1/1       Running   0          1m

最后,再次运行 kubectl get pods 以进行最终状态更新:

kubectl get pods
OutputNAME      READY     STATUS      RESTARTS   AGE
kaniko    0/1       Completed   0          2m

此输出序列告诉您 Init 容器已运行,克隆了 demo 卷内的 GitHub 存储库。 之后,Kaniko 构建过程运行并最终完成。

查看 pod 的日志:

kubectl logs kaniko

您将看到以下输出:

Outputtime="2018-08-02T05:01:24Z" level=info msg="appending to multi args docker.io/your-dockerhub-username/rsvpapp:kaniko"
time="2018-08-02T05:01:24Z" level=info msg="Downloading base image nkhare/python:alpine"
.
.
.
ime="2018-08-02T05:01:46Z" level=info msg="Taking snapshot of full filesystem..."
time="2018-08-02T05:01:48Z" level=info msg="cmd: CMD"
time="2018-08-02T05:01:48Z" level=info msg="Replacing CMD in config with [/bin/sh -c python rsvp.py]"
time="2018-08-02T05:01:48Z" level=info msg="Taking snapshot of full filesystem..."
time="2018-08-02T05:01:49Z" level=info msg="No files were changed, appending empty layer to config."
2018/08/02 05:01:51 mounted blob: sha256:bc4d09b6c77b25d6d3891095ef3b0f87fbe90621bff2a333f9b7f242299e0cfd
2018/08/02 05:01:51 mounted blob: sha256:809f49334738c14d17682456fd3629207124c4fad3c28f04618cc154d22e845b
2018/08/02 05:01:51 mounted blob: sha256:c0cb142e43453ebb1f82b905aa472e6e66017efd43872135bc5372e4fac04031
2018/08/02 05:01:51 mounted blob: sha256:606abda6711f8f4b91bbb139f8f0da67866c33378a6dcac958b2ddc54f0befd2
2018/08/02 05:01:52 pushed blob sha256:16d1686835faa5f81d67c0e87eb76eab316e1e9cd85167b292b9fa9434ad56bf
2018/08/02 05:01:53 pushed blob sha256:358d117a9400cee075514a286575d7d6ed86d118621e8b446cbb39cc5a07303b
2018/08/02 05:01:55 pushed blob sha256:5d171e492a9b691a49820bebfc25b29e53f5972ff7f14637975de9b385145e04
2018/08/02 05:01:56 index.docker.io/your-dockerhub-username/rsvpapp:kaniko: digest: sha256:831b214cdb7f8231e55afbba40914402b6c915ef4a0a2b6cbfe9efb223522988 size: 1243

从日志中,您可以看到 kaniko 容器从 Dockerfile 构建了映像并将其推送到您的 Docker Hub 帐户。

您现在可以拉取 Docker 映像。 请务必再次将 your-dockerhub-username 替换为您的 Docker Hub 用户名:

docker pull your-dockerhub-username/rsvpapp:kaniko

您将看到拉动的确认:

Outputkaniko: Pulling from your-dockerhub-username/rsvpapp
c0cb142e4345: Pull complete 
bc4d09b6c77b: Pull complete 
606abda6711f: Pull complete 
809f49334738: Pull complete 
358d117a9400: Pull complete 
5d171e492a9b: Pull complete 
Digest: sha256:831b214cdb7f8231e55afbba40914402b6c915ef4a0a2b6cbfe9efb223522988
Status: Downloaded newer image for your-dockerhub-username/rsvpapp:kaniko

您现在已经成功地构建了一个 Kubernetes 集群并在集群中创建了新的镜像。 让我们继续讨论 DeploymentsServices

第 4 步 — 创建 Kubernetes 部署和服务

Kubernetes Deployments 允许你运行你的应用程序。 部署为您的 Pod 指定所需的状态,确保您的部署过程中的一致性。 在此步骤中,您将在 ~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terraform/ 目录中创建一个名为 deployment.ymlNginx 部署文件,以创建 Nginx 部署。

首先,打开文件:

nano deployment.yml

将以下配置添加到文件中以定义您的 Nginx 部署:

~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terraform/deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

该文件定义了一个名为 nginx-deployment 的部署,它创建了三个 Pod,每个 Pod 在端口 80 上运行一个 nginx 容器。

要部署部署,请运行以下命令:

kubectl apply -f deployment.yml

您将看到 Deployment 已创建的确认信息:

Outputdeployment.apps/nginx-deployment created

列出您的部署:

kubectl get deployments
OutputNAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            3           29s

您可以看到 nginx-deployment 部署已创建,并且所需的 Pod 数量和当前数量相同:3

要列出 Deployment 创建的 Pod,请运行以下命令:

kubectl get pods
OutputNAME                                READY     STATUS      RESTARTS   AGE
kaniko                              0/1       Completed   0          9m
nginx-deployment-75675f5897-nhwsp   1/1       Running     0          1m
nginx-deployment-75675f5897-pxpl9   1/1       Running     0          1m
nginx-deployment-75675f5897-xvf4f   1/1       Running     0          1m

您可以从此输出中看到所需数量的 Pod 正在运行。

要在内部和外部公开应用程序部署,您需要创建一个名为 Service 的 Kubernetes 对象。 每个服务指定一个 ServiceType,它定义了服务的公开方式。 在此示例中,我们将使用 NodePort ServiceType,它将服务暴露在每个节点上的静态端口上。

为此,在 ~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terrafrom/ 目录中创建一个文件 service.yml

nano service.yml

添加以下内容以定义您的服务:

~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terrafrom/service.yml

kind: Service
apiVersion: v1
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30111

这些设置定义了服务 nginx-service,并指定它将以 Pod 上的端口 80 为目标。 nodePort 定义应用程序将接受外部流量的端口。

要部署服务,请运行以下命令:

kubectl apply -f service.yml

您将看到一个确认:

Outputservice/nginx-service created

列出服务:

kubectl get service

您将看到以下列表:

OutputNAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP        5h
nginx-service   NodePort    10.100.98.213   <none>        80:30111/TCP   7s

您的服务 nginx-service 暴露在端口 30111 上,您现在可以在任何节点的公共 IP 上访问它。 例如,导航到 http://node_1_ip:30111http://node_2_ip:30111 应该会将您带到 Nginx 的标准欢迎页面。

一旦你测试了部署,你可以清理部署和服务:

kubectl delete deployment nginx-deployment
kubectl delete service nginx-service

这些命令将删除您创建的部署和服务。

现在您已经使用了部署和服务,让我们继续创建自定义资源。

第 5 步 — 在 Kubernetes 中创建自定义资源

Kubernetes 提供有限但可用于生产的功能和特性。 但是,可以使用其 自定义资源 功能扩展 Kubernetes 的产品。 在 Kubernetes 中,resource 是 Kubernetes API 中的一个端点,用于存储 API objects 的集合。 例如,一个 Pod 资源包含一组 Pod 对象。 使用自定义资源,您可以为网络、存储等添加自定义产品。 这些添加可以在任何时候创建或删除。

除了创建自定义对象外,您还可以在控制平面中使用 Kubernetes Controller 组件的子控制器来确保对象的当前状态等于所需状态。 Kubernetes 控制器具有用于指定对象的子控制器。 例如,ReplicaSet 是一个子控制器,可确保所需的 Pod 数量保持一致。 当您将自定义资源与控制器结合使用时,您将获得一个真正的 声明性 API,它允许您指定所需的资源状态。

在此步骤中,您将创建自定义资源和相关对象。

要创建自定义资源,首先在 ~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terrafrom/ 目录中创建一个名为 crd.yml 的文件:

nano crd.yml

添加以下自定义资源定义 (CRD):

~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terrafrom/crd.yml

apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: webinars.digitalocean.com
spec:
  group: digitalocean.com
  version: v1
  scope: Namespaced
  names:
    plural: webinars
    singular: webinar
    kind: Webinar
    shortNames:
    - wb

要部署 crd.yml 中定义的 CRD,请运行以下命令:

kubectl create -f crd.yml 

您将看到资源已创建的确认信息:

Outputcustomresourcedefinition.apiextensions.k8s.io/webinars.digitalocean.com created

crd.yml 文件创建了一个新的 RESTful 资源路径:/apis/digtialocean.com/v1/namespaces/*/webinars。 您现在可以使用 webinarswebinarWebinarwb 来引用您的对象,正如您在 names 部分中列出的那样CustomResourceDefinition。 您可以使用以下命令检查 RESTful 资源:

kubectl proxy & curl 127.0.0.1:8001/apis/digitalocean.com

注意: 如果您按照先决条件中的初始服务器设置指南进行操作,那么您需要允许端口 8001 的流量才能进行此测试。 使用以下命令启用到此端口的流量:

sudo ufw allow 8001

您将看到以下输出:

OutputHTTP/1.1 200 OK
Content-Length: 238
Content-Type: application/json
Date: Fri, 03 Aug 2018 06:10:12 GMT

{
    "apiVersion": "v1", 
    "kind": "APIGroup", 
    "name": "digitalocean.com", 
    "preferredVersion": {
        "groupVersion": "digitalocean.com/v1", 
        "version": "v1"
    }, 
    "serverAddressByClientCIDRs": null, 
    "versions": [
        {
            "groupVersion": "digitalocean.com/v1", 
            "version": "v1"
        }
    ]
}

接下来,通过打开一个名为 webinar.yml 的文件来创建使用新自定义资源的对象:

nano webinar.yml

添加以下内容以创建对象:

~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terrafrom/webinar.yml

apiVersion: "digitalocean.com/v1"
kind: Webinar
metadata:
  name: webinar1
spec:
  name: webinar
  image: nginx

运行以下命令将这些更改推送到集群:

kubectl apply -f webinar.yml 

您将看到以下输出:

Outputwebinar.digitalocean.com/webinar1 created

您现在可以使用 kubectl 管理您的 webinar 对象。 例如:

kubectl get webinar
OutputNAME       CREATED AT
webinar1   21s

您现在有一个名为 webinar1 的对象。 如果有一个控制器,它就会拦截对象的创建并执行任何定义的操作。

删除自定义资源定义

要删除自定义资源的所有对象,请使用以下命令:

kubectl delete webinar --all

你会看见:

Outputwebinar.digitalocean.com "webinar1" deleted

删除自定义资源本身:

kubectl delete crd webinars.digitalocean.com

您将看到已删除的确认信息:

Outputcustomresourcedefinition.apiextensions.k8s.io "webinars.digitalocean.com" deleted

删除后,您将无法访问您之前使用 curl 命令测试的 API 端点。

本序列介绍了如何在不修改 Kubernetes 代码的情况下扩展 Kubernetes 功能。

第 6 步 — 删除 Kubernetes 集群

要销毁 Kubernetes 集群本身,您可以使用 ~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terrafrom 文件夹中的 destroy.sh 脚本。 确保您在此目录中:

cd ~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terrafrom

运行脚本:

./destroy.sh

通过运行此脚本,您将允许 Terraform 与 DigitalOcean API 通信并删除集群中的服务器。

结论

在本教程中,您使用了不同的工具来创建容器映像。 使用这些图像,您可以在任何环境中创建容器。 您还使用 Terraform 设置了 Kubernetes 集群,并创建了部署和服务对象来部署和公开您的应用程序。 此外,您通过定义自定义资源扩展了 Kubernetes 的功能。

您现在拥有在 Kubernetes 上构建 CI/CD 环境的坚实基础,我们将在以后的文章中对此进行探讨。