更新gitlab-ci文档part1

pull/447/head
gjmzj 2019-01-21 23:39:36 +08:00
parent 407dbce345
commit 6f23fe4d4e
4 changed files with 411 additions and 2 deletions

View File

@ -0,0 +1,88 @@
# 3.3 K8S 应用部署模板 app.yaml
以下示例配置仅做参考,描述一个简单 java spring boot项目的 k8s 部署文件模板在实际部署前CI/CD流程中会对变量做替换。详见 [gitlab-ci.yml文件](gitlab-ci.yml.md)。
``` bash
---
apiVersion: v1
kind: Namespace
metadata:
name: PROJECT_NS
---
apiVersion: v1
kind: Secret
metadata:
name: harborkey1
namespace: PROJECT_NS
data:
#待替换的变量DOCKER_KEY参考 docs/guide/harbor.md#k8s%E4%B8%AD%E4%BD%BF%E7%94%A8harbor
.dockerconfigjson: DOCKER_KEY
type: kubernetes.io/dockerconfigjson
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: APP_NAME
namespace: PROJECT_NS
spec:
replicas: APP_REP
template:
metadata:
labels:
run: APP_NAME
spec:
containers:
- name: APP_NAME
image: ProjectImage
imagePullPolicy: Always
env:
# 设置java的时区
- name: TZ
value: "Asia/Shanghai"
resources:
limits:
cpu: 500m
memory: 1600Mi
requests:
cpu: 200m
memory: 800Mi
ports:
- containerPort: 8080
imagePullSecrets:
- name: harborkey1
---
apiVersion: v1
kind: Service
metadata:
labels:
run: APP_NAME
name: APP_NAME
namespace: PROJECT_NS
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
run: APP_NAME
sessionAffinity: None
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: APP_NAME-ingress
namespace: PROJECT_NS
spec:
rules:
- host: AppDomain
http:
paths:
- path: /AppPath
backend:
serviceName: APP_NAME
servicePort: 80
```

View File

@ -0,0 +1,47 @@
# 3.2环境配置替换 config.sh
首先应用开发人员需要整理在不同环境(测试环境/生产环境的配置参数并在源代码中约定好替换的名称如db_host, db_usr然后用户必须在项目gitlab web界面“Settings”>"CI/CD">"Variables"配置变量最后根据gitlab-ci.yml文件定义CI/CD执行的需要编写如下简单变量替换shell脚本该shell脚本分别在测试环境打包阶段beta-build和生产环境打包阶段prod-build阶段运行。
以下脚本仅作示例,实际应根据项目需要增加/修改需替换变量名称与对应源代码中的配置文件
``` bash
#!/bin/bash
#set -o verbose
#set -o xtrace
beta_config() {
sed -i \
-e "s/db_host/$BETA_DB_HOST/g" \
-e "s/db_usr/$BETA_DB_USR/g" \
-e "s/db_pwd/$BETA_DB_PWD/g" \
example-web/src/main/resources/config/datasource.properties # 项目源码的配置文件
sed -i \
-e "s/redis_host/$BETA_REDIS_HOST/g" \
-e "s/redis_port/$BETA_REDIS_PORT/g" \
-e "s/redis_pwd/$BETA_REDIS_PWD/g" \
example-web/src/main/resources/config/redis.properties # 项目源码的配置文件
}
prod_config() {
sed -i \
-e "s/db_host/$PROD_DB_HOST/g" \
-e "s/db_usr/$PROD_DB_USR/g" \
-e "s/db_pwd/$PROD_DB_PWD/g" \
example-web/src/main/resources/config/datasource.properties
sed -i \
-e "s/redis_host/$PROD_REDIS_HOST/g" \
-e "s/redis_port/$PROD_REDIS_PORT/g" \
-e "s/redis_pwd/$PROD_REDIS_PWD/g" \
example-web/src/main/resources/config/redis.properties
}
if [[ "$CI_JOB_STAGE" == "beta-build" ]];then
beta_config
elif [[ "$CI_JOB_STAGE" == "prod-build" ]];then
prod_config
else
echo "error: undefined CI_JOB_STAGE!"
fi
```

View File

@ -1,6 +1,6 @@
# gitlab CI/CD 基础 # gitlab CI/CD 基础
gitlab-ci 兼容 travis ci 格式,也是最流行的 CI 工具之一;本文讲解利用 gitlab, gitlab-runner, docker, harbor, kubernetes 等流行开源工具搭建一个自动化CI/CD流水线举的例子以简单实用为原则没有选用 dinddocker in dockers打包、gitlab Auto DevOps 等先进但未必成熟的方式。一个最简单的流水线如下: gitlab-ci 兼容 travis ci 格式,也是最流行的 CI 工具之一;本文讲解利用 gitlab, gitlab-runner, docker, harbor, kubernetes 等流行开源工具搭建一个自动化CI/CD流水线举的例子以简单实用为原则暂时没有选用 dinddocker in dockers打包、gitlab Auto DevOps 等方式。一个最简单的流水线如下:
- 代码提交 --> 镜像构建 --> 部署测试 --> 部署生产 - 代码提交 --> 镜像构建 --> 部署测试 --> 部署生产
@ -10,5 +10,86 @@ gitlab-ci 兼容 travis ci 格式,也是最流行的 CI 工具之一;本文
- 若干虚机运行 gitlab-runner: 运行自动化流水线 pipeline - 若干虚机运行 gitlab-runner: 运行自动化流水线 pipeline
- 正常运行的容器仓库:[安装 Harbor 文档](../harbor.md) - 正常运行的容器仓库:[安装 Harbor 文档](../harbor.md)
- 正常运行的 k8s 集群:可以是自建/公有云提供商 - 正常运行的 k8s 集群:可以是自建/公有云提供商
- 了解代码管理流程 gitflow 等
## ## 1.准备测试项目代码
假设你要开发一个 spring boot 项目;先登陆你的 gitlab 账号,创建项目,上传你的代码;项目根目录看起来如下:
```
-rw-r--r-- 1 root root 44 Jan 2 16:38 eclipse.bat
drwxr-xr-x 8 root root 4096 Jan 7 15:29 .git/
-rw-r--r-- 1 root root 276 Jan 7 08:44 .gitignore
drwxr-xr-x 3 root root 4096 Jan 7 08:44 example-api/
drwxr-xr-x 3 root root 4096 Jan 7 08:44 example-biz/
drwxr-xr-x 3 root root 4096 Jan 2 16:38 example-dal/
drwxr-xr-x 3 root root 4096 Jan 2 16:38 example-web/
-rw-r--r-- 1 root root 54 Jan 2 16:38 install.bat
-rw-r--r-- 1 root root 10419 Jan 2 16:38 pom.xml
```
传统做法是在本地配置好相关环境后使用 mvn 编译生成jar包然后测试运行jar这里我们要打包成 docker 镜像,并创建 CI/CD 流水线如下示例在项目根目录创建2个文件夹及里面文件
``` bash
dockerfiles ### 新增文件夹用来 docker 镜像打包
└── Dockerfile # 定义 docker 镜像
.ci ### 新增文件夹用来存放 CI/CD 相关内容
├── app.yaml # k8s 平台的应用部署文件
├── config.sh # 配置替换脚本
└── gitlab-ci.yml # gitlab-ci 的主配置文件
```
## 2.准备 docker 镜像描述文件 Dockerfile
我们把 Dockerfile 放在独立目录下java spring boot 应用可以这样写:
``` bash
FROM openjdk:8-jdk-alpine
VOLUME /tmp
COPY *.jar app.jar # 这里 *.jar 包就是后续在cicd pipeline 过程中 mvn 生成的jar包移动到此目录
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
```
## 3.准备 CI/CD 相关脚本和文件
本地安装 gitlab 的同时也会安装帮助文档非常有用请阅读如下文档假设你本地gitlab使用的域名`http://gitlab.test.com`
- gitlab-ci 基本概念 http://gitlab.test.com/help/ci/README.md
- 变量 http://gitlab.test.com/help/ci/variables/README.md
目录`.ci`下面的三个文件`app.yaml`, `config.sh`, `gitlab-ci.yml`是互相关联的;整个流程中使用到的变量分为三种:
- 第一种是gitlab自身预定义变量比如项目名: CI_PROJECT_NAME流水线ID: CI_PIPELINE_ID无需更改
- 第二种是在gitlab-ci.yml文件中定义的变量一般是少量的自定义变量按需少量改动
- 第三种是用户可以在项目web界面配置的变量“Settings”>"CI/CD">"Variables",本示例项目用到该类型变量举例:
|变量|值|注解|
|:-|:-|:-|
|BETA_APP_REP|1|beta环境应用副本数|
|BETA_DB_HOST|1.1.1.1:3306|beta环境应用连接数据库主机|
|BETA_DB_PWD|xxxx|beta环境数据库连接密码|
|BETA_DB_USR|xxxx|beta环境数据库连接用户|
|BETA_REDIS_HOST|1.1.1.2|beta环境redis主机|
|BETA_REDIS_PORT|6379|beta环境redis端口|
|BETA_REDIS_PWD|xxxx|beta环境redis密码|
|BETA_HARBOR|1.1.1.3|beta环境镜像仓库地址|
|BETA_HARBOR_PWD|xxxx|beta环境镜像仓库密码|
|BETA_HARBOR_USR|xxxx|beta环境镜像仓库用户|
|PROD_APP_REP|2|prod环境应用副本数|
|PROD_DB_HOST|2.2.2.1:3306|prod环境应用连接数据库主机|
|PROD_DB_PWD|xxxx|prod环境数据库连接密码|
|PROD_DB_USR|xxxx|prod环境数据库连接用户|
|PROD_REDIS_HOST|2.2.2.2|prod环境redis主机|
|PROD_REDIS_PORT|6379|prod环境redis端口|
|PROD_REDIS_PWD|xxxx|prod环境redis密码|
|PROD_HARBOR|2.2.2.3|prod环境镜像仓库地址|
|PROD_HARBOR_PWD|xxxx|prod环境镜像仓库密码|
|PROD_HARBOR_USR|xxxx|prod环境镜像仓库用户|
|...|...|根据项目需要自行添加设置|
掌握了以上基础知识,可以开始以下三个任务:
- 3.1[配置 gitlab-ci.yml](gitlab-ci.yml.md), 整个CI/CD的主配置文件定义所有的CI/CD阶段和每个阶段的任务
- 3.2[配置 config.sh](config.sh.md),根据不同分支/环境替换不同的应用程序变量(对应上述第三种变量)
- 3.3[配置 app.yaml](app.yaml.md)K8S应用部署简单模板替换完成后可以部署到测试/生产的K8S平台上
## to be continued

View File

@ -0,0 +1,193 @@
# 配置 gitlab-ci.yml
项目组对应用CI/CD的背景需求及实现方案简介
- 应用测试环境部署在本地k8s平台生产环境部署在阿里云上k8s平台
- 应用的多个feature分支可以并行测试
- 对于即将发布的release分支本地提供封版测试环境阿里云上提供UAT测试环境
以下示例配置为个人经验总结,仅供参考,可以根据自己的理解和项目需要不断优化完善;总体来说 gitlab-ci.yml 配置很丰富基本上能够满足各种个性化的CI/CD流程需要。
``` bash
$ cat > .ci/gitlab-ci.yml << EOF
variables: ### 定义全局变量 http://gitlab.test.com/help/ci/variables/README.md
PROJECT_NS: '$CI_PROJECT_NAMESPACE-$CI_JOB_STAGE' # 定义项目命名空间对应k8s的namespace
APP_NAME: '$CI_PROJECT_NAME-$CI_COMMIT_REF_SLUG' # 使用项目名和git提交信息作为应用名
IMAGE_NAME: '$CI_PROJECT_NAMESPACE-$CI_PROJECT_NAME:$CI_PIPELINE_ID' # 定义镜像名称
stages: ### 定义ci各阶段
- beta-build # beta环境编译打包
- beta-deploy # beta环境部署
- beta-feature-delete # beta环境feature分支手动删除
- prod-build # prod环境编译打包
- prod-uat-deploy # prod-uat环境部署
- prod-deploy # prod环境部署
- prod-rollback # prod回滚
job_beta_build:
stage: beta-build # beta环境编译打包
tags:
- build-shell # 定义带`build-shell`标签的runner可以运行该job
only: # 定义只在如下分支或者tag运行该job
- master
- develop
- /^feature.*$/
- release
when: manual # 调试阶段可以先手动,后续可以注释掉以自动运行
script: ### runner上运行的脚本
- bash .ci/config.sh # 不同环境配置替换,后文详解 config.sh
- mvn clean install -Dmaven.test.skip=true -U # mvn 编译可以去runner 虚机上手动执行编译测试
- mv example-web/target/*.jar dockerfiles/ # 把mvn生成的xxx.jar移动到dockerfiles目录下
- export IMAGE=`echo $IMAGE_NAME | sed 's/\//-/g'` # 转换镜像名mygroup/java/example:172 >> mygroup-java-example:172
- cd dockerfiles && docker build -t $BETA_HARBOR/example/$IMAGE . # 创建 docker 镜像
- docker login -u $BETA_HARBOR_USR -p $BETA_HARBOR_PWD $BETA_HARBOR # 登陆到内部镜像仓库 harbor并推送
- docker push $BETA_HARBOR/example/$IMAGE
- docker logout $BETA_HARBOR
job_push_beta: ### 推送到beta环境可以推送不同分支 develop, feature-1, ...>
stage: beta-deploy # 可以做到多分支同时测试甚至最后的release分支也要在beta封版测试
tags:
- beta-shell # 定义带`beta-shell`标签的runner可以运行该job
only:
- master
- develop
- /^feature.*$/
- release
when: manual # 调试阶段可以先手动,后续可以注释掉以自动运行
variables:
BETA_EXP_Domain: '$CI_COMMIT_REF_SLUG.example.test.com' # job内部变量指定该应用在beta环境的 ingress 域名
script:
- export IMAGE=`echo $IMAGE_NAME | sed 's/\//-/g'` # 转换 $IMAGE_NAME 中可能的 / 字符
- export PROJECT_NS=`echo $PROJECT_NS | sed 's/\//-/g'` # 转换命名空间中可能有的 / 字符
# 替换beta环境的参数配置
- sed -i "s/PROJECT_NS/$PROJECT_NS/g" .ci/app.yaml ### app.yaml 即k8s的部署模板文件详见后面 app.yaml.md 文档,注意这里的变量有的来自>
- sed -i "s/APP_NAME/$APP_NAME/g" .ci/app.yaml # gitlab 系统变量, 有的是在项目 CI/CD 设置里面用户定义的变量
- sed -i "s/APP_REP/$BETA_APP_REP/g" .ci/app.yaml
- sed -i "s/AppDomain/$BETA_EXP_Domain/g" .ci/app.yaml
- sed -i "s/ProjectImage/$BETA_HARBOR\/example\/$IMAGE/g" .ci/app.yaml
- sed -i "s/DOCKER_KEY/$BETA_KEY/g" .ci/app.yaml # DOCKER_KEY 为k8s平台能从镜像仓库pull所需的认证信息详见harbor文档
#
- mkdir -p /opt/kube/$PROJECT_NS/$APP_NAME # 在runnerbeta-shell虚机本地创建应用配置目录调试检查用
- cp -f .ci/app.yaml /opt/kube/$PROJECT_NS/$APP_NAME
- kubectl --kubeconfig=/etc/.beta/config apply -f .ci/app.yaml # 部署应用runner虚机上预先配置了kubectl权限执行测试k8s平台
job_delete_beta: ### 多测试环境并行部署在beta k8s平台feature分支测试完毕后删除代码分支
stage: beta-feature-delete # 同时需要删除该分支在k8s平台上的部署可以由开发人员自行执行该job删除
tags:
- beta-shell
only:
- /^feature.*$/
when: manual
script:
- export PROJECT_NS=`echo $PROJECT_NS | sed 's/\//-/g'`
- kubectl --kubeconfig=/etc/.beta/config delete deploy,svc,ing $APP_NAME -n $PROJECT_NS
job_prod_build: ### prod环境编译打包这里prod环境我们使用阿里云上的K8S
stage: prod-build # 阿里云k8s平台上运行的uat环境和正式环境都使用本次打包镜像
tags:
- build-shell
only: # 仅master和release分支可以执行该job
- master
- release
when: manual
script:
- bash .ci/config.sh # config.sh 会执行替换生产环境的变量
- mvn clean install -Dmaven.test.skip=true -U # mvn 编译可以去runner 虚机上手动执行编译测试
- mv example-web/target/*.jar dockerfiles/ # 把mvn生成的xxx.jar移动到dockerfiles目录下
- export IMAGE=`echo $IMAGE_NAME | sed 's/\//-/g'`
- cd dockerfiles && docker build -t $PROD_HARBOR/example/$IMAGE .
- docker login -u $PROD_HARBOR_USR -p $PROD_HARBOR_PWD $PROD_HARBOR
- docker push $PROD_HARBOR/example/$IMAGE
- docker logout $PROD_HARBOR
job_push_prod_uat: ### 部署至阿里云uat环境
stage: prod-uat-deploy
tags:
- prod-shell
when: manual
only: # 仅master和release分支可以执行该job
- master
- release
variables:
PROD_EXP_Domain: 'example-uat.xxxx.com' # job内部变量指定该应用在uat环境的 ingress 域名
script:
- export IMAGE=`echo $IMAGE_NAME | sed 's/\//-/g'`
- export PROJECT_NS=`echo $PROJECT_NS | sed 's/\//-/g'`
# 替换prod环境的参数配置
- sed -i "s/PROJECT_NS/$PROJECT_NS/g" .ci/app.yaml
- sed -i "s/APP_NAME/$CI_PROJECT_NAME/g" .ci/app.yaml
- sed -i "s/APP_REP/1/g" .ci/app.yaml
- sed -i "s/AppDomain/$PROD_EXP_Domain/g" .ci/app.yaml
- sed -i "s/ProjectImage/$PROD_HARBOR\/example\/$IMAGE/g" .ci/app.yaml
- sed -i "s/DOCKER_KEY/$PROD_KEY/g" .ci/app.yaml
#
- mkdir -p /opt/kube/$PROJECT_NS/$APP_NAME
- cp -f .ci/app.yaml /opt/kube/$PROJECT_NS/$APP_NAME
- kubectl --kubeconfig=/etc/.aliyun/config apply -f .ci/app.yaml
job_push_prod_release: ### 部署至阿里云正式环境
stage: prod-deploy
tags:
- prod-shell
when: manual
only: # 仅master和release分支可以执行该job
- master
- release
variables:
PROD_EXP_Domain: 'example.xxxx.com' # 指定该应用在阿里云正式环境的 ingress 域名
script:
- export IMAGE=`echo $IMAGE_NAME | sed 's/\//-/g'`
- export PROJECT_NS=`echo $PROJECT_NS | sed 's/\//-/g'`
# 替换prod环境的参数配置
- sed -i "s/PROJECT_NS/$PROJECT_NS/g" .ci/app.yaml
- sed -i "s/APP_NAME/$CI_PROJECT_NAME/g" .ci/app.yaml
- sed -i "s/APP_REP/$PROD_APP_REP/g" .ci/app.yaml
- sed -i "s/AppDomain/$PROD_EXP_HOST/g" .ci/app.yaml
- sed -i "s/ProjectImage/$PROD_HARBOR\/example\/$IMAGE/g" .ci/app.yaml
- sed -i "s/DOCKER_KEY/$PROD_KEY/g" .ci/app.yaml
#
- mkdir -p /opt/kube/$PROJECT_NS/$APP_NAME
- cp -f .ci/app.yaml /opt/kube/$PROJECT_NS/$APP_NAME
- kubectl --kubeconfig=/etc/.aliyun/config apply -f .ci/app.yaml
1/3 rollback: ### 定义生产环境回退job
stage: prod-rollback
tags:
- prod-shell
when: manual
only:
- master
- /^release.*$/
variables:
PROJECT_NS: '$CI_PROJECT_NAMESPACE-prod-deploy' # 定义job内变量覆盖全局变量设置
script:
- kubectl --kubeconfig=/etc/.aliyun/config -n $PROJECT_NS rollout undo deployment $CI_PROJECT_NAME --to-revision=1
2/3 rollback:
stage: prod-rollback
tags:
- prod-shell
when: manual
only:
- master
- /^release.*$/
variables:
PROJECT_NS: '$CI_PROJECT_NAMESPACE-prod-deploy' # 定义job内变量覆盖全局变量设置
script:
- kubectl --kubeconfig=/etc/.aliyun/config -n $PROJECT_NS rollout undo deployment $CI_PROJECT_NAME --to-revision=2
3/3 rollback:
stage: prod-rollback
tags:
- prod-shell
when: manual
only:
- master
- /^release.*$/
variables:
PROJECT_NS: '$CI_PROJECT_NAMESPACE-prod-deploy' # 定义job内变量覆盖全局变量设置
script:
- kubectl --kubeconfig=/etc/.aliyun/config -n $PROJECT_NS rollout undo deployment $CI_PROJECT_NAME --to-revision=3
EOF
```