本机环境ubuntu 2204
开放对应端口或者关闭防火墙
sudo apt install ca-certificates curl openssh-server postfix
cd /tmp
curl -LO https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh
sudo bash /tmp/script.deb.sh
sudo apt install gitlab-ce
sudo vim /etc/gitlab/gitlab.rb
改成自己的ip
external_url 'http://10.211.55.8:9092'#本机局域网ip为10.211.55.8端口为9092
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 日志 |
http://10.211.55.8:9092
初始账号root,密码在/etc/gitlab/initial_root_password
cat /etc/gitlab/initial_root_password
preference处修改密码
sudo systemctl enable gitlab-runsvdir.service
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@
docker pull gitlab/gitlab-ce
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'
docker-compose up -d
docker exec -it gitlab cat /etc/gitlab/initial_root_password
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
配置阿里云仓库
<mirror>
<id>alimavenid>
<name>aliyun mavenname>
<url>http://maven.aliyun.com/nexus/content/groups/public/url>
<mirrorOf>centralmirrorOf>
mirror>
mirrors>
配置中使用JDK1.8进行编译
<profile>
<id>jdk1.8id>
<activation>
<activeByDefault>trueactiveByDefault>
<jdk>1.8jdk>
activation>
<properties>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
<maven.compiler.compilerVersion>1.8maven.compiler.compilerVersion>
properties>
profile>
注意如果是虚拟机,必须内存至少4G才能正常跑起来
官网地址:Jekins
本文用docker 安装
docker pull jenkins/jenkins:2.346.3-2-lts
# /usr/local/docker/
mkdir -p jenkins_docker
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/
docker-compose up -d
#本文中这个文件夹/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
docker exec -it jenkins cat /var/jenkins_home/secrets/initialAdminPassword
注意需要将远程路径上加上账号密码
http://root:[email protected]:9092/root/jenkins.git
将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/
路径是jenkins 容器中的映射路径,本文是安装在/var/jenkins_home
jar包构建好之后,就可以根据情况发布到测试或生产环境,这里需要用到之前下载好的插件Publish Over SSH。
为了让程序代码可以自动推送到测试环境基于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
在gitlab项目中打标签
Sonar Qube在7.9版本中已经放弃了对MySQL的支持,并且建议在商业环境中采用PostgreSQL,那么安装Sonar Qube时需要依赖PostgreSQL。
官网地址:sonarQube
并且这里会安装Sonar Qube的长期支持版本8.9
docker pull postgres
docker pull sonarqube:8.9.3-community
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
docker-compose up -d
解决,修改/etc/sysctl.conf
vm.max_map_count=262144
sysctl -p
访问:ip:9000
注意下载对应的sonarQube的版本,不同版本会不起作用
如果搜出来的不对的话,下载对应的jar报,放到插件目录下也会生效
配置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界面测试结果
下载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/
开启sonar qube权限验证
获取sonar Qube令牌
配置jenkins 的Sonar Qube信息
将sonarQube进行全部配置
配置任务的sonar-scanner
地址:harbor下载地址
tar -zxvf harbor-offline-installer-v2.3.4.tgz -C /usr/local/
cd /usr/local/harbor
cp harbor.yml.tmpl harbor.yml
## 当前目录 /usr/local/harbor
./install.sh
命名规则:harbor地址/项目名/镜像名:版本
修改镜像名称 |
---|
vim /etc/docker/daemon.json
阿里云上的容器镜像服务
{
"registry-mirrors": ["https://87hwjhy6.mirror.aliyuncs.com"],
"insecure-registries": ["192.168.37.131:80"]
}
docker login -u 用户名 -p 密码 Harbor地址
sudo chown root:root /var/run/docker.sock
sudo chmod o+rw /var/run/docker.sock
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
#从打包目录复制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
部署项目需要通过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/
deploy.sh 192.168.37.131:80 repo ${JOB_NAME} $tag $port
pipeline {
// 指定任务在哪个节点执行(Jenkins支持分布式)
agent any
// 配置全局环境,指定变量名=变量值信息
environment{
host = '192.168.11.11'
}
// 存放所有任务的合集
stages {
// 单个任务
stage('任务1') {
// 实现任务的具体流程
steps {
echo 'do something'
}
}
// 单个任务
stage('任务2') {
// 实现任务的具体流程
steps {
echo 'do something'
}
}
// ……
}
}
Ps:涉及到特定脚本,Jenkins给予了充足的提示,可以自动生成命令
总配置文件
//所有脚本命令都在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:[email protected]: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} "]
)
}
}
}
}
}
将*/master更改为标签${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} "]
)
}
}
具体语法可以参考官方文档
dingtalk:github地址
官方文档:文档地址
kubernates网址:kubernate
kuboard地址:kuboard
本文安装的是kubernates1.19
配置要求
# 修改 hostname
hostnamectl set-hostname your-new-host-name
# 查看修改结果
hostnamectl status
# 设置 hostname 解析
echo "127.0.0.1 $(hostname)" >> /etc/hosts
参考网址:设置固定ip
设置vmvare虚拟机的总体网络配置
curl 百度查看固定ip是否设置成功
# 在 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
# 只在 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
# 只在 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
在 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
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
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
watch kubectl get pods -n kuboard
资源的构建方式
命名空间:主要是为了对Kubernetes中运行的资源进行过隔离, 但是网络是互通的,类似Docker的容器,可以将多个资源配置到一个NameSpace中。而NameSpace可以对不同环境进行资源隔离,默认情况下Kubernetes提供了default命名空间,在构建资源时,如果不指定资源,默认采用default资源。
相关命令
# 查看现有的命名空间
kubectl get ns
# 创建命名空间
kubectl create ns 命名空间名称
# 删除现有的命名空间
kubectl delete ns 命名空间名称
yaml方式
apiVersion: v1
kind: NameSpace
metadata:
name: test
命令方式
# 查看所有运行的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: 容器名称
启动后可以看到
部署时,可以通过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名称 容器名=镜像:版本
可以将多个Pod对外暴露一个Service,让客户端可以通过Service访问到这一组Pod,并且可以实现负载均衡
kubectl expose deployment Deployment名称 --port=Service端口号 --target-port=容器内部端口号
ClusterIP的方式只能在Pod内部实现访问,但是一般需要对外暴露网关,所以需要NodePort的方式Pod外暴露访问
# 通过生成service映射一个Deployment下的所有pod中的某一个端口的容器
kubectl expose deployment Deployment名称 --port=Service端口号 --target=port=Pod内容器端口 --type=NodePort
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
Kubernetes推荐将Ingress作为所有Service的入口,提供统一的入口,避免多个服务之间需要记录大量的IP或者域名,毕竟IP可能改变,服务太多域名记录不方便。
Ingress底层其实就是一个Nginx, 可以在Kuboard上直接点击安装
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
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
在尝试用kubernetes的yml文件启动pipeline服务时,会出现Kubernetes无法拉取镜像的问题,这里需要在kubernetes所在的Linux中配置Harbor服务信息,并且保证Kubernetes可以拉取Harbor上的镜像
"insecure-registries": ["192.168.37.131:80"],
测试
执行kubectl命令,基于yml启动服务,并且基于部署后服务的提示信息以及Ingress的设置,直接访问
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 [email protected] kubectl apply -f /usr/local/k8s/pipeline.yml
ssh [email protected] 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 [email protected]
测试效果如下:不需要提供账号密码就表明成功了
执行流水线查看效果
Ps:这种方式更适应与CD操作,将项目将基于某个版本部署到指定的目标服务器
这里要实现自动化的一个CI操作,也就是开发人员Push代码到Git仓库后,Jenkins会自动的构建项目,将最新的提交点代码构建并进行打包部署,这里区别去上述的CD操作,CD操作需要基于某个版本进行部署,而这里每次都是将最新的提交点集成到主干上并测试。
开启Jenkins的自动构建
设置gitlab 的Webhooks
关闭jenkins的gitlab认证
再次测试
//所有脚本命令都在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:[email protected]: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 [email protected] kubectl apply -f /usr/local/k8s/pipeline.yml
ssh [email protected] 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} "]
)
}
}
}
}
}
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
因为pipeline没有改变时,每次不会重新加载,这样会导致Pod中的容器不会动态更新,这里需要使用kubectl的rollout restart命令滚动更新
ssh [email protected] kubectl rollout restart deployment pipeline -n test