生产实践-k8s安装Jenkins和Jenkins Kubernetes插件

环境要求:你需要一个正常可以使用的Kubernetes集群,集群中可以使用的内存大于等于4G。
Kubernetes版本1.18

Jenkins插件可以在Kubernetes集群中运行动态jenkins-slave代理。

基于Kubernetes的docker,自动化在Kubernetes中运行的Jenkins-slave代理的缩放。

该插件为每个jenkins-slave代理创建Kubernetes Pod,并在每个构建后停止它。

在Kubernetes中jenkins-slave代理启动,会自动连接到Jenkins主控制器。 对于某些环境变量,会自动注入:

  1. Jenkins_URL:Jenkins Web界面URL
  2. jenkins_secret:身份验证的秘密密钥
  3. jenkins_agent_name:jenkins代理的名称
  4. jenkins_name:jenkins代理的名称(已弃用。仅用于向后兼容性)

不需要在Kubernetes内运行Jenkins Controller。

在k8s中安装jenkins

官网:https://jenkins.io/download
docker:hub.docker.com/r/jenkins/jenkins/tags

建议下载长期支持的版本
To use the latest LTS: docker pull jenkins/jenkins:lts-jdk11
拉取镜像

docker pull jenkins/jenkins:2.289.2-lts-jdk11

重新打tag,上传私服

docker tag jenkins/jenkins:2.289.2-lts-jdk11 harbor.example.com/public/jenkins:2.289.2
docker push harbor.example.com/public/jenkins:2.289.2

制作镜像

mkdir /opt/dockerfile/jenkins -p
cd /opt/dockerfile/jenkins

制作密钥

ssh-keygen -t rsa -b 2048 -C "jenkins@example.com" -N "" -f /root/.ssh/id_rsa
cp /root/.ssh/id_rsa .

#公钥要上传到git

拷贝config.json

cp /root/.docker/config.json .

Dockerfile

vi Dockerfile
FROM harbor.example.com/public/jenkins:2.289.2
USER root
ADD id_rsa /root/.ssh/id_rsa
ADD config.json /root/.docker/config.json
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&\ 
    echo 'Asia/Shanghai' >/etc/timezone

build 镜像打tag

docker build . -t harbor.example.com/infra/jenkins:2.289.2

上传镜像到harbor

docker push harbor.example.com/infra/jenkins:2.289.2

在k8s上创建名称空间

kubectl create ns infra

创建可以访问harbor的secret

kubectl create secret docker-registry harbor --docker-server=harbor.example.com --docker-username=admin --docker-password=Harbor12345 -n infra

jenkins 拉取代码有两种方式(ssh;http)
用ssh的方式要配置密钥对,把公钥放到git里,打私钥放到jenkins镜像中

把公钥配置到git@gitee.com
测试jenkins镜像是否可以通过密钥来连接git

docker run --rm harbor.example.com/infra/jenkins:2.289.2 ssh -i /root/.ssh/id_rsa -T git@gitee.com

jenkins数据持久化配置

可以选择使用nfs+pvc

共享存储nfs

准备一台机器,搭建NFS服务,这台机器要是k8s集群可以访问到的

yum install nfs-utils -y
vim /etc/exports
/wyyt/data/nfs-volume *(rw,no_root_squash)
systemctl start nfs
systemctl enable nfs
mkdir /opt/data/nfs-volume/jenkins_home

在node节点里测试

yum install nfs-utils
showmount -e 10.4.7.1

创建pv

mkdir /opt/k8s-yaml/jenkins -p
cd /opt/k8s-yaml/jenkins
vi pv-nfs-jk.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-jk    #pv名称
spec:
  capacity:          #存储能力,一个pv对象都要指定一个存储能力,
    storage: 100Gi    #存储空间
  accessModes:
  - ReadWriteOnce       #访问模式
  persistentVolumeReclaimPolicy: Recycle        #回收策略
  nfs:          #服务模式 (nfs、ceph、hostpath等)
    path: /opt/data/nfs-volume/jenkins_home      #共享数据目录挂载点
    server: 10.4.7.200         #nfs服务器地址

kubectl apply -f pv-nfs-jk.yaml
persistentvolume/pv1 created
[root@master storage]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv1    1Gi        RWO            Recycle          Available                                   5s
  • pv-nfs-jk : 名称
  • 100Gi: 存储空间大小
  • RWO: 访问模式(ReadWriteOnce缩写)
  • Recycle: 回收策略
  • Available: PV状态

persistentVolumeReclaimPolicy回收策略

  • Retain (保留) 保留数据,需要管理员手动清理
  • Recycle (回收) 清除PV中的数据,效果相当于执行删除命令
  • Delete (删除) 与PV相连的后端存储完成volume的删除操作,常见于云服务商的存储服务

不过需要注意的是,目前只有NFS和HostPath两类支持回收策略,一般设置Retain比较保险

状态有以下几种

  • Available: PV状态,表示可用状态,还未被任何PVC绑定
  • Bound: 已绑定,已经绑定到某个PVC
  • Released: 已释放,对应的pvc已经删除,但资源还没有被集群收回
  • Failed: PV自动回收失败

创建pvc

vim pvc-nfs-jk.yaml 
 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: pvc-nfs-jk
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 100Gi

jenkins 资源配置清单

cd /opt/k8s-yaml/jenkins
vi dp.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: jenkins
  name: jenkins
  namespace: infra
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: jenkins
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      containers:
        - env:
            - name: JAVA_OPTS
              value: '-Xmx512m -Xms512m'
          image: 'harbor.example.com/infra/jenkins:2.289.2'
          imagePullPolicy: Always
          livenessProbe:
            failureThreshold: 3
            initialDelaySeconds: 15
            periodSeconds: 10
            successThreshold: 1
            tcpSocket:
              port: 8080
            timeoutSeconds: 1
          name: jenkins
          ports:
            - containerPort: 50000
              protocol: TCP
            - containerPort: 8080
              protocol: TCP
          readinessProbe:
            failureThreshold: 3
            initialDelaySeconds: 15
            periodSeconds: 10
            successThreshold: 1
            tcpSocket:
              port: 8080
            timeoutSeconds: 1
          resources:
            requests:
              cpu: 250m
              memory: 512Mi
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          volumeMounts:
            - mountPath: /run/docker.sock
              name: volume-image-0
            - mountPath: /var/jenkins_home
              name: volume-jenkins
            - mountPath: /etc/localtime
              name: volume-localtime
      volumes:
        - hostPath:
            path: /run/docker.sock
            type: ''
          name: volume-image-0
        - name: volume-jenkins
          persistentVolumeClaim:
            claimName: pvc-nfs-jk
        - hostPath:
            path: /etc/localtime
            type: ''
          name: volume-localtime
vi svc.yaml
kind: Service
apiVersion: v1
metadata: 
  name: jenkins-svc
  namespace: infra
spec:
  ports:
    - name: jenkins-svc-8080-8080
      port: 8080
      protocol: TCP
      targetPort: 8080
    - name: jenkins-svc-50000-50000
      port: 50000
      protocol: TCP
      targetPort: 50000
  selector:
    app: jenkins
vim ingress.yaml
kind: Ingress
apiVersion: extensions/v1beta1
metadata: 
  name: jenkins-ingress
  namespace: infra
spec:
  rules:
  - host: jenkins.example.com#ingress定义对外域名
    http:
      paths:
      - path: /
        backend: #绑定server资源配置清单内容
          serviceName: jenkins-svc
          servicePort: 80

在运维主机上应用资源配置清单

kubectl apply -f http://k8s-yaml.example.com/jenkins/dp.yaml
kubectl apply -f http://k8s-yaml.example.com/jenkins/svc.yaml
kubectl apply -f http://k8s-yaml.example.com/jenkins/ingress.yaml

查看jenkins密码

cd /opt/data/nfs-volume/jenkins_home/

安装插件

  1. Kubernetes plugin
  2. Kubernetes :: Pipeline :: DevOps Steps
  3. Github App Kubernetes Credentials
  4. Kubernetes Continuous Deploy Plugin

配置k8s插件

系统管理在凭据中添加凭据secret text
在这里插入图片描述

Secret填写你k8s集群的访问token
创建token
创建jenkins用户

kubectl create serviceaccount  jenkins -n infra

绑定admin角色到jenkins用户
$ clusterrolebinding NAME --clusterrole=NAME [–user=username] [–group=groupname] [–serviceaccount=namespace:serviceaccountname] [–dry-run]

kubectl create clusterrolebinding -n infra jenkins-cluster-admin --clusterrole='cluster-admin' --serviceaccount=infra:jenkins

查询token

kubectl get secrets -n infra-o jsonpath="{.items[?(@.metadata.annotations['kubernetes\.io/service-account\.name']=='jenkins')].data.token}" | base64 -d

结果填入secret
描述:访问k8stoken
在这里插入图片描述
系统管理在节点列表中选择configure clouds
在这里插入图片描述
在这里插入图片描述
名称:kubernetes
Kubernetes 地址:https://kubernetes.default.svc.cluster.local:443
Kubernetes 命名空间:infra
凭据:访问k8stoken
连接测试
在这里插入图片描述
在这里插入图片描述
Jenkins 地址:http://jenkins-svc:8080
Jenkins 通道:jenkins-svc:50000

保存应用

临时创建一个demo项目测试是否能正常动态启动jenkins-slave后销毁

创建一个叫demo 的Pipeline
pipeline脚本

def label = "mypod-${UUID.randomUUID().toString()}"
podTemplate(label: label, cloud: 'kubernetes') {
    node(label) {
        stage('Run shell') {
            sh 'sleep 130s'
            sh 'echo hello world.'
        }
    }
}

能正常启动一个jenkins-slave代理
在这里插入图片描述
参考文档:

https://plugins.jenkins.io/kubernetes/

Logo

开源、云原生的融合云平台

更多推荐