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

如果您开始使用容器,您可能想知道如何自动化构建,测试和部署过程。 在带有Kubernetes **系列的** CI / CD的第一篇文章中,我们将介绍与Kubernetes合作的主要主题。在本教程结束时,您将使用Docker,Buildah和Kaniko创建容器图像。您还将具有使用部署,服务和自定义资源设置Kubernetes集群的经验。

网络研讨会系列

本文补充了与Kubernetes一起进行CI / CD网络研讨会系列 本系列讨论如何采用Cloud Native方法构建,测试和部署应用程序,包括可与Kubernetes一起使用的发布管理,Cloud Native工具,Service Meshes和CI / CD工具。 它旨在帮助有兴趣将CI / CD最佳实践与Kubernetes集成到其工作流程中的开发人员和企业。

本教程包括本系列第一部分的概念和命令,即使用Kubernetes构建CI / CD的构建块。

介绍

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

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

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

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

本系列的后续文章将介绍相关主题:Kubernetes的包管理, Jenkins XSpinnaker等CI / CD工具,Services Meshes和GitOps。

先决条件

第1步 - 使用Docker和Buildah构建容器映像

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

使用Dockerfiles构建容器映像

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

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

mkdir demo
cd demo

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

nano Dockerfile

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

〜/演示/ 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 .

您将看到以下输出:

Sending 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
REPOSITORY          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是一个由Project Atomic开发的CLI工具,用于快速构建符合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 

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

go version go1.8 linux/amd64

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

运行以下命令以安装runcbuildah

mkdir ~/buildah
cd ~/buildah
export GOPATH=`pwd`
git clone https://github.com/projectatomic/buildah ./src/github.com/projectatomic/buildah
cd ./src/github.com/projectatomic/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存储库作为构建上下文。 该存储库还包含相关的Dockerfile:

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

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

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

sudo buildah images

您将看到以下输出:

IMAGE 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 ,是docker.io/teamcloudyuga/python:alpine的基本映像。

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

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

登录成功后,您将获得一个包含Docker Hub凭据的文件~/.docker/config.json 然后,您可以将该文件与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
REPOSITORY          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

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

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

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

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

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

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

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

ssh-keygen -t rsa

您将看到以下输出:

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

ENTER将密钥对保存在主目录的~/.ssh目录中,或输入另一个目标。

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

Enter passphrase (empty for no passphrase): 

在这种情况下,请在没有密码的情况下按ENTER以启用无密码登录节点。

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

Your 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安装的输出:

Terraform 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}'

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

MD5: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/ project目录:

ls
cluster.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

kubectl get nodes
NAME                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 docker image build命令,但这不是本机Kubernetes工具。 您必须依赖Docker守护程序来构建映像,并且需要在集群中的某个Pod上运行。

一个名为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.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时将发生的情况。 请务必使用您自己的Docker Hub用户名替换Pod的args字段中的your-dockerhub-username username:

〜/ K8S-CICD-网络研讨会/ webinar1 / 2-kubernetes / 1- Terraform /荚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.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.git将Git存储库克隆到名为demo的共享卷中。 Init容器在应用程序容器之前运行,可用于运行实用程序或其他不希望从应用程序容器运行的任务。 然后,您的应用程序容器kaniko将使用Dockerfile构建映像,并使用您传递给ConfigMap卷docker-config的凭据将生成的映像推送到Docker Hub。

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

kubectl apply -f pod-kaniko.yml 

您将看到以下确认:

pod/kaniko created

获取pod的列表:

kubectl get pods

您将看到以下列表:

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

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

kubectl get pods

您将看到以下内容:

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

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

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

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

检查pod的日志:

kubectl logs kaniko

您将看到以下输出:

time="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镜像。 请务必再次使用Docker Hub用户名替换your-dockerhub-username username:

docker pull your-dockerhub-username/rsvpapp:kaniko

您将看到拉动的确认:

kaniko: 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集群,并在集群中创建了新映像。 让我们继续讨论部署服务

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

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

首先,打开文件:

nano deployment.yml

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

〜/ K8S-CICD-网络研讨会/ 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容器。

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

kubectl apply -f deployment.yml

您将看到已创建部署的确认:

deployment.apps/nginx-deployment created

列出您的部署:

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

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

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

kubectl get pods
NAME                                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-网络研讨会/ 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

你会看到一个确认:

service/nginx-service created

列出服务:

kubectl get service

您将看到以下列表:

NAME            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在端口3011130111 ,您现在可以在任何节点的公共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中, 资源是Kubernetes API中的端点,用于存储API 对象的集合。 例如,Pod资源包含Pod对象的集合。 使用自定义资源,您可以为网络,存储等添加自定义产品。 可以随时创建或删除这些添加项。

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

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

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

nano crd.yml

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

〜/ K8S-CICD-网络研讨会/ 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 

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

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

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

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

注意:如果您遵循先决条件中的初始服务器设置指南,则需要允许流量到端口8001以使此测试起作用。 使用以下命令启用此端口的流量:

sudo ufw allow 8001

您将看到以下输出:

HTTP/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-网络研讨会/ 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 

您将看到以下输出:

webinar.digitalocean.com/webinar1 created

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

kubectl get webinar
NAME       CREATED AT
webinar1   21s

您现在有一个名为webinar1的对象。 如果存在Controller,它将截获对象创建并执行任何已定义的操作。

删除自定义资源定义

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

kubectl delete webinar --all

你会看见:

webinar.digitalocean.com "webinar1" deleted

删除自定义资源本身:

kubectl delete crd webinars.digitalocean.com

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

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

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

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

第6步 - 删除Kubernetes群集

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

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

运行脚本:

./destroy.sh

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

结论

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

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