1. 程式人生 > >jenkins X實踐系列(1) —— 背景知識

jenkins X實踐系列(1) —— 背景知識

本文介紹jenkins X(以下簡稱jx)相關的背景技術。

jenkins X 簡介

Jenkins X 是一個高度整合化的CI/CD平臺,基於Jenkins和Kubernetes實現,旨在解決微服務體系架構下的雲原生應用的持續交付的問題,簡化整個雲原生應用的開發、執行和部署過程。

jx 基於gitops,將k8s分為preview、staging、production幾個環境,

詳細的devops可以檢視下圖:

jx是雲原生CICD,devops的一個最佳實踐之一,目前在快速的發展成熟中。最近調研了JX,準備寫一個jx實踐系列,這裡為第一篇,介紹jx用到的一些相關元件,作為了解jx的背景知識。

jenkins pipeline

jx使用Jenkins Pipeline來執行CI流程,Jenkins Pipeline是jenkins的一套外掛,支援將連續輸送Pipeline實施和整合到Jenkins。Pipeline 提供了一組可擴充套件的工具,用於通過Pipeline DSL為程式碼建立簡單到複雜的傳送Pipeline 。

Jenkinsfile pipeline使用Groovy指令碼來定義CI流程,來看一個jx生成的實際案例:

pipeline {
    agent {
      label "jenkins-maven"
    }
    environment {
      ORG               = 'jqpeng'
      APP_NAME          = 'x-nginx'
      CHARTMUSEUM_CREDS = credentials('jenkins-x-chartmuseum')
    }
    stages {
      stage('CI Build and push snapshot') {
        when {
          branch 'PR-*'
        }
        environment {
          PREVIEW_VERSION = "0.0.0-SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER"
          PREVIEW_NAMESPACE = "$APP_NAME-$BRANCH_NAME".toLowerCase()
          HELM_RELEASE = "$PREVIEW_NAMESPACE".toLowerCase()
        }
        steps {
          container('maven') {
            sh "mvn versions:set -DnewVersion=$PREVIEW_VERSION"
            sh "mvn package -DskipTests"
            sh 'export VERSION=$PREVIEW_VERSION && skaffold build -f skaffold.yaml'


            sh "jx step post build --image $DOCKER_REGISTRY/$ORG/$APP_NAME:$PREVIEW_VERSION"
          }

          dir ('./charts/preview') {
           container('maven') {
            sh 'helm init --client-only --stable-repo-url=http://charts.iflyresearch.com/'
           
             sh "make preview"
             sh "jx preview --app $APP_NAME --dir ../.."
           }
          }
        }
      }
      stage('Build Release') {
        when {
          branch 'master'
        }
        steps {
          container('maven') {
            // ensure we're not on a detached head
            sh "git checkout master"
            sh "git config --global credential.helper store"

            sh "jx step git credentials"
            // so we can retrieve the version in later steps
            sh "echo \$(jx-release-version) > VERSION"
            sh "mvn versions:set -DnewVersion=\$(cat VERSION)"
          }
          dir ('./charts/x-nginx') {
            container('maven') {
              sh "make tag"
            }
          }
          container('maven') {
            sh 'mvn package -DskipTests'

            sh 'export VERSION=`cat VERSION` && skaffold build -f skaffold.yaml'


            sh "jx step post build --image $DOCKER_REGISTRY/$ORG/$APP_NAME:\$(cat VERSION)"
          }
        }
      }
      stage('Promote to Environments') {
        when {
          branch 'master'
        }
        steps {
          dir ('./charts/x-nginx') {
            container('maven') {
              sh 'jx step changelog --version v\$(cat ../../VERSION)'

              sh 'helm init --client-only --stable-repo-url=http://charts.iflyresearch.com/'

              // release the helm chart
              sh 'jx step helm release'

              // promote through all 'Auto' promotion Environments
              sh 'jx promote -b --all-auto --timeout 1h --version \$(cat ../../VERSION)'
            }
          }
        }
      }
    }
    post {
        always {
            cleanWs()
        }
    }
  }
  • pipeline 定義是一個pipeline
  • environment 定義環境變數
  • stages 定義流程
    • stage('CI Build and push snapshot') 定義子流程
      • when 匹配條件
      • environment 定義子流程環境變數
      • steps 定義流程制定的具體步驟
        • container('maven') 使用maven映象來構建
        • sh "git checkout master" 在maven映象執行命令
  • 其餘的看字面意思就可以理解了

執行構建後,開啟jenkins web頁面,可以看到構建pipelines

Pipeline

同時可以檢視Blue Ocean頁面

Blue Ocean

helm與charts

Helm是管理Kubernetes charts的工具,charts是預先配置好的安裝包資源,有點類似於Ubuntu的APT和CentOS中的yum。

可以使用helm來:

  • 查詢並使用已打包為Helm charts的熱門應用在Kubernetes中執行
  • 封裝並分享自己的應用
  • 建立可重複的Kubernetes應用程式版本
  • 智慧管理應用依賴
  • 管理Helm軟體包的版本

HELM

安裝helm

安裝helm很簡單,下載離線二進位制包,加壓後加入path即可

wget https://kubernetes-helm.storage.googleapis.com/helm-canary-linux-amd64.tar.gz

helm需要服務端Tiller支援,需要安裝到叢集中,可以使用下面的命令來安裝最新的2.11版本:

helm init --tiller-image anjia0532/kubernetes-helm.tiller:v2.11.0 --skip-refresh

參見:google gcr.io、k8s.gcr.io 國內映象

helm錯誤解決

Helm: Error: no available release name found

helm報這個錯誤 Helm: Error: no available release name found
錯誤的原因大概是因為 tiller沒有正確的角色許可權。
執行以下命令可解決這個問題。

kubectl create serviceaccount --namespace kube-system tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'

charts入門

先來看一個jx生成的charts檔案:

tree charts/

charts/
├── preview
│   ├── Chart.yaml
│   ├── Makefile
│   ├── requirements.yaml
│   └── values.yaml
├── x-nginx
│   ├── Chart.yaml
│   ├── Makefile
│   ├── README.md
│   ├── templates
│   │   ├── deployment.yaml
│   │   ├── _helpers.tpl
│   │   ├── NOTES.txt
│   │   └── service.yaml
│   └── values.yaml

Chart.yaml

chart檔案首先是一個Chart.yaml描述檔案,描述chart的基本資訊,包含name,version等描述資訊

cat charts/x-nginx/Chart.yaml 

apiVersion: v1
description: A Helm chart for Kubernetes
icon: https://raw.githubusercontent.com/jenkins-x/jenkins-x-platform/master/images/java.png
name: x-nginx
version: 0.1.0-SNAPSHOT
~                         

templates

templates存放的是模板檔案,遵循Go template語法,結合values.yaml的資料,可以生成部署到K8S所需的yaml配置檔案。

來簡單看下deployment.yaml:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: {{ template "fullname" . }}
  labels:
    draft: {{ default "draft-app" .Values.draft }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}"
spec:
  replicas: {{ .Values.replicaCount }}
  template:
    metadata:
      labels:
        draft: {{ default "draft-app" .Values.draft }}
        app: {{ template "fullname" . }}
{{- if .Values.podAnnotations }}
      annotations:
{{ toYaml .Values.podAnnotations | indent 8 }}
{{- end }}
    spec:
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        ports:
        - containerPort: {{ .Values.service.internalPort }}
      terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }}

注意,模板遵循Go template語法,都是go生態,可以稍微學習瞭解下。上面的模板是Deployment的yaml配置檔案,大括號包裹起來的部分是Go template,對應的Values是在values.yaml檔案中定義的:

# Default values for Maven projects.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
  repository: draft
  tag: dev
  pullPolicy: IfNotPresent
service:
  name: x-nginx
  type: ClusterIP
  externalPort: 80
  internalPort: 8080
  annotations:
    fabric8.io/expose: "true"
    fabric8.io/ingress.annotations: "kubernetes.io/ingress.class: nginx"
resources:
  limits:
    cpu: 500m
    memory: 512Mi
  requests:
    cpu: 400m
    memory: 512Mi
terminationGracePeriodSeconds: 10

簡單學習下常用語法:

  • {{ .Values.replicaCount }} 對應values.yaml中的replicaCount,通過{{ .Values.$varname }} 語法引用
  • {{ default "draft-app" .Values.draft }} 如果draft沒有定義,使用預設的"draft-app"
  • {{- if .Values.podAnnotations }} {{- end }} 條件語法
  • {{ toYaml .Values.podAnnotations | indent 8 }} 輸出為yaml,indent指定縮排

驗證模板

charts通過go模板渲染後,最後生成yaml格式部署檔案,可以使用helm install --dry-run --debug <chart_dir>命令來驗證chart配置,檢視最終生成的配置檔案。

$:~/workspace/xnginx/charts/x-nginx$ helm install --dry-run --debug .
[debug] Created tunnel using local port: '40868'

[debug] SERVER: "127.0.0.1:40868"

[debug] Original chart version: ""
[debug] CHART PATH: /workspace/xnginx/charts/x-nginx

NAME:   messy-seastar
REVISION: 1
RELEASED: Tue Nov 20 09:20:39 2018
CHART: x-nginx-0.1.0-SNAPSHOT
USER-SUPPLIED VALUES:
{}

COMPUTED VALUES:
image:
  pullPolicy: IfNotPresent
  repository: draft
  tag: dev
replicaCount: 1
resources:
  limits:
    cpu: 500m
    memory: 512Mi
  requests:
    cpu: 400m
    memory: 512Mi
service:
  annotations:
    fabric8.io/expose: "true"
    fabric8.io/ingress.annotations: 'kubernetes.io/ingress.class: nginx'
  externalPort: 80
  internalPort: 8080
  name: x-nginx
  type: ClusterIP
terminationGracePeriodSeconds: 10

HOOKS:
MANIFEST:

---
# Source: x-nginx/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: x-nginx
  labels:
    chart: "x-nginx-0.1.0-SNAPSHOT"
  annotations:
    fabric8.io/expose: "true"
    fabric8.io/ingress.annotations: 'kubernetes.io/ingress.class: nginx'
    
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
    name: http
  selector:
    app: messy-seastar-x-nginx
---
# Source: x-nginx/templates/deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: messy-seastar-x-nginx
  labels:
    draft: draft-app
    chart: "x-nginx-0.1.0-SNAPSHOT"
spec:
  replicas: 1
  template:
    metadata:
      labels:
        draft: draft-app
        app: messy-seastar-x-nginx
    spec:
      containers:
      - name: x-nginx
        image: "draft:dev"
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080
      terminationGracePeriodSeconds: 10

其他命令

  • 部署 helm install .
  • 打包分享helm package .

charts mirror 映象

官方的charts映象由於GFW原因,不能訪問,可以使用github映象:

 helm repo add stable https://burdenbear.github.io/kube-charts-mirror/

當然,為了更好使用,可以部署本地映象

  • clone mirror倉庫到本地,存放到cephfs /charts目錄,然後建立一個nginx,掛載這個pv即可。
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolume
metadata:
  name: cephfs-charts-pv
  namespace: nginx-ingress
  labels:
    name: cephfs-charts-pv
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteMany
  cephfs:
    monitors: 
    - 192.168.86.156:6789
    path: /charts/kube-charts-mirror-master/docs/
    user: admin
    secretRef:
      name: ceph-secret
    readOnly: false
  persistentVolumeReclaimPolicy: Retain
EOF

skaffold

Skaffold 是谷歌開源的簡化本地 Kubernetes 應用開發的工具。它將構建映象、推送映象以及部署 Kubernetes 服務等流程自動化,可以方便地對 Kubernetes 應用進行持續開發。其功能特點包括

  • 沒有伺服器元件

  • 自動檢測程式碼更改並自動構建、推送和部署服務

  • 自動管理映象標籤

  • 支援已有工作流

  • 儲存檔案即部署

Skaffold

直接進入正題,skaffold通過skaffold.yaml來定義build、deploy,並且可以區分dev環境和正式環境:

apiVersion: skaffold/v1alpha2
kind: Config
build:
  tagPolicy:
    envTemplate:
      template: "{{.DOCKER_REGISTRY}}/jqpeng/x-nginx:{{.VERSION}}"
  artifacts:
  - imageName: changeme
    workspace: ./xnginx-admin
    docker: {}
  local: {}
deploy:
  kubectl:
    manifests:
profiles:
- name: dev
  build:
    tagPolicy:
      envTemplate:
        template: "{{.DOCKER_REGISTRY}}/jqpeng/x-nginx:{{.DIGEST_HEX}}"
    artifacts:
    - docker: {}
    local: {}
  deploy:
    helm:
      releases:
      - name: x-nginx
        chartPath: charts/x-nginx
        setValueTemplates:
          image.repository: "{{.DOCKER_REGISTRY}}/jqpeng/x-nginx"
          image.tag: "{{.DIGEST_HEX}}"
  • apiVersion 指定API版本,jx用的還是v1alpha2,相對較老
  • build.tagPolicy.template 配置了image的名稱模板,DOCKER_REGISTRY,Version等是環境變數
  • artifacts 陣列,用於指定構建docker映象,可以有多個,workspace制定工作目錄(新版本的api變為了context)
  • deploy 指定部署方式
  • profiles 區分環境,這裡定義了dev環境
    • 設定template ,image的tag為DIGEST_HEX,校驗碼
    • 部署使用helm

如上的配置,在jx裡如何運作的呢?

  • 正式構建環境,只進行構建
    在jenkinsfile裡
     sh 'export VERSION=`cat VERSION` && skaffold build -f skaffold.yaml'

在devpod裡,實現構建和部署

skaffold run -p dev

Draft

draft 是微軟開源的“A tool for developers to create cloud-native applications on Kubernetes”,一個為方便開發者在K8S建立雲原生應用的工具,它可以幫助開發人員簡化容器應用程式的開發流程。

上面我們瞭解了JENKINSFile,charts配置檔案,難道每個專案需要按我們自己來寫這些配置檔案嗎?
Draft告訴你,可以不!Draft最大的益處是,可以自動識別你的工程,然後根據模板庫生成對應的配置檔案,酷不酷?

Draft 主要由三個命令組成

  • draft init:初始化 docker registry 賬號,並在 Kubernetes 叢集中部署 draftd(負責映象構建、將映象推送到 docker registry 以及部署應用等)

  • draft create:draft 根據 packs 檢測應用的開發語言,並自動生成 Dockerfile 和 Kubernetes Helm Charts

  • draft up:根據 Dockfile 構建映象,並使用 Helm 將應用部署到 Kubernetes 叢集(支援本地或遠端叢集)。同時,還會在本地啟動一個 draft client,監控程式碼變化,並將更新過的程式碼推送給 draftd。

不過,在jx中,僅僅只使用了draft的識別語言,生成配置檔案的功能,相關的draft模板可以在# draft-packs 裡看到。

jx draft-packs

Nexus

jx使用Nexus 來做預設的製品倉庫(Artifact repository),Nexus大家應該不預設,好多公司和團隊的maven倉庫均是通過Nexus搭建的。

Nexus還可以作為npm,nuget,docker倉庫。

Chartmuseum 與Monocular

Chartmuseum - 是一個helm chart倉庫,jx用他來做chart倉庫。

Monocular是一個web應用可以用來從helm charts倉庫搜尋和發現charts。

Monocular Screenshot


作者:Jadepeng
出處:jqpeng的技術記事本--http://www.cnblogs.com/xiaoqi
您的支援是對博主最大的鼓勵,感謝您的認真閱讀。
本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。