文章目录
- 1. 搭建 gitlab
- 2. 下载jdk和maven
- 3. 安装jenkins
- 4. 跑通CI的过程
- 5.sonarQube环境搭建
- 6. 集成Harbor
- 7. jenkins流水线
- 8. 集成kubernates
1. 搭建 gitlab
1.1 安装包安装方式
本机环境ubuntu 2204
开放对应端口或者关闭防火墙
1.1.1 安装依赖
sudo apt install ca-certificates curl openssh-server postfix
1.1.2 安装gitlab
cd /tmp
curl -LO https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh
1.1.3 运行安装程序
sudo bash /tmp/script.deb.sh
1.1.4 安装gitlab应用程序
sudo apt install gitlab-ce
1.1.5 修改配置参数
sudo vim /etc/gitlab/gitlab.rb
改成自己的ip
external_url 'http://10.211.55.8:9092'#本机局域网ip为10.211.55.8端口为9092
1.1.6 运行命令重新配置
sudo gitlab-ctl reconfigure
gitlab 命令集合
常用命令 | 说明 |
---|---|
sudo gitlab-ctl reconfigure | 重新加载配置,每次修改/etc/gitlab/gitlab.rb文件之后执行 |
sudo gitlab-ctl status | 查看 GitLab 状态 |
sudo gitlab-ctl start | 启动 GitLab |
sudo gitlab-ctl stop | 停止 GitLab |
sudo gitlab-ctl restart | 重启 GitLab |
sudo gitlab-ctl tail | 查看所有日志 |
sudo gitlab-ctl tail nginx/gitlab_acces.log | 查看 nginx 访问日志 |
sudo gitlab-ctl tail postgresql | 查看 postgresql 日志 |
1.1.7登录
http://10.211.55.8:9092
初始账号root,密码在/etc/gitlab/initial_root_password
cat /etc/gitlab/initial_root_password
1.1.8 修改密码
preference处修改密码
1.1.9 设置gitlab开机自启动
sudo systemctl enable gitlab-runsvdir.service
1.1.10 获取修改超级管理员的账号
cd /opt/gitlab/bin
sudo gitlab-rails console
u=User.where(id:1).first
u.password=12345678
u.password_confirmation=12345678
u.save!
exit
遇到的问题
解决:在远程地址上加上用户名密码 root:password@
1.2 docker 安装gitlab
1.2.1 拉取镜像
docker pull gitlab/gitlab-ce
1.2.2 编写dockerfile文件
version: '3.1'
services:
gitlab:
image: 'gitlab/gitlab-ce:latest'
container_name: gitlab
privileged: true
restart: always
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://192.168.11.11:8929'
gitlab_rails['gitlab_shell_ssh_port'] = 2224
ports:
- '8929:8929'
- '2224:2224'
volumes:
- './config:/etc/gitlab'
- './logs:/var/log/gitlab'
- './data:/var/opt/gitlab'
1.2.3 启动
docker-compose up -d
1.2.4获取初始密码
docker exec -it gitlab cat /etc/gitlab/initial_root_password
1.2.5 登录
1.2.6修改密码和修改语言
2. 下载jdk和maven
2.1 下载jdk8和maven安装包丢到虚拟机
2.2 解压配置环境变量
export JAVA_HOME=/usr/local/jdk1.8.0_341
export MAVEN_HOME=/usr/local/apache-maven-3.8.6
export PATH=$PATH:JAVA_HOME/bin:$MAVEN_HOME/bin
source /etc/profile
2.3配置maven setting.xml
配置阿里云仓库
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
配置中使用JDK1.8进行编译
<profile>
<id>jdk1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
3. 安装jenkins
注意如果是虚拟机,必须内存至少4G才能正常跑起来
官网地址:Jekins
本文用docker 安装
3.1 下载镜像源
docker pull jenkins/jenkins:2.346.3-2-lts
3.2 新建jenkins_docker目录
# /usr/local/docker/
mkdir -p jenkins_docker
3.3 新建docker-compose.yaml文件
version: "3.1"
services:
jenkins:
image: jenkins/jenkins:2.346.3-2-lts
container_name: jenkins
ports:
- 8081:8080
- 50000:50000
volumes:
- ./data/:/var/jenkins_home/
docker logs 会看到perssion deny报错
解决
# /usr/local/docker/jenkins_docker
chmod -R a+w data/
3.4 重启docker-compose
docker-compose up -d
3.5 网速慢可以修改镜像源
#本文中这个文件夹/usr/local/docker/jenkins_docker/data/
# 修改数据卷中的hudson.model.UpdateCenter.xml文件
<?xml version='1.1' encoding='UTF-8'?>
<sites>
<site>
<id>default</id>
<url>https://updates.jenkins.io/update-center.json</url>
</site>
</sites>
# 将下载地址替换为http://mirror.esuni.jp/jenkins/updates/update-center.json
<?xml version='1.1' encoding='UTF-8'?>
<sites>
<site>
<id>default</id>
<url>http://mirror.esuni.jp/jenkins/updates/update-center.json</url>
</site>
</sites>
# 清华大学的插件源也可以https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
3.6 初始密码查看
docker exec -it jenkins cat /var/jenkins_home/secrets/initialAdminPassword
3.7 下载必要插件
4. 跑通CI的过程
4.1 编写一个springboot测试项目,上传到gitlab
注意需要将远程路径上加上账号密码
http://root:password@10.211.55.8:9092/root/jenkins.git
4.2 新建jenkins任务
4.3 配置源码拉取路径
4.4 配置maven构建代码
将maven和jdk环境,挪到相应的docker-compose的data目录下
cp /usr/local/apache-maven-3.8.6 /usr/local/docker/jekins_docker/data/
cp /usr/local/jdk1.8.0_341 /usr/local/docker/jekins_docker/data/
4.4.1 配置java和maven到Jenkins
路径是jenkins 容器中的映射路径,本文是安装在/var/jenkins_home
4.4.2 配置maven构建代码
4.5 配置publish发布远程操作
jar包构建好之后,就可以根据情况发布到测试或生产环境,这里需要用到之前下载好的插件Publish Over SSH。
- 配置Publish Over SSH连接测试、生产环境
4.6 配置任务的构建后操作,发布jar包到目标服务
4.6.2 持续集成
为了让程序代码可以自动推送到测试环境基于Docker服务运行,需要添加Docker配置和脚本文件让程序可以在集成到主干的同时运行起来。
添加dockerfile 文件
FROM openjdk:18.0.2.1-oracle
COPY jenkins.jar /usr/local/
WORKDIR /usr/local/
CMD java -jar jenkins.jar
docker-compose 文件
version: '3.1'
services:
jenkins:
build:
context: ./
dockerfile: Dockerfile
image: jenkins:v1.0.0
container_name: jenkins_test
ports:
- 8088:8080
4.7 构建
4.8 根据版本进行构建
基于git标签构建
在gitlab项目中打标签
任务构建时,采用Shell方式构建,拉取指定tag版本代码
4.9 构建的时候就可以根据版本进行构建
5.sonarQube环境搭建
Sonar Qube在7.9版本中已经放弃了对MySQL的支持,并且建议在商业环境中采用PostgreSQL,那么安装Sonar Qube时需要依赖PostgreSQL。
官网地址:sonarQube
并且这里会安装Sonar Qube的长期支持版本8.9
5.1 拉取镜像
docker pull postgres
docker pull sonarqube:8.9.3-community
5.2 编写dockerfile
version: "3.1"
services:
db:
image: postgres
container_name: db
ports:
- 5432:5432
networks:
- sonarnet
environment:
POSTGRES_USER: sonar
POSTGRES_PASSWORD: sonar
sonarqube:
image: sonarqube:8.9.3-community
container_name: sonarqube
depends_on:
- db
ports:
- "9000:9000"
networks:
- sonarnet
environment:
SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar
SONAR_JDBC_USERNAME: sonar
SONAR_JDBC_PASSWORD: sonar
networks:
sonarnet:
driver: bridge
5.3 启动容器
docker-compose up -d
会报错
解决,修改/etc/sysctl.conf
vm.max_map_count=262144
sysctl -p
访问:ip:9000
5.4 下载中文插件
注意下载对应的sonarQube的版本,不同版本会不起作用
如果搜出来的不对的话,下载对应的jar报,放到插件目录下也会生效
中文插件地址:中文插件
5.5 sonarQube基本使用
配置maven的settings.xml文件
<profile>
<id>sonar</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<sonar.login>admin</sonar.login>
<sonar.password>123456789</sonar.password>
<sonar.host.url>http://192.168.11.11:9000</sonar.host.url>
</properties>
</profile>
在代码位置执行命令
mvn sonar:sonar
查看sonarQube界面测试结果
5.6 sonarscanner 实现代码检测
-
下载Sonar-scanner:地址
-
下载4.6.x版本即可,要求Linux版本
-
解压并配置sonar服务端信息
yum -y install unzip
unzip sonar-scanner-cli/sonar-scanner-cli-4.6.0.2311-linux.zip
修改conf 下的sonar-scanner.properties
执行检测代码
~/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=demo -Dsonar.projectKey=java -Dsonar.java.binaries=target/
5.7 jenkins 集成sonarqube
jenkins安装插件
开启sonar qube权限验证
获取sonar Qube令牌
配置jenkins 的Sonar Qube信息
将sonarQube进行全部配置
配置任务的sonar-scanner
6. 集成Harbor
6.1 下载安装包
地址:harbor下载地址
6.2 拖拽到linux并解压
tar -zxvf harbor-offline-installer-v2.3.4.tgz -C /usr/local/
6.3 修改配置文件
cd /usr/local/harbor
cp harbor.yml.tmpl harbor.yml
6.4 启动harbor
## 当前目录 /usr/local/harbor
./install.sh
6.5 登录harbor
6.6 harbor的基本使用
6.6.1 创建用户
6.6.2 构建私有项目
6.6.3 给项目赋予用户
6.6.4 发布镜像到harbor
命名规则:harbor地址/项目名/镜像名:版本
修改镜像名称 |
---|
6.6.5 修改jenkins的daemon.json
vim /etc/docker/daemon.json
阿里云上的容器镜像服务
{
"registry-mirrors": ["https://87hwjhy6.mirror.aliyuncs.com"],
"insecure-registries": ["192.168.37.131:80"]
}
6.6.6 设置登录仓库信息
docker login -u 用户名 -p 密码 Harbor地址
6.6.7 推送镜像到Harbor
6.6.8 从Harbor拉取镜像ls
6.7 jenkins 使用宿主机docker
6.7.1 设置宿主机docker.sock权限
sudo chown root:root /var/run/docker.sock
sudo chmod o+rw /var/run/docker.sock
6.7.2 修改docker-compose.yml
version: "3.1"
services:
jenkins:
image: jenkins/jenkins
container_name: jenkins
restart: always
ports:
- 8081:8080
- 50000:50000
volumes:
- ./data/:/var/jenkins_home/
- /usr/bin/docker:/usr/bin/docker
- /var/run/docker.sock:/var/run/docker.sock
- /etc/docker/daemon.json:/etc/docker/daemon.json
6.7.3 添加构建操作
#从打包目录复制jar包到docker 目录下
cp target/*.jar docker/
## 构建docker 镜像
docker build -t ${JOB_NAME}:$tag docker/
#登录harbor地址
docker login -u admin -p password 192.168.37.131:80
#给镜像打上符合harbor规则的标签
docker tag ${JOB_NAME}:$tag 192.168.37.131:80/repo/${JOB_NAME}:$tag
#上传harbor镜像到仓库
docker push 192.168.37.131:80/repo/${JOB_NAME}:$tag
6.8 编写部署脚本
部署项目需要通过Publish Over SSH插件,让目标服务器执行命令。为了方便一次性实现拉取镜像和启动的命令,推荐采用脚本文件的方式。
添加脚本文件到目标服务器,再通过Publish Over SSH插件让目标服务器执行脚本即可。
deploy.sh
harbor_addr=$1
harbor_repo=$2
project=$3
version=$4
port=$5
imageName=$harbor_addr/$harbor_repo/$project:$version
echo $imageName
containerId=`docker ps -a | grep ${project} | awk '{print $1}'`
echo $containerId
if [ "$containerId" != "" ] ; then
docker stop $containerId
docker rm $containerId
echo "Delete Container Success"
fi
imageId=`docker images | grep ${project} | awk '{print $3}'`
if [ "$imageId" == "" ] ; then
docker rmi -f $imageId
echo "Delete Image"
fi
docker login -u admin -p password $harbor_addr
docker pull $imageName
docker run -d -p $port:8080 --name $project $imageName
echo "start Container Success"
echo $project
并设置为可执行权限
chmod a+x deploy.sh
将deploy放置到环境变量
cp deploy.sh /usr/bin/
6.9 配置构建后操作
deploy.sh 192.168.37.131:80 repo ${JOB_NAME} $tag $port
7. jenkins流水线
7.1 新建流水线任务
7.2 Groovy脚本
pipeline {
// 指定任务在哪个节点执行(Jenkins支持分布式)
agent any
// 配置全局环境,指定变量名=变量值信息
environment{
host = '192.168.11.11'
}
// 存放所有任务的合集
stages {
// 单个任务
stage('任务1') {
// 实现任务的具体流程
steps {
echo 'do something'
}
}
// 单个任务
stage('任务2') {
// 实现任务的具体流程
steps {
echo 'do something'
}
}
// ……
}
}
7.3 查看效果
Ps:涉及到特定脚本,Jenkins给予了充足的提示,可以自动生成命令
7.4 Jenkinsfile实现
总配置文件
//所有脚本命令都在pipeline中
pipeline {
//指定在哪个节点执行(jenkins支持分布式)
agent any
//配置全局环境变量
environment {
harborHost = '192.168.37.131:80'
harborRepo = 'repo'
harborUser = 'admin'
harborPasswd = 'password'
}
//存放所有任务集合
stages {
//单个任务
stage('拉取Git代码') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[url: 'http://root:password@192.168.37.132:8929/root/mytest.git']]])
}
}
stage('通过maven构建项目') {
steps {
sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'
}
}
stage('检测代码质量') {
steps {
sh '/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.host.url=http://192.168.37.132:9000 -Dsonar.projectname=${JOB_NAME} -Dsonar.projectKey=${JOB_NAME} -Dsonar.java.binaries=target/ -Dsonar.login=1ac110ff9ad377073b7df04d5b36029549212e37'
}
}
stage('构建代码') {
steps {
sh '''mv target/*.jar docker/
docker build -t ${JOB_NAME}:$tag docker/
docker image prune -f'''
}
}
stage('制作自定义镜像并发布Harbor') {
steps {
sh '''docker login -u ${harborUser} -p ${harborPasswd} ${harborHost}
docker tag ${JOB_NAME}:$tag ${harborHost}/${harborRepo}/${JOB_NAME}:$tag
docker push ${harborHost}/${harborRepo}/${JOB_NAME}:$tag'''
}
}
stage('基于Harbor部署工程') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'test', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "deploy.sh $harborHost $harborRepo $JOB_NAME $tag $host_port $container_port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
post {
success {
dingtalk(
robot: 'dingtalk',
type: 'MARKDOWN',
title: "success: ${JOB_NAME}",
text: ["- 成功构建: ${JOB_NAME}项目!\n- 版本: ${tag}\n- 持续时间:${currentBuild.durationString}\n- 任务:#${JOB_NAME} "]
)
}
failure {
dingtalk(
robot: 'dingtalk',
type: 'MARKDOWN',
title: "fail: ${JOB_NAME}",
text: ["- 构建失败: ${JOB_NAME}项目!\n- 版本: ${tag}\n- 持续时间:${currentBuild.durationString}\n- 任务:#${JOB_NAME} "]
)
}
}
}
}
}
7.4.1 配置pipeline
7.4.2 准备Jenkinsfile,在gitlab上创建Jenkinsfile文件
7.4.3 参数化构建
7.4.4 拉取git代码
将*/master更改为标签${tag}
7.4.5 通过Maven 构建项目
7.4.6 检测代码质量
7.4.7 构建代码
7.4.8 制作自定义镜像并发布到harbor
7.4.9 生成Publish Over SSH脚本
注意下面用到变量的地方,用流水线生成的是单引号,要改成双引号
stage('基于Harbor部署工程') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'test', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "deploy.sh $harborHost $harborRepo $JOB_NAME $tag $host_port $container_port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
7.5 jenkins整合钉钉
7.5.1 安装插件
7.5.1 内部创建群组并构建机器人
7.5.3 jenkins配置钉钉
7.5.4 jenkinsfile中编写通知消息的语法
post {
success {
dingtalk(
robot: 'dingtalk',
type: 'MARKDOWN',
title: "success: ${JOB_NAME}",
text: ["- 成功构建: ${JOB_NAME}项目!\n- 版本: ${tag}\n- 持续时间:${currentBuild.durationString}\n- 任务:#${JOB_NAME} "]
)
}
failure {
dingtalk(
robot: 'dingtalk',
type: 'MARKDOWN',
title: "fail: ${JOB_NAME}",
text: ["- 构建失败: ${JOB_NAME}项目!\n- 版本: ${tag}\n- 持续时间:${currentBuild.durationString}\n- 任务:#${JOB_NAME} "]
)
}
}
具体语法可以参考官方文档
dingtalk:github地址
官方文档:文档地址
8. 集成kubernates
kubernates网址:kubernate
kuboard地址:kuboard
8.1 kubernate总体架构
8.2 安装kubernates
本文安装的是kubernates1.19
配置要求
8.2.1 修改hostname
# 修改 hostname
hostnamectl set-hostname your-new-host-name
# 查看修改结果
hostnamectl status
# 设置 hostname 解析
echo "127.0.0.1 $(hostname)" >> /etc/hosts
8.2.2 设置两个机器的设置成固定ip
参考网址:设置固定ip
设置vmvare虚拟机的总体网络配置
curl 百度查看固定ip是否设置成功
8.2.3 安装docker及kubelet
# 在 master 节点和 worker 节点都要执行
# 最后一个参数 1.19.5 用于指定 kubenetes 版本,支持所有 1.19.x 版本的安装
# 腾讯云 docker hub 镜像
# export REGISTRY_MIRROR="https://mirror.ccs.tencentyun.com"
# DaoCloud 镜像
# export REGISTRY_MIRROR="http://f1361db2.m.daocloud.io"
# 华为云镜像
# export REGISTRY_MIRROR="https://05f073ad3c0010ea0f4bc00b7105ec20.mirror.swr.myhuaweicloud.com"
# 阿里云 docker hub 镜像
export REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com
curl -sSL https://kuboard.cn/install-script/v1.19.x/install_kubelet.sh | sh -s 1.19.5
8.2.4 初始化master节点
# 只在 master 节点执行
# 替换 x.x.x.x 为 master 节点实际 IP(请使用内网 IP)
# export 命令只在当前 shell 会话中有效,开启新的 shell 窗口后,如果要继续安装过程,请重新执行此处的 export 命令
export MASTER_IP=x.x.x.x
# 替换 apiserver.demo 为 您想要的 dnsName
export APISERVER_NAME=apiserver.demo
# Kubernetes 容器组所在的网段,该网段安装完成后,由 kubernetes 创建,事先并不存在于您的物理网络中
export POD_SUBNET=10.100.0.1/16
echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
curl -sSL https://kuboard.cn/install-script/v1.19.x/init_master.sh | sh -s 1.19.5
8.2.5 查看master 节点初始化情况
# 只在 master 节点执行
# 执行如下命令,等待 3-10 分钟,直到所有的容器组处于 Running 状态
watch kubectl get pod -n kube-system -o wide
# 查看 master 节点初始化结果
kubectl get nodes -o wide
Ps:如果出现NotReady的情况执行(最新版本的BUG,1.19一般没有)
docker pull quay.io/coreos/flannel:v0.10.0-amd64
mkdir -p /etc/cni/net.d/
cat <<EOF> /etc/cni/net.d/10-flannel.conf
{"name":"cbr0","type":"flannel","delegate": {"isDefaultGateway": true}}
EOF
mkdir /usr/share/oci-umount/oci-umount.d -p
mkdir /run/flannel/
cat <<EOF> /run/flannel/subnet.env
FLANNEL_NETWORK=172.100.0.0/16
FLANNEL_SUBNET=172.100.1.0/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true
EOF
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml
安装网络服务插件
export POD_SUBNET=10.100.0.0/16
kubectl apply -f https://kuboard.cn/install-script/v1.22.x/calico-operator.yaml
wget https://kuboard.cn/install-script/v1.22.x/calico-custom-resources.yaml
sed -i "s#192.168.0.0/16#${POD_SUBNET}#" calico-custom-resources.yaml
kubectl apply -f calico-custom-resources.yaml
8.2.6 初始化worker节点
在 master 节点上执行,获取加入集群的方法
# 只在 master 节点执行
kubeadm token create --print-join-command
初始化从节点
#只在 worker 节点执行
#替换 x.x.x.x 为 master 节点的内网 IP
export MASTER_IP=x.x.x.x
#替换 apiserver.demo 为初始化 master 节点时所使用的 APISERVER_NAME
export APISERVER_NAME=apiserver.demo
echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
#kubeadm token create 命令的输出
kubeadm join apiserver.demo:6443 --token mpfjma.4vjjg8flqihor4vt --discovery-token-ca-cert-hash sha256:6f7a8e40a810323672de5eee6f4d19aa2dbdb38411845a1bf5dd63485c43d303
8.2.7 查看初始化结果
kubectl get nodes -o wide
Ps:如果出现NotReady的情况执行(最新版本的BUG,1.19一般没有)
docker pull quay.io/coreos/flannel:v0.10.0-amd64
mkdir -p /etc/cni/net.d/
cat <<EOF> /etc/cni/net.d/10-flannel.conf
{"name":"cbr0","type":"flannel","delegate": {"isDefaultGateway": true}}
EOF
mkdir /usr/share/oci-umount/oci-umount.d -p
mkdir /run/flannel/
cat <<EOF> /run/flannel/subnet.env
FLANNEL_NETWORK=172.100.0.0/16
FLANNEL_SUBNET=172.100.1.0/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true
EOF
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml
8.3 安装kuboard
8.3.1 在线安装
kubectl apply -f https://addons.kuboard.cn/kuboard/kuboard-v3.yaml
# 您也可以使用下面的指令,唯一的区别是,该指令使用华为云的镜像仓库替代 docker hub 分发 Kuboard 所需要的镜像
# kubectl apply -f https://addons.kuboard.cn/kuboard/kuboard-v3-swr.yaml
8.3.2 查看kuboard的安装情况
watch kubectl get pods -n kuboard
8.3.3 访问kuboard
- 在浏览器中打开链接 http://your-node-ip-address:30080
用户名: admin
密码: Kuboard123
8.4 kubernates操作
资源的构建方式
- 采用kubectl的命令方式
- yaml文件方式
8.4.1 namespace
命名空间:主要是为了对Kubernetes中运行的资源进行过隔离, 但是网络是互通的,类似Docker的容器,可以将多个资源配置到一个NameSpace中。而NameSpace可以对不同环境进行资源隔离,默认情况下Kubernetes提供了default命名空间,在构建资源时,如果不指定资源,默认采用default资源。
相关命令
# 查看现有的命名空间
kubectl get ns
# 创建命名空间
kubectl create ns 命名空间名称
# 删除现有的命名空间
kubectl delete ns 命名空间名称
yaml方式
apiVersion: v1
kind: NameSpace
metadata:
name: test
8.4.2 Pod
- pod: 是kubernates运行的一组容器,pod是kubernates的最小单位,但是对于docker而言,pod中运行多个容器
命令方式
# 查看所有运行的pod
kubectl get pods -A
# 查看指定Namespace 下的pod
kubectl get pod [-n 命名空间]
# 创建pod
kubectl run pod名称 --image=镜像名称
# 查看pod的详细信息
kubectl describe pod pod名称
# 删除pod
kubectl delete pod pod名称 [-n 命名空间](默认是default)
# 查看pod输出日志
kubectl logs -f pod名称
# 进去pod容器内部
kubectl exec -it pod名称 --bash
# 查看kubernates给Pod 分配的ip信息,并且通过ip和容器端口,可以直接访问
kubectl get pod -owide
yaml方式
apiVersion: v1
kind: Pod
metadata:
labels:
run: 运行的pod名称
name: pod名称
namespace: 命名空间
spec:
containers:
- image: 镜像名称
name: 容器名称
启动后可以看到
8.4.3 Deployment
部署时,可以通过Deployment管理和编排Pod
命令方式
# 基于Deployment启动容器
kubectl create deployment deployment名称 --image=镜像名称
# 用deployment启动的容器会在被删除后自动再次创建,达到故障漂移的效果
# 需要使用deploy的方式删除deploy
# 查看现在的deployment
kubectl get deployment
# 删除 deployment
kubectl delete deployment deployment名称
# 基于Deployment启动容器并设置Pod集群数
kubectl create deployment deployment名称 --image=镜像名称 --replicas 集群个数
配置文件方式
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
弹性伸缩
# 基于scale实现弹性伸缩
kubectl scale deploy/Deployment名称 --replicas 集群个数
# 或者修改yaml文件
kubectl edit deploy Deployment名称
灰度发布
Deploy可以在部署新版本数据时,成功启动一个pod,才会下线一个老版本的Pod
kubectl set image deployment/Deployment名称 容器名=镜像:版本
8.4.4 Service
可以将多个Pod对外暴露一个Service,让客户端可以通过Service访问到这一组Pod,并且可以实现负载均衡
8.4.4.1 ClusterIP方式
- 命令实现效果
kubectl expose deployment Deployment名称 --port=Service端口号 --target-port=容器内部端口号
- 通过kubectl get service 查看Service提供的端口
8.4.4.2 NodePort方式
ClusterIP的方式只能在Pod内部实现访问,但是一般需要对外暴露网关,所以需要NodePort的方式Pod外暴露访问
- 命令实现方式
# 通过生成service映射一个Deployment下的所有pod中的某一个端口的容器
kubectl expose deployment Deployment名称 --port=Service端口号 --target=port=Pod内容器端口 --type=NodePort
8.4.4.3 通过yml方式实现
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx-deployment
template:
metadata:
labels:
app: nginx-deployment
spec:
containers:
- name: nginx-deployment
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx-service
name: nginx-service
spec:
selector:
app: nginx-deployment
ports:
- port: 8888
protocol: TCP
targetPort: 80
type: NodePort
8.4.5 ingress
Kubernetes推荐将Ingress作为所有Service的入口,提供统一的入口,避免多个服务之间需要记录大量的IP或者域名,毕竟IP可能改变,服务太多域名记录不方便。
Ingress底层其实就是一个Nginx, 可以在Kuboard上直接点击安装
8.4.5.1 ingress使用yaml文件方式部署
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
spec:
ingressClassName: ingress
rules:
- host: nginx.mashibing.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-service
port:
number: 8888
Kuboard安装的Ingress有admission的校验配置,需要先删除配置再启动
找到指定的ingress的校验信息,删除即可
# 查看校验webhook的配置
kubectl get -A ValidatingWebhookConfiguration
# 删除指定的校验
kubectl delete ValidatingWebhookConfiguration ingress-nginx-admission-my-ingress-controller
8.5 jenkins 集成Kubernetes
8.5.1 准备部署的yml文件
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: test
name: pipeline
labels:
app: pipeline
spec:
replicas: 2
selector:
matchLabels:
app: pipeline
template:
metadata:
labels:
app: pipeline
spec:
containers:
- name: pipeline
image: 192.168.37.131:80/repo/pipeline:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
namespace: test
labels:
app: pipeline
name: pipeline
spec:
selector:
app: pipeline
ports:
- port: 8082
targetPort: 8080
type: NodePort
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: test
name: pipeline
spec:
ingressClassName: ingress
rules:
- host: gek.test.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: pipeline
port:
number: 8082
8.5.2 Harbor私服配置
在尝试用kubernetes的yml文件启动pipeline服务时,会出现Kubernetes无法拉取镜像的问题,这里需要在kubernetes所在的Linux中配置Harbor服务信息,并且保证Kubernetes可以拉取Harbor上的镜像
- 设置Master和Worker的私服地址信息
"insecure-registries": ["192.168.37.131:80"],
在kuboard上设置密文并测试
测试
执行kubectl命令,基于yml启动服务,并且基于部署后服务的提示信息以及Ingress的设置,直接访问
8.5.3 jenkins远程调用
8.5.3.1 将pipeline,yml配置到Gitlab中
8.5.3.2配置Jenkins的目标服务器,可以将yml文件传输到K8s的Master上
8.5.3.3 修改Jenkinsfile,增加将pipeline.yml文件上传到k8s-master上的步骤
stage('将yml文件上传到k8s集群') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'pipeline', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'pipeline.yml')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
stage('执行yml文件,运行到k8s') {
steps {
sh '''ssh root@192.168.37.138 kubectl apply -f /usr/local/k8s/pipeline.yml
ssh root@192.168.37.138 kubectl rollout restart deployment pipeline -n test'''
}
}
完成将yml上传到k8s集群的操作,并执行yml文件,需要实现 ssh无密码登录
进入jenkins 找到.ssh下面的公钥文件
docker exec -it jenkins bash
#进入容器
cd ~
mkdir .ssh
cd .ssh
# 生成 ssh 公钥私钥
ssh-keygen -t rsa
# 将公钥 copy 到k8s的master节点
ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.37.138
测试效果如下:不需要提供账号密码就表明成功了
执行流水线查看效果
Ps:这种方式更适应与CD操作,将项目将基于某个版本部署到指定的目标服务器
8.6 基于gitlab的webkhooks 实现一个CI
这里要实现自动化的一个CI操作,也就是开发人员Push代码到Git仓库后,Jenkins会自动的构建项目,将最新的提交点代码构建并进行打包部署,这里区别去上述的CD操作,CD操作需要基于某个版本进行部署,而这里每次都是将最新的提交点集成到主干上并测试。
8.6.1 webhooks通知
开启Jenkins的自动构建
设置gitlab 的Webhooks
关闭jenkins的gitlab认证
再次测试
8.6.2 修改jenkinsfile 将之前的${tag}去掉
//所有脚本命令都在pipeline中
pipeline {
//指定在哪个节点执行(jenkins支持分布式)
agent any
//配置全局环境变量
environment {
harborHost = '192.168.37.131:80'
harborRepo = 'repo'
harborUser = 'admin'
harborPasswd = 'password'
}
//存放所有任务集合
stages {
//单个任务
stage('拉取Git代码') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[url: 'http://root:password@192.168.37.132:8929/root/mytest.git']]])
}
}
stage('通过maven构建项目') {
steps {
sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'
}
}
stage('检测代码质量') {
steps {
sh '/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.host.url=http://192.168.37.132:9000 -Dsonar.projectname=${JOB_NAME} -Dsonar.projectKey=${JOB_NAME} -Dsonar.java.binaries=target/ -Dsonar.login=1ac110ff9ad377073b7df04d5b36029549212e37'
}
}
stage('构建代码') {
steps {
sh '''mv target/*.jar docker/
docker build -t ${JOB_NAME}:latest docker/
docker image prune -f'''
}
}
stage('制作自定义镜像并发布Harbor') {
steps {
sh '''docker login -u ${harborUser} -p ${harborPasswd} ${harborHost}
docker tag ${JOB_NAME}:latest ${harborHost}/${harborRepo}/${JOB_NAME}:latest
docker push ${harborHost}/${harborRepo}/${JOB_NAME}:latest'''
}
}
stage('将yml文件上传到k8s集群') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'pipeline', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'pipeline.yml')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
stage('执行yml文件,运行到k8s') {
steps {
sh '''ssh root@192.168.37.138 kubectl apply -f /usr/local/k8s/pipeline.yml
ssh root@192.168.37.138 kubectl rollout restart deployment pipeline -n test'''
}
}
stage('基于Harbor部署工程') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'test', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "deploy.sh $harborHost $harborRepo $JOB_NAME latest $host_port $container_port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
post {
success {
dingtalk(
robot: 'dingtalk',
type: 'MARKDOWN',
title: "success: ${JOB_NAME}",
text: ["- 成功构建: ${JOB_NAME}项目!\n- 版本: latest\n- 持续时间:${currentBuild.durationString}\n- 任务:#${JOB_NAME} "]
)
}
failure {
dingtalk(
robot: 'dingtalk',
type: 'MARKDOWN',
title: "fail: ${JOB_NAME}",
text: ["- 构建失败: ${JOB_NAME}项目!\n- 版本: latest\n- 持续时间:${currentBuild.durationString}\n- 任务:#${JOB_NAME} "]
)
}
}
}
}
}
8.6.3 修改pipeline.yml,更改镜像版本
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: test
name: pipeline
labels:
app: pipeline
spec:
replicas: 2
selector:
matchLabels:
app: pipeline
template:
metadata:
labels:
app: pipeline
spec:
containers:
- name: pipeline
image: 192.168.37.131:80/repo/pipeline:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
namespace: test
labels:
app: pipeline
name: pipeline
spec:
selector:
app: pipeline
ports:
- port: 8082
targetPort: 8080
type: NodePort
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: test
name: pipeline
spec:
ingressClassName: ingress
rules:
- host: gek.test.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: pipeline
port:
number: 8082
8.6.4 滚动更新
因为pipeline没有改变时,每次不会重新加载,这样会导致Pod中的容器不会动态更新,这里需要使用kubectl的rollout restart命令滚动更新
ssh root@192.168.37.138 kubectl rollout restart deployment pipeline -n test