发布流程

使用 Gitlab 作为代码仓库 & 使用 Harbor 作为镜像仓库

1.部署gitlab

mkdir gitlab
cd gitlab
docker run -d \
--name gitlab \
-p 8443:443 \
-p 9999:80 \
-p 9998:22 \
-v $PWD/config:/etc/gitlab \
-v $PWD/logs:/var/log/gitlab \
-v $PWD/data:/var/opt/gitlab \
-v /etc/localtime:/etc/localtime \
--restart=always \
lizhenliang/gitlab-ce-zh:latest

访问地址:http://IP:9999

初次会先设置管理员密码 ,然后登陆,默认管理员用户名root,密码就是刚设置的。

创建项目,提交测试代码

进入后先创建项目,提交代码,以便后面测试。

unzip tomcat-java-demo-master.zip
cd tomcat-java-demo-master
git init
git remote add origin http://192.168.0.13:9999/root/java-demo.git
git add .
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
git commit -m 'all'
git push origin master

2、部署Harbor镜像仓库

2.1 安装docker与docker-compose

2.2 解压离线包部署

# tar zxvf harbor-offline-installer-v2.0.0.tgz
# cd harbor
# cp harbor.yml.tmpl harbor.yml
# vi harbor.yml
hostname: reg.ctnrs.com
https: # 先注释https相关配置
harbor_admin_password: Harbor12345
# ./prepare
# ./install.sh

2.3 在Jenkins主机配置Docker可信任,如果是HTTPS需要拷贝证书

由于habor未配置https,还需要在docker配置可信任。

# cat /etc/docker/daemon.json 
{"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"],
"insecure-registries": ["192.168.0.12"]
}
# systemctl restart docker

在Kubernetes平台部署Jenkins

部署nfs-pv自动供给

#安装nfs安装包(每个k8s节点都要安装)
yum install nfs-utils
#创建nfs共享目录
mkdir -p /nfs/kubernetes
#修改nfs配置文件
vim /etc/exports
/nfs/kubernetes *(rw,no_root_squash)
#启动nfs并加入开机自启
systemctl start nfs
systemctl enable nfs

#部署NFS实现自动创建PV插件:
git clone https://github.com/kubernetes-incubator/external-storage
cd nfs-client/deploy
kubectl apply -f rbac.yaml # 授权访问apiserver
kubectl apply -f deployment.yaml # 部署插件,需修改里面NFS服务器地址与共享目录
kubectl apply -f class.yaml # 创建存储类
kubectl get sc # 查看存储类

3.部署Jenkins

需要提前准备好PV自动供给,为Jenkins持久化数据。

cd jenkins 
kubectl apply -f jenkins.yaml
kubectl get pods,svc -n ops -o wide

访问地址:http://NodePort:30008

第一次部署会进行初始化:

点无,不安装任何插件

4.安装插件

默认从国外网络下载插件,会比较慢,建议修改国内源:

# 进入到nfs共享目录
cd /nfs/kubernetes/ops-jenkins-pvc-0b76f611-9e06-433d-a666-8e7d0e9f1138/updates
sed -i 's/https:\/\/updates.jenkins.io\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' default.json
sed -i 's/http:\/\/www.google.com/https:\/\/www.baidu.com/g' default.json

# 删除pod重建,pod名称改成你实际的
kubectl delete pod jenkins-d58f4db66-9cthj -n ops

http://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json

管理Jenkins->系统配置–>管理插件–>分别搜索Git Parameter/Git/Pipeline/kubernetes/Config File Provider,选中点击安装。

  • Git Parameter:Git参数化构建

  • Git:拉取代码

  • Pipeline:流水线

  • kubernetes:连接Kubernetes动态创建Slave代理

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

5、添加kubernetes集群

管理Jenkins->Manage Nodes and Clouds->configureClouds->Add

构建Jenkins-Slave镜像

jenkins-slave.zip

6.构建Slave镜像

cd jenkins-slave

课件目录里涉及四个文件:

  • Dockerfile:构建镜像

  • jenkins-slave:shell脚本启动slave.jar

  • settings.xml:修改maven官方源为阿里云源

  • slave.jar:agent程序,接受master下发的任务

构建并推送到镜像仓库:

docker build -t 192.168.0.12/library/jenkins-slave-jdk:1.8 .
docker push 192.168.0.12/library/jenkins-slave-jdk:1.8

Jenkins在K8S中动态创建代理

Kubernetes插件:Jenkins在Kubernetes集群中运行动态代理

插件介绍:https://github.com/jenkinsci/kubernetes-plugin

Jenkins Pipeline 介绍

Jenkins Pipeline是一套运行工作流框架,将原本独立运行单个或者多个节点的任 务链接起来,实现单个任务难以完成的复杂流程编排和可视化。

  • Jenkins Pipeline是一套插件,支持在Jenkins中实现持续集成和持续交付;

  • Pipeline通过特定语法对简单到复杂的传输管道进行建模;

  • Jenkins Pipeline的定义被写入一个文本文件,称为Jenkinsfile。

  • Stages 是 Pipeline 中最主要的组成部分,Jenkins 将会按照 Stages 中描述的顺序 从上往下的执行。

  • Stage:阶段,一个 Pipeline 可以划分为若干个 Stage,每个 Stage 代表一组操作, 比如:Build、Test、Deploy

  • Steps:步骤,Steps 是最基本的操作单元,可以是打印一句话,也可以是构建一 个 Docker 镜像,由各类 Jenkins 插件提供,比如命令:sh ‘mvn’,就相当于我 们平时 shell 终端中执行 mvn命令一样。

Jenkins在Kubernetes中持续部署

自动部署应用(yaml):

将kubectl工具封装到Slave镜像中,并通过Config File Provider插件存储连接K8s集群的kubeconfig认证文件,然后 挂载到Slave容器中,这样就能用kubectl apply deploy.yaml --kubeconfig=config

注:为提高安全性,kubeconfig文件应分配权限

除了上述方式,还可以使用Kubernetes Continuous Deploy插件,将资源配置(YAML)部署到Kubernetes,这种 不是很灵活性

7.编写Pipeline脚本

创建命名空间

kubectl create ns dev
kubectl create ns test
kubectl create ns prod

将镜像仓库认证凭据保存在K8s Secret中

kubectl create secret docker-registry registry-pull-secret --docker-username=admin --docker-password=Harbor12345 --docker-server=192.168.0.12 -n dev
kubectl create secret docker-registry registry-pull-secret --docker-username=admin --docker-password=Harbor12345 --docker-server=192.168.0.12 -n test
kubectl create secret docker-registry registry-pull-secret --docker-username=admin --docker-password=Harbor12345 --docker-server=192.168.0.12 -n prod

部署文件:deploy.yaml (将部署文件跟git仓库文件放在一起)

apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: REPLICAS
selector:
matchLabels:
app: java
template:
metadata:
labels:
app: java
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: 40
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 40
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: java-demo
spec:
selector:
app: java
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: NodePort

创建项目->流水线->Pipeline脚本如下:

// 公共
def registry = "192.168.0.12"
// 项目
def project = "demo"
def app_name = "java-demo"
def image_name = "${registry}/${project}/${app_name}:${BUILD_NUMBER}"
def git_address = "http://192.168.0.13:9999/root/java-demo.git"
// 认证
def secret_name = "registry-pull-secret"
def docker_registry_auth = "e2c15e7c-766e-4961-bddb-2160e6e1859b"
def git_auth = "d17ea255-ade3-4623-b2ce-0b40b87e7164"
def k8s_auth = "6f488843-b5e2-49ca-949b-eccb75b54f6c"

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
RUN rm -rf /usr/local/tomcat/webapps/*
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
"""
}
}
}
}
}

上述脚本中,registry变量值改成你的镜像仓库地址。

将之前部署该项目涉及的yaml合并到一个名为deploy.yaml文件中,并提交到该项目代码仓库,与 pom.xml同级目录,用于上述脚本自动部署使用。

1、将harbor认证和gitlab认证保存到Jenkins凭据

管理Jenkins->安全–>管理凭据->Jnekins->添加凭据->Username with password

  • Username:用户名

  • Password:密码 ID:留空

  • Description:描述

分别添加连接git和harbor凭据,并修改上面脚本docker_registry_auth 和git_auth变量的值为Jenkins 凭据ID。

2、将kubeconfig存储在Jenkins,用于slave镜像里kubectl连接k8s集群

管理Jenkins-> Managed files->Add->Custom file ->Content字段内容是kubeconfig(默认路径在 master节点/root/.kube/config),然后复制ID替换上述脚本中k8s_auth变量的值。

8.构建测试

流水线脚本与源代码一起版本管理

Jenkinsfile文件建议与源代码一起版本管理,实现流水线即代码(Pipeline as Code)。 这样做的好处:

  • 自动为所有分支创建流水线脚本

  • 方便流水线代码复查、追踪、迭代

  • 可被项目成员查看和编辑

参考链接:https://www.cnblogs.com/u1s1/p/14231196.html