发布流程设计
在Kubernetes平台部署Jenkins
[root@k8smaster cicd]# kubectl
apply -f jenkins.yml
[root@k8smaster cicd]# kubectl get pod -n ops
NAME READY STATUS RESTARTS AGE
jenkins-f656474b8-dxhvk 1/1 Running 0 95s
[root@k8smaster cicd]# kubectl logs jenkins-f656474b8-dxhvk -n ops -f
Please use the following password to proceed to installation:
1cdf4c21f73c4edc83c555121d8596f6
This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
##访问jenkins
http://192.168.153.21:30008/
构建slave镜像
Jenkins Master/Slave架构
Jenkins在K8S中动态创建代理
相关操作
[root@k8smaster cicd]# cd jenkins-slave/
[root@k8smaster jenkins-slave]# chmod 777 kubectl
[root@k8smaster jenkins-slave]# ls
Dockerfile jenkins-slave kubectl settings.xml slave.jar
------------------------------------------------------------------------------------
#构建并推送到镜像仓库
docker build -t 192.168.153.27/library/jenkins-slave-jdk:1.8 .
docker push 192.168.153.27/library/jenkins-slave-jdk:1.8
安装插件
修改国内源
#进入nfs共享目录
[root@k8smaster cicd]# cd /ifs/kubernetes/ops-jenkins-pvc-18e51a58-a3fb-41df-91e9-207508d6f86aa/updates
[root@k8smaster updates]# sed -i 's/https:\/\/updates.jenkins.io\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' default.json
[root@k8smaster updates]# sed -i 's/http:\/\/www.google.com/https:\/\/www.baidu.com/g' default.json
#重启jenkins
[root@k8smaster updates]# kubectl delete pod jenkins-f656474b8-dxhvk -n ops
pod "jenkins-f656474b8-dxhvk" deleted
[root@k8smaster updates]# kubectl get pods -n ops
NAME READY STATUS RESTARTS AGE
jenkins-f656474b8-5gmc7 1/1 Running 0 24s
安装相关插件
Git Parameter:Git参数化构建
Git:拉取代码
Pipeline:流水线
kubernetes:连接Kubernetes动态创建Slave代理
Config File Provider:存储kubectl用于连接k8s集群的kubeconfig配置文件
---------------------------------------------------------------------------------
添加k8s集群
进入配置页面
Configure Clouds
#Kubernetes 地址
[root@k8smaster cicd]# kubectl get svc -n default
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 29d
https://kubernetes.default
---------------------------------------------------------------------------------
#Jenkins 地址
[root@k8smaster cicd]# kubectl get svc -n ops
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
jenkins NodePort 10.109.120.192 <none> 80:30008/TCP,50000:31434/TCP 56m
http://jenkins.ops
注意:一定是http://jenkins.ops而不是https://jenkins.ops
---------------------------------------------------------------------------------
#测试连接
Connected to Kubernetes v1.19.0
Jenkins Pipeline
testjenkins脚本
pipeline {
agent {
kubernetes {
label "jenkins-slave"
yaml """
kind: Pod
metadata:
name: jenkins-slave
spec:
containers:
- name: jnlp
image: "192.168.153.27/library/jenkins-slave-jdk:1.8"
"""
}
}
stages {
stage('第一步测试'){
steps {
sh 'hostname'
}
}
}
}
pipeline执行过程
##构建过程拉起一个jenkins-slave的pod
[root@k8smaster cicd]# kubectl get pod -n ops
NAME READY STATUS RESTARTS AGE
jenkins-f656474b8-5gmc7 1/1 Running 0 41m
jenkins-slave-jmkq8-8bnvj 0/1 ContainerCreating 0 11s
##完成后jenkins-slave的pod自动消失
[root@k8smaster cicd]# kubectl get pod -n ops
NAME READY STATUS RESTARTS AGE
jenkins-f656474b8-5gmc7 1/1 Running 0 41m
项目搭建
凭据
git-auth :ff221d86-51db-429f-b0e2-ad5ba09d5cb0
harbor-auth:ab69906e-3549-4e3a-bc7c-ace44bccbab6
配置文件
[root@k8smaster jenkins-slave]# cat /root/.kube/config
Managed files:26c9cacb-e481-46fc-bf31-0c6fe4455d1f
创建registry-pull-secret
[root@k8smaster jenkins-slave]# kubectl create namespace dev
namespace/dev created
[root@k8smaster jenkins-slave]# kubectl create secret docker-registry registry-pull-secret --docker-username=admin --docker-password=Harbor12345 --docker-server=192.168.153.25 -n dev
secret/registry-pull-secret created
pipeline脚本
// 公共
def registry = "192.168.153.27"
// 项目
def project = "demo"
def app_name = "java-demo"
def image_name = "${registry}/${project}/${app_name}:${BUILD_NUMBER}"
def git_address = "http://192.168.153.18/root/javademo2.git"
// 认证
def secret_name = "registry-pull-secret"
def docker_registry_auth = "ab69906e-3549-4e3a-bc7c-ace44bccbab6"
def git_auth = "ff221d86-51db-429f-b0e2-ad5ba09d5cb0"
def k8s_auth = "26c9cacb-e481-46fc-bf31-0c6fe4455d1f"
pipeline {
agent {
kubernetes {
label "jenkins-slave"
yaml """
kind: Pod
metadata:
name: jenkins-slave
spec:
containers:
- name: jnlp
image: "${registry}/library/jenkins-slave-jdk:1.8"
imagePullPolicy: Always
volumeMounts:
- name: docker-cmd
mountPath: /usr/bin/docker
- name: docker-sock
mountPath: /var/run/docker.sock
- name: maven-cache
mountPath: /root/.m2
volumes:
- name: docker-cmd
hostPath:
path: /usr/bin/docker
- name: docker-sock
hostPath:
path: /var/run/docker.sock
- name: maven-cache
hostPath:
path: /tmp/m2
"""
}
}
parameters {
gitParameter branch: '', branchFilter: '.*', defaultValue: 'master', description: '选择发布的分支', name: 'Branch', quickFilterEnabled: false, selectedValue: 'NONE', sortMode: 'NONE', tagFilter: '*', type: 'PT_BRANCH'
choice (choices: ['1', '3', '5', '7'], description: '副本数', name: 'ReplicaCount')
choice (choices: ['dev','test','prod'], description: '命名空间', name: 'Namespace')
}
stages {
stage('拉取代码'){
steps {
checkout([$class: 'GitSCM',
branches: [[name: "${params.Branch}"]],
doGenerateSubmoduleConfigurations: false,
extensions: [], submoduleCfg: [],
userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_address}"]]
])
}
}
stage('代码编译'){
steps {
sh """
mvn clean package -Dmaven.test.skip=true
"""
}
}
stage('构建镜像'){
steps {
withCredentials([usernamePassword(credentialsId: "${docker_registry_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
sh """
echo '
FROM lizhenliang/tomcat
LABEL maitainer lizhenliang
ADD target/*.war /usr/local/tomcat/webapps/ROOT.war
' > Dockerfile
docker build -t ${image_name} .
docker login -u ${username} -p '${password}' ${registry}
docker push ${image_name}
"""
}
}
}
stage('部署到K8S平台'){
steps {
configFileProvider([configFile(fileId: "${k8s_auth}", targetLocation: "admin.kubeconfig")]){
sh """
sed -i 's#IMAGE_NAME#${image_name}#' deploy.yaml
sed -i 's#SECRET_NAME#${secret_name}#' deploy.yaml
sed -i 's#REPLICAS#${ReplicaCount}#' deploy.yaml
kubectl apply -f deploy.yaml -n ${Namespace} --kubeconfig=admin.kubeconfig
"""
}
}
}
}
}
Gitlab
创建deploy.yaml文件
apiVersion: apps/v1
kind: Deployment
metadata:
name: java-demo
spec:
replicas: REPLICAS
selector:
matchLabels:
project: www
app: java-demo
template:
metadata:
labels:
project: www
app: java-demo
spec:
imagePullSecrets:
- name: SECRET_NAME
containers:
- image: IMAGE_NAME
name: java-demo
resources:
requests:
cpu: 0.5
memory: 500Mi
limits:
cpu: 1
memory: 1Gi
livenessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 50
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 50
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: java-demo
spec:
selector:
project: www
app: java-demo
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: NodePort
编译构建
查看结果
[root@k8smaster cicd]# kubectl get pod,svc -n dev
NAME READY STATUS RESTARTS AGE
pod/java-demo-6668db84f7-2dxnw 1/1 Running 0 4m4s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/java-demo NodePort 10.107.64.65 <none> 80:32495/TCP 4m4s
流水线即代码
Jenkinsfile放入Gitlab
编辑Pipeline
编译构建