K8S - Jenkins在K8S下的持续集成

image

关于搭建Kubernetes环境可以参考我前面的公众号文章:Centos7下使用kubeadm搭建Kubernetes-v1.14.2,本篇文章主要实现Jenkins在k8s集群的安装、slave节点在k8s内自动创建销毁,通过pipeline实现java项目的持续集成发布。

安装Jenkins服务到K8S集群

使用Dockerfile制作Jenkins镜像

下载war包进行的安装,Dockerfile如下,war包下载地址:https://jenkins.io/zh/download

FROM java:8
RUN echo 'hello docker, start build image'

RUN mkdir -p /app
WORKDIR /app

RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo "Asia/Shanghai" > /etc/timezone

COPY jenkins.war .

CMD ["java" ,"-Xms1024m","-Xmx1024m", "-jar","/app/jenkins.war"]

制作镜像

docker build -t registry.cn-hangzhou.aliyuncs.com/hiningmeng/jenkins:2.176.2  .

docker push registry.cn-hangzhou.aliyuncs.com/hiningmeng/jenkins:2.176.2

K8S安装Jenkins应用

在k8s集群内创建Jenkins工作的namespace,我这边统一放在devops这个ns底下;

kubectl create ns devops

我这里把Jenkins工作目录单独挂载到PVC,需要先创建pv-pvc,挂载点是使用的nfs服务,请先创建好服务,jenkins-pv-pvc.yaml如下:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: jenkins-home-pv
spec:
  capacity:
    storage: 100Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: 192.168.1.100
    path: "/data/jenkins_home"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jenkins-home-pvc
  namespace: devops
spec:
  accessModes: ["ReadWriteMany"]
  resources:
    requests:
      storage: 100Gi

为Jenkins创建单独的ServiceAccount,这里的ClusterRole直接使用的cluster-admin,jenkins-serveraccount.yaml如下;

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

编写Deployment文件,我使用到了node标签apps.k8s.icjl/devops,打标签的命令如下:

kubectl label node your-node-name apps.k8s.icjl/devops=

jenkins-deployment.yaml如下:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: jenkins
  namespace: devops
  labels:
    app: jenkins
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      serviceAccountName: jenkins-admin
      imagePullSecrets:
        - name: ram-secret
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: apps.k8s.icjl/devops
                operator: Exists
      containers:
      - name: jenkins
        image: registry.cn-hangzhou.aliyuncs.com/hiningmeng/jenkins:2.176.2
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: jenkins-home
          mountPath: /root/.jenkins
          readOnly: false
        ports:
        - containerPort: 8080
        - containerPort: 50000
      volumes:
      - name: jenkins-home
        persistentVolumeClaim:
          claimName: jenkins-home-pvc

创建service,这边使用了NodePort,jenkins-service.yaml如下;

apiVersion: v1
kind: Service
metadata:
  labels:
    app: jenkins
  name: jenkins
  namespace: devops
  annotations:
    prometheus.io/scrape: 'true'
spec:
  type: NodePort
  ports:
  - name: jenkins-web
    port: 8080
    targetPort: 8080
    nodePort: 31442
  - name: jenkins-agent
    port: 50000
    targetPort: 50000
    nodePort: 30005
  selector:
    app: jenkins

也可以使用ingress暴露的方式,jenkins-ingress.yaml如下:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: jenkins
  labels:
    name: jenkins
  namespace: devops
spec:
  rules:
  - host: jenkins.hiningmeng.cn
    http:
      paths:
      - path: /
        backend:
          serviceName: jenkins
          servicePort: 8080

执行

 kubectl apply -f jenkins-pv-pvc.yaml
 kubectl apply -f jenkins-serveraccount.yaml
 kubectl apply -f jenkins-deployment.yaml
 kubectl apply -f jenkins-service.yaml
 kubectl apply -f jenkins-ingress.yaml
image-20190806145150888

Jenkins配置

系统管理 --> 插件管理 --> available,安装需要的插件,有的插件下载不下来可以去官网下载之后上传安装。

  • Kubernetes
  • pipeline
  • Git Parameter
配置Kubernetes云信息

在系统管理 --> 系统设置 ,最后面有个Cloud设置,Add a new cloud


image

添加具体的Kubernetes信息,K8S服务器可以是Jenkins本身所在的服务器,也可以是其他集群(需要配置证书),这里以本身所在集群为例。

  • 名称 :用于pipeline调用云名称
  • Kubernetes地址:可以通过kubectl cluster-info命令获取
  • Kubernetes 服务证书 key:本身所在的集群因为我们通过sa所以不需要
  • Kubernetes 命名空间:Jenkins的nodePod节点启动的namespace
  • Jenkins 地址:主节点8080端口通过nodeport暴露出来的,地址:端口
  • Jenkins 通道:主节点50000端口通过nodeport暴露出来的,地址:端口
image
创建pipeline任务

选择新建任务,构建流水线。


image

安装了Git Parameter插件之后,可以进行分支的选择,需要进行参数化构建,这个可以在页面设置,也可以放到pipeline里面,这边直接在页面配置参数。


image

其中Use repository如果不设置,后面的Pipeline from SCRM的时候,就会取不到分支;

指定pipeline地址,可以直接在页面写,做好是通过Git的方式管理。


image

Git管理Pipeline的Jenkinsfile文件,需要提供证书拉取


image
编写Jenkinsfile文件
#定义参数label,K8S启动的pod名称通过这个来制定
def label = "JenkinsPOD-${UUID.randomUUID().toString()}"
#定义jenkins的工作目录
def jenworkspace="/home/jenkins/workspace/${params.PROJECT}"
#maven项目缓存,提供编译速度
def mvnrepo="/tmp/repository"
#kubectl和docker执行文件,这个可以打到镜像里面,这边直接共享的方式提供
def sharefile="/tmp/sharefile"
#deployment等K8S的yaml文件目录
def k8srepo='/tmp/k8s_repos'

#cloud为我们前面提供的云名称,nodeSelector是K8S运行pod的节点选择
podTemplate(label: label, cloud: 'kubernetes-hiningmeng',nodeSelector: 'devops.k8s.icjl/jenkins=jnlp',
    containers: [
        containerTemplate(
            name: 'jnlp',
            image: 'registry-vpc.cn-hangzhou.aliyuncs.com/hiningmeng/jnlp:v1',
            ttyEnabled: true,
            alwaysPullImage: false),
        containerTemplate(
            name: 'jnlp-maven',
            image: 'jenkins/jnlp-agent-maven',
            //image:'ungerts/jnlp-agent-maven',
            ttyEnabled: true,
            alwaysPullImage: false,
            command: 'cat')
    ],
    volumes: [
        hostPathVolume(hostPath: '/var/run/docker.sock', mountPath:'/var/run/docker.sock'),
        persistentVolumeClaim(mountPath: "$mvnrepo", claimName: 'maven-repo-pvc', readOnly: false),
        persistentVolumeClaim(mountPath: "$sharefile", claimName: 'sharefile-repo-pvc', readOnly: false),
    ]
)
{

    node (label) {
        stage('Hello World'){
            container('jnlp'){
                echo "hello, world"
                sh "ln -s $sharefile/kubectl  /usr/bin/kubectl"
                sh "ln -s $sharefile/docker /usr/bin/docker"

            }
        }
        stage('Git Pull'){
            dir("$jenworkspace"){
                git branch: "${params.BRANCH}", changelog: false, credentialsId: 'jenkins-pull-key', poll: false, url: "${params.CODE_URL}"
            }
        }
        stage('Mvn Package'){
            container('jnlp-maven'){
                dir("$jenworkspace"){
                    sh "mvn clean install -Dmaven.test.skip=true  -U  -s  $sharefile/settings.xml"
                }
            }
        }
        stage('Docker build'){
            ...
        }
        stage('K8S Deploy'){
            ...
        }
    }
}


具体的脚本还是自己摸索一下,不同的项目定制即可,大体的架子如上面的实例

构建项目
image

任务一次都没构建的时候会出现报错,构建一次就没问题了;

image

如果一切正常的话,在K8S的devops命名空间会创建出新的POD


image

至此,简单的可伸缩的基于K8S的Jenkins就完成了,如有问题欢迎交流。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容