Jenkins On Kubernetes---Jenkins上Kubernetes Plugin的使用

之前写过一篇《Jenkins On Mesos—Jenkins上Mesos Plugin的使用》的博客,说的是Jenkins通过Mesos Plugin来实现slave节点的动态扩展和收缩。如果使用docker的人,不知道kubernetes的话,总是显得有些尴尬,所以最近自己也开始在测试环境使用目前火热的Kubernetes 1.8版(之前是在用Marathon+Mesos那一套)。Marathon、Mesos有的功能,Kubernetes当然也都有。这里就记录一下Kubernetes上实现slave节点动态增减的Kubernetes Plugin配置的一点实践。

配置Jenkins Server

首先,需要有一套k8s集群环境。之前已经部好了,这里就不说k8s的搭建,只说Jenkins插件。我的k8s集群是配置了SSL加密证书的,所以Jenkins Server要想能与k8s集群的apiserver通信,需要先通过权限认证。k8s里面有个Service Account的概念,配置使用Service Account来实现给Jenkins Server的授权。

Service Account:
相对于kubectl访问apiserver时用的user account,service account方案是为了给Pod中的process访问k8s API提供的一种身份标识。简单的说就是,通过service account可以实现给Pod中的进程授权访问k8s API。

下面是配置Jenkins Server用到的yaml配置文件:
jenkins-rbac.yaml

---
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: jenkins
  name: jenkins-admin
  namespace: kube-system

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: jenkins-admin
  labels:
    k8s-app: jenkins
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: jenkins-admin
  namespace: kube-system

说明:这里是创建了一个名为jenkins-admin的ServiceAccount,直接继承了cluster-admin的权限。还可以根据自己实际情况,创建指定权限的ClusterRole,比如(仅供参考):

---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  labels:
    k8s-app: jenkins
  name: jenkins
rules:
- apiGroups: ["", "extensions", "apps"]
  resources:
    - nodes
    - nodes/proxy
    - endpoints
    - secrets
    - pods
    - deployments
    - services
  verbs: ["get", "list", "watch"]

jenkins.yaml

apiVersion: apps/v1beta2 # for versions before 1.8.0 use apps/v1beta1
kind: Deployment
metadata:
  name: jenkins
  namespace: kube-system
  labels:
    k8s-app: jenkins
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: jenkins
  template:
    metadata:
      labels:
        k8s-app: jenkins
    spec:
      containers:
      - name: jenkins
        image: my.example.com/library/centos7.4-ssh-maven-jenkins:2.19
        imagePullPolicy: Always
        volumeMounts:
        - name: jenkins-home
          mountPath: /var/jenkins_home
        ports:
        - containerPort: 8080
        - containerPort: 50000
      volumes:
        - name: jenkins-home
          hostPath:
            path: /var/www/webapps/jenkins
      nodeSelector:
        jenkins: "true"
      serviceAccount: "jenkins-admin"

注: 这里的Jenkins镜像我是用的自己定制的,可以替换成自己需要的镜像。serviceAccount指定上面创建的jenkins-admin账号。

jenkins-service.yaml

jenkins-service.yaml
---
kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: jenkins
  name: jenkins
  namespace: kube-system
  annotations:
    prometheus.io/scrape: 'true'
spec:
  ports:
    - port: 8080
      name: jenkins
      nodePort: 31888
      targetPort: 8080
    - port: 50000
      name: jenkins-agent
      nodePort: 50000
      targetPort: 50000
  type: NodePort
  selector:
    k8s-app: jenkins

说明:Service配置暴露两个端口,一个是Jenkins Server的访问端口,这里nodePort方式指定的是31888;另一个是Jenkins Agent通信用的端口,默认是50000,如果不暴露的话,Jenkins slave节点是无法和Jenkins Server建了连接的。注:nodePort方式默认的端口范围是30000~32767,不包含50000端口的,可以参考这里进行修改。

配置Kubernetes Plugin

用上面的yaml配置在k8s上将Jenkins Server运行之后,在Jenkins的【插件管理】里面搜索Kubernetes plugin并安装。
这里写图片描述
接下来,在【系统管理】-【系统设置】-【新增一个云】-【Kubernetes】配置k8s的插件。
这里写图片描述
参考上图的说明,进行配置。三个标记到的地方,是需要配置的必须信息,可以根据自己的情况进行配置。要注意的是,这里的Name字段配的名字,后面在配置pipeline的Jenkins任务时,是需要用到的(假设这里使用的名字叫Kubernetes)。然后点【Test Connection】,如果前面的Service Account配置的没问题的话,就会提示“Connection successful”,否则,会有访问apiserver的403权限报错。
这里写图片描述
到这里,最基本的配置其实就可以了。比如,用pipeline方式创建一个如下的Jenkins构建任务:
这里写图片描述

pipeline scripts的内容如下:

/* cloud字段指定系统设置里配置的Kubernetes云的名字,本例用的是:Kubernetes */
podTemplate(label: 'mypod', cloud: 'Kubernetes') {
    node('mypod') {
        stage('Run shell') {
            sh 'echo hello world'
        }
    }
}

这里是一个简单的示例,此插件的更多pipeline写法可以参考: https://github.com/jenkinsci/kubernetes-plugin

点击Jenkins任务构建,观察会自动生成作为slave节点的Pod:
这里写图片描述

运行成功的Jenkins任务输出日志里,可以看到运行的slave节点名:
这里写图片描述

等任务构建完成之后,会发现slave节点又动态的消失了:
这里写图片描述

以上,就完成了我们希望通过Kubernetes Plugin来完成Jenkins Slave节点动态创建和回收的目的。

制作自己的slave节点镜像

上面虽然已经可以实现Jenkins Slave节点的动态创建和回收了,但是使用的是默认的slave镜像:jenkinsci/jnlp-slave。在Jenkins触发任务构建的时候,kubernetest plugin会先去公共的docker仓库获取这个镜像,然后运行容器作为slave节点。实际使用中,我们往往希望用自己预装了一些软件的镜像来做slave节点,来完成我们需要的构建任务。这里就可以参考jenkinsci/jnlp-slave(https://github.com/jenkinsci/docker-jnlp-slave)的制作,来做自己的slave节点镜像。

Jenkins slave连接Server的方法

Jenkins Server和slave节点直接有几种连接方式:ssh连接和jnlp连接。Kubernetes plugin插件用的是jnlp方式。这种方式是通过运行slave.jar,指定Jenkins Server的url参数和secret token参数,来建立连接。

jenkinsci/jnlp-slave镜像是以jenkinsci/slave (https://github.com/jenkinsci/docker-slave)为基础镜像制作的。参考这两个镜像的Dockerfile,做一个自己的:

FROM my.example.com/library/centos7.4-ssh-docker-maven:latest

ENV HOME /home/jenkins
ARG AGENT_WORKDIR=/home/jenkins/agent

COPY slave.jar /usr/share/jenkins/slave.jar
COPY jenkins-slave /usr/local/bin/jenkins-slave

RUN groupadd -g 1000 jenkins \
  && useradd -c "Jenkins user" -d $HOME -u 1000 -g 1000 -m jenkins \
  && chmod 755 /usr/share/jenkins \
  && chmod 644 /usr/share/jenkins/slave.jar 

USER jenkins
ENV AGENT_WORKDIR=${AGENT_WORKDIR}
RUN mkdir /home/jenkins/.jenkins && mkdir -p ${AGENT_WORKDIR}

VOLUME /home/jenkins/.jenkins
VOLUME ${AGENT_WORKDIR}
WORKDIR /home/jenkins

ENTRYPOINT ["jenkins-slave"]

说明:这里的基础镜像是用的自己之前制作的基于centos的镜像(默认的jnlp-slave镜像是基于ubuntu系做的)。slave.jar这个包,可以在自己Jenkins Server的访问地址后添加/jnlpJars/slave.jar路径来获取到(如:http://your-jenkins-server/jnlpJars/slave.jar)。jenkins-slave这个脚本,可以在 https://github.com/jenkinsci/docker-jnlp-slave/blob/master/jenkins-slave 下载到。

使用docker build命令将上面的Dockerfile制作成镜像之后,上传到自己的docker私有仓库来供k8s获取就可以了。

指定使用自制的slave节点镜像

pipeline类型的方式

要想使用自己的slave节点镜像,在配置pipeline脚本的时候,就需要参数指明了。

podTemplate(label: 'mypod-1', cloud: 'Kubernetes', containers: [
    containerTemplate(
        name: 'jnlp', 
        image: 'my.example.com/library/centos7.4-ssh-docker-maven-jenkins-slave:2.19', 
        alwaysPullImage: true, 
        args: '${computer.jnlpmac} ${computer.name}'),

  ],
  volumes: [
    hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock'),
],) 
{
    node('mypod-1') {
        stage('Task-1') {
            stage('show release version') {
                sh 'cat /etc/redhat-release '
            }
        }
    }
}

说明: containerTemplate的name属性必须叫jnlp,才能用images指定的镜像替换默认的jenkinsci/jnlp-slave镜像。此外,还要args参数传递两个jenkins-slave运行需要的参数。

非pipeline类型的方式

如果不使用pipeline类型任务的话,要想使用kubernetes plugin的云构建任务,还需要回到【系统设置】-【云】-【Kubernetes】-【Add Pod Template】里面继续配置
这里写图片描述
这里有两点需要注意:Labels和Containers下的Name字段的名字配置。Labels名在配置非pipeline任务时,用来指定任务运行的节点。
这里写图片描述
Name名则必须叫jnlp,才能用指定的Docker image代替默认的jenkinsci/jnlp-slave镜像,否则,你配的不叫jnlp的容器会被运行,但是Kubernetes plugin还是会用默认的jenkinsci/jnlp-slave镜像与Jenkins Server建立连接。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值