基於Kubernetes Gitlab CICD

原文:https://i4t.com/4373.htmlphp


在大多數狀況,構建項目都會佔用大量的系統資源,若是讓gitlab自己來運行構建任務的話,顯然Gitlab的性能會大幅度降低。gitlab ci最大的做用就是管理各個項目的構建狀態,所以,運行構建任務這種浪費資源的事情交給一個獨立的gitlab runner來作就會好不少,更重要的是gitlab runner能夠安裝到不一樣的機器上,甚至是咱們本機,這樣徹底就不會影響Gitlab自己了。html

從gitlab8.0開始,gitlab CI就已經集成在Gitlab中,咱們只須要在項目中添加一個.gitlab-ci.yaml文件,而後運行一個Runner,便可進行持續集成。node

什麼是Runner?
Gitlab Runner是一個開源項目,用於運行您的做業並將結果發送給gitlab。它與Gitlab CI結合使用,gitlab ci是Gitlab隨附的用於協調做用的開源持續集成服務。git

Gitlab Runner是用Go編寫的,能夠做爲一個二進制文件運行,不須要特定於語言的要求
它皆在GNU/Linux,MacOS和Windows操做系統上運行。若是要使用Docker,Gitlab Runner須要最少Docker v1.13.0golang

image_1dlm944o51fvmi72kfc1jrke6f5h.png-298.8kB

本文項目演示圖redis

A7624C76-2F87-48C1-837B-CCD55AB35584.png-178kB


Gitlab 安裝

gitlab官方提供了Helm的方式在Kubernetes集羣中來快速安裝,可是在使用的過程當中發現Helm提供的Chart包中有不少其餘額外的配置,因此咱們這裏自定義的方式來安裝,也就是本身來自定義一些資源清單文件。sql

gitlab主要涉及3個應用:Redis、Postgresql、Gitlab核心程序docker

部署服務也能夠在不跑在容器上,不影響gitlab的cicd。我這裏使用k8s安裝gitlab,而且沒有使用持久化存儲,若是想使用持久化存儲能夠在參考一下 prometheus搭建的文章

建立命名空間數據庫

kubectl create namespace kube-ops

首先須要先部署Redis服務 (gitlab-redis.yaml)vim

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: redis
  namespace: kube-ops
  labels:
    name: redis
spec:
  template:
    metadata:
      name: redis
      labels:
        name: redis
    spec:
      containers:
      - name: redis
        image: sameersbn/redis
        imagePullPolicy: IfNotPresent
        ports:
        - name: redis
          containerPort: 6379
        volumeMounts:
        - mountPath: /var/lib/redis
          name: data
        livenessProbe:
          exec:
            command:
            - redis-cli
            - ping
          initialDelaySeconds: 30
          timeoutSeconds: 5
        readinessProbe:
          exec:
            command:
            - redis-cli
            - ping
          initialDelaySeconds: 5
          timeoutSeconds: 1
      volumes:
      - name: data
        emptyDir: {}

---
apiVersion: v1
kind: Service
metadata:
  name: redis
  namespace: kube-ops
  labels:
    name: redis
spec:
  ports:
    - name: redis
      port: 6379
      targetPort: redis
  selector:
    name: redis

數據庫Postgresql部署 (gitlab-postgresql.yaml)

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: postgresql
  namespace: kube-ops
  labels:
    name: postgresql
spec:
  template:
    metadata:
      name: postgresql
      labels:
        name: postgresql
    spec:
      containers:
      - name: postgresql
        image: sameersbn/postgresql:10
        imagePullPolicy: IfNotPresent
        env:
        - name: DB_USER
          value: gitlab
        - name: DB_PASS
          value: passw0rd
        - name: DB_NAME
          value: gitlab_production
        - name: DB_EXTENSION
          value: pg_trgm
        ports:
        - name: postgres
          containerPort: 5432
        volumeMounts:
        - mountPath: /var/lib/postgresql
          name: data
        livenessProbe:
          exec:
            command:
            - pg_isready
            - -h
            - localhost
            - -U
            - postgres
          initialDelaySeconds: 30
          timeoutSeconds: 5
        readinessProbe:
          exec:
            command:
            - pg_isready
            - -h
            - localhost
            - -U
            - postgres
          initialDelaySeconds: 5
          timeoutSeconds: 1
      volumes:
      - name: data
        emptyDir: {}

---
apiVersion: v1
kind: Service
metadata:
  name: postgresql
  namespace: kube-ops
  labels:
    name: postgresql
spec:
  ports:
    - name: postgres
      port: 5432
      targetPort: postgres
  selector:
    name: postgresql

gitlab應用配置以下 (gitlab.yaml)

這裏沒有使用官方的鏡像倉庫,而是使用第三方
http://www.damagehead.com/doc...
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: gitlab
  namespace: kube-ops
  labels:
    name: gitlab
spec:
  template:
    metadata:
      name: gitlab
      labels:
        name: gitlab
    spec:
      containers:
      - name: gitlab
        image: sameersbn/gitlab:11.8.1
        imagePullPolicy: IfNotPresent
        env:
        - name: TZ
          value: Asia/Shanghai
        - name: GITLAB_TIMEZONE
          value: Beijing
        - name: GITLAB_SECRETS_DB_KEY_BASE
          value: long-and-random-alpha-numeric-string
        - name: GITLAB_SECRETS_SECRET_KEY_BASE
          value: long-and-random-alpha-numeric-string
        - name: GITLAB_SECRETS_OTP_KEY_BASE
          value: long-and-random-alpha-numeric-string
        - name: GITLAB_ROOT_PASSWORD
          value: admin321
        - name: GITLAB_ROOT_EMAIL
          value: 381493251@qq.com
        - name: GITLAB_HOST
          value: 10.4.82.135:30004
        - name: GITLAB_PORT
          value: "80"
        - name: GITLAB_SSH_PORT
          value: "22"
        - name: GITLAB_NOTIFY_ON_BROKEN_BUILDS
          value: "true"
        - name: GITLAB_NOTIFY_PUSHER
          value: "false"
        - name: GITLAB_BACKUP_SCHEDULE
          value: daily
        - name: GITLAB_BACKUP_TIME
          value: 01:00
        - name: DB_TYPE
          value: postgres
        - name: DB_HOST
          value: postgresql
        - name: DB_PORT
          value: "5432"
        - name: DB_USER
          value: gitlab
        - name: DB_PASS
          value: passw0rd
        - name: DB_NAME
          value: gitlab_production
        - name: REDIS_HOST
          value: redis
        - name: REDIS_PORT
          value: "6379"
        ports:
        - name: http
          containerPort: 80
        - name: ssh
          containerPort: 22
        volumeMounts:
        - mountPath: /home/git/data
          name: data
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 180
          timeoutSeconds: 5
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          timeoutSeconds: 1
      volumes:
      - name: data
        emptyDir: {}

---
apiVersion: v1
kind: Service
metadata:
  name: gitlab
  namespace: kube-ops
  labels:
    name: gitlab
spec:
  type: NodePort
  ports:
    - name: http
      port: 80
      targetPort: http
      nodePort: 30004
    - name: ssh
      port: 22
      targetPort: ssh
  selector:
    name: gitlab


################
GITLAB_HOST = 這裏的域名是咱們Git clone代碼的域名,我這裏直接使用svc+port進行演示

接下來進行部署,須要提早建立好命名空間,上面咱們已經建立了

kubectl apply -f .
deployment.apps/postgresql created
service/postgresql created
deployment.apps/redis created
service/redis created
deployment.apps/gitlab created
service/gitlab created

檢查pod和svc運行情況

[root@abcdocker gitlab]# kubectl get pod,svc -n kube-ops
NAME                              READY   STATUS    RESTARTS   AGE
pod/gitlab-57cf47cd7d-cfpmn       0/1     Running   1          5m14s
pod/postgresql-7c6bf8974d-r9djh   1/1     Running   0          5m19s
pod/redis-c45ffd79b-75vbd         1/1     Running   0          5m17s

NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                    AGE
service/gitlab       NodePort    10.254.212.182   <none>        80:30004/TCP,22:8530/TCP   5m11s
service/postgresql   ClusterIP   10.254.255.216   <none>        5432/TCP                   5m18s
service/redis        ClusterIP   10.254.83.148    <none>        6379/TCP                   5m15s

這裏我採用的是nodePort的方式,而後咱們直接訪問節點任意IP+30004端口便可訪問 (若是pod沒有報錯,耐心等待一會就能夠訪問了)

用戶名: root
密碼:admin321
用戶名和密碼配置在gitlab配置文件中!

123.png-202.8kB

接下來建立個項目要進行演示

image_1dllo23au1bqg1f3oghpfio1r073a.png-159.9kB
image_1dllo35t01gfhh5i1b251tkbpsc3n.png-343.2kB

接下來添加提交代碼
如何提交代碼我這裏就不詳細介紹了,項目的REDME也提示咱們了

image_1dllo72evptg1rka17hv1g901pq844.png-240.8kB

[root@abcdocker tmp]# git clone http://10.4.82.135:30004/root/abcdocker.git
正克隆到 'abcdocker'...
Username for 'http://10.4.82.135:30004': root
Password for 'http://root@10.4.82.135:30004':
warning: 您彷佛克隆了一個空版本庫。

wget http://down.i4t.com/abcdocker-gitlab-demo.tar.gz

#git代碼提交
git add *
git add .* (記得提交隱藏文件)
git commit -m "abcdocker"
git push -u origin master

Gitlab Runner 安裝

gitlab runner支持多種方式安裝,我這裏就採起在k8s中安裝。

官方文檔地址: https://docs.gitlab.com/runne...

image_1dlm9cmqti6p1guq7h4aqe7n6e.png-209.9kB

首先咱們須要檢查一下k8s集羣的狀態

[root@abcdocker ~]# kubectl cluster-info
Kubernetes master is running at https://10.4.82.139:8443
CoreDNS is running at https://10.4.82.139:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

接下來咱們打開gitlab地址

以下圖所示,左邊表明runner狀態,右邊是配置runner信息
image_1dlma89l83erat1u6urk1hfq7a.png-359.8kB

接下來進行配置gitlab runner資源清單 (runner-configmap.yaml)

apiVersion: v1
data:
  REGISTER_NON_INTERACTIVE: "true"
  REGISTER_LOCKED: "false"
  METRICS_SERVER: "0.0.0.0:9100"
  CI_SERVER_URL: "http://gitlab.kube-ops.svc.cluster.local/ci"
  RUNNER_REQUEST_CONCURRENCY: "4"
  RUNNER_EXECUTOR: "kubernetes"
  KUBERNETES_NAMESPACE: "kube-ops"
  KUBERNETES_PRIVILEGED: "true"
  KUBERNETES_CPU_LIMIT: "1"
  KUBERNETES_CPU_REQUEST: "500m"
  KUBERNETES_MEMORY_LIMIT: "1Gi"
  KUBERNETES_SERVICE_CPU_LIMIT: "1"
  KUBERNETES_SERVICE_MEMORY_LIMIT: "1Gi"
  KUBERNETES_HELPER_CPU_LIMIT: "500m"
  KUBERNETES_HELPER_MEMORY_LIMIT: "100Mi"
  KUBERNETES_PULL_POLICY: "if-not-present"
  KUBERNETES_TERMINATIONGRACEPERIODSECONDS: "10"
  KUBERNETES_POLL_INTERVAL: "5"
  KUBERNETES_POLL_TIMEOUT: "360"
kind: ConfigMap
metadata:
  labels:
    app: gitlab-ci-runner
  name: gitlab-ci-runner-cm
  namespace: kube-ops
  • CI_SERVER_URL 這個地址是gitlab的地址,若是gitlab在宿主機直接寫宿主機的ip便可,容器是格式爲svc名稱.命名空間.svc.cluster.local (若是都按照個人文檔來進行安裝不須要修改別的配置了)

若是定義的gitlab域名並非經過外網DNS解析,而是經過/etc/hosts進行映射,那麼咱們須要在Runner的Pod中去添加對應的hosts(我這裏使用的是ip+端口)。咱們須要經過--pre-clone-script參數來指定一段腳原本添加hosts信息,也就是在ConfigMap中添加環境變量RUNNER_PRE_CLONE_SCRIPT的值

RUNNER_PRE_CLONE_SCRIPT = "echo 'xx.xx.xxx.xx git.i4t.com' >> /etc/hosts"
注意: 在ConfigMap添加新選項後,須要刪除Gitlab ci Runner Pod
由於咱們使用envFrom來注入上面的這些環境變量而不是直接使用 env(envfrom 經過將環境變量放置到ConfigMaps或Secrets來幫助減少清單文件)

若是咱們想添加其餘選項,能夠在Pod中運行gitlab-ci-multi-runner register --help 命令來查看全部可以使用的選項,只須要爲配置的標誌添加env變量便可

gitlab-runner@gitlab-ci-runner-0:/$ gitlab-ci-multi-runner register --help
[...]
--kubernetes-cpu-limit value                          The CPU allocation given to build containers (default: "1") [$KUBERNETES_CPU_LIMIT]
--kubernetes-memory-limit value                       The amount of memory allocated to build containers (default: "4Gi") [$KUBERNETES_MEMORY_LIMIT]
--kubernetes-service-cpu-limit value                  The CPU allocation given to build service containers (default: "1") [$KUBERNETES_SERVICE_CPU_LIMIT]
--kubernetes-service-memory-limit value               The amount of memory allocated to build service containers (default: "1Gi") [$KUBERNETES_SERVICE_MEMORY_LIMIT]
--kubernetes-helper-cpu-limit value                   The CPU allocation given to build helper containers (default: "500m") [$KUBERNETES_HELPER_CPU_LIMIT]
--kubernetes-helper-memory-limit value                The amount of memory allocated to build helper containers (default: "3Gi") [$KUBERNETES_HELPER_MEMORY_LIMIT]
--kubernetes-cpu-request value                        The CPU allocation requested for build containers [$KUBERNETES_CPU_REQUEST]
...
--pre-clone-script value                              Runner-specific command script executed before code is pulled [$RUNNER_PRE_CLONE_SCRIPT]
[...]

建立

[root@abcdocker gitlab]# kubectl apply -f runner-configmap.yaml
configmap/gitlab-ci-runner-cm created

[root@abcdocker gitlab]# kubectl get configmaps  -n kube-ops
NAME                  DATA   AGE
gitlab-ci-runner-cm   19     12s

咱們還須要配置一個用於註冊、運行和取消gitlab ci runner的小腳本。只有當Pod正常經過Kubernetes (TERM信號)終止時,纔會觸發註銷註冊。若是強行終止Pod(SIGKILL信號),Runner將不會本身註銷自身。必須手動完成對這種Runner的清理 (二進制安裝非K8s上不受這個影響)

(runner-scripts-cm.yaml)

apiVersion: v1
data:
  run.sh: |
    #!/bin/bash
    unregister() {
        kill %1
        echo "Unregistering runner ${RUNNER_NAME} ..."
        /usr/bin/gitlab-ci-multi-runner unregister -t "$(/usr/bin/gitlab-ci-multi-runner list 2>&1 | tail -n1 | awk '{print $4}' | cut -d'=' -f2)" -n ${RUNNER_NAME}
        exit $?
    }
    trap 'unregister' EXIT HUP INT QUIT PIPE TERM
    echo "Registering runner ${RUNNER_NAME} ..."
    /usr/bin/gitlab-ci-multi-runner register -r ${GITLAB_CI_TOKEN}
    sed -i 's/^concurrent.*/concurrent = '"${RUNNER_REQUEST_CONCURRENCY}"'/' /home/gitlab-runner/.gitlab-runner/config.toml
    echo "Starting runner ${RUNNER_NAME} ..."
    /usr/bin/gitlab-ci-multi-runner run -n ${RUNNER_NAME} &
    wait
kind: ConfigMap
metadata:
  labels:
    app: gitlab-ci-runner
  name: gitlab-ci-runner-scripts
  namespace: kube-ops

建立

[root@abcdocker gitlab]# kubectl apply -f runner-scripts-cm.yaml
configmap/gitlab-ci-runner-scripts created

咱們須要建立一個GITLAB_CI_TOKEN,而後咱們使用gitlab ci runner token來建立一個Kubernetes secret對象。須要提早對token進行base64轉碼

[root@abcdocker gitlab]# echo BMxb1ezMiTYFxtZTsVxP|base64 -w0
Qk14YjFlek1pVFlGeHRaVHNWeFAK
這裏的token就是咱們gitlab runner上截圖的地方,base64只有在k8s環境上須要

以下圖
image_1dlmgfl3pqe1ghk1sdd18hgmcb8n.png-89.1kB

接下來使用上面的token建立一個Sercret對象 (gitlab-ci-token-secret.yaml)

[root@abcdocker gitlab]# cat gitlab-ci-token-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: gitlab-ci-token
  namespace: kube-ops
  labels:
    app: gitlab-ci-runner
data:
  GITLAB_CI_TOKEN: Qk14YjFlek1pVFlGeHRaVHNWeFAK

建立

[root@abcdocker gitlab]# kubectl apply -f gitlab-ci-token-secret.yaml
secret/gitlab-ci-token created

接下來建立真正運行Runner的控制器鏡像,這裏使用Statefulset,在開始運行的時候,嘗試取消註冊全部的同名Runner,當節點丟失時(即NodeLost事件),這尤爲有用,而後再嘗試註冊本身並開始運行。在正常中止Pod的時候,Runner將會運行unregister命令來嘗試取消本身,因此gitlab就不能再使用這個Runner,這個則是經過kubernetes Pod生命週期中的hooks來完成的

runner-statefulset.yaml

apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: gitlab-ci-runner
  namespace: kube-ops
  labels:
    app: gitlab-ci-runner
spec:
  updateStrategy:
    type: RollingUpdate
  replicas: 2
  serviceName: gitlab-ci-runner
  template:
    metadata:
      labels:
        app: gitlab-ci-runner
    spec:
      volumes:
      - name: gitlab-ci-runner-scripts
        projected:
          sources:
          - configMap:
              name: gitlab-ci-runner-scripts
              items:
              - key: run.sh
                path: run.sh
                mode: 0755
      serviceAccountName: gitlab-ci
      securityContext:
        runAsNonRoot: true
        runAsUser: 999
        supplementalGroups: [999]
      containers:
      - image: gitlab/gitlab-runner:latest
        name: gitlab-ci-runner
        command:
        - /scripts/run.sh
        envFrom:
        - configMapRef:
            name: gitlab-ci-runner-cm
        - secretRef:
            name: gitlab-ci-token
        env:
        - name: RUNNER_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        ports:
        - containerPort: 9100
          name: http-metrics
          protocol: TCP
        volumeMounts:
        - name: gitlab-ci-runner-scripts
          mountPath: "/scripts"
          readOnly: true
      restartPolicy: Always

上面咱們命名了一個gitlab-ci的serviceAccount,這裏要新建一個rbac文件 (runner-rbac.yaml)

apiVersion: v1
kind: ServiceAccount
metadata:
  name: gitlab-ci
  namespace: kube-ops
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: gitlab-ci
  namespace: kube-ops
rules:
  - apiGroups: [""]
    resources: ["*"]
    verbs: ["*"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: gitlab-ci
  namespace: kube-ops
subjects:
  - kind: ServiceAccount
    name: gitlab-ci
    namespace: kube-ops
roleRef:
  kind: Role
  name: gitlab-ci
  apiGroup: rbac.authorization.k8s.io

建立完畢

[root@abcdocker gitlab]# kubectl apply -f runner-rbac.yaml
serviceaccount/gitlab-ci created
role.rbac.authorization.k8s.io/gitlab-ci created
rolebinding.rbac.authorization.k8s.io/gitlab-ci created
[root@abcdocker gitlab]# kubectl apply -f runner-statefulset.yaml
statefulset.apps/gitlab-ci-runner created

接下來咱們檢查咱們建立的

[root@abcdocker gitlab]# kubectl get pod,svc,cm -n kube-ops
NAME                              READY   STATUS    RESTARTS   AGE
pod/gitlab-57cf47cd7d-cfpmn       1/1     Running   1          47h
pod/gitlab-ci-runner-0            1/1     Running   0          2m51s
pod/gitlab-ci-runner-1            1/1     Running   0          119s
pod/postgresql-7c6bf8974d-r9djh   1/1     Running   0          47h
pod/redis-c45ffd79b-75vbd         1/1     Running   0          47h

NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                    AGE
service/gitlab       NodePort    10.254.212.182   <none>        80:30004/TCP,22:8530/TCP   47h
service/postgresql   ClusterIP   10.254.255.216   <none>        5432/TCP                   47h
service/redis        ClusterIP   10.254.83.148    <none>        6379/TCP                   47h

NAME                                 DATA   AGE
configmap/gitlab-ci-runner-cm        19     150m
configmap/gitlab-ci-runner-scripts   1      78m


#目前pod gitlab-ci-runner0和1都已經屬於正常的運行狀態

此時咱們查看gitlab中的Runners就已經將這2個pod節點添加進來了

這裏咱們也能夠更改Runner的一些配置,好比添加tag標籤等

123.png-334.7kB


gitlab CICD 配置

首先咱們須要有一個項目,接下來咱們進行gitlab配置演示

#項目下載
wget http://down.i4t.com/gitlab-ci-k8s-demo.tar.gz  #須要修改
須要各位本身進行配置gitlab,新建一個項目並上傳。詳細步驟這裏再也不介紹

若是項目裏面有勾選Auto DevOps記得取消,對咱們的cicd會有影響
image_1dlu1qh731viml6v1vho1qem12iib9.png-252.1kB

項目介紹
本次環境使用的是go環境,只是爲了演示。Java和php的構建方式也差很少相同。初次演示能夠經過個人模板進行演示

image_1dlu3cathjm3c681esr3051eu2cj.png-143.3kB

這裏其實是引用了相似於Jenkins pipline的腳本格式

gitlab-ci.yaml介紹

image:
  name: golang:1.10.3-stretch    #這裏的全局鏡像就是當下面的stage裏面沒有定義鏡像時,使用的就是這裏全局的鏡像地址。可是當咱們指定鏡像時,就不會使用全局變量
  entrypoint: ["/bin/sh", "-c"]

# The problem is that to be able to use go get, one needs to put
# the repository in the $GOPATH. So for example if your gitlab domain
# is mydomainperso.com, and that your repository is repos/projectname, and
# the default GOPATH being /go, then you'd need to have your
# repository in /go/src/mydomainperso.com/repos/projectname
# Thus, making a symbolic link corrects this.
before_script:    #在咱們的go環境中,默認的go path是在咱們go的目錄下面,因此咱們要在go目錄下面建立一個src。至關於咱們項目中的一個地址 。而後咱們將項目地址ln到咱們的go path地址中去
  - mkdir -p "/go/src/git.qikqiak.com/${CI_PROJECT_NAMESPACE}"
  - ln -sf "${CI_PROJECT_DIR}" "/go/src/git.i4t.com/${CI_PROJECT_PATH}"
  - cd "/go/src/git.i4t.com/${CI_PROJECT_PATH}/"

stages:             ##這裏stages表明一個項目,每一個名稱下面能夠建立一個或多個任務,而且是同時執行的。前面是stages執行完畢後纔會執行下一個
  - test
  - build
  - release
  - review
  - deploy

test1:
  stage: test       #這裏經過stage進行匹配任務標籤,而且test1和test2是屬於隊形操做,並非串行操做
  script:
    - make test

test2:
  stage: test
  script:
    - sleep 3
    - echo "We did it! Something else runs in parallel!"

compile:      #這build階段執行一個compile任務
  stage: build           #當咱們上面test執行完畢後,就會開始執行build操做
  script:      #經過script執行一個具體的命令,這裏是進行make build操做
    # Add here all the dependencies, or use glide/govendor/...
    # to get them automatically.
    - make build     #這裏的build是在咱們build咱們Makefile裏面的腳本,固然也能夠修改其餘成命令
  artifacts:     #這裏的就是將咱們build的一個值掛載一下,能夠到下面的job進行獲取,咱們在瀏覽器上也能夠獲取到這個文件,能夠直接下載。至關於將app這個標籤的文件暴露出來
    paths:
      - app

image_build:       #這裏到了release階段,作了一個imageBuild操做(這裏指的就是鏡像構建)這裏使用docker build就須要docker命令
  stage: release
  image: docker:latest   #這裏的鏡像就是使用docker的鏡像,這個鏡像是提供了一個docker命令,當咱們docker build的時候須要將全部的文件提交到一個docker daemon裏面去作的一個構建工做。因此這裏還須要一個service,來指定docker所依賴的服務。下面咱們就引用了一個docker in docker的一個鏡像。這個service實際上就是咱們docker鏡像所依賴的一個服務,若是咱們還依賴其餘鏡像,直接在下面添加就能夠了
  variables:          #這裏的配置主要是指定docker的一個host
    DOCKER_DRIVER: overlay
    DOCKER_HOST: tcp://localhost:2375
  services:      #這裏就是表明咱們service暴露的端口就是2375,至關於將咱們docker的客戶端和service關聯起來了。這樣當咱們執行docker build的命令就會調用咱們的docker daemon來進行一個build的操做
    - name: docker:17.03-dind
      command: ["--insecure-registry=registry.i4t.com"]   #這裏能夠寫私有倉庫,可是爲了演示,我這裏直接修改成公有倉庫,若是這裏不寫倉庫地址會出現509的錯誤
  script:   #這裏就是執行一個真正的腳本,來進行build一個操做
    - docker info
    - docker login -u "${CI_REGISTRY_USER}" -p "${CI_REGISTRY_PASSWORD}" registry.i4t.com   #這裏的用戶名密碼不方便寫死,因此這裏寫成變量。在gitlab項目中進行添加配置
    - docker build -t "${CI_REGISTRY_IMAGE}:latest" .
    - docker tag "${CI_REGISTRY_IMAGE}:latest" "${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_NAME}"    #須要說明一點,這裏的ci_commit_ref_name實際上就是gitlab commit版本號,在以前的jenkins中已經使用過不少次,具體不詳細介紹(須要請點擊i4t.com找jenkins文檔)
    - test ! -z "${CI_COMMIT_TAG}" && docker push "${CI_REGISTRY_IMAGE}:latest"
    - docker push "${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_NAME}"

deploy_review:        #這裏這一個預覽環境,至關於開發環境。 
  image: registry.cn-beijing.aliyuncs.com/abcdocker/k8s:kubectl     #這裏的image是一個kubectl的命令,這個鏡像實際上就是內置了一個二進制的kubectl命令,可是咱們知道若是咱們想使用kubectl命令是須要提供apiserver的一些相關配置,才能夠鏈接到咱們的kubernetes集羣
  stage: review
  only:
    - branches   #只有提交到咱們的gitlab指定的分支上,纔會執行咱們的這個job任務。若是提交的是tag上來,是不會觸發咱們的任務的
  except:
    - tags
  environment:    #這裏咱們定義了一個環境,而且在裏面定義了一個url。這樣當咱們觸發了review job,咱們能夠經過下面的域名進行訪問
    name: dev
    url: https://dev-gitlab-k8s-demo.i4t.com   #這裏的若是安裝了Traefik能夠直接綁定host或者經過dns進行配置,也能夠是svc
    on_stop: stop_review    #這裏咱們添加了一個回調,當咱們中止咱們dev環境時去作的一件事情(這裏的stop_review在下面進行查看)
  script:   #這裏的命令就是替換常常鏡像版本號的一些操做,deployment等相關文件都須要提交的gitlab上
    - kubectl version
    - cd manifests/
    - sed -i "s/__CI_ENVIRONMENT_SLUG__/${CI_ENVIRONMENT_SLUG}/" deployment.yaml ingress.yaml service.yaml
    - sed -i "s/__VERSION__/${CI_COMMIT_REF_NAME}/" deployment.yaml ingress.yaml service.yaml
    - |
      if kubectl apply -f deployment.yaml | grep -q unchanged; then
          echo "=> Patching deployment to force image update."
          kubectl patch -f deployment.yaml -p "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"ci-last-updated\":\"$(date +'%s')\"}}}}}"
      else
          echo "=> Deployment apply has changed the object, no need to force image update."
      fi
    - kubectl apply -f service.yaml || true
    - kubectl apply -f ingress.yaml
    - kubectl rollout status -f deployment.yaml
    - kubectl get all,ing -l ref=${CI_ENVIRONMENT_SLUG}

stop_review:   #這裏就是上面review中引用的stop_review。中止前作的一件事情
  image: registry.cn-beijing.aliyuncs.com/abcdocker/k8s:kubectl
  stage: review
  variables:
    GIT_STRATEGY: none
  when: manual
  only:         #這裏除了咱們的master分支和tag,其餘的分支均可以進行一個branches job任務
    - branches
  except:
    - master
    - tags
  environment:
    name: dev   #這裏的環境也是dev
    action: stop   #執行的動做,這裏表明執行stop動做
  script:     #這裏執行的命令就是將以前構建的項目中的鏡像及相關配置都進行刪除的一個操做
    - kubectl version  
    - kubectl delete ing -l ref=${CI_ENVIRONMENT_SLUG}    #這裏經過ref標籤進行匹配刪除(這裏中的環境配置都是在咱們manifests目錄中引用)
    - kubectl delete all -l ref=${CI_ENVIRONMENT_SLUG}

deploy_live:      #這裏是真正的deploy階段,真正去部署(這裏是定義了一個deploy_live的任務)
  image: registry.cn-beijing.aliyuncs.com/abcdocker/k8s:kubectl  #這裏仍是使用的kubectl命令
  stage: deploy
  environment:    #這裏定義了一個標籤爲live的一個線上環境
    name: live
    url: https://live-gitlab-k8s-demo.i4t.com   #這裏就是部署完成以後線上的一個地址
  only:
    - tags    #只有咱們提交一個tag標籤的時候,纔會執行job任務
  when: manual   #這裏的參數表明手動的進行執行
  script:   #下面的命令操做和前面的dev環境中配置的命令是同樣的,實際上就是一個替換鏡像的一個操做
    - kubectl version
    - cd manifests/
    - sed -i "s/__CI_ENVIRONMENT_SLUG__/${CI_ENVIRONMENT_SLUG}/" deployment.yaml ingress.yaml service.yaml
    - sed -i "s/__VERSION__/${CI_COMMIT_REF_NAME}/" deployment.yaml ingress.yaml service.yaml
    - kubectl apply -f deployment.yaml
    - kubectl apply -f service.yaml
    - kubectl apply -f ingress.yaml
    - kubectl rollout status -f deployment.yaml
    - kubectl get all,ing -l ref=${CI_ENVIRONMENT_SLUG}

如今咱們要配置一下kubectl,默認狀況下kubectl須要使用證書才能夠鏈接到k8s集羣。在服務器上默認使用的是/root/.kube/config,gitlab 也有添加證書的位置,咱們進行添加配置

1111.png-244.4kB

點擊添加集羣

image_1dmsvht9cnhv1rsc15k31g1g93l1u.png-124.1kB

這裏簡單說一下

Kubernetes cluster name 集羣名稱能夠隨便寫
API URL 這裏實際上就是apiserver地址,經過kubectl cluster-info查看到

CA TOken能夠經過/root/.kube/config裏面獲取到,也可使用下面的方式獲取到

獲取證書token等相關配置

#除了使用/root/.kube/config獲取還能夠經過 獲取

#這裏先建立一個命名空間

kubectl create ns gitlab

#由於在操做的時候會涉及rbac權限的問題,這裏要建立一個rbac的文件。咱們將集羣的cluster的權限綁定到ServerAccount
[root@yzsjhl82-135 ~]# cat gitlabdemo-sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: gitlab
  namespace: gitlab

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: gitlab
subjects:
  - kind: ServiceAccount
    name: gitlab
    namespace: gitlab
roleRef:
    apiGroup: rbac.authorization.k8s.io
    kind: ClusterRole
    name: cluster-admin
cluster-admin是內置的一個角色,擁有集羣全部權限的一個角色

而後咱們進行建立

[root@abcdocker ~]# kubectl create ns gitlab
[root@abcdocker ~]# kubectl apply -f gitlabdemo-sa.yaml
serviceaccount/gitlab unchanged
clusterrolebinding.rbac.authorization.k8s.io/gitlab created

[root@abcdocker ~]# kubectl get sa -n gitlab
NAME      SECRETS   AGE
default   1         74m
gitlab    1         3m10s

咱們建立的serviceaccount實際上就是一個secret,接下來咱們進行獲取token和ca

[root@abcdocker ~]# kubectl get secret -n gitlab
NAME                  TYPE                                  DATA   AGE
default-token-pmlvw   kubernetes.io/service-account-token   3      112m
gitlab-token-5cgx2    kubernetes.io/service-account-token   3      40m

[root@abcdocker ~]# kubectl get secrets gitlab-token-5cgx2 -n gitlab -o yaml
apiVersion: v1
data:
  ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR4akNDQXE2Z0F3SUJBZ0lVR29Balg2cGdQVUJkL1ZEU2RrbzlvOFR5ckQwd0RRWUpLb1pJaHZjTkFRRUwKQlFBd2FERUxNQWtHQTFVRUJoTUNRMDR4RURBT0JnTlZCQWdUQjBKbGFVcHBibWN4RURBT0JnTlZCQWNUQjBKbAphVXBwYm1jeEREQUtCZ05WQkFvVEEyczRjekVTTUJBR0ExVUVDeE1KTkZCaGNtRmthV2R0TVJNd0VRWURWUVFECkV3cHJkV0psY201bGRHVnpNQ0FYRFRFNU1EZ3lOakV6TURNd01Gb1lEekl4TVRrd09EQXlNVE13TXpBd1dqQm8KTVFzd0NRWURWUVFHRXdKRFRqRVFNQTRHQTFVRUNCTUhRbVZwU21sdVp6RVFNQTRHQTFVRUJ4TUhRbVZwU21sdQpaekVNTUFvR0ExVUVDaE1EYXpoek1SSXdFQVlEVlFRTEV3azBVR0Z5WVdScFoyMHhFekFSQmdOVkJBTVRDbXQxClltVnlibVYwWlhNd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURLNm02UXd2dUwKYWw1S1h2aVFlbDJXL0pFTm5OSVVsalNmUHhraVE2NUloUStLaEVaeEJ3S0hZczNzMFdYMDFVQUtVeDNVVmMxSgo2V3pQL3MvbGlCaC8xVmxwOXpNRFR1OEhjbWdKVW01VnBmTTFhQ1d4eXk2bHZXVWl4V1FadVNCSjFZT2NJN3R4ClZYbktxR3FnS2RuTEJyamJGSWNtdnJFV01RMmRUcjBOWUZuaVd5UkRmQXlpdW11NEtnZEVZSmlIYXFXNm1xYVMKK1d3czFaWEZzRHl6SzNvQWxmTTZ4ZEhXMk9OQ0JadFovaTFtMTBsV3FTS0hsZlBRU1VOcDRMaURHWElaTFpKeApOQ1Z5T2lINFI4T1RaM3dhME9yOVhEeVEzMmIrNkhYa01FMTAvaFc5bnRlanRCZXExVzNjMTVOeVRzemJYYWQzCjJyZ3ZvZ1JtcFNwUkFnTUJBQUdqWmpCa01BNEdBMVVkRHdFQi93UUVBd0lCQmpBU0JnTlZIUk1CQWY4RUNEQUcKQVFIL0FnRUNNQjBHQTFVZERnUVdCQlErQ3RaTWZrbGV1MmtCY0hFc2RzcVMxRVJ5YkRBZkJnTlZIU01FR0RBVwpnQlErQ3RaTWZrbGV1MmtCY0hFc2RzcVMxRVJ5YkRBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQUF4Wlo5R0NOCmdJMzVWaDNvdE9IUkw4eXJSSEw5b05qbzdVQnZEU2JBZkp2dDd1WGx3WmF0bXBZTUN1MEpVUnJnMWM0Rng3cWUKUHdOQVNnQUFuVHZKZmdEYlZRWDlTM25CcytJYzdTUE5wdXVacTloZzhmSHkyaHRYZ0RiL3lOMkdpNlBBK29zTwpWdWRTYXI5S0tMcVJzNnBuU2tPOEJkbmtPR2llUks5WnJIOVlnS3VodFVhbmZGSEhJeTE0ZXJqQ0s3YUV0S2FOCmxJQVNhV2crYkNnK29JdklqcjdyRzZoU1VFZWkwdVJGbHg5OXN0OVBSeUVaVTZ2MVpETEt6bjY0MUp1elREeDkKTVhLdUtKQUF1anUyc1c0VjZ2VEowR1pGUGNobkxrZSs1NC9QSnVsLytzVExRS1puVE9EMm9KdW1VMEFiVnFMRwpZa1VLUWJ2dUhzMW9sUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
  namespace: Z2l0bGFi
  token: ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklpSjkuZXlKcGMzTWlPaUpyZFdKbGNtNWxkR1Z6TDNObGNuWnBZMlZoWTJOdmRXNTBJaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5dVlXMWxjM0JoWTJVaU9pSm5hWFJzWVdJaUxDSnJkV0psY201bGRHVnpMbWx2TDNObGNuWnBZMlZoWTJOdmRXNTBMM05sWTNKbGRDNXVZVzFsSWpvaVoybDBiR0ZpTFhSdmEyVnVMVFZqWjNneUlpd2lhM1ZpWlhKdVpYUmxjeTVwYnk5elpYSjJhV05sWVdOamIzVnVkQzl6WlhKMmFXTmxMV0ZqWTI5MWJuUXVibUZ0WlNJNkltZHBkR3hoWWlJc0ltdDFZbVZ5Ym1WMFpYTXVhVzh2YzJWeWRtbGpaV0ZqWTI5MWJuUXZjMlZ5ZG1salpTMWhZMk52ZFc1MExuVnBaQ0k2SWpFNFptWXlabVpqTFdWak1UVXRNVEZsT1MxaE5UZGxMVFV5TlRRd01HUTNZakk0TkNJc0luTjFZaUk2SW5ONWMzUmxiVHB6WlhKMmFXTmxZV05qYjNWdWREcG5hWFJzWVdJNloybDBiR0ZpSW4wLmxacC02bGdnXzUzcnJiYjI1Y0xQWnlXSlpLQ0JQYUJSc0IybDAzMmNHSEFzSWpLdmJOemVpQnJ4M2U4SGNoVjVxNGJ5NDljem53dmkyeXAzZDJ0TGpZOTZTTUt3UDRQQUJjcFozci1YM2NMUFEzTGZrUkhXZlJyQktNY3BYbm1mRmRnZUJ4LXFTRS00ZFo3LTF3ZzNwTDV1ZkZWaEo1OTlZbHBqXzU4OFpxc0c2YTk4WjR1NDVyeTlpSHd2QV9KRDVDcGRvU1FObDk1ZGw2dDlra0c0NHZET2N1cG5WQkIxS1ByeXJsY3FyMlozVjJ4MEVHQWRxSjdUU0JwZWxSaTIyVmFHcGRyMmdhUjV4dTU4cEVKUjdDYl9BUnBHRVZaZ0JvZF9SWmtWU0FtTkdGVVV2YWZSdHBNZ3RLVTM4RkMzZ1drVVBleVZMY2o4Yk9DQTdscndnUQ==
kind: Secret
metadata:
  annotations:
    kubernetes.io/service-account.name: gitlab
    kubernetes.io/service-account.uid: 18ff2ffc-ec15-11e9-a57e-525400d7b284
  creationTimestamp: "2019-10-11T10:51:36Z"
  name: gitlab-token-5cgx2
  namespace: gitlab
  resourceVersion: "6743518"
  selfLink: /api/v1/namespaces/gitlab/secrets/gitlab-token-5cgx2
  uid: 18f0217c-ec15-11e9-8945-525400a79155
type: kubernetes.io/service-account-token

在上面咱們已經看到了ca.crt和token,可是咱們是不可使用。還須要使用base64進行轉碼

echo "xxxx"|base64 -d

#須要複製所有,包括--BEGIN
#生成token,方法相同

image_1dmta8fckp9d1r711c7gblp1mhb2b.png-854.5kB

而後咱們點擊ADD
image_1dmtaehpb1frs19111qa12nkrmp2o.png-119.7kB

若是咱們點擊添加提示下方報錯,就須要添加一個容許鉤子的一個操做

錯誤圖

image_1dmtbejc51aj9sfd1s5n1nj61v3q35.png-187.1kB

解決方法
Admin area => Settings => Network ,而後點擊 Outbound requests 右邊 的「expand」按鈕
image_1dmtbgobn4351o81fqub2a16t93i.png-110.9kB

添加完成以下圖 (如今咱們是已經能夠訪問到咱們的集羣)
image_1dmtbi4ar12lvelfdqt13k91h0o3v.png-218.6kB

.gitlab-ci.yaml文件裏面,咱們引用了不少環境變量 (好比docker帳號密碼文件等)這種文件不能夠明文顯示,因此在配置文件使用了變量,如今就須要去gitlab上配置一下這個變量

image_1dmtd5bi5eebnnm8cq19ibhf64c.png-151.7kB

image_1dmtd5p7ejvh19ui1p57niq1b014p.png-147.1kB

在下面添加鏡像地址,容器倉庫的帳號密碼就能夠
CI_REGISTRY_USER
CI_REGISTRY_PASSWORD
CI_REGISTRY_IMAGE

gitlab ci變量文檔 https://docs.gitlab.com/ee/ci...

image_1dmtdcjo3qol1jv1f4h1pbuppr56.png-85.8kB


在前面咱們已經提交了git代碼,若是沒有提交測試能夠解壓下面的文件,在提交一次

wget http://down.i4t.com/abcdocker-gitlab-demo.tar.gz
代碼文件,裏面包含gitlab ci腳本及本次演示環境

咱們這裏提交一個代碼進去,進行演示

1111111111111.png-266kB

在咱們的kube-ops命名空間下,gitlab會生成runner鏡像,裏面包含咱們ci腳本定義的鏡像以及runner鏡像
image_1dn7piuas1aku1io6lfhken3061e.png-98.2kB

接下來咱們能夠在gitlab查看ci構建步驟

構建請注意,若是沒有.gitlab-ci.yaml文件,gitlab不會觸發ci腳本

image_1dn7plbis1kdedhqokr5fj1usa2b.png-173.3kB

點擊下方能夠看到詳細的構建步驟

image_1dn7pn3j7njgmn21som1ln1ovs48.png-122.9kB

能夠查看到詳細的構建步驟,和jenkins pipline做用相同

3333.png-182.4kB

在Build階段咱們添加了一個變量,使咱們build完成後能夠將打包的文件下載下來
image_1dn7qsdh01op91ofl16hhat6ju078.png-359.4kB

構建完成後就會出現下方,而且還能夠重複構建
image_1dn7qtjf0epj18i81gd73371cs87l.png-79.4kB

接下來咱們能夠查看一下pod和svc等相關狀態
image_1dn7qvqo9giqmsp12jcog81evi82.png-138.9kB

可使用ingress訪問,或者經過nodeport方式訪問。這裏我使用nodeport方式進行訪問演示
image_1dn7r1qct2q91r0i19a31n1ags38f.png-52.1kB

咱們能夠根據本身的需求進行修改


小結
1.這裏pod的版本號我使用的是commit版本號,能夠確保惟一性
2.這裏提交代碼只有的master上會進行處罰
3.這裏個人鏡像倉庫使用的是阿里雲

文檔若是有問題請在下方評論,我會及時進行修改並進行答疑。 着急能夠點擊右下方加羣,羣裏@管理員
2019年10月15日21:54:47

相關文章
相關標籤/搜索