1、速部署ack-jenkins
容器服务-Kubernetes -> 市场 -> 应用目录 -> ack-jenkins:
点击 参数 菜单修改 AdminPassword 字段, 选择Kubernetes集群、填写命名空间和发布名称并点击 创建:
访问jenkins服务并登陆:
ps:如未设置登陆密码,则可在部署完毕后使用如下命名查看:
$ printf $(kubectl get secret --namespace ci jenkins-ci-jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo
2、配置 Kubernetes Cloud
2.1、配置 Kubernetes Cloud
Jenkins使用Kubernetes Plugin连接Kubernetes集群并动态生成和释放slave pod,关于slave pod的模板配置需要在 系统管理 -> 系统配置 -> 云 中进行配置
- 名称:kubernetes;
- Kubernetes 地址:https://kubernetes.default.svc.cluster.local:443;jenkins 系统安装在当前集群中,可以使用内部服务端点访问集群的 API Server
- Kubernetes 命名空间:jenkins;动态 slave pod 会在命名空间 jenkins 下生成和销毁
点击测试按钮验证连接无误:
- Jenkins 地址:http://ack-jenkins-default:8080;slave pod连接jenkins master使用的服务端点
- Jenkins 通道:ack-jenkins-default-agent:50000;slave pod使用jnlp连接jenkins master
- Pod Templates -> 名称: slave-pipeline; slave pod名称
- Pod Templates -> 命名空间:jenkins
- Pod Templates -> 标签列表:slave-pipeline;jenkins 构建任务通过此标签选择使用哪个模板生成slave pod
- Pod Templates -> 容器列表 -> jnlp;用于jnlp连接jenkins master
- Pod Templates -> 容器列表 -> kaniko;用于构建和推送容器镜像
- Pod Templates -> 容器列表 -> maven:用于maven构建和打包应用
- Pod Templates -> 容器列表 -> kubectl:用于kubectl命令行部署应用
- Pod Templates -> 环境变量;为kaniko设置DOCKER_CONFIG指定docker.json文件路径
创建jenkins-docker-cfg secret用于镜像仓库权限设置
本示例中使用了阿里云镜像服务提供的杭州区域镜像仓库:
$ docker login -u xxx -p xxx registry-vpc.cn-beijing.aliyuncs.com
Login Succeeded
$ kubectl create secret generic jenkins-docker-cfg -n ci --from-file=/root/.docker/config.json
配置slave pod启动时挂载 secret jenkins-docker-cfg:
如果需要设置maven缓存目录,可以挂载hostPath volume 或者共享存储卷到/root/.m2/repository:
如果需要更改 settings.xml,先创建 ConfigMap:
kubectl create configmap maven-config --from-file=settings.xml -n jenkins
再配置挂载到slave pod:
如果需要部署应用到本集群,可以在slave pod中使用ServiceAccount通过kubectl部署,配置ServiceAccount:
2.2 创建构建任务
创建构建任务cicd-pipeline,拉取源码项目https://github.com/haoshuwei/jenkins-demo.git,分支master;maven打包构建,kaniko构建和推送容器镜像;kubectl部署到本集群。
在本示例中,需要打包容器镜像为:registry-vpc.cn-beijing.aliyuncs.com/haoshuwei24/application-demo:20200915
则配置构建参数如下:
构建任务配置如下:
执行构建:
可以在 https://github.com/haoshuwei/jenkins-demo.git 中查看Jenkinsfile内容。
3、连接外部集群
连接外部集群需要创建和使用证书
示例:创建k8sCertAuth证书
在此步骤中,我们需要先创建和配置一个名称为k8sCertAuth
的集群证书, 点击 凭证 添加证书:
4、详解构建任务示例demo-pipeline
demo-pipeline
构建任务完成的持续集成/持续交付任务为:拉取源码、构建应用war包、打包和推送容器镜像以及部署应用到k8s集群。示例源码项目地址为https://github.com/AliyunContainerService/jenkins-demo.git
, 整个构建流程会按照示例项目中Jenkinsfile
声明的内容执行构建。
4.1、demo-pipeline的任务配置
demo-pipeline设置了4个构建参数,分别为origin_repo
repo
image_tag
和 branch
, branch
用于指定本次构建拉取应用源码仓库的哪个分支, 另外3个变量用于构建和推送应用容器镜像的地址,例如示例应用的容器镜像要推送到 registry.cn-hangzhou.aliyuncs.com/ack-cicd/ack-jenkins-demo:latest
, 则origin_repo
为registry.cn-hangzhou.aliyuncs.com/ack-cicd
, repo
为ack-cicd
,image_tag
为latest
。
构建任务中配置从Git仓库拉取源码并指定Jenkinsfile路径:
4.2、 Jenkinsfile解析
我们在示例源码项目的Jenkinsfilejenkins-demo/Jenkinsfile中定义了以下内容:
pipeline{
// 定义groovy脚本中使用的环境变量
environment{
// 将构建任务中的构建参数转换为环境变量
IMAGE_TAG = sh(returnStdout: true,script: 'echo $image_tag').trim()
ORIGIN_REPO = sh(returnStdout: true,script: 'echo $origin_repo').trim()
REPO = sh(returnStdout: true,script: 'echo $repo').trim()
BRANCH = sh(returnStdout: true,script: 'echo $branch').trim()
}
// 定义本次构建使用哪个标签的构建环境,本示例中为 “slave-pipeline”
agent{
node{
label 'slave-pipeline'
}
}
// "stages"定义项目构建的多个模块,可以添加多个 “stage”, 可以多个 “stage” 串行或者并行执行
stages{
// 定义第一个stage, 完成克隆源码的任务
stage('Git'){
steps{
git branch: '${BRANCH}', credentialsId: '', url: 'https://github.com/AliyunContainerService/jenkins-demo.git'
}
}
// 添加第二个stage, 运行源码打包命令
stage('Package'){
steps{
container("maven") {
sh "mvn package -B -DskipTests"
}
}
}
// 添加第三个stage, 运行容器镜像构建和推送命令, 用到了environment中定义的groovy环境变量
stage('Image Build And Publish'){
steps{
container("kaniko") {
sh "kaniko -f `pwd`/Dockerfile -c `pwd` --destination=${ORIGIN_REPO}/${REPO}:${IMAGE_TAG} --skip-tls-verify"
}
}
}
// 添加第四个stage, 部署应用到指定k8s集群
stage('Deploy to Kubernetes') {
parallel {
steps {
container('kubectl') {
step([$class: 'KubernetesDeploy', authMethod: 'certs', apiServerUrl: 'https://kubernetes.default.svc.cluster.local:443', credentialsId:'k8sCertAuth', config: 'deployment.yaml',variableState: 'ORIGIN_REPO,REPO,IMAGE_TAG'])
}
}
}
}
}
}
4.2.1 environment{}
代码块
用于获取构建参数并转换为Jenkinsfile中使用的环境变量。
4.2.2 agent{}
代码块
用于指定本次构建使用的构建节点标签为slave-pipeline
。 进入 系统管理 -> 系统设置 -> 云 可以看到Kubernetes云的配置, 此配置用于定义如何动态创建构建节点:
我们可以从上图的Kubernetes云配置中看到, 当我们执行构建任务时,jenkins会动态连接本集群的api server url:https://kubernetes.default.svc.cluster.local:443
在 jenkins
命名空间下创建 slave pod slave-pipeline-xxx
, 此slave pod包含4个containers, 分别为用于slave连接master的jnlp
、用于maven编译打包java源码的maven
、用于容器镜像构建和部署的kaniko
以及用于部署k8s应用的kubectl
。
当使用kaniko容器进行容器镜像构建和推送时, 我们需要获取镜像推送到仓库的权限, 这个权限是以k8s secret的方式挂载到slave-pipeline-xxx的pod里的,环境变量DOCKER_CONFIG
则定义了kaniko获取镜像仓库推送权限文件的默认路径。 在此我们需要创建名为jenkins-docker-cfg
的secret:
在一台linux机器上执行以下命令:
$ docker login -u xxx -p xxx registry.cn-hangzhou.aliyuncs.com
$ kubectl create secret generic jenkins-docker-cfg -n ci --from-file=/root/.docker/config.json
4.2.3 stages{}
代码块
stages{}
代码块定义了多个stage,分别完成持续集成/持续部署过程中的不同步骤。
4.2.3.1 源码拉取
源码仓库中一般包含Jenkinsfile
Dockerfile
deployment.yaml
等文件
stage('Git'){
steps{
git branch: '${BRANCH}', credentialsId: '', url: 'https://github.com/AliyunContainerService/jenkins-demo.git'
}
}
4.2.3.2 maven编译和打包源码
maven编译的时候,用户通常会想使用缓存功能, maven缓存需要使用NAS共享存储,创建nas volume并挂载到Kubernetes云的slave-pipeline模板上, 类似jenkins-docker-cfg的挂载。
stage('Package'){
steps{
container("maven") {
sh "mvn package -B -DskipTests"
}
}
}
4.2.3.3 kaniko构建和推送镜像
kaniko工具构建容器镜像可以不依赖docker daemon进程,在用户态空间完成镜像构建和推送, 更安全可靠。
stage('Image Build And Publish'){
steps{
container("kaniko") {
sh "kaniko -f `pwd`/Dockerfile -c `pwd` --destination=${ORIGIN_REPO}/${REPO}:${IMAGE_TAG} --skip-tls-verify"
}
}
}
4.2.3.4 kubectl部署k8s应用
stage('Deploy to Kubernetes') {
steps {
container('kubectl') {
step([$class: 'KubernetesDeploy', authMethod: 'certs', apiServerUrl: 'https://kubernetes.default.svc.cluster.local:443', credentialsId:'k8sCertAuth', config: 'deployment.yaml',variableState: 'ORIGIN_REPO,REPO,IMAGE_TAG'])
}
}
}
在此步骤中,我们需要先创建和配置一个名称为k8sCertAuth
的集群证书, 点击 凭证 添加证书:
variableState: 'ORIGIN_REPO,REPO,IMAGE_TAG'
字段声明需要替换deployment.yaml
文件中的哪些环境变量。
5、系统配置详解
5.1 构建环境配置说明
(1)kubernetes集群动态分配构建pod的配置;
(2)slave-pipeline 使用了4个container分别完成流水线中各个stage的构建,Kubernetes Pod Templates配置
container jnlp:
container kaniko:
container kubectl:
container maven:
(3) 使用到的构建镜像:
-
jnlp 用于构建节点jnlp连接master:
jenkinsci/jnlp-slave:3.35-5
-
maven 用于mvn打包构建:
maven:3.6.2-jdk-14
-
kaniko 用于镜像构建和推送:
registry.cn-hangzhou.aliyuncs.com/acs/kaniko:v0.14.0
-
kubectl 用于kubectl部署应用:
registry.cn-hangzhou.aliyuncs.com/acs/kubectl:1.14.8
(4) kaniko配置镜像仓库权限:
5.2 示例项目说明
(1)示例项目中使用的源码仓库
https://github.com/AliyunContainerService/jenkins-demo.git
(2)kaniko 构建和推送docker镜像说明
kaniko可以不依赖docker daemon并在用户空间执行完成Dockerfile中的每一行命令,最终完成docker镜像的构建和推送。
kaniko -f `pwd`/Dockerfile -c `pwd` --destination=${origin_repo}/${repo}:${image_tag}
(3)部署应用到Kubernetes集群插件说明
插件配置如下:
对应的Pipeline语法为:
step([$class: 'KubernetesDeploy', authMethod: 'certs', apiServerUrl: 'https://kubernetes.default.svc.cluster.local:443', credentialsId:'k8sCertAuth', config: 'deployment.yaml',variableState: 'ORIGIN_REPO,REPO,IMAGE_TAG'])
声明的变量ORIGIN_REPO,REPO,IMAGE_TAG可在构建执行时把deployment.yaml文件中对应的变量值替换为实际值:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: jenkins-java-demo
spec:
replicas: 2
selector:
matchLabels:
app: jenkins-java-demo
template:
metadata:
labels:
app: jenkins-java-demo
spec:
containers:
- name: jenkins-java-demo
image: ${ORIGIN_REPO}/${REPO}:${IMAGE_TAG}
imagePullPolicy: Always
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: jenkins-java-demo
spec:
ports:
- port: 80
targetPort: 8080
name: jenkins-java-demo
selector:
app: jenkins-java-demo
type: LoadBalancer
(4)Jenkinsfile说明
pipeline{
// 定义groovy脚本中使用的环境变量
environment{
// 本示例中使用DEPLOY_TO_K8S变量来决定把应用部署到哪套容器集群环境中,如“Production Environment”, “Staging001 Environment”等
IMAGE_TAG = sh(returnStdout: true,script: 'echo $image_tag').trim()
ORIGIN_REPO = sh(returnStdout: true,script: 'echo $origin_repo').trim()
REPO = sh(returnStdout: true,script: 'echo $repo').trim()
BRANCH = sh(returnStdout: true,script: 'echo $branch').trim()
}
// 定义本次构建使用哪个标签的构建环境,本示例中为 “slave-pipeline”
agent{
node{
label 'slave-pipeline'
}
}
// "stages"定义项目构建的多个模块,可以添加多个 “stage”, 可以多个 “stage” 串行或者并行执行
stages{
// 定义第一个stage, 完成克隆源码的任务
stage('Git'){
steps{
git branch: '${BRANCH}', credentialsId: '', url: 'https://github.com/AliyunContainerService/jenkins-demo.git'
}
}
// 添加第二个stage, 运行源码打包命令
stage('Package'){
steps{
container("maven") {
sh "mvn package -B -DskipTests"
}
}
}
// 添加第四个stage, 运行容器镜像构建和推送命令, 用到了environment中定义的groovy环境变量
stage('Image Build And Publish'){
steps{
container("kaniko") {
sh "kaniko -f `pwd`/Dockerfile -c `pwd` --destination=${ORIGIN_REPO}/${REPO}:${IMAGE_TAG}"
}
}
}
stage('Deploy to Kubernetes') {
parallel {
stage('Deploy to Production Environment') {
when {
expression {
"$BRANCH" == "master"
}
}
steps {
container('kubectl') {
step([$class: 'KubernetesDeploy', authMethod: 'certs', apiServerUrl: 'https://kubernetes.default.svc.cluster.local:443', credentialsId:'k8sCertAuth', config: 'deployment.yaml',variableState: 'ORIGIN_REPO,REPO,IMAGE_TAG'])
}
}
}
stage('Deploy to Staging001 Environment') {
when {
expression {
"$BRANCH" == "latest"
}
}
steps {
container('kubectl') {
step([$class: 'KubernetesDeploy', authMethod: 'certs', apiServerUrl: 'https://kubernetes.default.svc.cluster.local:443', credentialsId:'k8sCertAuth', config: 'deployment.yaml',variableState: 'ORIGIN_REPO,REPO,IMAGE_TAG'])
}
}
}
}
}
}
}
了解更多阿里云容器服务内容,请访问 https://www.aliyun.com/product/containerservice
评论区