本文介绍jenkins X(如下简称jx)相关的背景技术。html
jenkins X 简介
Jenkins X 是一个高度集成化的CI/CD平台,基于Jenkins和Kubernetes实现,旨在解决微服务体系架构下的云原生应用的持续交付的问题,简化整个云原生应用的开发、运行和部署过程。java
jx 基于gitops,将k8s分为preview、staging、production几个环境,linux
详细的devops能够查看下图:nginx
jx是云原生CICD,devops的一个最佳实践之一,目前在快速的发展成熟中。最近调研了JX,准备写一个jx实践系列,这里为第一篇,介绍jx用到的一些相关组件,做为了解jx的背景知识。git
jenkins pipeline
jx使用Jenkins Pipeline来执行CI流程,Jenkins Pipeline是jenkins的一套插件,支持将连续输送Pipeline实施和整合到Jenkins。Pipeline 提供了一组可扩展的工具,用于经过Pipeline DSL为代码建立简单到复杂的传送Pipeline 。github
Jenkinsfile pipeline使用Groovy脚原本定义CI流程,来看一个jx生成的实际案例:golang
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镜像执行命令
- stage('CI Build and push snapshot') 定义子流程
- 其他的看字面意思就能够理解了
执行构建后,打开jenkins web页面,能够看到构建pipelinesweb
同时能够查看Blue Ocean页面docker
helm与charts
Helm是管理Kubernetes charts的工具,charts是预先配置好的安装包资源,有点相似于Ubuntu的APT和CentOS中的yum。npm
能够使用helm来:
- 查找并使用已打包为Helm charts的热门应用在Kubernetes中运行
- 封装并分享本身的应用
- 建立可重复的Kubernetes应用程序版本
- 智能管理应用依赖
- 管理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.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 里看到。
Nexus
jx使用Nexus 来作默认的制品仓库(Artifact repository),Nexus你们应该不默认,好多公司和团队的maven仓库均是经过Nexus搭建的。
Nexus还能够做为npm,nuget,docker仓库。
Chartmuseum 与Monocular
Chartmuseum - 是一个helm chart仓库,jx用他来作chart仓库。
Monocular是一个web应用能够用来从helm charts仓库搜索和发现charts。
做者:Jadepeng 出处:jqpeng的技术记事本--http://www.cnblogs.com/xiaoqi 您的支持是对博主最大的鼓励,感谢您的认真阅读。 本文版权归做者全部,欢迎转载,但未经做者赞成必须保留此段声明,且在文章页面明显位置给出原文链接,不然保留追究法律责任的权利。