本文将描述,在使用带有Core许可的Gitlab中,它是如何将Kubernetes集群集成到Gitlab CI/CD的进程里。在下面的例子中,我们会使用这个方法来集成Kubernetes。先来看看Gitlab的官方支持文档以及我们自己的解决方案。

Gitlab官方的Kubernetes特性

Gitlab为Kubernetes提供三个级别的支持。它们是实例级(instance-level)、组级(group-level)和项目级(project-level)。先看看这些级别的配置细节。

第一个是实例级。实例级的Kubernetes集群允许将Kubernetes集群连接到某个GitLab实例。它使你能够跨多个项目使用相同的集群配置。

另一个配置级别是组级集群。组级的Kubernetes集群允许将Kubernetes集群连接到你的组。它使你能够跨多个项目使用相同的集群配置。

最后一个配置是项目级别。项目级配置允许将几个项目与Kubernetes集群集成。当然你也可以对所有的项目都这样做。

如果只对一个Kubernetes集群使用这些配置是免费,如果对多个Kubernetes集群集成,需要购买premium或silver的 GitLab许可。这些许可同时也隶属于GitLab企业版。因此,建议大家如果打算升级Gitlab,最低也要升级到企业核心版(Enterprise Edition Core)。

我们有多个Kubernetes集群。我们需要为Kubernetes集成付费吗?

答案是否定的。如果你有“.kubeconfig”的文件,你完全不需要为Kubernetes的集成付费。

这是怎么办到的?

我们使用定制的kubectl基础镜像来部署拥有自己kubeconfig的Kubernetes集群。

先从启用CI/CD开始

把kubeconfig放到kubectl的基础镜像里。首先,在GitLab上创建一个空的项目。创建完项目之后,添加一个.gitlab-ci.yml文件到项目的根目录。这个文件就为这个项目启用了CI/CD管道。

如何保存kubeconfig文件

要在CI/CD管道中使用kubeconfig文件,需要先创建一个文件夹比如“kube-configs”,再把kubeconfig文件放在各个环境名的子文件夹里,如dev、stage、prod等。

图1:kube-config文件夹

图2:Environment文件夹里的config文件

Config 文件的例子

apiVersion: v1

kind: Config

current-context: current-context-name

preferences: {}

clusters:

- cluster:

Certificate-authority-data: U0FNUExFVEVYVA==

server: https://10.10.43.1:6443

name: cluster-name

contexts:

- context:

cluster: cluster-name

user: admin-cluster-name

name: admin-cluster-name

users:

- name: admin-cluster-name

user:

client-certificate-data:U0FNUExFVEVYVA==

Client-key-data: U0FNUExFVEVYVA==

项目结构

项目的结构如图3所示

图3:项目结构

通常一个项目里,会有kube-configs文件夹,.gitognore, .gitlab-ci.yml和Dockerfile。

• Kube-configs:用于保存配置文件。

• .gitignore:用于忽略代码库中的一些文件。

• .gitlab-ci.yml:用于创建和管理CI/CD进程。

• Dockerfile:用于构建Docker镜像。

使用Dockerfile进行构建

要创建Docker镜像,必须要使用Dockerfile。我们的Dockerfile是这样的,

FROM alpine:latest

ARG ENVIRONMENT

ENV KUBECTL_VERSION="1.15.2"

ENV KUBE_ENVIRONMENT=$ENVIRONMENT

RUN apk update && apk add git gettext

RUN apk add --no-cache curl

RUN curl -LO https://storage.googleapis.com ... ase/v ${KUBECTL_VERSION}/bin/linux/amd64/kubectl

COPY kube-configs ./kube-configs

RUN chmod +x kubectl

RUN mv kubectl /usr/local/bin/kubectl

RUN mkdir ~/.kube

RUN echo ${KUBE_ENVIRONMENT}

RUN cp /kube-configs/${KUBE_ENVIRONMENT}/config ~/.kube/config

RUN cat ~/.kube/config

RUN kubectl cluster-info

我们的Dockerfile使用的是alpine Linux发行版。

为什么选择Alpine作为Docker的基础镜像?

原因就是,小(Small)、简单(Simple)、安全(Secure)。Alpine Linux是一个基于musl libc和busybox的面向安全的轻量级Linux发行版。Alpine的尺寸真的非常小,只有3.98MB。

Linux OS镜像对比

这个图表告诉我们Alpine Linux真的非常小。

图4: Linux OS镜像对比

选择完基础镜像之后,还有一个Docker参数,用于将环境变量传递到Dockerfile。Dockerfile中有KUBECTL_VERSION和KUBE_ENVIRONMENT这样的环境变量。KUBECTL_VERSION用于在安装时决定kubectl包的版本。KUBE_ENVIRONMENT来设定kubeconfig的环境变量。

基础镜像Alpine非常轻量和简单。也正是基于这个原因,我们还需要为构建过程添加一些被忽略掉的包。这些包一般是git、gettext和curl。

下面继续谈谈kubectl, kubectl是部署Kubernetes最重要的命令。Kubectl是一个命令行界面,用于在Kubernetes集群上运行命令。我们在CI/CD管道上使用这个命令将项目部署到Kubernetes。

现在构建的步骤基本上已经准备好,只剩下一件事:把kubeconfig文件传递给kubectl。完成这些步骤之后,我们就可以构建Docker基础镜像了。下面就是这部分的步骤。

COPY kube-configs ./kube-configs # copy config files to container

RUN chmod +x kubectl # give permission to kubectl

RUN mv kubectl /usr/local/bin/kubectl # move kubectl to bin folder

RUN mkdir ~/.kube # create folder for configs

RUN echo ${KUBE_ENVIRONMENT} # for check environments (dev,stage, etc.)

RUN cp /kube-configs/${KUBE_ENVIRONMENT}/config ~/.kube/config # to copy configs

RUN cat ~/.kube/config # to check config

RUN kubectl cluster-info # to check all configs are true or false

CI/CD步骤

下面是.gitlab-ci.yml文件以及具体描述。当然,你可以根据描述重新编排你自己的步骤。

We select docker latest image as a base image for CI/CD steps. Because of our commands based on docker command.

image: docker:latest

Stages describe the steps of the pipeline. For this project, we need only one step, which is the built step.

stages:

- Build

Before the steps we need to login to our container registry for pull or push docker images. Also, we use GitLabs' docker container registry.

before_script:

- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY

This job is for the Development environment. In this job, we pass the ENVIRONMENT ARGUMENT to our Dockerfile.

In this job, our ENVIRONMENT is dev. For this reason, our Dockerfile read kubeconfigs for a dev environment.

After the build completes, we push that image to the GitLab container registry.

This job works in the build stage and only works for develop branch.

environment and tags are used for gitlab runner management. information link is https://docs.gitlab.com/runner/register/

Build for Dev:

stage: Build

only:

- develop

environment:

name: build

tags:

- build

script:

- docker build --build-arg ENVIRONMENT=dev -t $CI_REGISTRY_IMAGE:dev .

- docker push $CI_REGISTRY_IMAGE:dev

Same as Build for Dev Step

Build for Stage:

stage: Build

only:

- develop

environment:

name: build

tags:

- build

script:

- docker build --build-arg ENVIRONMENT=stage -t $CI_REGISTRY_IMAGE:stage .

- docker push $CI_REGISTRY_IMAGE:stage

配置完Gitlab的CI/CD文件(.gitlab-ci.yml),我们现在已经可以开始部署自定义的kubectl镜像了。

管道

正常来讲一共有7步,但这篇文章我们只提了dev和stage的步骤。其他几步都是一样的没什么区别。

我们的管道如下图5

图5:管道

容器仓库

我们使用Gilab自己的容器仓库,这些构建好的镜像都放在Docker 容器镜像仓库,以备所需。

Gitlab里的容器仓库如图6

图6:Gitlab的容器仓库

应用实例

当以环境名称为基础的kubectl镜像做好后,在你的Gitlab项目里,打开.gitlab-ci-yml文件,添加一个名为Deployment的新的阶段。

stages:

- Build

- Analysis

- Test

- Deployment # Adding a new stage

然后,添加各种新的部署任务到每个环境下

Deploy To Dev:

stage: Deployment

image: registry.example.com:5005/base/docker-kubectl:dev

allow_failure: false

only:

- develop

dependencies:

- SonarQube

tags:

- build

script:

- cd kubernetes/

- /bin/sh deploy.sh dev $CI_PROJECT_NAME $CI_COMMIT_SHORT_SHA

Deploy To Stage:

stage: Deployment

image: registry.example.com:5005/base/docker-kubectl:stage

allow_failure: false

only:

- develop

dependencies:

- SonarQube

tags:

- build

script:

- cd kubernetes/

- /bin/sh deploy.sh stage $CI_PROJECT_NAME $CI_COMMIT_SHORT_SHA

如你所见,我们的部署任务都有自己的基础镜像。镜像的格式都是docker-kubectl:{ENVIRONMENT}。在给出一个基础镜像之后,我们需要执行一些shell脚本,其中包含一些管道值({ENVIRONMENT},$CI_PROJECT_NAME,$CI_COMMIT_SHORT_SHA)。这些值分别是环境名、项目名和commit short SHA。在本例中,这些值传递到shell脚本“deploy.sh”之后,完成整个部署过程。

部署脚本

在我们的项目里,有一个用于存储部署脚本和Kubernetes YAML文件的Kubernetes文件夹。例如部署和服务YAML文件。

我们为这些YAML文件提供以环境名为规则的前缀。随后,sh脚本将使用这些基于环境名前缀的文件。

图7:部署模板和脚本

在deploy.sh中,我们已经将值从管道传递到YAML文件,我们用这些值替换模板的值。之后,再生成最终的部署和服务的YAML文件推送到Kubernetes。

Kubectl apply命令将生成的YAML文件发送到Kubernetes并完成部署过程。在部署完成后再删除刚刚生成的文件并完成清理过程。

deploy.sh文件如下所示,

!/usr/bin/env bash

export ENVIRONMENT=${1}

export APP_NAME=${2}

export SHORT_SHA=${3}

for f in ${ENVIRONMENT}_

.yaml

do

envsubst <$f> "$(basename "gen_"$f)"

done

kubectl apply -f gen_${ENVIRONMENT}_service.yaml

kubectl apply --validate=false -f gen_${ENVIRONMENT}_deployment.yaml

.yaml

结论

在Kubernetes部署过程中我们使用了这样的结构,并且我们发现这种方式在创建完基础 kubectl镜像之后应用起来非常简单方便。

我们都做了什么?

• 基于kubeconfig环境参数,从Alpine Linux创建一个kubectl基础镜像。

• 创建一个CI/CD管道来构建和推送kubectl基础镜像。

• 在现有的项目管道(.gitlab-ci.yml)上添加部署步骤。并将kubectl基础镜像作为一个部署的基础镜像。

• 创建一个部署脚本。

• 使用管道的值生成Kubernetes服务和部署的YAML文件。

• 使用kubectl命令将YAML文件应用到Kubernetes集群。

• 清理生成的文件。

如果你正在使用带有Core许可的GitLab EE版本。你可以用这种方法集成多个Kubernetes集群。

原文连接: https://medium.com/trendyol-te ... 8a5a4

相关文章