1. 程式人生 > 其它 >Kubernetes DevOps: Gitlab

Kubernetes DevOps: Gitlab

Gitlab 官方提供了 Helm 的方式在 Kubernetes 叢集中來快速安裝,但是在使用的過程中發現 Helm 提供的 Chart 包中有很多其他額外的配置,所以我們這裡使用自定義的方式來安裝,也就是自己來定義一些資源清單檔案。

Gitlab 主要涉及到3個應用:Redis、Postgresql、Gitlab 核心程式,實際上我們只要將這3個應用分別啟動起來,然後加上對應的配置就可以很方便的安裝 Gitlab 了,我們這裡選擇使用的映象不是官方的,而是 Gitlab 容器化中使用非常多的一個第三方映象:sameersbn/gitlab,基本上和官方保持同步更新,地址:http://www.damagehead.com/docker-gitlab/

如果我們已經有可使用的 Redis 或 Postgresql 服務的話,那麼直接配置在 Gitlab 環境變數中即可,如果沒有的話就單獨部署,我們這裡為了展示 gitlab 部署的完整性,還是分開部署。

首先部署需要的 Redis 服務,對應的資源清單檔案如下:(gitlab-redis.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  namespace: kube-ops
  labels:
    name: redis
spec:
  selector:
    matchLabels:
      name: redis
  template:
    metadata:
      name: redis
      labels:
        name: redis
    spec:
      containers:
      - name: redis
        image: sameersbn/redis:4.0.9-2
        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: 30
          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: v1
kind: PersistentVolumeClaim
metadata:
  name: postgresql-pvc
  namespace: kube-ops
spec:
  storageClassName: rook-ceph-block
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgresql
  namespace: kube-ops
  labels:
    name: postgresql
spec:
  selector:
    matchLabels:
      name: postgresql
  template:
    metadata:
      name: postgresql
      labels:
        name: postgresql
    spec:
      containers:
      - name: postgresql
        image: sameersbn/postgresql:10-2
        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
        - name: USERMAP_UID
          value: "999"
        - name: USERMAP_GID
          value: "999"
        ports:
        - name: postgres
          containerPort: 5432
        volumeMounts:
        - mountPath: /var/lib/postgresql
          name: data
        readinessProbe:
          exec:
            command:
            - pg_isready
            - -h
            - localhost
            - -U
            - postgres
          initialDelaySeconds: 30
          timeoutSeconds: 1
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: postgresql-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: postgresql
  namespace: kube-ops
  labels:
    name: postgresql
spec:
  ports:
    - name: postgres
      port: 5432
      targetPort: postgres
  selector:
    name: postgresql

為了提高資料庫的效能,我們這裡也沒有使用共享儲存之類的,而是直接用的 Local PV 將應用固定到一個節點上。然後就是我們最核心的 Gitlab 的應用,對應的資源清單檔案如下:(gitlab.yaml)

apiVersion: v1
kind: PersistentVolume
metadata:
  name: gitlab-pv
spec:
  storageClassName: local  # Local PV
  capacity:
    storage: 20Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  local:  
    path: /data/k8s/gitlab/data/
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - ydzs-node4
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: gitlab-pvc
  namespace: kube-ops
spec:
  storageClassName: local
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gitlab
  namespace: kube-ops
  labels:
    name: gitlab
spec:
  selector:
    matchLabels:
      name: gitlab
  template:
    metadata:
      name: gitlab
      labels:
        name: gitlab
    spec:
      initContainers:
      - name: fix-permissions
        image: busybox
        command: ["sh", "-c", "chown -R 1000:1000 /home/git/data"]
        securityContext:
          privileged: true
        volumeMounts:
        - name: data
          mountPath: /home/git/data
      containers:
      - name: gitlab
        image: sameersbn/gitlab:12.9.5
        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: [email protected]
        - name: GITLAB_HOST
          value: git.k8s.local
        - 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
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 60
          timeoutSeconds: 1
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: gitlab-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: gitlab
  namespace: kube-ops
  labels:
    name: gitlab
spec:
  ports:
    - name: http
      port: 80
      targetPort: http
    - name: ssh
      port: 22
      targetPort: ssh
  selector:
    name: gitlab
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: gitlab
  namespace: kube-ops
spec:
  entryPoints:
  - web   
  routes:
  - kind: Rule
    match: Host(`git.k8s.local`)
    services:
    - name: gitlab
      port: 80

同樣因為我們這裡的 gitlab 映象內部是一個 git 的使用者(id=1000),所以我們這裡為了持久化資料通過一個 initContainers 將我們的資料目錄許可權進行更改:

initContainers:
- name: fix-permissions
  image: busybox
  command: ["sh", "-c", "chown -R 1000:1000 /home/git/data"]
  securityContext:
    privileged: true
  volumeMounts:
  - name: data
    mountPath: /home/git/data

由於 gitlab 啟動非常慢,也非常消耗資源,我們同樣還是用的 Local PV,為了不讓應用重啟,我們這裡也直接去掉了 livenessProbe,這樣可以防止 gitlab 自動重啟,要注意的是其中 Redis 和 Postgresql 相關的環境變數配置,另外,我們這裡添加了一個 IngressRoute 物件,來為我們的 Gitlab 配置一個域名 git.k8s.local,這樣應用部署完成後,我們就可以通過該域名來訪問了,然後直接部署即可:

$ kubectl apply -f gitlab-redis.yaml gitlab-postgresql.yaml gitlab.yaml

建立完成後,檢視 Pod 的部署狀態:

$ kubectl get pods -n kube-ops
NAME                                           READY     STATUS    RESTARTS   AGE
gitlab-7d855554cb-twh7c                        1/1       Running   0          10m
postgresql-8566bb959c-2tnvr                    1/1       Running   0          17h
redis-8446f57bdf-4v62p                         1/1       Running   0          17h

可以看到都已經部署成功了,然後我們可以通過 Ingress 中定義的域名 git.k8s.local(需要做 DNS 解析或者在本地 /etc/hosts 中新增對映)來訪問 Portal:

使用使用者名稱 root,和部署的時候指定的超級使用者密碼 GITLAB_ROOT_PASSWORD=admin321 即可登入進入到首頁:

Gitlab 執行後,我們可以註冊為新使用者並建立一個專案,還可以做很多的其他系統設定,比如設定語言、設定應用風格樣式等等。

點選 Create a project 建立一個新的專案,和 Github 使用上沒有多大的差別:

建立完成後,我們可以新增本地使用者的一個 SSH-KEY,這樣我們就可以通過 SSH 來拉取或者推送程式碼了。SSH 公鑰通常包含在 ~/.ssh/id_rsa.pub 檔案中,並以 ssh-rsa 開頭。如果沒有的話可以使用 ssh-keygen 命令來生成,id_rsa.pub 裡面的內容就是我們需要的 SSH 公鑰,然後新增到 Gitlab 中。

由於平時使用的 ssh 預設是 22 埠,現在如果用預設的 22 埠去連線,是沒辦法和 Gitlab 容器中的 22 埠進行對映的,因為我們只是通過 Service 的 22 埠進行了對映,要想通過節點去進行 ssh 連結就需要在節點上一個埠和容器內部的 22 埠進行繫結,所以這裡我們可以通過 NodePort 去對映 Gitlab 容器內部的 22 埠,我們可以將環境變數設定為 GITLAB_SSH_PORT=30022,將 Gitlab 的 Service 也設定為 NodePort 型別:

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

注意上面 ssh 對應的 nodePort 埠設定為 30022,這樣就不會隨機生成了,重新更新下 Deployment 和 Service,更新完成後,現在我們在專案上面 Clone 的時候使用 ssh 就會帶上埠號了:

現在就可以使用 Clone with SSH 的地址了,由於上面我們配置了 SSH 公鑰,所以就可以直接訪問上面的倉庫了:

$ git clone ssh://[email protected]:30022/root/gitlab-demo.git
Cloning into 'gitlab-demo'...
Warning: the ECDSA host key for '[git.k8s.local]:30022' differs from the key for the IP address '[123.59.188.11]:300
22'
Offending key for IP in /Users/ych/.ssh/known_hosts:195
Matching host key in /Users/ych/.ssh/known_hosts:204
Are you sure you want to continue connecting (yes/no)? yes
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.

然後隨便在該專案下面新增一些資源:

$ echo "# hello world" >  README.md
$ git add .
$ git commit -m "change README"
[master 1023f85] change README
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git push origin master
Warning: the ECDSA host key for '[git.k8s.local]:30022' differs from the key for the IP address '[123.59.188.11]:30022'
Offending key for IP in /Users/ych/.ssh/known_hosts:195
Matching host key in /Users/ych/.ssh/known_hosts:204
Are you sure you want to continue connecting (yes/no)? yes
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 259 bytes | 259.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To ssh://git.k8s.local:30022/root/gitlab-demo.git
   dfc35a2..1023f85  master -> master

然後重新整理瀏覽器,就可以看到剛剛建立的 Git 倉庫中多了一個 README.md 的檔案:

到這裡就表明我們的 GitLab 就成功部署到了 Kubernetes 叢集當中了。