Jenkins + k8s 實現企業 CI/CD 落地

1、概述

1.一、環境介紹

咱們使用的是 AWS 的 EC2 來搭建咱們的集羣,安裝方式使用 kubeadm 來進行安裝,若是使用二進制安裝,能夠參考我相關文檔。node

  • 系統版本:ubuntu 16.04
  • k8s 版本:1.17.1
  • docker 版本:18.06-ce

1.二、流程圖

Jenkins + k8s 實現企業 CI/CD 落地

1.三、集羣配置

名稱 配置 內網IP 外網IP
k8s-master 2核4GB 172.31.20.184 54.226.118.74
k8s-node1 2核4GB 172.31.27.69 52.90.221.230
k8s-node2 2核4GB 172.31.30.9 3.85.219.119

Jenkins + k8s 實現企業 CI/CD 落地

2、k8s 部署

2.一、安裝 docker

安裝源你們能夠參照官方文檔 https://docs.docker.com/install/linux/docker-ce/ubuntu/ ,我這裏再也不進行演示,如沒有特殊說明,操做將在三臺集羣上面都要執行。linux

apt-get install docker-ce=18.06.3~ce~3-0~ubuntu
systemctl enable docker

2.二、安裝 kubeadm, kubelet and kubectl

安裝源文檔請參考官方文檔 https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm ,詳細步驟我這裏進行省略。nginx

sudo apt-get update && sudo apt-get install -y apt-transport-https curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

2.三、安裝 k8s 集羣

請參考文檔 https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/ ,在 master 節點運行。git

kubeadm init --kubernetes-version=v1.17.1 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.96.0.0/12

在 node 節點上運行添加集羣的命令。github

kubeadm join 172.31.20.184:6443 --token w3fu9a.rs8eknt079n2e8r8 \
    --discovery-token-ca-cert-hash sha256:7392d6f6576b3c9ba5f78d1c54d9a0b1369f77bd498da8104a096b62c6b14c06

之後的 kubectl 都是在 master 節點上進行操做,添加 cni 插件,咱們這裏選擇 flannel。web

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/2140ac876ef134e0ed5af15c65e414cf26827915/Documentation/kube-flannel.yml

到目前爲止,咱們的集羣已經建立完成,參照官方文檔執行,過程很簡單。docker

root@ip-172-31-20-184:~# kubectl get no
NAME               STATUS   ROLES    AGE   VERSION
ip-172-31-20-184   Ready    master   21m   v1.17.1
ip-172-31-27-69    Ready    <none>   16m   v1.17.1
ip-172-31-30-9     Ready    <none>   16m   v1.17.1

3、組件安裝

整個 CI/CD 過程當中咱們用到了不少工具,好比 gitlab,jenkins,harbor,在生產環境,建議你們把 gitlab 和 harbor 放在獨立的機器上面,我這裏爲了簡便,直接放在 k8s 集羣中。ubuntu

3.一、安裝 helm3

請參見官方文檔 https://helm.sh/docs/intro/install/api

wget https://get.helm.sh/helm-v3.0.2-linux-amd64.tar.gz
tar xf helm-v3.0.2-linux-amd64.tar.gz
mv linux-amd64/helm /usr/local/bin/
chmod +x /usr/local/bin/helm

3.二、安裝 gitlab

參見官方文檔 https://docs.gitlab.com/charts/installation/bash

helm repo add gitlab https://charts.gitlab.io/

後來發現 gitlab 目前還不支持 helm3,那我就選擇了使用 EC2 來進行建立。
https://about.gitlab.com/install/#ubuntu?version=ce

3.三、安裝 harbor

參見官方文檔 https://github.com/goharbor/harbor-helm/blob/master/README.md

helm repo add harbor https://helm.goharbor.io
helm install my-release harbor/harbor

安裝過程當中仍是出現了一些問題,是由於沒有 pv,懶得去設置了,後來仍是選擇了單機進行安裝。
參照下面文檔安裝 https://github.com/goharbor/harbor/blob/master/docs/installation_guide.md

3.四、安裝 jenkins

3.4.一、優勢

咱們以雲原生的方式,將jenkins master,jenkins slave所有部署於kubernetes之上,從而打造一個高可用,彈性伸縮的CI/CD管道。

  1. 推送代碼到託管鏡像倉庫
  2. gitlab 基於webhook觸發jenkins pipeline項目
  3. Jenkins master分配kubernetes slave做爲項目的執行環境,同時k8s啓動slave pod
  4. Jenkins slave pod運行pipeline中指定的任務第一步從私有代碼倉庫拉下代碼
  5. Jenkins slave pod執行代碼測試,測試完畢後依據代碼倉庫格式,構造鏡像
  6. Jenkins slave pod推送鏡像到Harbor上
  7. Jenkins slave pod執行應用服務的更新任務
  8. 應用服務pod所在節點拉取相應的鏡像,完成鏡像的替換,即應用的更新
  • 服務高可用:當 Jenkins Master 出現故障時,Kubernetes 會自動建立一個新的 Jenkins Master 容器,而且將 Volume 分配給新建立的容器,保證數據不丟失,從而達到集羣服務高可用。
  • 動態伸縮:合理使用資源,每次運行 Job 時,會自動建立一個 Jenkins Slave,Job 完成後,Slave 自動註銷並刪除容器,資源自動釋放,並且 Kubernetes 會根據每一個資源的使用狀況,動態分配 Slave 到空閒的節點上建立,下降出現因某節點資源利用率高,還排隊等待在該節點的狀況。
  • 擴展性好:當 Kubernetes 集羣的資源嚴重不足而致使 Job 排隊等待時,能夠很容易的添加一個 Kubernetes Node 到集羣中,從而實現擴展。

3.4.二、建立 nfs

由於 master 須要持久存儲,咱們這裏就簡單的選擇 nfs ,咱們在 master 節點上進行建立服務。
建立過程請參照文檔 https://blog.csdn.net/qq_37860012/article/details/86717891

root@ip-172-31-20-184:/home/nfs# showmount -e 172.31.20.184
Export list for 172.31.20.184:
/home/nfs/jenkins *

master 節點目前授予權限。

chown ubuntu.ubuntu -R /home/nfs/jenkins

3.4.三、建立 nginx-ingress

參考文檔 https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-manifests/

3.4.五、安裝 jenkins

前面所須要的東西都已經配置好了,那咱們開始安裝 jenkins,請應用我下面的 yaml 文件

apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: jenkins
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
  resources: ["pods/exec"]
  verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
  resources: ["pods/log"]
  verbs: ["get","list","watch"]
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: jenkins
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: jenkins
subjects:
- kind: ServiceAccount
  name: jenkins
---
apiVersion: v1
kind: Service
metadata:
  name: jenkins
spec:
  selector:
    app: jenkins
  ports:
  - name: http
    port: 8080
    targetPort: 8080
    protocol: TCP
  - name: agent
    port: 50000
    protocol: TCP
    targetPort: 50000
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: name-virtual-host-ingress
spec:
  rules:
  - host: jenkins.wzlinux.com
    http:
      paths:
      - backend:
          serviceName: jenkins
          servicePort: 8080
---
apiVersion: apps/v1
kind: Deployment  
metadata:  
  name: jenkins
spec:  
  replicas: 1 
  selector: 
    matchLabels:
      app: jenkins
  strategy:  
    type: RollingUpdate  
    rollingUpdate:  
      maxSurge: 2  
      maxUnavailable: 0  
  template:  
    metadata:  
      labels:  
        app: jenkins  
    spec:
      securityContext:
        fsGroup: 1000
      serviceAccountName: jenkins
      containers:  
      - name: jenkins
        image: jenkins/jenkins:lts-alpine
        imagePullPolicy: IfNotPresent  
        ports:  
        - containerPort: 8080  
          name: web  
          protocol: TCP  
        - containerPort: 50000  
          name: agent  
          protocol: TCP  
        volumeMounts:  
        - name: jenkins-home
          mountPath: /var/jenkins_home
        env:  
        - name: JAVA_OPTS  
          value: "-Xms1G -Xmx1G -XX:PermSize=512m -XX:MaxPermSize=1024m -Duser.timezone=Asia/Shanghai"
        - name: TRY_UPGRADE_IF_NO_MARKER
          value: "true"
      volumes:  
      - name: jenkins-home
        # hostPath:
        #   path: "/home/jenkins"
        nfs:  
          server: 172.31.20.184
          path: "/home/nfs/jenkins/"
相關文章
相關標籤/搜索