在Google Kubernetes集群创建分布式Jenkins(一)-CSDN博客

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

因为项目需要在GKE的集群上需要创建一个CICD的环境记录一下安装部署一个分布式Jenkins集群的过程。

分布式Jenkins由一个主服务器和多个Agent组成Agent可以执行主服务器分派的任务。如下图所示

如上图Jenkins Agent可以运行不同的操作系统执行主服务器分派的编译打包或测试等任务。

在Jenkins的官网上介绍了在K8S上安装的几种方式包括了Helm, operator等。但是我直接用Helm最新版的Jenkins安装始终遇到问题日志报错信息是Google的OAUTH插件编译有问题如果用旧版本的可以安装成功但是我不想用旧的版本而新版本的问题暂时没找到解决的思路另外Helm安装的values配置过于繁杂。我考虑用最传统的Yaml manifest的方式来部署这个Jenkins。

创建Jenkin主服务器

首先是创建namespace的manifest配置如下

apiVersion: v1
kind: Namespace
metadata:
  name: "jenkins"
  labels:
    name: "jenkins"

定义Storage class的manifest

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: storage-jenkins
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard
  fstype: ext4
volumeBindingMode: WaitForFirstConsumer

定义PVC保存Jenkins的相关数据

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: jenkins-pvc 
  namespace: jenkins
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: "storage-jenkins" 
  resources:
    requests:
      storage: 30Gi 

然后就是创建一个deployment部署Jenkins pod注意在containers的env里面增加了一个环境变量定义了jenkins uri的前缀然后在probe的path里也相应的加了/jenkins前缀。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
  namespace: jenkins
spec:
  selector:
    matchLabels:
      app: jenkins
  replicas: 1
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      volumes:
        - name: pvc-jenkins 
          persistentVolumeClaim:
            claimName: jenkins-pvc 
      containers:
      - name: jenkins
        image: "jenkins/jenkins:lts"
        securityContext:
          runAsUser: 0
        volumeMounts:
          - mountPath: "/var/jenkins_home/"
            name: pvc-jenkins
        env:
        - name: JENKINS_OPTS
          value: --prefix=/jenkins 
        ports:
        - containerPort: 8080
        - containerPort: 50000 
        resources:
          limits:
            cpu: "2"
            memory: "4Gi"
          requests:
            cpu: "1"
            memory: "2Gi"
        livenessProbe:
          httpGet:
            path: "/jenkins/login"
            port: 8080
          initialDelaySeconds: 90
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 5
        readinessProbe:
          httpGet:
            path: "/jenkins/login"
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3

创建一个service来暴露Jenkins的地址和端口注意这里加了GCP的neg注解使得可以使用ingress来暴露另外指定了jenkins agent和jenkis master之间通讯的接口50000

apiVersion: v1
kind: Service
metadata:
  name: jenkins-svc
  namespace: jenkins
  annotations:
   cloud.google.com/neg: '{"ingress": true}'
  labels:
    app: jenkins
spec:
  ports:
  - name: jenkinsport
    port: 8080
    targetPort: 8080
  - name: slaveconnectors
    port: 50000
    targetPort: 50000
  selector:
    app: jenkins

再创建一个ingress使得可以从公网访问

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: jenkins-ingress
  namespace: jenkins
spec:
  rules:
      - http:
         paths:
            - path: /jenkins
              pathType: Prefix
              backend:
                 service:
                     name: jenkins-svc
                     port:
                       number: 8080

最后创建一个kustomization.yaml把以上部分组合起来

resources:
  - namespace.yaml
  - storage-class.yaml
  - pvc.yaml
  - deployment.yaml
  - service.yaml
  - ingress.yaml

然后运行命令kubectl apply -k kustomization_dir/即可部署。等待ingress创建完成后在gcp console的网页上找到相应的地址在浏览器上访问即可进入jenkins的配置页面。如果不能访问我们需要检查一下Firewall是否没有放通。

初次访问配置页面需要输入admin password这个可以从Jenkins pod的日志查到。

kubectl logs <jenkins_pod_name> -n jenkins

之后我们可以安装建议的插件然后创建一个Jenkins的用户

安装Jenkins动态Agent

有了主服务器之后我们就可以配置动态Agent了。以下是Jenkins创建动态Agent的流程图

  1. 当触发Jenkins任务的时候Jenkins kubernetes插件会给K8S服务器发起一个API调用创建一个Agent pod.
  2. 这个Jenkins agent pod会运行在K8S上来运行Jenkins任务当任务完成时会自动中止。
  3. 当Jenkins agent pod启动时会读取环境变量配置并和Jenkins主服务器通过JNLP的方式沟通。

安装Jenkins kubernetes插件

在Jenkins的Manage Jenkins页面选择Plugin搜索Kubernetes并安装。安装完成后重启Jenkins

1. 连接Kubernetes

在Jenkins的Manage Jenkins->Clouds->New Cloud类型选择Kubernetes.

然后在配置项里面Kubernetes url和Kubernetes server certificate key都不用输入因为我们的Jenkins master server是在同一个Kubernetes里面。Namespace输入jenkins。然后赋予jenkins这个namespace下的default用户cluster-admin的role。如以下命令

kubectl create clusterrolebinding jenkins --clusterrole cluster-admin --serviceaccount=jenkins:default

点击Test Connection如果正常就会显示连接成功。

2. 配置Jenkins URL

输入Jenkins service的internal DNS的名称因为我们之前定义了jenkins前缀所以URL是http://jenkins-svc.jenkins.svc.cluster.local:8080/jenkins

3. 创建Pod和Container template

Pod label key设置为jenkinsvalue设置为slave。Pod template name输入jenkins-slavenamespace输入Jenkinslabels输入slave。Containers里面先不加container templateJenkins默认是用Jenkins/inbound-agent这个镜像

然后需要Add volume detail因为我们的Jenkins agent是docker in docker所以需要选择Host path volume然后把kubernetes节点的docker daemon socket mount到Jenkins agent pod. 在Host path和mount path分别输入/var/run/docker.sock

4. 配置Service Account

因为Jenkins agent pod需要权限来调用GCP的服务例如推送image到repository等。需要创建一个service account来给agent使用。

首先在K8S的jenkins namespace创建一个service account

kubectl create serviceaccount jenkins-sa --namespace jenkins

在GCP IAM里面创建一个service account

gcloud iam service-accounts create jenkins-sa --project=PROJECT_ID

给这个service account赋予需要的role可以用以下命令

gcloud projects add-iam-policy-binding PROJECT_ID --member "serviceAccount:jenkins-sa@PROJECT_ID.iam.gserviceaccount.com" --role "ROLE_NAME"

把这两个service account绑定起来使得K8S的service account可以模仿GCP的service account

gcloud iam service-accounts add-iam-policy-binding jenkins-
sa@PROJECT_ID.iam.gserviceaccount.com --role roles/iam.workloadIdentityUser --member
"serviceAccount:PROJECT_ID.svc.id.goog[jenkins/jenkins-sa]"

Annotate K8S的service account加上email地址

kubectl annotate serviceaccount jenkins-sa --namespace jenkins
iam.gke.io/gcp-service-account=jenkins-sa@PROJECT_ID-
v1.iam.gserviceaccount.com

最后还要把Run as user id设为0使得jenkins agent pod以root用户来运行以避免权限问题。最后Save即可完成配置。

5. 设置Agent连接端口

回到Manage jenkins的manage globle security里面在Agent的设置下选择指定端口填入50000

运行Jenkins CICD pipeline

现在可以构建一个CICD pipeline了。下图是构建CICD的一个流程图

这里面包括了几个步骤

  1. 往Git仓库提交代码通过hook触发jenkins任务
  2. Jenkins启动agent pod运行打包任务
  3. 把打包的镜像推送到registry
  4. 更新部署的manifest更新镜像的标签
  5. 把应用部署到GKE

我这里将扩展一下这些步骤增加Jenkin和Github webhook的集成使得用户提交PR的时候自动触发UT检查然后当用户执行merge操作的时候来触发打包任务。这部分的内容比较多我将在下一篇博客中记录具体的操作过程。

现在我将建立一个简单的任务测试一下我们配置的Jenkins是否能正常工作。

在主页面选择新建任务然后选择pipeline然后在pipeline script里面输入以下内容

pipeline {
  agent{
    kubernetes{
        label 'slave'
    }
  }
  environment {
    ZONE = "us-central1"
    PROJECT_ID = "curious-athlete-401708"
  }

  stages{      
    stage("test"){
      steps{
        script{
          sh 'echo "testing"'
        }
      }
    }
  }
}

运行这个任务我们可以看到页面会显示自动创建一个jenkins-slave-xxxx的pod然后在这个pod上运行我们的pipeline。运行结束之后我们可以查看Job的console log可以看到成功执行了pipeline里面定义的echo testing

可见我们已经成功配置了一个Kubernetes上的分布式jenkins环境。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: gok8s

“在Google Kubernetes集群创建分布式Jenkins(一)-CSDN博客” 的相关文章