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集群
#在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)
安装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
#将内容粘贴
[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==
#如图
#使用方法
#制作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("构建失败 ❌","暂停或中断")
}
}
}
}