本文以NodeJS开发框架为例,讲解如何组合Kubernetes、GitLab、Docker、Docker Registry等技术,实现CI/CD的自动化。
NodeJS 示例
本文假设开发机器已经安装nodejs、express、express generator、docker
通过以下命令产生一个基本框架
express --no-view --git
然后运行nodejs
,在浏览器中访问http://localhost:3000/
即可看到express的页面。
npm start
在Kubernetes集群中创建Gitlab账户
创建gitlab-service-account.yaml文件
该文件中创建了一个gitlab-service-account
账户,并做了角色绑定。
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: gitlab-service-account
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: gitlab-service-account-role-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: gitlab-service-account
namespace: default
在Kubernetes
中创建账户和角色绑定
kubectl apply -f gitlab-service-account.yaml
部署Docker Registry
本示例选择在CentOS 7上安装VMware Harbor
,如何部署请参阅网上其他文章,或看稍后的文章。
GitLab 配置
GitLab的部署在本篇中也不详述,请参与其他部分-。
为了使用CI/CD,我们需要在GitLab中设置环境变量。
位置:项目设置->CI/CD->环境变量,展开后即可设置。
注意:为了安全,REGISTRY_PASSWORD
, K8S_USER_TOKEN
, K8S_CA_PEM
应该予以保护。
REGISTRY_SERVER
: Docker Registry的URL,!!!如果是Docker Hub,则需要修改本文件
REGISTRY_USER
: 登录Docker Registry的用户名
REGISTRY_PASSWORD
: 登录Docker Registry的密码
K8S_SERVER
: Kubernetes API Server
K8S_USER_TOKEN
: 链接Kubernetes集群的用户令牌。
获取用户TOKEN的方式:
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep gitlab-admin | awk '{print $1}')
K8S_CA_PEM
: Kubernetes集群的CA证书
获取方式:
kubectl get secret -o jsonpath="{['data']['ca\.crt']}"
通过 GitLab 构建 Docker
接下来,我们在看在GitLab中如何构建Docker
创建.gitlab-ci.yml文件
image: docker:latest
services:
- docker:dind
stages:
- build
- deploy
variables:
CONTAINER_IMAGE: testapp:${CI_COMMIT_SHORT_SHA}
DOCKER_HOST: tcp://localhost:2375/
DOCKER_DRIVER: overlay2
REGISTRY_IMAGE: ${REGISTRY_SERVER}/library/testapp:${CI_COMMIT_SHORT_SHA}
build:
stage: build
script:
- docker login -u ${REGISTRY_USER} -p ${REGISTRY_PASSWORD} ${REGISTRY_SERVER}
- docker build -t ${CONTAINER_IMAGE} .
- docker tag ${CONTAINER_IMAGE} ${REGISTRY_IMAGE}
- docker push ${REGISTRY_IMAGE}
- docker tag ${CONTAINER_IMAGE} testapp:latest
其中docker:latest
是来自于Docker Hub的镜像,并使用Docker-in-Docker(dind)
技术。
${CI_COMMIT_SHORT_SHA}
:GitLab在提交代码时会生成一个简短的SHA码,这是该环境变量;
DOCKER_HOST
和 DOCKER_DRIVER
必须如此设置,否则将会出现无法打开socket的错误提示。
REGISTRY_IMAGE
是组合后的本地Registry的URL
其中的Build脚本对应几个步骤:
- 登录本地Registry;
- 构建Docker
- 标记Docker为本地Registry
- 推送Docker到本地Registry
- 标记本地Docker为最新版本。这条实际上没有用。
创建 Dockerfile
FROM node:10
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --registry
RUN npm ci --only=production
# Bundle app source
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
部署到Kubernetes集群中
创建deployment.yaml文件
apiVersion: apps/v1
kind: Deployment
metadata:
name: testapp
labels:
app: testapp
spec:
replicas: 2
selector:
matchLabels:
app: testapp
tier: frontend
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
template:
metadata:
labels:
app: testapp
tier: frontend
spec:
containers:
- name: testapp
image: docker.shmtu.edu.cn/library/testapp:
ports:
- containerPort: 3000
livenessProbe:
httpGet:
path: /
port: 3000
initialDelaySeconds: 2
periodSeconds: 2
readinessProbe:
httpGet:
path: /
port: 3000
initialDelaySeconds: 2
periodSeconds: 2
imagePullSecrets:
- name: local-registry
其中有几个需要说明的地方:
1、因为需要选用本地Registry的镜像,所以需要先创建secret:
kubectl create secret docker-registry local-registry \
--docker-server=docker.shmtu.edu.cn \
--docker-username= \
--docker-password=
创建完成后,可以查看是否正确:
kubectl get secret local-registry --output="jsonpath={.data.\.dockerconfigjson}" | base64 -d
2、作为App监控的livenessProbe和readinessProbe最好也配置上。
其余参数不做讲解。
部署Service
由于deployment.yaml
每次都会执行,其中的pod都会创建,这样就需要我们把service部署文件放在外面,第一次部署之前执行一次即可。
apiVersion: v1
kind: Service
metadata:
name: testapps-svc
namespace: gitlab-managed-apps
labels:
app: testapp-svc
spec:
type: NodePort
ports:
- port: 3000
nodePort: 30300
selector:
app: testapp
tier: frontend
修改 .gitlab-ci.yml 文件
在 .gitlab-ci.yml 文件中,添加deploy
阶段的内容
deploy:
stage: deploy
image: docker.shmtu.edu.cn/library/helm-kubectl:1.14.1
script:
- kubectl version
- kubectl config set-cluster k8s --server="${K8S_SERVER}"
- kubectl config set clusters.k8s.certificate-authority-data "${K8S_CA_PEM}"
- kubectl config set-credentials gitlab --token="${K8S_USER_TOKEN}"
- kubectl config set-context default --cluster=k8s --user=gitlab
- kubectl config use-context default
- sed -i "s//${CI_COMMIT_SHORT_SHA}/g" deployment.yaml
- cat deployment.yaml
- kubectl apply -f deployment.yaml
注意:
1、目前dtzar/helm-kubectl
Docker镜像支持到kubectl v1.13.4
,而我们的集群是v1.14.0
,所以我们自行Build了这个Docker,并推送到本地的Docker Registry中。
2、其中的cat deployment.yaml
并不必要,仅仅是为了排错使用,可以去掉该命令。