K8S搭建jenkins并自动化发布

#yaml并做持久化存储

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jenkins-pvc
  namespace: jenkins
spec:
  storageClassName: "course-nfs-storage"
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins
  namespace: jenkins
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: jenkins
rules:
  - apiGroups: ["extensions", "apps"]
    resources: ["deployments", "ingresses"]
    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", "events"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: jenkins
  namespace: jenkins
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: jenkins
subjects:
  - kind: ServiceAccount
    name: jenkins
    namespace: jenkins
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
  namespace: jenkins
spec:
  selector:
    matchLabels:
      app: jenkins
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      serviceAccount: jenkins
      initContainers:
        - name: fix-permissions
          image: busybox:1.35.0
          command: ["sh", "-c", "chown -R 1000:1000 /var/jenkins_home"]
          securityContext:
            privileged: true
          volumeMounts:
            - name: jenkinshome
              mountPath: /var/jenkins_home
      containers:
        - name: jenkins
          image: jenkins/jenkins:2.414.1-lts-jdk11
          imagePullPolicy: IfNotPresent
          env:
            - name: JAVA_OPTS
              value: -Dhudson.model.DownloadService.noSignatureCheck=true
          ports:
            - containerPort: 8080
              name: web
              protocol: TCP
            - containerPort: 50000
              name: agent
              protocol: TCP
          readinessProbe:
            httpGet:
              path: /login
              port: 8080
            initialDelaySeconds: 60
            timeoutSeconds: 5
            failureThreshold: 12
          volumeMounts:
            - name: jenkinshome
              mountPath: /var/jenkins_home
      volumes:
        - name: jenkinshome
          persistentVolumeClaim:
            claimName: jenkins-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: jenkins
  namespace: jenkins
  labels:
    app: jenkins
spec:
  selector:
    app: jenkins
  ports:
    - name: web
      port: 8080
      targetPort: web
    - name: agent
      port: 50000
      targetPort: agent
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: jenkins
  namespace: jenkins
spec:
  ingressClassName: nginx
  rules:
    - host: jenkins.test.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: jenkins
                port:
                  name: web

apiVersion: v1
kind: PersistentVolume
metadata:
  name: jenkins-pv
  namespace: app
spec:
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: jenkins-pv
  nfs:
    path: /usr/local/work/work/jenkins/data
    server: 192.168.2.249
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jenkins-pvc
  namespace: app
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  storageClassName: jenkins-pv
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins
  namespace: app
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: jenkins
rules:
  - apiGroups: ["extensions", "apps"]
    resources: ["deployments", "ingresses"]
    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", "events"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: jenkins
  namespace: app
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: jenkins
subjects:
  - kind: ServiceAccount
    name: jenkins
    namespace: app
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
  namespace: app
spec:
  selector:
    matchLabels:
      app: jenkins
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      serviceAccount: jenkins
      initContainers:
        - name: fix-permissions
          image: busybox:1.35.0
          command: ["sh", "-c", "chown -R 1000:1000 /var/jenkins_home"]
          securityContext:
            privileged: true
          volumeMounts:
            - name: jenkins-data
              mountPath: /var/jenkins_home
      containers:
        - name: jenkins
          image: jenkins/jenkins:2.414.1-lts-jdk11
          imagePullPolicy: IfNotPresent
          env:
            - name: JAVA_OPTS
              value: -Dhudson.model.DownloadService.noSignatureCheck=true
          ports:
            - containerPort: 8080
              name: web
              protocol: TCP
            - containerPort: 50000
              name: agent
              protocol: TCP
          readinessProbe:
            httpGet:
              path: /login
              port: 8080
            initialDelaySeconds: 60
            timeoutSeconds: 120
            failureThreshold: 12
          volumeMounts:
            - name: jenkins-data
              mountPath: /var/jenkins_home
      volumes:
        - name: jenkins-data
          persistentVolumeClaim:
            claimName: jenkins-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: jenkins
  namespace: app
  labels:
    app: jenkins
spec:
  selector:
    app: jenkins
  ports:
    - name: web
      port: 8080
      targetPort: web
    - name: agent
      port: 50000
      targetPort: agent
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: jenkins
  namespace: app
spec:
  ingressClassName: nginx
  rules:
    - host: jenkins.ingress.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: jenkins
                port:
                  name: web

#登录jenkins后安装kubernetes插件并添加k8s集群

微信截图_20230912095051.png#在clouds中添加

[root@k8s-master ~]# cat  /root/.kube/config
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJek1EZ3pNREUyTkRZek4xb1hEVE16TURneU56RTJORFl6TjFvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTUFWCnpLVXdYenFhNTNTdWM1Z2paR0xraC9xQ3A1ZDVtREc1SCs5NjR4NlE1TEkxWWVaUVpNKzRJTFEwMmFsWWpTaVMKY3o1aGFaYkhOVjlidHVqM2Iwb3ZxczlhNURESnlQVTFFZStQMFJWdHNQY0dDZUxDSU5ORlJzSUZKcmpwM1FHNwpXOHBVMFg4VWVTK1U4dzREWHFPSFFwOWlsTHBFNlFSbXg0eWVKU1NHOEpXSGtScmR3VCtETU5uUW9ieFpvQ0dyClZVWitOTVNhVWtJai94bWxkSkpUeGFzV2wvU3NnazNHMUxQSHlucDhaK0pPbFhDVyt4TTRQRCs0Q0FXcVY3NzAKZEhKM3dLajZkWlU0V01PMFlteTQzbGdudWxWeTBOMCtLSUhKbmRBNXAwMUlINFE5MnQvT3JDK0Ywa2U5Z3VmZApVeVd1WHVMRy9rKzdYRmhkaEZjQ0F3RUFBYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZLQ2VSajJHMk91VlE4NFZCZHpYMGZEd1JrZ2lNQTBHQ1NxR1NJYjMKRFFFQkN3VUFBNElCQVFDbWZGSDdNazlKTTFrZmR6eU4yUWgvRGQvYU5JK2paYnYwRUJvSHZteXZtMXhHZEF5MwpWaEVxeDlOSFlpTUZxSkp2aUVPbkdiL0c3ZXZZOG9HdU02bEpFMW94OUJDSmg5OUkyeWRGL3cvSUs5ZTFxZCtRCjNtaXZ1NTZ5RkwwazZOZndmeXA0eHJNZXlBUHFuVVVNMml0MERjMGt3UXpqS09vamZYK3NjMDE1UlNmNHFhbHkKekRYVFViVFhZdDl0dis1czNva0g5eDhhS0tNdk1TYVJmNVhBOStqNncrbzdQQjUzWkNzRDcyK1hoNnh6NFVWeApEQzBNQlBtRzZvZlNiY1kyZmpVeG5SNFdyN1VZMk1FTTNUVnpCYXZuKzU5Y0ZWVm5LNW9pSGQ4Y2FBR2xQaXpOCnoyenowK05iaVlQbUZTWmlzcVhLb3ZWUGNlWmJjMEQyNlpyQwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    server: https://192.168.2.249:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    namespace: kube-system
    user: jjy
  name: jjy-context
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: jjy
  user:
    client-certificate: /usr/local/work/test/rdbc/jjy.crt
    client-key: /usr/local/work/test/rdbc/jjy.key

查看certificate-authority-data的内容并转化成base64 encoded文件

echo LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJek1EZ3pNREUyTkRZek4xb1hEVE16TURneU56RTJORFl6TjFvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTUFWCnpLVXdYenFhNTNTdWM1Z2paR0xraC9xQ3A1ZDVtREc1SCs5NjR4NlE1TEkxWWVaUVpNKzRJTFEwMmFsWWpTaVMKY3o1aGFaYkhOVjlidHVqM2Iwb3ZxczlhNURE== | base64 -d > ./ca.crt

[root@k8s-master ~]# cat ca.crt 
-----BEGIN CERTIFICATE-----
MIIC5zCCAc+gAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl
cm5ldGVzMB4XDTIzMDgzMDE2NDYzN1oXDTMzMDgyNzE2NDYzN1owFTETMBEGA1UE
AxMKa3ViZXJuZXRlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMAV
zKUwXzqa53Suc5gjZGLkh/qCp5d5mDG5H+964x6Q5LI1YeZQZM+4ILQ02alYjSiS
cz5haZbHNV9btuj3b0ovqs9a5DDJyPU1Ee+P0RVtsPcGCeLCINNFRsIFJrjp3QG7
W8pU0X8UeS+U8w4DXqOHQp9ilLpE6QRmx4yeJSSG8JWHkRrdwT+DMNnQobxZoCGr
VUZ+NMSaUkIj/xmldJJTxasWl/Ssgk3G1LPHynp8Z+JOlXCW+xM4PD+4CAWqV770
dHJ3wKj6dZU4WMO0Ymy43lgnulVy0N0+KIHJndA5p01IH4Q92t/OrC+F0ke9gufd
UyWuXuLG/k+7XFhdhFcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB
/wQFMAMBAf8wHQYDVR0OBBYEFKCeRj2G2OuVQ84VBdzX0fDwRkgiMA0GCSqGSIb3
DQEBCwUAA4IBAQCmfFH7Mk9JM1kfdzyN2Qh/Dd/aNI+jZbv0EBoHvmyvm1xGdAy3
VhEqx9NHYiMFqJJviEOnGb/G7evY8oGuM6lJE1ox9BCJh99I2ydF/w/IK9e1qd+Q
3mivu56yFL0k6Nfwfyp4xrMeyAPqnUUM2it0Dc0kwQzjKOojfX+sc015RSf4qaly
zDXTUbTXYt9tv+5s3okH9x8aKKMvMSaRf5XA9+j6w+o7PB53ZCsD72+Xh6xz4UVx
DC0MBPmG6ofSbcY2fjUxnR4Wr7UY2MEM3TVzBavn+59cFVVnK5oiHd8caAGlPizN
z2zz0+NbiYPmFSZisqXKovVPceZbc0D26ZrC
-----END CERTIFICATE-----

#查看ca.crt的内容并添加到Kubernetes 服务证书 key中

查看client-certificate-data和client-key-data的内容并转化成base64 encoded文件

echo LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0...(此处省略)  |base64 -d > ./client.crt

echo LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLR...(此处省略   |base64 -d > ./client.key

#生成Client P12认证文件cert.pfx
openssl pkcs12 -export -out ./cert.pfx -inkey ./client.key -in ./client.crt -certfile ./ca.crt
Enter Export Password:

#输入一个密码用于jenkins的凭证

#添加凭据

#最后jenkins添加凭据并点击测试

#还需添加jenkins地址(jenkins为service,app为namespace)

微信截图_20231016112650.png

安装Config File Provider插件

也可安装Image Tag Parameter插件用于检测harbor仓库的版本情况

Config File Provider:存储kubectl用于连接k8s集群的kubeconfig配置文件

#可参考Jenkins Config File Provider 插件 创建kubeconfig文件_configfileprovider_富士康质检员张全蛋的博客-CSDN博客

#此文件
cat /root/.kube/config

#1

微信截图_20231013120134.png微信截图_20231013120325.png#将内容粘贴

[root@k8s-master ~]# cat .kube/config
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJek1EZ3pNREUyTkRZek4xb1hEVE16TURneU56RTJORFl6TjFvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTUFWCnpLVXdYenFhNTNTdWM1Z2paR0xraC9xQ3A1ZDVtREc1SCs5NjR4NlE1TEkxWWVaUVpNKzRJTFEwMmFsWWpTaVMKY3o1aGFaYkhOVjlidHVqM2Iwb3ZxczlhNURESnlQVTFFZStQMFJWdHNQY0dDZUxDSU5ORlJzSUZKcmpwM1FHNwpXOHBVMFg4VWVTK1U4dzREWHFPSFFwOWlsTHBFNlFSbXg0eWVKU1NHOEpXSGtScmR3VCtETU5uUW9ieFpvQ0dyClZVWitOTVNhVWtJai94bWxkSkpUeGFzV2wvU3NnazNHMUxQSHlucDhaK0pPbFhDVyt4TTRQRCs0Q0FXcVY3NzAKZEhKM3dLajZkWlU0V01PMFlteTQzbGdudWxWeTBOMCtLSUhKbmRBNXAwMUlINFE5MnQvT3JDK0Ywa2U5Z3VmZApVeVd1WHVMRy9rKzdYRmhkaEZjQ0F3RUFBYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZLQ2VSajJHMk91VlE4NFZCZHpYMGZEd1JrZ2lNQTBHQ1NxR1NJYjMKRFFFQkN3VUFBNElCQVFDbWZGSDdNazlKTTFrZmR6eU4yUWgvRGQvYU5JK2paYnYwRUJvSHZteXZtMXhHZEF5MwpWaEVxeDlOSFlpTUZxSkp2aUVPbkdiL0c3ZXZZOG9HdU02bEpFMW94OUJDSmg5OUkyeWRGL3cvSUs5ZTFxZCtRCjNtaXZ1NTZ5RkwwazZOZndmeXA0eHJNZXlBUHFuVVVNMml0MERjMGt3UXpqS09vamZYK3NjMDE1UlNmNHFhbHkKekRYVFViVFhZdDl0dis1czNva0g5eDhhS0tNdk1TYVJmNVhBOStqNncrbzdQQjUzWkNzRDcyK1hoNnh6NFVWeApEQzBNQlBtRzZvZlNiY1kyZmpVeG5SNFdyN1VZMk1FTTNUVnpCYXZuKzU5Y0ZWVm5LNW9pSGQ4Y2FBR2xQaXpOCnoyenowK05iaVlQbUZTWmlzcVhLb3ZWUGNlWmJjMEQyNlpyQwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    server: https://192.168.2.249:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    namespace: kube-system
    user: jjy
  name: jjy-context
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: jjy
  user:
    client-certificate: /usr/local/work/test/rdbc/jjy.crt
    client-key: /usr/local/work/test/rdbc/jjy.key
- name: kubernetes-admin
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURFekNDQWZ1Z0F3SUJBZ0lJRlVpUWQ4Q0lRQk13RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TXpBNE16QXhOalEyTXpkYUZ3MHlOREE0TWpreE5qUTJNemxhTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTNGbmpPemdpdy9ZcDFaZ1AKZVdNb3RqOHJiZEdXWTdVWE1lcHJSNDgvV1BYN1JOT3M0TzlyRFJ3emhhMTQxZXVmeWpZZDBOK0Fad0EyMkpCRwpIL1VVQjIwMDNNbDYzK3JLa0xlUUh2R3FZdFkrWXFKUkREakp5cE8zLzJPWDdnQm9VN25pYVhwdmtOVy85eDV3Ck5INzQ0aDRDRFJScm5mNDhKY255NktmUDNtMThsazYrV0Fxc2JPWFpqSUZFSDhnSGxKNkJvOXo5bE1ZM3h2blkKYXBXcWVYeUpXSElLLzJSV3Z3eGF2aVVQQ09RK1hGNWZwSjg3UHk1Q2J1dzR0djZHaitPdDQwZXZjalluNzVQSAo3YVZMQXZCdURlTnhQKzZDNExPakNtcE9CKzhTVFg5NnN4VU1SNTRaUWVwZFVZbytCZEZpdU1LaHlFNU1YQWdICkV5UlNJUUlEQVFBQm8wZ3dSakFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0h3WURWUjBqQkJnd0ZvQVVvSjVHUFliWTY1VkR6aFVGM05mUjhQQkdTQ0l3RFFZSktvWklodmNOQVFFTApCUUFEZ2dFQkFMTGdNbC9ydkZlTnZrTUgvYTJQc1Y3c1hpZHdxTGJCMUxnSHVuTEtPZG5ONXhyc295aTB1STYyCnJJMDFEdEg3eGRMN01scmovbUI2UllQZEMwZzhhS2lpUWQzNlV6aExzNHB5U2dLVER0bU1aajFVME9vaTM3RmwKcElLTXorV1RvY1YrZFo3TFFmendHMTQvbzZSR2pZUzNWWlYvVnNQTlk3TjZkbnJidE9RelVTdXA2Q1JacXQrUgozU3BCanJXbmw5K0J5bUt0RCtUbFRUR0RTVTA0anZnOFZyUzdNalV4ck1Nc0p0Zkp4dysveXFSK2hNbjZJTlRXCnpWWWcrcGR2TFJ3N0pYME9YVHFHQU8xVUFwbFc5OUdyVlNDSVRpeU5VYlFtVjFRSDc5ZHB6MUdSaEZwdmFXMmoKZU1nYU1MYjZGZUtnMzRFU0hEa1JVVERaQVJidVFCdz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
    client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBM0Zuak96Z2l3L1lwMVpnUGVXTW90ajhyYmRHV1k3VVhNZXByUjQ4L1dQWDdSTk9zCjRPOXJEUnd6aGExNDFldWZ5allkME4rQVp3QTIySkJHSC9VVUIyMDAzTWw2MytyS2tMZVFIdkdxWXRZK1lxSlIKRERqSnlwTzMvMk9YN2dCb1U3bmlhWHB2a05XLzl4NXdOSDc0NGg0Q0RSUnJuZjQ4SmNueTZLZlAzbTE4bGs2KwpXQXFzYk9YWmpJRkVIOGdIbEo2Qm85ejlsTVkzeHZuWWFwV3FlWHlKV0hJSy8yUld2d3hhdmlVUENPUStYRjVmCnBKODdQeTVDYnV3NHR2NkdqK090NDBldmNqWW43NVBIN2FWTEF2QnVEZU54UCs2QzRMT2pDbXBPQis4U1RYOTYKc3hVTVI1NFpRZXBkVVlvK0JkRml1TUtoeUU1TVhBZ0hFeVJTSVFJREFRQUJBb0lCQUI4eDRvZDV0UUpGRVRzWgo0ZWJ2Y000TU4xdSt0aW03YzJNdnFxeGd6VGtNNmR1ZWsvVHNNQjJWQm41QVJzRVNNSGJ5SGxwNXFiWHJROWg0CjVGU1YzNVlGa2R4SDhjdE5kQXYwME1Sd3RneDBCRFQyZ2I3WE0wb29pMzN1WFkzbUpON2xpL1llelRpVjZpMVQKODlLYXZ5VlQxanAvejVSNGI0OXgvWitPVWxGTXIySUxHUnl5QWRiQ3VlQ2hYRkwxNnc1b0lReFBQS3NkWllvTQo2cGpsbit3a0xmZkRqWVBXRkxhSC9qU2pTWXB1aHYyOXdqeHJ1VjZYa3ZJUmhaNGk4QUFHT3FxeC9lU2FuTDZZCkw4bGk1Q2xtSkhkMVErZzBpamo1ZUxKSTlmUGtjVUpRdnRNeFpOLzdOUDFyS0FRVDgzbDJVQlcxUXBmNzBuaW4KZVJxWndLRUNnWUVBNEpOc053bnpTQkVxeWJYZmh5OXA5TjNwQi9DZkVrV2UrODBsNHdNMmcwaE1jYVgwUElYbwpwNXh6YUVIOWpHUklCWWdSbExxbklCYnN2ekhaQTJmU3AwcmVCY1VIWExQTkx4VmdDRzl3ZkUvMVA0NWhoRHJwCkhSRDMrUTd3VXVpSnpDWkdYL1lqVWZwenI1ODRramNVUndvRms3QkhXdEpTTFdDQ0xrSHV5ZTBDZ1lFQSt5OGgKSVg3bUN1SWs0MFJxRmY5ZTlLRVpYOEJlTE0yaVJ2a0s5YUV5MzJkZ1EvVGtNWDMyMXlCN0lKb0Y1ZTFsZnIyTApHS25tdXBOejlyL0xNNDJEcXFjRjZkOVNydkM1Wk1KeWUyaEhod0c0aGMrSVBBRENjb1JxT0pYV0lkYW0yejJFCmRHb05Kd2dndW9TNXMwanRTUjB3UWJTZWxqbjEzMldreitBVjBvVUNnWUF3TjViWmJscDhrNnNES2ZoM052ZmgKNmk5WlZCRmpRKzF4bE1kWXFWenY3UHIwdjdQanRzQ1FGQ2czTDB2Mzg2UC9CQXI2U3VVTkg3N3ZBZzNkREZLUApOcVRheWtYZFlvRmdaWTk3NENsZmwyOUptUkZZNmFrWlk0WktSQ25YTXpRNno5RDJVNHViMDFFNVdNODFuWHZPCkVObkhydVp6R29zb1VQdENZVWVhdFFLQmdENVE0L1JPYWozNit0SFRVRXBpejZqN0tyTmhvenVVVEpVMUJlNEkKYnZtVHlRTXpCMFhzRFVnenk3ZzczZ2k4QzdrVXh5UjRTa0N4Z2t5T0twaUFuRkRESFNsM2VTamptZXNRZnB4MQpNNEdnQUtwWjRWK1poS1FxaTd1OEdLTE9nUmpWT3o0eWJVN29xazM3emFKWURsNWNPbk9pbnRHQVVhcDVxaGpVCmJEV05Bb0dCQUpnM1BUZWZkK09telRBendjZ3FJcEhVQWgwVGFoZlB0Z3NZdXVoWDFHdlhnbHBxY2ZkaHZyQzIKWG5lOHdmSGZXbXNqWjNENG5HVWk4ZTBZVEFGZTl3Ukh4SWU2SWZLUWpWV05RYTZ4NC9JZXZRRHo0MzVCVmFzagpVdzFCNmMzU21KNEVzS0RBbERZV1Z4UnBhK1ozaG9aaDdhWmEyNGZIVUduK1E3Nm9VWFM1Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==

#如图

微信截图_20231013133344.png#使用方法

微信截图_20231013133645.png

#制作kubectl镜像

#本地下载
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.20.1/bin/linux/amd64/kubectl
#kubedog下载
github地址:https://github.com/werf/kubedog
wget https://tuf.kubedog.werf.io/targets/releases/0.9.0/linux-amd64/bin/kubedog

vim Dockerfile

FROM alpine:latest

COPY kubectl /usr/local/bin/

RUN chmod +x /usr/local/bin/kubectl

#制作kubedog镜像

#由于kubedog命令无法引用Config File Provider插件的kubeconfig所以需要将kubeconfig复制粘贴到容器
cat /root/.kube/config
#kubedog下载 
#github地址:https://github.com/werf/kubedog
wget https://tuf.kubedog.werf.io/targets/releases/0.9.0/linux-amd64/bin/kubedog

vim Dockerfile
FROM alpine:latest

COPY kubedog /usr/local/bin/

COPY config /root/

RUN chmod +x /usr/local/bin/kubedog
RUN mkdir /root/.kube
RUN mv /root/config /root/.kube/

#最终pipeline

pipeline {
  agent {
    kubernetes {
      yaml '''
        apiVersion: v1
        kind: Pod
        metadata:
          labels:
            some-label: some-label-value
        spec:
          containers:
          - name: golang
            image: 192.168.2.247/k8s-test/golang:1.21.0
            command:
            - cat
            tty: true
          - name: docker
            image: 192.168.2.247/k8s-test/docker:24.0.5
            command:
            - cat
            tty: true
            volumeMounts:
            - name: docker-sock
              mountPath: /var/run/docker.sock
          - name: kubedog
            image: 192.168.2.247/k8s-test/kubedog
            command:
            - cat
            tty: true
          - name: kubectl
            image: 192.168.2.247/k8s-test/kubectl:1.20
            command:
            - cat
            tty: true
            volumeMounts:
            - name: kubeconfig
              mountPath: /etc/kubeconfig
              readOnly: true
          volumes:
          - name: docker-sock
            hostPath:
              path: /var/run/docker.sock
              type: ''
          - name: kubeconfig
            configMap:
              name: kubectl-config
        '''
    }
  }
  environment {
    GOPROXY = 'https://goproxy.io,direct'
    Harbor_Dir = '192.168.2.247'
    Harbor_USER = 'admin'
    Harbor_PASSWD = 'ASDFasdf123'
    project = 'zgy-printer'
  }
  options {
		timestamps()	// 日志会有时间
		skipDefaultCheckout()	// 删除隐式checkout scm语句
		disableConcurrentBuilds()	//禁止并行
		timeout(time:1,unit:'HOURS') //设置流水线超时时间
	}
  stages {
    stage('拉取代码') {
        steps {
            checkout scmGit(branches: [[name: 'pre-main']], extensions: [], userRemoteConfigs: [[credentialsId: 'f6ed2c6d-e966-40da-8525-5204e725fdbe', url: 'http://test/test.git']])
            }
        }
    stage('打包') {
      steps {
        container('golang') {
          sh '''
            go env -w GOPROXY=$GOPROXY
            go build -o $project ./*.go
            '''
        }
        container('docker') {
          sh '''
            docker login $Harbor_Dir -u $Harbor_USER -p $Harbor_PASSWD
            docker build -f ./k8s-deploy/Dockerfile -t $project .
            docker tag $project 192.168.2.247/k8s-zgy-printer/$project
            docker push 192.168.2.247/k8s-test/$project
            docker rmi $project
            '''
        }
      }
    }
    stage('部署') {
      steps {
        script{
          container('kubectl') {
          configFileProvider([configFile(fileId: 'd3ffdeb7-3b77-4e1e-a6ab-6d65a8d6cc9d', targetLocation: 'kubectl-config')]) {
          sh '''
            kubectl apply -f k8s-deploy/$project.yaml --kubeconfig=kubectl-config
            '''
            }
          }
        }
      }
    }
    stage('检查更新') {
      steps {
        script{
          container('kubedog') {
          sh '''
cat << EOF| kubedog multitrack
{
    "Deployments": [
      {
        "ResourceName": "$project",
        "Namespace": "work"
      }
    ]
}
EOF
            '''
          }
        }
      }
    }
  }
}
#参数解答
timestamps(): 这个选项将在控制台输出中添加时间戳,以显示每个构建步骤的开始和结束时间。

skipDefaultCheckout(): 这个选项告诉 Jenkins 不要自动执行默认的代码仓库检出步骤。这对于使用其他方式手动控制代码检出的情况很有用。

disableConcurrentBuilds(): 这个选项禁用并发构建,确保只有一个构建在任何给定时间运行,以避免竞争条件。

timeout(time: 1, unit: 'HOURS'): 这个选项设置构建的超时时间为1小时。如果构建运行时间超过1小时,它将被终止
#pipeline示例  源:()


def labels = "slave-${UUID.randomUUID().toString()}"

// 引用共享库
@Library("jenkins_shareLibrary")

// 应用共享库中的方法
def tools = new org.devops.tools()
def sonarapi = new org.devops.sonarAPI()
def sendEmail = new org.devops.sendEmail()
def build = new org.devops.build()
def sonar = new org.devops.sonarqube()

// 前端传来的变量
// git分支
def gitBranch = env.branch
// git地址
def gitUrl = env.git_url
// 编译命令
def buildShell = env.build_shell
// 应用镜像
def image = env.image
// 镜像仓库地址
def dockerRegistryUrl = env.dockerRegistryUrl
// 存放kubernetes yaml配置清单的git地址
def cd_devops_git = env.devops_cd
// 代码扫描的目录
def projectDir = env.projectDir
// yaml清单的根目录,按应用组分组
def app_project = env.app_project
// 代码子目录
def project_sub_dir = env.project_sub_dir
// 指定发布环境
def specify_env = env.specify_env

// 固定变量
// def SonarServer = "http://sonar.devops.svc.cluster.local:9000/api"
// def dockerRegistryUrl = "registry.cn-hangzhou.aliyuncs.com"
// def cd_devops_git = "gitee.com/jokerbai/devops-cd.git"
// def base_image = "harbor-test.asgq.com/cartechfinbase/jdk:8u144_test"
// 基础镜像
// def base_image = "harbor-test.asgq.com/cartechfinbase/jdk_skywalking:8u144-4"
def base_image = "harbor-test.asgq.com/cartechfinbase/jdk:8u144_test"



pipeline {
    agent {
    kubernetes {
        label labels
      yaml """
apiVersion: v1
kind: Pod
metadata:
  labels:
    some-label: some-label-value
spec:
  volumes:
  - name: docker-sock
    hostPath:
      path: /var/run/docker.sock
      type: ''
  - name: maven-cache
    nfs:
      server: 172.17.100.50
      path: /home/middleware/jenkins_cache/m2
  - name:  shared-dir
    emptyDir: {}
  containers:
  - name: jnlp
    image: harbor-test.asgq.com/library/jenkins/inbound-agent:4.3-4
  - name: maven
    image: harbor-test.asgq.com/library/maven:3.5.0.1-alpine
    command:
    - cat
    tty: true
    volumeMounts:
    - name: maven-cache
      mountPath: /root/.m2
  - name: docker
    image: harbor-test.asgq.com/library/docker:19.03.11
    command:
    - cat
    tty: true
    volumeMounts:
    - name: docker-sock
      mountPath: /var/run/docker.sock
  - name: kustomize
    image: harbor-test.asgq.com/library/kustomize:v3.8.1
    command:
    - cat
    tty: true
    volumeMounts:
    - name: shared-dir
      mountPath: /tmp/dir
  - name: kubedog
    image: harbor-test.asgq.com/library/kubedog:v3.8.1
    command:
    - cat
    tty: true
    volumeMounts:
    - name: shared-dir
      mountPath: /tmp/dir
"""
    }
  }

    environment{
        auth = 'joker'
    }

    options {
		timestamps()	// 日志会有时间
		skipDefaultCheckout()	// 删除隐式checkout scm语句
		disableConcurrentBuilds()	//禁止并行
		timeout(time:1,unit:'HOURS') //设置流水线超时时间
	}


    stages {
        // 拉取代码
        stage('GetCode') {
            steps {
                checkout([$class: 'GitSCM', branches: [[name: "${gitBranch}"]],
                    doGenerateSubmoduleConfigurations: false,
                    extensions: [],
                    submoduleCfg: [],
                    userRemoteConfigs: [[credentialsId: 'gitlab', url: "${gitUrl}"]]])
                }
            }

        // 单元测试和编译打包
        stage('Build&Test') {
            steps {
                container('maven') {
                    script{
                        tools.PrintMes("编译打包","blue")
                        build.DockerBuild("${buildShell}")
                        // sh """${buildShell}"""
                    }
                }
            }
        }
        // 代码扫描
        
        // 构建镜像
        stage('BuildImage') {
            steps {
                withCredentials([[$class: 'UsernamePasswordMultiBinding',
                credentialsId: 'dockerhub',
                usernameVariable: 'DOCKER_HUB_USER',
                passwordVariable: 'DOCKER_HUB_PASSWORD']]) {
                    container('docker') {
                        script{
                            tools.PrintMes("构建镜像","green")
                            imageTag = tools.createVersion()
                            sh """
							if [[ ${project_sub_dir} != "null" ]];then
								cd ${project_sub_dir}
							fi
                            sed -i "s+^FROM .*+FROM ${base_image}+g" Dockerfile
                            docker login ${dockerRegistryUrl} -u ${DOCKER_HUB_USER} -p ${DOCKER_HUB_PASSWORD}
                            docker build -t ${image}:${imageTag} .
                            docker push ${image}:${imageTag}
                            docker rmi ${image}:${imageTag}
                            """
                        }
                    }
                }
            }
        }
        // 部署
        stage('Deploy') {
            steps {
                 withCredentials([[$class: 'UsernamePasswordMultiBinding',
                credentialsId: 'ci-devops',
                usernameVariable: 'DEVOPS_USER',
                passwordVariable: 'DEVOPS_PASSWORD']]){
                    container('kustomize') {
                        script{
                            TMP_DIR="${JOB_NAME}".split("_")[0]
							APP_DIR="${TMP_DIR}".split("/")[1]
                            sh """
                            git remote set-url origin http://${DEVOPS_USER}:${DEVOPS_PASSWORD}@${cd_devops_git}
                            git config --global user.name "123"
                            git config --global user.email "baidan@asgq.com"
                            git clone http://${DEVOPS_USER}:${DEVOPS_PASSWORD}@${cd_devops_git} /opt/devops-cd
                            cd /opt/devops-cd
                            git pull
							if [[ ${app_project} != "null" ]];then
								cd /opt/devops-cd/${app_project}/${APP_DIR}/${specify_env}
							else
								cd /opt/devops-cd/${APP_DIR}/${specify_env}
							fi
                            kustomize edit set image ${image}:${imageTag}
                            git commit -am 'image update'
                            git push origin master
                            awk '/namespace/{print $NF}' kustomization.yaml > /tmp/dir/namespace
                            """
                        }
                    }
                }
            }
        }
        // 设置job build description
		stage('Set build') {
            steps {
              script {
             // Set build parameters
             currentBuild.description = "分支: $gitBranch \n 环境: $specify_env"
            }
          }
        }

        // 启动状态检查
		stage('Check startup Status') {
            steps {
                container('kubedog') {
                    script{
                    TMP_DIR="${JOB_NAME}".split("_")[0]
					APP_DIR="${TMP_DIR}".split("/")[1]
                    sh """
                    ns=`cat /tmp/dir/namespace`
cat << EOF| kubedog multitrack -t 180
{
  "Deployments": [
    {
      "ResourceName": "${APP_DIR}",
      "Namespace": "${ns}"
    }
  ]
}
EOF
                    """
                    }
                }
            }
        }
    }
    // 构建后的操作
	post {
		success {
			script{
				println("success:只有构建成功才会执行")
				currentBuild.description
				// deploy.AnsibleDeploy("${deployHosts}","-m ping")
				// sendEmail.SendEmail("构建成功",toEmailUser)
				// dingmes.SendDingTalk("构建成功 ✅")
			}
		}
		failure {
			script{
				println("failure:只有构建失败才会执行")
				currentBuild.description
				//sendEmail.SendEmail("构建失败",toEmailUser)
				// dingmes.SendDingTalk("构建失败 ❌")
			}
		}
		aborted {
			script{
				println("aborted:只有取消构建才会执行")
				currentBuild.description
				//sendEmail.SendEmail("取消构建",toEmailUser)
				// dingmes.SendDingTalk("构建失败 ❌","暂停或中断")
			}
		}
	}
}