本文将描述,在使用带有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镜像。要创建 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真的非常小。
图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
下面是.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:流水线
我们使用 GitLab 自己的容器仓库,这些构建好的镜像都放在 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_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
rm gen_*.yaml
在 Kubernetes 部署过程中我们使用了这样的结构,并且我们发现这种方式在创建完基础 kubectl 镜像之后应用起来非常简单方便。
如果你正在使用带有Core许可的GitLab EE版本。你可以用这种方法集成多个Kubernetes 集群。
原文链接:https://medium.com/trendyol-tech/multiple-kubernetes-integration-with-gitlab-core-features-dba22488a5a4