自动化CICD总览:

拉取代码 --> 代码编译 --> 单元测试 --> 构建镜像 --> 部署到K8S集群 --> 功能验证

Aspose.Words.a3669c4a-a615-4737-8894-65a49c667547.002

前提条件:

  • Jenkins部署在K8S集群中(非集群中需要配置jenkins可以连接当前的K8S集群);
  • Gitlab服务正常启动;
  • Harbor服务正常启动;

一、成果概览

原数据信息:

Aspose.Words.a3669c4a-a615-4737-8894-65a49c667547.004

参数化构建:

Aspose.Words.a3669c4a-a615-4737-8894-65a49c667547.005

构建过程:

Aspose.Words.a3669c4a-a615-4737-8894-65a49c667547.006

自动发布到Kubernetes集群:

Aspose.Words.a3669c4a-a615-4737-8894-65a49c667547.007

流程结束:

Aspose.Words.a3669c4a-a615-4737-8894-65a49c667547.008

二、部署Jenkins(v2.504.1)

1、定义控制器文件

(1)定义jenkins-deploy-svc.yaml文件

[root@master01 4]# vim jenkins-deploy-svc.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
  namespace: devops
spec:
  selector:
    matchLabels:
      app: jenkins
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      terminationGracePeriodSeconds: 10
      serviceAccount: jenkins-sa
      containers:
      - name: jenkins
        image: registry.cn-hangzhou.aliyuncs.com/abroad_images/jenkins:2.387.2-lts
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080
          name: web
          protocol: TCP
        - containerPort: 50000
          name: agent
          protocol: TCP
        resources:
          limits:
            cpu: 2000m
            memory: 3Gi
          requests:
            cpu: 500m
            memory: 1Gi
        livenessProbe:
          httpGet:
            path: /login
            port: 8080
          initialDelaySeconds: 60
          timeoutSeconds: 5
          failureThreshold: 12
        readinessProbe:
          httpGet:
            path: /login
            port: 8080
          initialDelaySeconds: 60
          timeoutSeconds: 5
          failureThreshold: 12
        volumeMounts:
        - name: jenkinshome
          mountPath: /var/jenkins_home
        env:
          - name: JAVA_OPTS
            value: -XshowSettings:vm -Dhudson.slaves.NodeProvisioner.initialDelay=0 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Duser.timezone=Asia/Shanghai -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85
      securityContext:
        #ifsGroup: 1000
        runAsUser: 0
      volumes:
      - name: jenkinshome
        persistentVolumeClaim:
          claimName: jenkins-pvc

---
apiVersion: v1
kind: Service
metadata:
  name: jenkins
  namespace: devops
  labels:
    app: jenkins
spec:
  selector:
    app: jenkins
  type: ClusterIP
  ports:
  - name: web
    port: 8080
    targetPort: web
  - name: agent
    port: 50000
    targetPort: agent

默认情况下,Jenkins生成代理是保守的。

例如,如果队列中有两个构建,它不会立即生成两个执行器。它将生成一个执行器,并等待某个时间释放第一个执行器,然后再决定生成第二个执行器。Jenkins确保它生成的每个执行器都得到了最大限度的利用。

如果你想覆盖这个行为,并生成一个为每个构建队列不等待的执行器,所以在Jenkins启动时候添加这些参数

  • -Dhudson.slaves.NodeProvisioner.initialDelay=0
  • -Dhudson.slaves.NodeProvisioner.MARGIN=50
  • -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85

(2)定义jenkins-rbac.yaml

[root@master01 4]# vim jenkins-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins-sa
  namespace: devops

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: jenkins-cr
rules:
  - apiGroups: ["extensions", "apps"]
    resources: ["deployments"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
  - apiGroups: [""]
    resources: ["services"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["create","delete","get","list","patch","update","watch"]
  - apiGroups: [""]
    resources: ["pods/exec"]
    verbs: ["create","delete","get","list","patch","update","watch"]
  - apiGroups: [""]
    resources: ["pods/log"]
    verbs: ["get","list","watch"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: jenkins-crd
roleRef:
  kind: ClusterRole
  name: jenkins-cr
  apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
  name: jenkins-sa
  namespace: devops

说明:新版本rbac已经不支持rbac.authorization.k8s.io/v1beta1

(3)定义jenkins-pvc.yaml

[root@master01 4]# vim jenkins-pvc.yaml
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: jenkins-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Delete
  nfs:
    server: 192.168.1.66
    path: /opt/sharedata/data/jenkins

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jenkins-pvc
  namespace: devops
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 10Gi

(4)定义jenkins-ing.yaml

[root@master01 4]# vim jenkins-ing.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/enable-cors: 'true'
    nginx.ingress.kubernetes.io/proxy-body-size: 50M
  name: jenkins-ingress
  namespace: devops
spec:
  ingressClassName: nginx
  rules:
  - host: jenkins.zhang-qing.com
    http:
      paths:
      - path: /
        pathType: ImplementationSpecific
        backend:
          service:
            name: jenkins
            port:
              number: 8080

2、Jenkins使用NFS做数据持久化

#在nfs机器上创建相关目录
[root@node01 ~]# mkdir -p /opt/sharedata/data/jenkins

#在nfs机器上修改/etc/exports文件
[root@node01 ~]# vim /etc/exports
/opt/sharedata 192.168.1.0/24(rw,sync,insecure,no_subtree_check,no_root_squash)
/opt/sharedata/data/jenkins 192.168.1.0/24(rw,sync,insecure,no_subtree_check,no_root_squash)

#在nfs机器配置生效
[root@k8s-node01 ~]# exportfs -r

#在nfs机器重新加载NFS
[root@k8s-node01 ~]# systemctl reload nfs-server

3、开始部署

(1)创建ns

[root@master01 4]# k create ns devops

(2)部署

[root@master01 ~]# cd /root/4
[root@master01 4]# kaf jenkins-deploy-svc.yaml,jenkins-rbac.yaml,jenkins-pvc.yaml,jenkins-ing.yaml

(3)查看

#查看pod
[root@master01 4]# kgp -n devops -owide | grep jenkins
jenkins-b6bf6dd-vwrhz         1/1     Running   0             41m     172.31.112.148   master01   <none>           <none>

#查看pvc
[root@master01 4]# kg pvc -n devops | grep jenkins
jenkins-pvc       Bound    pvc-d0a1cc4a-789e-4129-9e51-102fe701f0e5   10Gi       RWX            nfs-storage    141m

#查看svc
[root@master01 4]# kg svc -n devops | grep jenkins
jenkins           ClusterIP   10.0.6.148     <none>        8080/TCP,50000/TCP   141m

4、登录测试

初始化的密码我们可以在 jenkins 的容器的日志中进行查看,也可以通过指定数据位置查看:

# 方式一:在日志中查看
[root@master01 harbor]# k logs -f jenkins-b6bf6dd-vwrhz   -n devops
...
...
Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:

61a0d866a86c4add9a79d85c7c994d2b
...
...

# 方式二:指定数据位置查看
[root@master01 4]# kubectl exec -it jenkins-b6bf6dd-vwrhz -ndevops -- cat /var/jenkins\_home/secrets/initialAdminPassword
61a0d866a86c4add9a79d85c7c994d2b

需要在 nfs 共享数据目录下面把我们的目录权限重新分配下即可:

$ chown -R 1000 /opt/sharedata/data/jenkins

打开浏览器,输入http://jenkins.zhang-qing.com/后,填写管理员密码61a0d866a86c4add9a79d85c7c994d2bimage-20231115204639199

点击【选择插件来安装】

image-20231115205237245

选择【无】后,点击【安装】

image-20231115205512350

配置管理员用户,配置完成后,选择【保存并完成】

image-20231116223834076

配置Jenkins URL,点击【保存并完成】

image-20231223191130368

上面配置完成后,代表Jenkins部署完成

image-20231118101915571