先决条件
- Kubernetes集群
- Helm
- Gitlab
使用Helm在kubernetes集中安装gitlab-runner
Harobr 私有仓库或阿里云 hub.docker.io 仓库等
helm 安装 gitlab-runner 请自行查看相关文档或者values.yaml中的注解
构建过程
整个构建过程分为三步
整个构建过程分为三步:
- 编译 java代码 使用maven镜像
- 构建docker镜像,使用kaniko来构建
- 使用kubectl来更新deployment的镜像
下面按gitlab-ci 的job来逐步分析各个流程
编译Java
build-maven-project: image: mave:3.6.2-jdk-8-with-nexus stage: build tags: - "build" cache: key: maven paths: - ~/.m2 script: - mvn clean install -DskipTests artifacts: name: "$CI_JOB_NAME" paths: - target/*.jar
image 指令使用 mave:3.6.2-jdk-8-with-nexus工具镜像来编译此java项目,因为使用了私服,所以maven镜像不能直接使用官方镜像,而是以官方镜像为基础镜像,加入自己的maven 配置settings.xml文件。至于kubernetes集群如何正确解析nexus私服的地址,最后再说。
例: 构建仓库为nexus私服的maven镜像 Dockerfile
FROM maven:3.6.2-jdk-8 COPY settings.xml /usr/share/maven/ref/
构建maven工具镜像
docker build . -t maven:3.6.2-jdk-8-with-nexus
artifacts 是上传编译成果,会把编译出来 的jar文件保存到gitlab上,以让下一流程使用
cache tags 等指令请查阅gitlab-ci官方文档,也可以加入自己需要的指令。
构建Docker镜像
build-docker-image: tags: - "build" stage: image image: name: gcr.io/kaniko-project/executor:debug entrypoint: [""] script: - echo "nameserver 8.8.8.8" >> /etc/resolv.conf - echo "{\"auths\":{\"http://harbor.mydomain.hb\":{\"auth\":\"YWRtaW46SGFyYm9yMTIzNDU=\"},\"https://index.docker.io/v1/\":{\"auth\":\"eWl5ZWhhaWNoYW8xMzE0Omxld2lzxOQ==\"},\"registry.cn-hangzhou.aliyuncs.com\":{\"auth\":\"emh1c2h1Y2xvdWQ6sMNzIxMTY2OTQ=\"}},\"HttpHeaders\":{\"User-Agent\":\"Docker-Client/19.03.2 (linux)\"}}" > /kaniko/.docker/config.json - /kaniko/executor --insecure-registry harbor.mydomain.bh --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --build-arg SUFFIX=-0.0.1-SNAPSHOT.jar --build-arg SERVICE_NAME=$CI_PROJECT_NAME --build-arg SERVICE_PORT=8091 --build-arg ENVIRONMENT=local --destination harbor.mydomain.hb/namespace/${CI_PROJECT_NAME}:${CI_COMMIT_SHA}
image 指令使用gcr.io/kaniko-project/executor:debug 镜像来构建镜像
kaniko是谷哥推出的构建工具,允许在非特权容器构建镜像,也就是我常说的docker in docker或者dind,
scripts 指令执行了三条命令
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
解释: 容器中的DNS只能解析集群内的地址,不能解析其它地址,所以要写一条nameserver ,让kaniko容器能 够解析 hub.docker.io 和你的私有仓库的地址,也可以在hosts文件中写入其它地址。
echo "{\"auths\":{\"http://harbor.mydomain.hb\":{\"auth\":\"YWRtaW46SGFyYm9yMTIzNDU=\"},\"https://index.docker.io/v1/\":{\"auth\":\"eWl5ZWhhaWNoYW8xMzE0Omxld2lzNzExOQ==\"},\"registry.cn-hangzhou.aliyuncs.com\":{\"auth\":\"emh1c2h1Y2xvdWQ6eHFsMTM1NzIxMTY2OTQ=\"}},\"HttpHeaders\":{\"User-Agent\":\"Docker-Client/19.03.2 (linux)\"}}" > /kaniko/.docker/config.json
Kaniko没有登录镜像仓库的指令 ,而使用了docker的.docker/config.json文件来验证仓库权限,所以我们要写入config.json文件。config.json文件会在你使用docker login $registry 时生成,在用户目录下.docker/ 目录下。
/kaniko/executor --insecure-registry harbor.mydomain.hb \ --context $CI_PROJECT_DIR \ --dockerfile $CI_PROJECT_DIR/Dockerfile \ --build-arg SUFFIX=-0.0.1-SNAPSHOT.jar \ --build-arg SERVICE_NAME=$CI_PROJECT_NAME \ --build-arg SERVICE_PORT=8091 \ --build-arg ENVIRONMENT=local \ --destination harbor.mydomain.hb/namespace/${CI_PROJECT_NAME}:${CI_COMMIT_SHA}
原命令中没有换行 这里换行是为了方便解说
- /kaniko/executor是构建工具
- --insecure-registry harbor.mydomain.hb 指令是指登录非https的仓库
- --context $CI_PROJECT_DIR 构建时的目录
- --dockerfile $CI_PROJECT_DIR/Dockerfile Dockerfile路径
- --build-arg SERVICE_PORT=8091 构建参数,是Dockerfile ARG指令定义的参数
- --destination harbor.mydomain.hb/namespace/${CI_PROJECT_NAME}:${CI_COMMIT_SHA} 定义镜像名,构建完成后镜像推送到远程仓库
布署镜像到Kubernetes集群
这一步kubectl的镜像要自己构建一个
例:构建 kubectl 镜像
FROM busybox:1.30 COPY config /root/.kube/config COPY kubectl /usr/bin/kubectl RUN chmod +x /usr/bin/kubectl
构建镜像
docker build . -t kubectl:1.15.3-with-local-cluster
布署镜像到Kubernetes
deploy-service: stage: deploy tags: - "build" image: name: harbor.mydomain.bh/namespace/kubectl:1.15.3-with-local-cluster script: - kubectl set image deployment ${CI_PROJECT_NAME}-deployment ${CI_PROJECT_NAME}=harbor.zscloud.zs/zscloud/${CI_PROJECT_NAME}:${CI_COMMIT_SHA}
其它问题
kubernetes gitlab nexus registry 是内网私有地址,构建时无法解析地址:
例:
gitlab的地址为: gitlab.mydomain.com
nexus: nexus.mydomain.com
registyr: harbor.mydomain.com
此时,gitlab-runner所启动的容器没只有kubernetes的DNS,是无法解析这些私有域名的,可以kubernetes 集群中 CoreDns的配置文件中写入
.:53 { errors health kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure upstream fallthrough in-addr.arpa ip6.arpa ttl 30 } hosts { 10.10.20.12 gitlab.mydomain.com 10.10.20.12 smtp.mydomain.com 10.10.20.12 nexus.mydomain.com 10.10.20.12 harbor.mydomain.com fallthrough } prometheus :9153 forward . /etc/resolv.conf cache 30 loop reload loadbalance }
当然,在job中也可以先向工具镜像的hosts或者resolv.conf中写入相关内容
参考文档
kaniko Github
gitlab-ci语法