CICD初探(三)Gitlab CICD实践-分支触发-部署到k8s

CICD初探(三)Gitlab CICD实践-分支触发-部署到k8s

Wed Sep 5, 2018

2400 Words|Read in about 5 Min
Tags: devops  

大家好,又来了!CICD系列文章写的有点乱,因为我自己也在摸索中!本文重点介绍gitlab在做cicd的时候如何通过分支来区分已经如何推送到k8s中!有些细节前面几篇文章已经解释过了,不过也有些地方介绍的含糊不清,请见谅!~ 下面我会简单介绍从项目建立开始一直到部署到k8s的过程(有些过程适当省略,可以看前几篇)!

创建一个工程

在gitlab上tfcloud组织中创建一个zeus的新工程,不用多介绍!看下图

new project

配置cicd

这里可以看前面文章的介绍,这里要注意的是tags我打了两个标签! develop,master

[[email protected] ~]# gitlab-runner register
Running in system-mode.

Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
http://10.100.7.46:8088
Please enter the gitlab-ci token for this runner:
NUWMQhB-X36UDiYs4QFA
Please enter the gitlab-ci description for this runner:
[web-helm-5]: zeus
Please enter the gitlab-ci tags for this runner (comma separated):
develop,master
Registering runner... succeeded                     runner=NUWMQhB-
Please enter the executor: kubernetes, docker-ssh, virtualbox, docker+machine, docker-ssh+machine, docker, parallels, shell, ssh:
docker
Please enter the default Docker image (e.g. ruby:2.1):
golang:alpine
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

因为我选择的是docker环境,所以我要在配置文件里加上docker相关信息,打开config.toml文件(文件目录根据实际情况而定))

vim /etc/gitlab-runner/config.toml

volumes = ["/cache"]

改为

volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"]

编写.gitlab-ci.yml文件

先上一个可以根据不同分支触发编译的配置

### 这里我自己打了一个golang翻墙的镜像!可以不使用我这个。
image: imscc/alpine_go:sslocal

stages:
  - build
# job名字,随意
daily-build:
  stage: build # 此job属于哪个阶段
  only: # 此job匹配哪个branch或者tag或者trigger
    - develop #- <一个匹配日常分支的正则>
  except:
    - master # 此job忽略tag
    # - triggers # 此job忽略trigger
  script:
    - echo "I'm develop" # job执行的脚本
  tags:
    - develop

# 大概意思同上
publish-build:
  stage: build
  only: 
    - master
  except:
    - develop
  script:
    - echo "I'm master !!!!"
  tags:
    - master

测试

下载工程到本地

git clone http://10.100.7.46:8088/tfcloud/zeus.git
cd zeus

创建develop分支

git branch  develop
git checkout develop

创建源文件

touch main.go
touch main.go

package main

import (
	"fmt"
	"log"
	"net/http"
)

func sayhelloName(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello Wrold!")
}

func main() {
	http.HandleFunc("/", sayhelloName)
	err := http.ListenAndServe(":9090", nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

提交develop分支

➜  zeus git:(develop) ✗ git branch develop
fatal: A branch named 'develop' already exists.
➜  zeus git:(develop) ✗ git add .
➜  zeus git:(develop) ✗ git status
On branch develop
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	new file:   main.go
	new file:   zeus

➜  zeus git:(develop) ✗ git commit -m  "commit develop"
[develop 6a1c8a1] commit develop
 2 files changed, 19 insertions(+)
 create mode 100644 main.go
 create mode 100755 zeus
➜  zeus git:(develop) git push origin develop
Counting objects: 4, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 3.08 MiB | 4.40 MiB/s, done.
Total 4 (delta 0), reused 0 (delta 0)
remote:
remote: To create a merge request for develop, visit:
remote:   http://10.100.7.46:8088/tfcloud/zeus/merge_requests/new?merge_request%5Bsource_branch%5D=develop
remote:
To http://10.100.7.46:8088/tfcloud/zeus.git
   c2ab533..6a1c8a1  develop -> develop

激动人心的时刻到了,去看下cicd是否触发! commit develop

develop job 上图就是我们提并触发的!

下面我们合并一下代码到master,然后看下结果!!!

➜  zeus git:(develop) git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
➜  zeus git:(master) git merge origin/develop
Merge made by the 'recursive' strategy.
 main.go |  19 +++++++++++++++++++
 zeus    | Bin 0 -> 6473572 bytes
 2 files changed, 19 insertions(+)
 create mode 100644 main.go
 create mode 100755 zeus
➜  zeus git:(master) git push origin master
Counting objects: 2, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 305 bytes | 305.00 KiB/s, done.
Total 2 (delta 1), reused 0 (delta 0)
To http://10.100.7.46:8088/tfcloud/zeus.git
   d1fc152..95b4797  master -> master

master job

OK!!! 分支触发cicd基本上就到这里了!祝你好运!下面进行k8s部署环节!!!

部署

思考一下部署一个应用到k8s环境需要准备些什么?

  • 应用镜像
  • k8s授权操作
  • 服务配置文件
  • 部署脚本
  • kubectl

根据上述需求我们一步一步来!

应用镜像

具体细节我就不啰嗦了,可以参考前面都文章 Dockerfile:

FROM alpine:latest

MAINTAINER imscc<[email protected]>

WORKDIR /httx/run/zeus/
COPY zeus /httx/run/zeus
EXPOSE 9090
CMD [ "./zeus" ]

k8s授权操作

我这里是最简单都做法,把k8s都config文件放到工程中,直接使用的,各位看官也可以将文件放到gitlab-runner的宿主机上!

服务配置文件

这个是k8s服务部署的基础,不懂的可以google一下如何部署一个简单的服务! 我这里直接上配置文件了!配置里面注意下面两个配置!这里我会根据不同的分支做不同的处理的(高亮的部分)!!!一个是运行空间!一个是版本号!!!

  • namespace: RUN_ENV
  • image: harbor.tf.cn/tfcloud/zeus:Image_Version
apiVersion: v1
kind: Service
metadata:
  name: zeus-svc
  namespace: RUN_ENV
spec:
  type: NodePort
  selector:
    run: zeus
  ports:
  - protocol: TCP
    # nodePort: 30020
    port: 9090
    targetPort: 9090
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: zeus
  namespace: RUN_ENV
spec:
  replicas: 3
  template:
    metadata:
      labels:
        run: zeus
    spec:
      containers:
      - name: zeus
        image: harbor.tf.cn/tfcloud/zeus:Image_Version
        ports:
        - containerPort: 9090

部署脚本

这个没啥好介绍的,说白了就一句话

kubectl apply -f kube_zeus.yml

kubectl

kubectl是操作k8s集群的工具,我这里使用的是docker中运行的,我自己打包了一个docker镜像 地址

回炉.gitlab-ci.yml文件

写的很啰嗦,直接上了,细节有注释!!!

image: imscc/alpine_go:sslocal

stages:
  - build
  - release
  - deploy

# 编译develop分支
build-develop:
  stage: build
  only:
    - develop
  except:
    - master
  script:
    - mkdir -p /go/src/github.com/$CI_PROJECT_NAMESPACE
    - cd /go/src/github.com/$CI_PROJECT_NAMESPACE
    - ln -s $CI_PROJECT_DIR
    - cd $CI_PROJECT_NAME
    # 写go的人都知道在编译的时候有时候会需要依赖,下载依赖的时候可能会背墙
    # 所以我这里打包了一个shadowsocks的golang编译环境,不过前提是你已经部署了代理服务
    # 配置shadowsocks代理
    # - sslocal -s ip地址  -p 端口    -l 1080 -k  密码  -t 600 -m 加密协议 &
    # - polipo &
    # - export http_proxy=localhost:8123
    # - export ALL_PROXY=$http_proxy
    # - sleep 3
    # - go get ./...
    - go build -o zeus
    - cd $CI_PROJECT_DIR
  artifacts:
    name: binary-files
    paths:
    - ./zeus
  tags:
    - develop
    - master

# 编译master分支    
build-master:
  stage: build
  only:
    - master
  except:
    - develop
  script:
    - mkdir -p /go/src/github.com/$CI_PROJECT_NAMESPACE
    - cd /go/src/github.com/$CI_PROJECT_NAMESPACE
    - ln -s $CI_PROJECT_DIR
    - cd $CI_PROJECT_NAME
    # - sslocal -s ip地址  -p 端口    -l 1080 -k  密码  -t 600 -m 加密协议 &
    # - polipo &
    # - export http_proxy=localhost:8123
    # - export ALL_PROXY=$http_proxy
    # - sleep 3
    # - go get ./...
    - go build -o zeus
    - cd $CI_PROJECT_DIR
  artifacts:
    name: binary-files
    paths:
    - ./zeus
  tags:
    - develop
    - master

# 打包develop镜像
release-develop:
  image: docker
  stage: release
  only:
    - develop
  except:
    - master
  script:
    - echo "hi , release !"
    - ls .
    - docker info
    # 这里的变量配置参考前面文章
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD https://harbor.tf.cn
    # CI_COMMIT_SHA是提交的sha值,我用来做版本号了!
    - docker build --pull -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker rmi $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  tags:
    - develop
    - master

# 打包master镜像
release-master:
  image: docker
  stage: release
  only:
    - master
  except:
    - develop
  script:
    - echo "hi , release !"
    - ls .
    - docker info
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD https://harbor.tf.cn
    - docker build --pull -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker rmi $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  tags:
    - develop
    - master

# 部署develop环境
deploy-develop-kubernetes:
  stage: deploy
  image: imscc/alpine:latest
  only:
    - develop
  except:
    - master
  script:
    - mkdir /root/.kube
    - cp ./config /root/.kube/
    - kubectl cluster-info
    # 这里一定要用双引号,不然$不会生效!
    - sed -i "s/RUN_ENV/develop/g" kube_zeus.yml
    - sed -i "s/Image_Version/$CI_COMMIT_SHA/g" kube_zeus.yml
    - cat kube_zeus.yml
    - kubectl apply -f kube_zeus.yml
  tags:
    - develop
    - master

# 部署master环境
deploy-master-kubernetes:
  stage: deploy
  image: imscc/alpine:latest
  only:
    - master
  except:
    - develop
  script:
    - mkdir /root/.kube
    - cp ./config /root/.kube/
    - kubectl cluster-info
    # 这里一定要用双引号,不然$不会生效!
    - sed -i "s/RUN_ENV/master/g" kube_zeus.yml
    - sed -i "s/Image_Version/$CI_COMMIT_SHA/g" kube_zeus.yml
    - cat kube_zeus.yml
    - kubectl apply -f kube_zeus.yml
  tags:
    - develop
    - master

提交测试

在测试之前现在k8s环境创建测试空间

kubectl create namespace master
kubectl create namespace develop
➜  zeus git:(develop) git push origin  develop
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 284 bytes | 284.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote:
remote: To create a merge request for develop, visit:
remote:   http://10.100.7.46:8088/tfcloud/zeus/merge_requests/new?merge_request%5Bsource_branch%5D=develop
remote:
To http://10.100.7.46:8088/tfcloud/zeus.git
   7c035e8..ccaad31  develop -> develop

部署develop

➜  zeus git:(develop) kubectl get service -n develop
NAME       TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
zeus-svc   NodePort   10.43.106.4   <none>        9090:30020/TCP   5m

➜  zeus git:(develop) curl 10.100.7.45:30020

Hello Wrold!%

同样把代码合并到master上,看看效果

部署master

➜  zeus git:(master) kubectl get service -n master
NAME       TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
zeus-svc   NodePort   10.43.243.171   <none>        9090:31642/TCP   30s
➜  zeus git:(master) curl 10.100.7.45:31642
Hello Wrold!%

好了,本文基本结束!本篇文章是前面几篇的基础上总结了一下!要成功还是要认真看下前面几篇文章的,祝你好运!!!!

See Also

Wed Sep 5, 2018

2400 Words|Read in about 5 Min
Tags: devops