多个Kubernetes集群同GitLab Core功能的集成


本文将描述,在使用带有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等。
m1.png

图1:kube-config文件夹

m2.png

图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所示:
m3.png

图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/kubernetes-release/release/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真的非常小。
m4.png

图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。
m5.png

图5:流水线

容器仓库

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

GitLab里的容器仓库如图6。
m6.png

图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脚本将使用这些基于环境名前缀的文件。
m7.png

图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
rm gen_*.yaml

结论

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

我们都做了什么?

  • 基于kubeconfig环境参数,从Alpine Linux创建一个kubectl基础镜像。
  • 创建一个CI/CD流水线道来构建和推送kubectl基础镜像。
  • 在现有的项目流水线(.gitlab-ci.yml)上添加部署步骤。并将kubectl基础镜像作为一个部署的基础镜像。
  • 创建一个部署脚本。
  • 使用流水线的值生成Kubernetes服务和部署的YAML文件。
  • 使用kubectl命令将YAML文件应用到Kubernetes集群。
  • 清理生成的文件。


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

原文连接:Multiple Kubernetes Cluster Integration with Gitlab Core features(翻译:伊海峰)

0 个评论

要回复文章请先登录注册