局域网中有两台服务器proxmox进行了虚拟化,跑一些测试应用。今天正好想要安装一下clickhouse跑一下。安装前准备:
测试服务器是否支持sse 4.2指令集……如下
[root@slave1 app]# grep -q sse4_2 /proc/cpuinfo && echo "SSE 4.2 supported" || echo "SSE 4.2 not supported“"
SSE 4.2 not supported“
突然就慌了,我的服务器cpu是intel的 怎么会不支持sse 4.2呢?
root@proxmox2:/etc/pve/qemu-server# grep -q sse4_2 /proc/cpuinfo && echo "SSE 4.2 supported" || echo "SSE 4.2 not supported“"
SSE 4.2 supported
点击对应虚拟机-硬件-处理器-编辑
看了下cpu有个类别?
下拉有很多选项 包括AMD 和intel的架构 当然了 默认的是 kvm64.问题会不会出现在这里呢?
百度搜索 proxmox sse4.2
两篇文章中都有类似的问题,提出的解决方式是修改cpu的mode 为 host-model:
尝试着修改一下cpu类型为host:
重启虚拟机并登陆验证:
[root@slave1 ~]# grep -q sse4_2 /proc/cpuinfo && echo "SSE 4.2 supported" || echo "SSE 4.2 not supported“"
SSE 4.2 supported
java程序员们想弄一个私有maven仓库,嗯 正常的是用nexus or artfactory? artfactory是两三年前听jfrog的讲座知道的,程序说他原来用的nexus。那就搞一个nexus了。
基础环境参照:https://cloud.tencent.com/developer/article/1806089–kubernetes集群1.20.5版本(当然了进行了小版本升级1.21了,系列笔记中有提)
https://cloud.tencent.com/developer/article/1806896–网关层的代理traefik
https://cloud.tencent.com/developer/article/1806549–存储块腾讯云cbs
all on kubernetes 是个人的原则。就在kubernetes的环境上搭建一个私有maven仓库了。
注: 不做特殊说明,工具类软件我都安装在kube-ops namespace命名空间下
嗯 存储用的都是腾讯云的cbs存储
[root@sh-master-01 ~]# kubectl get storageclass
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
cbs-csi com.tencent.cloud.csi.cbs Delete Immediate false 70d
cat pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
namespace: kube-ops
name: sonatype-nexus
labels:
app: sonatype-nexus
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Gi
storageClassName: cbs-csi
selector:
matchLabels:
app: sonatype-nexus
kubectl apply -f pvc.yaml
嗯 好吧cbs-csi 不支持selector的标签….将就的用吧…腾讯一直讲自己今年的开源项目是最多的,但是如kubernetes-csi-tencentcloud这样的项目,三年了吧 提交了issue也没有关闭呢也没有人回复。所以能用就行了…还是适应它吧……
kubectl delete -f pvc.yaml
cat pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
namespace: kube-ops
name: sonatype-nexus
labels:
app: sonatype-nexus
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Gi
storageClassName: cbs-csi
kubectl apply -f pvc.yaml
kubectl describe pvc sonatype-nexus -n kube-ops
kubectl get pvc -n kube-ops
cat nexus.yaml
apiVersion: v1
kind: Service
metadata:
name: sonatype-nexus
labels:
app: sonatype-nexus
spec:
type: ClusterIP
ports:
- name: sonatype-nexus
port: 8081
targetPort: 8081
protocol: TCP
selector:
app: sonatype-nexus
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sonatype-nexus
labels:
app: sonatype-nexus
spec:
replicas: 1
selector:
matchLabels:
app: sonatype-nexus
template:
metadata:
labels:
app: sonatype-nexus
spec:
containers:
- name: sonatype-nexus
image: sonatype/nexus3:3.30.0
imagePullPolicy: IfNotPresent
ports:
- name: server
containerPort: 8081
livenessProbe: #存活探针
httpGet:
path: /
port: 8081
initialDelaySeconds: 30
periodSeconds: 30
failureThreshold: 6
readinessProbe: #就绪探针
httpGet:
path: /
port: 8081
initialDelaySeconds: 30
periodSeconds: 30
failureThreshold: 6
env:
- name: INSTALL4J_ADD_VM_PARAMS #设置分配资源大小,一定要等于或小于resources设置的值
value: "
-Xms1200M
-Xmx1200M
-XX:MaxDirectMemorySize=2G
-XX:+UnlockExperimentalVMOptions
-XX:+UseCGroupMemoryLimitForHeap
"
resources: #资源限制
limits:
cpu: 1000m #推荐设置为4000m以上cpu,由于资源有限,所以都是设置的最小值
memory: 2048Mi
requests:
cpu: 500m
memory: 1024Mi
volumeMounts:
- name: sonatype-nexus-data
mountPath: /nexus-data
volumes:
- name: sonatype-nexus-data
persistentVolumeClaim:
claimName: sonatype-nexus #设置为上面创建的 PVC
[root@sh-master-01 qa]# kubectl get pods -n kube-ops
NAME READY STATUS RESTARTS AGE
gitlab-b9d95f784-7h8dt 1/1 Running 0 49d
gitlab-redis-cd56f5cc9-g9gm8 1/1 Running 0 61d
jenkins-0 2/2 Running 0 49d
postgresql-5bd6b44d45-wzkwr 1/1 Running 1 61d
sonatype-nexus-5d98d78b86-nk75v 0/1 CrashLoopBackOff 6 9m5s
查看报错如下:
嗯权限不够 咋整….嗯 由于pvc只能挂载单个pod,先执行:
kubectl delete -f nexus.yaml -n kube-ops
然后修改nexus.yaml如下:
cat nexus.yaml
apiVersion: v1
kind: Service
metadata:
name: sonatype-nexus
labels:
app: sonatype-nexus
spec:
type: ClusterIP
ports:
- name: sonatype-nexus
port: 8081
targetPort: 8081
protocol: TCP
selector:
app: sonatype-nexus
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sonatype-nexus
labels:
app: sonatype-nexus
spec:
replicas: 1
selector:
matchLabels:
app: sonatype-nexus
template:
metadata:
labels:
app: sonatype-nexus
spec:
initContainers:
- name: init
image: busybox
command: ["sh", "-c", "chown -R 200:200 /nexus-data"]
volumeMounts:
- name: sonatype-nexus-data
mountPath: /nexus-data
containers:
- name: sonatype-nexus
image: sonatype/nexus3:3.30.0
imagePullPolicy: IfNotPresent
ports:
- name: server
containerPort: 8081
livenessProbe: #存活探针
httpGet:
path: /
port: 8081
initialDelaySeconds: 30
periodSeconds: 30
failureThreshold: 6
readinessProbe: #就绪探针
httpGet:
path: /
port: 8081
initialDelaySeconds: 30
periodSeconds: 30
failureThreshold: 6
env:
- name: INSTALL4J_ADD_VM_PARAMS #设置分配资源大小,一定要等于或小于resources设置的值
value: "
-Xms1200M
-Xmx1200M
-XX:MaxDirectMemorySize=2G
-XX:+UnlockExperimentalVMOptions
-XX:+UseCGroupMemoryLimitForHeap
"
resources: #资源限制
limits:
cpu: 1000m #推荐设置为4000m以上cpu,由于资源有限,所以都是设置的最小值
memory: 2048Mi
requests:
cpu: 500m
memory: 1024Mi
volumeMounts:
- name: sonatype-nexus-data
mountPath: /nexus-data
volumes:
- name: sonatype-nexus-data
persistentVolumeClaim:
claimName: sonatype-nexus #设置为上面创建的 PVC
[root@sh-master-01 nexus]# kubectl apply -f nexus.yaml -n kube-ops
service/sonatype-nexus created
deployment.apps/sonatype-nexus created
[root@sh-master-01 nexus]# kubectl get pods -n kube-ops
NAME READY STATUS RESTARTS AGE
gitlab-b9d95f784-7h8dt 1/1 Running 0 49d
gitlab-redis-cd56f5cc9-g9gm8 1/1 Running 0 61d
jenkins-0 2/2 Running 0 49d
postgresql-5bd6b44d45-wzkwr 1/1 Running 1 61d
sonatype-nexus-79f85cc57c-scb9b 0/1 Init:0/1 0 28s
[root@sh-master-01 nexus]# kubectl get pods -n kube-ops
NAME READY STATUS RESTARTS AGE
gitlab-b9d95f784-7h8dt 1/1 Running 0 49d
gitlab-redis-cd56f5cc9-g9gm8 1/1 Running 0 61d
jenkins-0 2/2 Running 0 49d
postgresql-5bd6b44d45-wzkwr 1/1 Running 1 61d
sonatype-nexus-79f85cc57c-scb9b 0/1 PodInitializing 0 2m
kubectl describe pods sonatype-nexus-79f85cc57c-scb9b -n kube-ops
嗯可以running了
然后获取一下用户名 密码:
做一个ingress 代理?
cat ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nexus-ingress
namespace: kube-ops
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/router.entrypoints: web
nginx.ingress.kubernetes.io/ssl-redirect: 'true'
spec:
rules:
- host: nexus.sainaihe.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: sonatype-nexus
port:
number: 8081
kubectl apply -f ingress.yaml
嗯跨域了可咋整? 我的两个主域名都泛域名强制跳转https了,短时间没有想好怎么解决….我就直接用了另外一个单独域名。不强跳可以直接访问了。同理我是不是可以加一个https的单独的设置….有时间了再试一下。先跑通一下nexus的代理应用……
http访问:
如下。第一次是要修改密码的关于初始密码的获取可以参照:1.2中获取初始密码的方式
嗯 对了呢 记得关闭匿名访问。anonymous
打开 Repositories->Create repository->maven2(proxy) 并设置要代理的 Maven 仓库名称与地址
设置“仓库名称”与“仓库地址”。
保存上面设置后回到仓库页面,可以看到已经添加了一个新的仓库 aliyun.
打开 Repositories->maven public 并设置代理仓库优先级置顶
设置 maven 的 Settings.xml 文件,按照下面配置进行设置私服地址和验证的用户名、密码。
随手打开一个idea项目添加了一个
更新maven项目:
ok如下可以从个人配置的maven代理仓库更新了!
我是盗用了下程序的ava maven项目,pom.xml添加如下配置:
<distributionManagement>
<!-- Maven 上传设置 -->
<repository>
<id>nexus</id> <!-- 保持和Settings.xml中配置的Server ID一致 -->
<name>releases</name>
<url>http://http://nexus.xxx.com//repository/maven-releases/</url> <!-- 推送到Maven仓库的maven-releases下 -->
</repository>
</distributionManagement>
.当然了仓库自己新建了两个:zhangpeng-releases对应release
zhangpeng-snapshots 对应snapshots
、
mvn deploy打包:
登陆nexus:
嗯对我来说这就算是成功了……
我的基础环境all in kubernetes,参见:https://cloud.tencent.com/developer/article/1806089,https://cloud.tencent.com/developer/article/1811859后端大佬们玩springboot cloud项目.故要讲springboot cloud项目部署在kubernetes集群中。其实使用springboot cloud架构我还是有所反对的。看过一些文章如:https://www.cnblogs.com/lakeslove/p/10997011.html。springboot与我的kubernetes有很多的重合功能了。本来就是差不多同时兴起的项目….如果用新的东西 我还是比较想上服务网格:istio这样的。既然决定springboot cloud on kubernets了 那就先这样玩了……
关于打包 都是maven的本来可以直接接手的。但是程序喜欢自己打,我就只在项目里面放Dockerfile.只负责镜像层面了:
基本就是这个样子,当然了发布环境的时候我本来想写configmap的方式直接让程序去读我的环境变量的……但是程序找我要数据库 redis的连接地址 账号密码 说要写在 配置文件application.yml中,无果。随他去了。自己拉了一下t项目试一下是否可以在springboot中使用configmap的方式。
百度随手搜了一下啊关键词 springboot kubernetes configmap一堆:
比如图上这个,但是都感觉不是我想要的,我就想简单的整下我的变量。然后无意间看到了:https://capgemini.github.io/engineering/externalising-spring-boot-config-with-kubernetes/就按照这个方式来搞一下了:
注: 因为就是简单测试下我不想让他们写死文件,其他过程就省了了 我就直接打个包测试下了
参照原配置文件:
修改后的:
变量名都是自己随手写的 主要测试效果能否实现。当然了实际的需要和程序统一的还是规范化参数要好的,${}的格式都是。
嗯提取了8个参数将其变量化。
docker打包没有集成在我的jenkins pipeline里面(程序的库,我就不做过多参与了),生成jar包
将jar包上传到我一台有docker环境的服务器上面打包成docker image:
cat Dockerfile
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD target/game-1.0-SNAPSHOT.jar game-1.0-SNAPSHOT.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/game-1.0-SNAPSHOT.jar"]
docker build -t ccr.ccs.tencentyun.com/xxxx/xxxx:0.2 .
docker push ccr.ccs.tencentyun.com/xxxx/xxxx:0.2
cat spring-boot.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: spring-config
data:
dev-config.json:
'{
"redis.database.host": "xxxx",
"redis.database.port": "xxxx",
"redis.database.password": "xxxx",
"mysql.database.url": "jdbc:mysql://xxxx:3306/xxxx",
"mysql.database.username": "xxxx",
"mysql.database.password": "xxxxx",
"cloud.nacos.server-addr": "http://xxxx:8848",
"cloud.nacos.discovery.server-addr": "http://xxxx:8848"
}'
apply部署configmap文件:
kubectl apply -f spring-config.yaml -n qa
describe一下:
cat test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: pvp-test
spec:
replicas: 1
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: pvp-test
template:
metadata:
labels:
app: pvp-test
spec:
containers:
- name: pvp-test
image: ccr.ccs.tencentyun.com/xxxx/xxxx:0.2
env:
- name: SPRING_PROFILES_ACTIVE
value: "qa"
- name: SPRING_APPLICATION_JSON
valueFrom:
configMapKeyRef:
name: spring-config
key: dev-config.json
envFrom:
- configMapRef:
name: deploy
ports:
- containerPort: 8001
name: game-http
- containerPort: 8011
name: game-tcp
resources:
requests:
memory: "512M"
cpu: "500m"
limits:
memory: "512M"
cpu: "500m"
imagePullSecrets:
- name: tencent
---
apiVersion: v1
kind: Service
metadata:
name: pvp-test
labels:
app: pvp-test
spec:
ports:
- port: 8001
name: game-http
targetPort: 8001
- port: 8011
name: game-tcp
targetPort: 8011
selector:
app: pvp-test
kubectl apply -f 2.yaml -n qa
注: imagePullSecrets为下载image的秘钥。如果你是公开的仓库可以忽略。我的仓库用的腾讯云的个人版。秘钥自己创建名字就叫tencent了.
测试时候比较仓库 配置文件都起名 1 2 这样的yaml文件了见谅
kubectl get pods -n qa
kubectl logs -f pvp-test-7f49fcdb9-dsjlz -n qa
启动的过程中是有错误的但是先忽略这个。因为我看了一下啊nacos中 我的服务其实已经注册上了….。初步我想要 结果算是实现了!
字面上的意思吧?
User “system:serviceaccount:qa:default” cannot get resource “configmaps” in API group “” in the namespace “qa”.
这里算是RBAC clusterrole rolebinding的一个复习吧。
cat configmap-get.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: qa
name: configmap-get
rules:
- apiGroups: [""]
resources: ["configmap"]
verbs: ["get"]
与serviceaccount:qa:default绑定
kubectl create clusterrolebinding configmap-get-configmap --clusterrole=configmap-get --serviceaccount=qa:default
杀死容器继续查看新的容器 的log
kubectl delete pods pvp-test-7f49fcdb9-dsjlz -n qa
kubectl logs -f pvp-test-7f49fcdb9-ck9m6 -n qa
依然报错…仔细一看日志….嗯 参数应该是configmaps….,我少写了一个s吧?修改configmap-get.yaml文件如下:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: qa
name: configmap-get
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get"]
apply 重新部署clusterrole。删除旧pod重新查看日志:
kubectl apply -f configmap-get.yaml
kubectl delete pods pvp-test-7f49fcdb9-ck9m6 -n qa
嗯这次总算成功了
今天复习了好几个知识点……
Kubernetes 1.20.5 upgrade 1.21.0,升级完成突然发现Prometheus discover中两个服务down了,收到微信报警
登陆Prometheus控制台一看controller-manager kube-scheduler服务确实是down:
登陆集群查看kubectl get pods -n kube-system服务都是正常的。当然了也可以kubectl logs -f $podname -n kube-system去查看一下相关pod的log日志进行确认一下。
仔细一想是不是升级的时候controller-manager kube-scheduler服务的配置文件给升级了呢…记得在搭建Prometheus-oprator的时候手动修改过两个服务的配置文件what仔细一想也对…upgrade的时候 它难道把两个配置文件改了?
继续参照:Kubernetes 1.20.5 安装Prometheus-Oprator中1.5 查看controller-manager kube-scheduler服务的配置:
注:配置文件路径为:/etc/kubernetes/manifests
cat cat kube-controller-manager.yaml 发现–bind-address=127.0.0.1了 恢复了初始的设置,在安装Prometheus-oprator的时候将其修改为0.0.0.0的同理修改。
修改scheduler配置文件–bind-address=0.0.0.0
注: 修改配置文件是针对所有master节点配置文件的。
重启 三个master节点kubelet服务:
注:我记得应该修改了相关的配置服务 控制平面的相关pods是会重启的吧?重启kubelet只是个人确保一下啊正常……
systemctl restart kubelet
等待服务跑起来running……
登陆Prometheus web控制台确认监控恢复正常状态:
集群环境参照:centos8+kubeadm1.20.5+cilium+hubble环境搭建。kubernets有了新的版本。1.21.0。嗯准备升级一下啊。
yum list --showduplicates kubeadm --disableexcludes=kubernetes
yum install kubeadm-1.21.0 kubectl-1.21.0 --disableexcludes=kubernetes
kubeadm upgrade plan
注:集群环境是一个ha的环境。这部操作选择了再sh-master-01节点执行
kubeadm upgrade apply v1.21.0 --certificate-renewal=false
–certificate-renewal=false 嗯 我不想重新生成证书….搭建了才没有多久……
嗯 报错了 找不到coredns的镜像:我还有个1.16的kubernetes的集群对比了一下,貌似coredns的目录层级多了一级?
查看了一眼默认仓库:
然后 ctr images pull registry.aliyuncs.com/google_containers/coredns/coredns:v1.8.0
仓库下也确实没有这个image。也特意看了下阿里云 包括腾讯云的镜像仓库貌似不支持这样的层级的目录?可能在设计的时候都没有想到后面有这样的层级吗?
一般来说是下载镜像 然后修改镜像tag…..可是我试了几次upgrade仍然是失败:
各种找文章的顺路看到了https://blog.51cto.com/u_3252740/2717642
就顺路玩了一下:
kubectl -n kube-system edit cm kubeadm-config
coredns的镜像仓库是可以单独定义的:那我就单独定义一下吧,整成k8s.gcr.io佛系定义。就想单独定义一下dns的仓库。
ctr -n k8s.io images pull uhub.service.ucloud.cn/uxhy/v1.8.0
ctr -n k8s.io images pull uhub.service.ucloud.cn/uxhy/coredns:v1.8.0
ctr -n k8s.io images tag uhub.service.ucloud.cn/uxhy/coredns:v1.8.0 k8s.gcr.io/coredns/coredns:v1.8.0
然后
master-01 忘了截图借用了下其他节点的截图
kubeadm upgrade apply v1.21.0 --certificate-renewal=false
基本上就是重复1.2的步骤 然后kubeadm upgrade node。之前貌似一直是kubeadm upgrade apply了?
另外一般的安全操作建议是kubectl drain
sh-master-02 sh-master-03节点执行一下操作
ctr -n k8s.io images pull uhub.service.ucloud.cn/uxhy/v1.8.0
ctr -n k8s.io images pull uhub.service.ucloud.cn/uxhy/coredns:v1.8.0
ctr -n k8s.io images tag uhub.service.ucloud.cn/uxhy/coredns:v1.8.0 k8s.gcr.io/coredns/coredns:v1.8.0
yum install kubeadm-1.21.0 kubectl-1.21.0 --disableexcludes=kubernetes
kubeadm upgrade node
草率了1.2 执行:yum install kubeadm-1.21.0 kubectl-1.21.0 –disableexcludes=kubernetes 糊里糊涂怎么没有加上kubelet呢?以后还是加在一起去安装了。
yum install -y kubelet-1.21.0 --disableexcludes=kubernetes
sudo systemctl daemon-reload
sudo systemctl restart kubelet
yum install -y kubeadm-1.21.0 kubelet-1.21.0 kubectl-1.21.0 --disableexcludes=kubernetes
kubeadm upgrade node
kubectl drain <node-to-drain> --ignore-daemonsets
kubectl uncordon
sudo systemctl daemon-reload
sudo systemctl restart kubelet
kubectl get node
kubectl get pods -n kube-system
生产环境都部署在kubernetes集群上,使用jenkins打包镜像并部署在kubernetes集群中。关于jenkins的安装参照:https://duiniwukenaihe.github.io/2019/11/19/k8s-install-jenkins/。当然了也有helm的安装方式https://duiniwukenaihe.github.io/2021/03/31/Kubernetes-1.20.5-helm-%E5%AE%89%E8%A3%85jenkins/。
代码仓库是搭建的gitlab仓库。仓库中每个子项目多包含Dockerfile文件。镜像的tag采用了时间戳的命名方式:
return new Date().format('yyyyMMddHHmm')
仓库的branch也可以定义一下:
当然了 这里有两个插件要安装的:
这是一个非常古老的插件了。但是还比较好用。下载地址:http://mirror.xmission.com/jenkins/plugins/dynamicparameter/ 。安装的方式是上传:
仓库是自己搞的 直接先xxxx了。偷懒写的明文用户名密码,docker image仓库直接使用的腾讯云的镜像仓库个人版。
echo env.data
pipeline {
agent any
parameters {
gitParameter branchFilter: 'origin/(.*)', defaultValue: 'develop', name: 'BRANCH', type: 'PT_BRANCH'
}
stages {
stage('Checkout') {
agent { node { label 'xxxx-jnlp'} }
steps {
sh '''
git clone --depth=1 -b cache http://xxx:xxx@github.com/xxx/xxx.git'''
}
}
stage('docker build dataloader') {
agent { node { label 'xxxx-jnlp'} }
steps {
sh ''' cd /home/jenkins/agent/workspace/develop-xxxxme/xxxxme/dataloader
docker login --username=xxxxxx ccr.ccs.tencentyun.com -p xxxxx
docker build --build-arg NODE_ENV=game-ucenter -t ccr.ccs.tencentyun.com/xxxx-master/dataloader-game-ucenter:$data .
docker push ccr.ccs.tencentyun.com/xxxx-master/dataloader-game-ucenter:$data'''
}
}
stage('docker build datawriter-old') {
agent { node { label 'xxxx-jnlp'} }
steps {
sh ''' cd /home/jenkins/agent/workspace/develop-xxxxme/xxxxme/datawriter-old
docker login --username=xxxxxx ccr.ccs.tencentyun.com -p xxxxx
docker build --build-arg NODE_ENV=game-ucenter -t ccr.ccs.tencentyun.com/xxxx-master/datawriter-game-ucenter:$data .
docker push ccr.ccs.tencentyun.com/xxxx-master/datawriter-game-ucenter'''
}
}
stage('docker build datawriter') {
agent { node { label 'xxxx-jnlp'} }
steps {
sh ''' cd /home/jenkins/agent/workspace/develop-xxxxme/xxxxme/datawriter
docker login --username=xxxxxx ccr.ccs.tencentyun.com -p xxxxx
docker build --build-arg NODE_ENV=xxxx-maker -t ccr.ccs.tencentyun.com/xxxx-master/datawriter-maker:$data .
docker build --build-arg NODE_ENV=xxxx-comment -t ccr.ccs.tencentyun.com/xxxx-master/datawriter-comment:$data .
docker push ccr.ccs.tencentyun.com/xxxx-master/datawriter-maker:$data
docker push ccr.ccs.tencentyun.com/xxxx-master/datawriter-comment:$data'''
}
}
stage('docker build game-ucenter') {
agent { node { label 'xxxx-jnlp'} }
steps {
sh ''' cd /home/jenkins/agent/workspace/develop-xxxxme/xxxxme/game-ucenter
docker login --username=xxxxxx ccr.ccs.tencentyun.com -p xxxxx
docker build -t ccr.ccs.tencentyun.com/xxxx-master/game-ucenter:$data .
docker push ccr.ccs.tencentyun.com/xxxx-master/game-ucenter:$data'''
}
}
stage('docker build xxxx-comment') {
agent { node { label 'xxxx-jnlp'} }
steps {
sh ''' cd /home/jenkins/agent/workspace/develop-xxxxme/xxxxme/xxxx-comment
docker login --username=xxxxxx ccr.ccs.tencentyun.com -p xxxxx
docker build -t ccr.ccs.tencentyun.com/xxxx-master/xxxx-comment:$data .
docker push ccr.ccs.tencentyun.com/xxxx-master/xxxx-comment:$data'''
}
}
stage('docker build xxxx-maker') {
agent { node { label 'xxxx-jnlp'} }
steps {
sh ''' cd /home/jenkins/agent/workspace/develop-xxxxme/xxxxme/xxxx-maker
docker login --username=xxxxxx ccr.ccs.tencentyun.com -p xxxxx
docker build -t ccr.ccs.tencentyun.com/xxxx-master/xxxx-maker:$data .
docker push ccr.ccs.tencentyun.com/xxxx-master/xxxx-maker:$data'''
}
}
stage('docker build MessageConsumer') {
agent { node { label 'xxxx-jnlp'} }
steps {
sh ''' cd /home/jenkins/agent/workspace/develop-xxxxme/xxxxme/messageconsumer
docker login --username=xxxxxx ccr.ccs.tencentyun.com -p xxxxx
docker build --build-arg NODE_ENV=xxxx-maker -t ccr.ccs.tencentyun.com/xxxx-master/messageconsumer:$data .
docker push ccr.ccs.tencentyun.com/xxxx-master/messageconsumer:$data'''
}
}
stage('docker build xxxxtimer ') {
agent { node { label 'xxxx-jnlp'} }
steps {
sh ''' cd /home/jenkins/agent/workspace/develop-xxxxme/xxxxme/xxxxtimer
docker login --username=xxxxxx ccr.ccs.tencentyun.com -p xxxxx
docker build -t ccr.ccs.tencentyun.com/xxxx-master/xxxxtimer:$data .
docker push ccr.ccs.tencentyun.com/xxxx-master/xxxxtimer:$data'''
}
}
stage('docker build mail-koa ') {
agent { node { label 'xxxx-jnlp'} }
steps {
sh ''' cd /home/jenkins/agent/workspace/develop-xxxxme/xxxxme/mail-koa
docker login --username=xxxxxx ccr.ccs.tencentyun.com -p xxxxx
docker build -t ccr.ccs.tencentyun.com/xxxx-master/mail-koa:$data .
docker push ccr.ccs.tencentyun.com/xxxx-master/mail-koa:$data'''
}
}
stage('docker build xxxx-diversion ') {
agent { node { label 'xxxx-jnlp'} }
steps {
sh ''' cd /home/jenkins/agent/workspace/develop-xxxxme/xxxxme/diversion
docker login --username=xxxxxx ccr.ccs.tencentyun.com -p xxxxx
docker build -t ccr.ccs.tencentyun.com/xxxx-master/xxxx-diversion:$data .
docker push ccr.ccs.tencentyun.com/xxxx-master/xxxx-diversion:$data'''
}
}
stage('项目部署') {
agent { node { label 'build01'} }
steps {
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/dataloader-game-ucenter.tpl > /home/jenkins/workspace/yaml/develop/dataloader-game-ucenter.yaml"
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/datawriter-comment.tpl > /home/jenkins/workspace/yaml/develop/datawriter-comment.yaml"
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/datawriter-game-ucenter.tpl > /home/jenkins/workspace/yaml/develop/datawriter-game-ucenter.yaml"
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/datawriter-maker.tpl > /home/jenkins/workspace/yaml/develop/datawriter-maker.yaml"
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/game-ucenter.tpl > /home/jenkins/workspace/yaml/develop/game-ucenter.yaml"
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/xxxx-comment.tpl > /home/jenkins/workspace/yaml/develop/xxxx-comment.yaml"
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/xxxx-maker.tpl > /home/jenkins/workspace/yaml/develop/xxxx-maker.yaml"
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/messageconsumer.tpl > /home/jenkins/workspace/yaml/develop/messageconsumer.yaml"
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/xxxxtimer.tpl > /home/jenkins/workspace/yaml/develop/xxxxtimer.yaml"
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/mail-koa.tpl > /home/jenkins/workspace/yaml/develop/mail-koa.yaml"
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/xxxx-diversion.tpl > /home/jenkins/workspace/yaml/develop/xxxx-diversion.yaml"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/dataloader-game-ucenter.yaml --namespace=develop"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/datawriter-comment.yaml --namespace=develop"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/datawriter-game-ucenter.yaml --namespace=develop"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/datawriter-maker.yaml --namespace=develop"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/game-ucenter.yaml --namespace=develop"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/xxxx-comment.yaml --namespace=develop"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/xxxx-maker.yaml --namespace=develop"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/messageconsumer.yaml --namespace=develop"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/xxxxtimer.yaml --namespace=develop"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/mail-koa.yaml --namespace=develop"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/xxxx-diversion.yaml --namespace=develop"
}
}
}
}
这样的一个pipeline 算是解决了我初期的问题。能直接一步发版了。但是在后面的使用中出现了下面的一些问题:
使用Git Parameter插件的话,新建的分支应该是要拉取一次后才能有这个参数的。对于我来说不利于迭代,因为程序也经常建立一些无规则的分支。我就设置了默认的cache分支,然后切换分支的话让他自己定义就好了。
还整了一个选项参数:srcType .copy泽阳老师课程来的。虽然仓库默认都是gitlab了。但是凑个数添加一下svn。
将仓库 还有gitlab秘钥都在jenkins中新建为秘钥:
先把拉取代码的stage上一下:
stage("GetCode"){
agent { label "build" }
steps{
script{
println("下载代码 --> 分支: ${env.branchName}")
checkout([$class: 'GitSCM', branches: [[name: "${env.branchName}"]],
extensions: [],
userRemoteConfigs: [[credentialsId: 'XXXX',
url: "${env.gitHttpURL}"]]])
}
}
}
至于stage的发布选取https://www.cnblogs.com/jwentest/p/7113399.html看到了这样的复选框的方式看了下
,觉得貌似可以用。
也做了这样的测试,但是到pipeline里面是不是要转成列表还要循环?这样的步骤个人不熟悉。放弃了。
最终用了另外一种方式:对于每一个子项目。我都添加了一个布尔值参数。然后只给常用的加上了 默认值。每个stage做一个when的判断:
基本就是这样的,然后我的pipeline直接用上了 :
when {
environment name: 'XXXX', value: 'true'
}
这样就能解决了选择发布发布的选择问题。然后就说dockerhub秘钥的明文问题了:
stage('docker build XXX') {
agent { label "build" }
when {
environment name: 'xxxx', value: 'true'
}
steps {
sh " cd XXX&&docker build -t ccr.ccs.tencentyun.com/xxxx/XXXX:$data ."
withCredentials([usernamePassword(credentialsId: 'XXXXX', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {
sh "docker login -u ${dockerUser} -p ${dockerPassword} ccr.ccs.tencentyun.com"
sh "docker push ccr.ccs.tencentyun.com/xxx-master/xxxx:$data"
}
}
}
然后就说我的发布流程根据tpl模板生成yaml 文件然后apply就做成了并行的stage:
parallel {
}
如下:
pipeline {
agent { label "build" }
stages {
stage("GetCode"){
agent { label "build" }
steps{
script{
println("下载代码 --> 分支: ${env.branchName}")
checkout([$class: 'GitSCM', branches: [[name: "${env.branchName}"]],
extensions: [],
userRemoteConfigs: [[credentialsId: 'xxxx-open-php',
url: "${env.gitHttpURL}"]]])
}
}
}
stage('docker build dataloader') {
agent { label "build" }
when {
environment name: 'dataloader', value: 'true'
}
steps {
sh ''' cd dataloader
docker login --username=xxxx ccr.ccs.tencentyun.com -p Aa123456.
docker build --build-arg NODE_ENV=xxxx-maker -t ccr.ccs.tencentyun.com/xxxx-master/dataloader-maker:$data .
docker build --build-arg NODE_ENV=xxxx-comment -t ccr.ccs.tencentyun.com/xxxx-master/dataloader-comment:$data .
docker build --build-arg NODE_ENV=game-ucenter -t ccr.ccs.tencentyun.com/xxxx-master/dataloader-game-ucenter:$data .'''
withCredentials([usernamePassword(credentialsId: 'xxxx', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {
sh "docker login -u ${dockerUser} -p ${dockerPassword} ccr.ccs.tencentyun.com"
sh "docker push ccr.ccs.tencentyun.com/xxxx-master/dataloader-maker:$data"
sh "docker push ccr.ccs.tencentyun.com/xxxx-master/dataloader-comment:$data"
sh "docker push ccr.ccs.tencentyun.com/xxxx-master/dataloader-game-ucenter:$data"
}
}
}
stage('docker build datawriter-old') {
agent { label "build" }
when {
environment name: 'datawriter-old', value: 'true'
}
steps {
sh " cd datawriter-old&&docker build -t ccr.ccs.tencentyun.com/xxxx-master/datawriter-old:$data ."
withCredentials([usernamePassword(credentialsId: 'xxxx', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {
sh "docker login -u ${dockerUser} -p ${dockerPassword} ccr.ccs.tencentyun.com"
sh "docker push ccr.ccs.tencentyun.com/xxxx-master/datawriter-old:$data"
}
}
}
stage('docker build datawriter') {
agent { label "build" }
when {
environment name: 'datawriter', value: 'true'
}
steps {
sh ''' cd datawriter
docker login --username=xxxx ccr.ccs.tencentyun.com -p Aa123456.
docker build --build-arg NODE_ENV=xxxx-maker -t ccr.ccs.tencentyun.com/xxxx-master/datawriter-maker:$data .
docker build --build-arg NODE_ENV=xxxx-comment -t ccr.ccs.tencentyun.com/xxxx-master/datawriter-comment:$data .'''
withCredentials([usernamePassword(credentialsId: 'xxxx', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {
sh "docker login -u ${dockerUser} -p ${dockerPassword} ccr.ccs.tencentyun.com"
sh "docker push ccr.ccs.tencentyun.com/xxxx-master/datawriter-maker:$data"
sh "docker push ccr.ccs.tencentyun.com/xxxx-master/datawriter-comment:$data"
}
}
}
stage('docker build game-ucenter') {
agent { label "build" }
when {
environment name: 'game-ucenter', value: 'true'
}
steps {
sh " cd game-ucenter&&docker build -t ccr.ccs.tencentyun.com/xxxx-master/game-ucenter:$data ."
withCredentials([usernamePassword(credentialsId: 'xxxx', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {
sh "docker login -u ${dockerUser} -p ${dockerPassword} ccr.ccs.tencentyun.com"
sh "docker push ccr.ccs.tencentyun.com/xxxx-master/game-ucenter:$data"
}
}
}
stage('docker build xxxx-comment') {
agent { label "build" }
when {
environment name: 'xxxx-comment', value: 'true'
}
steps {
sh " cd xxxx-comment&&docker build -t ccr.ccs.tencentyun.com/xxxx-master/xxxx-comment:$data ."
withCredentials([usernamePassword(credentialsId: 'xxxx', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {
sh "docker login -u ${dockerUser} -p ${dockerPassword} ccr.ccs.tencentyun.com"
sh "docker push ccr.ccs.tencentyun.com/xxxx-master/xxxx-comment:$data"
}
}
}
stage('docker build xxxx-maker') {
agent { label "build" }
when {
environment name: 'xxxx-maker', value: 'true'
}
steps {
sh " cd xxxx-maker&&docker build -t ccr.ccs.tencentyun.com/xxxx-master/xxxx-maker:$data ."
withCredentials([usernamePassword(credentialsId: 'xxxx', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {
sh "docker login -u ${dockerUser} -p ${dockerPassword} ccr.ccs.tencentyun.com"
sh "docker push ccr.ccs.tencentyun.com/xxxx-master/xxxx-maker:$data"
}
}
}
stage('docker build MessageConsumer') {
agent { label "build" }
when {
environment name: 'MessageConsumer', value: 'true'
}
steps {
sh " cd messageconsumer&&docker build -t ccr.ccs.tencentyun.com/xxxx-master/messageconsumer:$data ."
withCredentials([usernamePassword(credentialsId: 'xxxx', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {
sh "docker login -u ${dockerUser} -p ${dockerPassword} ccr.ccs.tencentyun.com"
sh "docker push ccr.ccs.tencentyun.com/xxxx-master/messageconsumer:$data"
}
}
}
stage('docker build xxxxtimer ') {
agent { label "build" }
when {
environment name: 'xxxxtimer', value: 'true'
}
steps {
sh " cd xxxxtimer&&docker build -t ccr.ccs.tencentyun.com/xxxx-master/xxxxtimer:$data ."
withCredentials([usernamePassword(credentialsId: 'xxxx', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {
sh "docker login -u ${dockerUser} -p ${dockerPassword} ccr.ccs.tencentyun.com"
sh "docker push ccr.ccs.tencentyun.com/xxxx-master/xxxxtimer:$data"
}
}
}
stage('docker build mail-koa ') {
agent { label "build" }
when {
environment name: 'mail-koa', value: 'true'
}
steps {
sh " cd mail-koa&&docker build -t ccr.ccs.tencentyun.com/xxxx-master/mail-koa:$data ."
withCredentials([usernamePassword(credentialsId: 'xxxx', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {
sh "docker login -u ${dockerUser} -p ${dockerPassword} ccr.ccs.tencentyun.com"
sh "docker push ccr.ccs.tencentyun.com/xxxx-master/mail-koa:$data"
}
}
}
stage('docker build xxxx-diversion ') {
agent { label "build" }
when {
environment name: 'diversion', value: 'true'
}
steps {
sh " cd diversion&&docker build -t ccr.ccs.tencentyun.com/xxxx-master/xxxx-diversion:$data ."
withCredentials([usernamePassword(credentialsId: 'xxxx', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {
sh "docker login -u ${dockerUser} -p ${dockerPassword} ccr.ccs.tencentyun.com"
sh "docker push ccr.ccs.tencentyun.com/xxxx-master/xxxx-diversion:$data"
}
}
}
stage('develop') {
parallel {
stage("develop dataloader") {
when {
environment name: 'dataloader', value: 'true'
}
steps {
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/dataloader-comment.tpl > /home/jenkins/workspace/yaml/develop/dataloader-comment.yaml"
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/dataloader-game-ucenter.tpl > /home/jenkins/workspace/yaml/develop/dataloader-game-ucenter.yaml"
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/dataloader-maker.tpl > /home/jenkins/workspace/yaml/develop/dataloader-maker.yaml"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/dataloader-game-ucenter.yaml --namespace=develop"
}
}
stage("develop datawriter-old") {
when {
environment name: 'datawriter-old', value: 'true'
}
steps {
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/datawriter-game-ucenter.tpl > /home/jenkins/workspace/yaml/develop/datawriter-game-ucenter.yaml"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/datawriter-game-ucenter.yaml --namespace=develop"
}
}
stage("develop datawriter") {
when {
environment name: 'datawriter', value: 'true'
}
steps {
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/datawriter-maker.tpl > /home/jenkins/workspace/yaml/develop/datawriter-maker.yaml"
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/datawriter-comment.tpl > /home/jenkins/workspace/yaml/develop/datawriter-comment.yaml"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/datawriter-comment.yaml --namespace=develop"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/datawriter-maker.yaml --namespace=develop"
}
}
stage("develop game-ucenter") {
when {
environment name: 'game-ucenter', value: 'true'
}
steps {
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/game-ucenter.tpl > /home/jenkins/workspace/yaml/develop/game-ucenter.yaml"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/game-ucenter.yaml --namespace=develop"
}
}
stage("develop xxxx-comment") {
when {
environment name: 'xxxx-comment', value: 'true'
}
steps {
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/xxxx-comment.tpl > /home/jenkins/workspace/yaml/develop/xxxx-comment.yaml"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/xxxx-comment.yaml --namespace=develop"
}
}
stage("develop xxxx-maker") {
when {
environment name: 'xxxx-maker', value: 'true'
}
steps {
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/xxxx-maker.tpl > /home/jenkins/workspace/yaml/develop/xxxx-maker.yaml"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/xxxx-maker.yaml --namespace=develop"
}
}
stage("develop MessageConsumer") {
when {
environment name: 'messageconsumer', value: 'true'
}
steps {
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/messageconsumer.tpl > /home/jenkins/workspace/yaml/develop/messageconsumer.yaml"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/messageconsumer.yaml --namespace=develop"
}
}
stage("develop xxxxtimer") {
when {
environment name: 'xxxxtimer', value: 'true'
}
steps {
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/xxxxtimer.tpl > /home/jenkins/workspace/yaml/develop/xxxxtimer.yaml"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/xxxxtimer.yaml --namespace=develop"
}
}
stage("develop mail-koa") {
when {
environment name: 'mail-koa', value: 'true'
}
steps {
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/mail-koa.tpl > /home/jenkins/workspace/yaml/develop/mail-koa.yaml"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/mail-koa.yaml --namespace=develop"
}
}
stage("develop xxxx-diversion") {
when {
environment name: 'xxxx-diversion', value: 'true'
}
steps {
sh "sed -e 's/{data}/$data/g' /home/jenkins/workspace/yaml/develop/xxxx-diversion.tpl > /home/jenkins/workspace/yaml/develop/xxxx-diversion.yaml"
sh "sudo kubectl apply -f /home/jenkins/workspace/yaml/develop/xxxx-diversion.yaml --namespace=develop"
}
}
}
}
}
}
直接偷懒在web 上设置了:
当然了也可以在pipeline中设置:
选择天数和最大个数:
将生成的option放入pipeline脚本即可。做完了测试了一下:
算是基本满足自己的需求了,这算是学了泽阳大佬的jenkins课程后改的自己过去写的第一个pipeline。包括很多步骤都没有加。比如代码扫描,程序测试流程。还有构建后邮件或者钉钉通知。先把这流水线改的顺眼一些吧….另外这周when的判断还是有点抵触,后面看看能不能有更好的方法去简练一些pipeline呢。当前就是看着顺眼能跑。
SonarQube 是一个用于代码质量管理的开源平台,用于管理源代码的质量。同时 SonarQube 还对大量的持续集成工具提供了接口支持,可以很方便地在持续集成中使用 SonarQube。此外 SonarQube 的插件还可以对 Java 以外的其他编程语言提供支持,对国际化以及报告文档化也有良好的支持。
注:这东西个人还是仅测试不敢玩哈哈哈。个性的程序员太多,出现各种各样的坏味道对应小运维来说也不知道怎么该跟程序所解释对接。不能作为一个清晰既定的衡量标准去衡量各种。各种阀值做不到正确的配置。只用于演示演示。
过去个人玩是只在kubernetes上部署了SonarQube 的7.9lts版本(community社区版本)。lts顾名思义长期稳定支持版。kubernetes的部署方式可以参见豆丁大佬的博文:http://www.mydlq.club/article/25/。个人也写个一篇类似的文章helm的安装方式搭建:https://duiniwukenaihe.github.io/2019/11/29/k8s-helm-install-postgresql-sonarqube/
注:报名了泽阳大佬的jenkins CI/CD训练营。基本就是按照阳明大佬的步骤来的.想更深入学习的可以报名:https://www.idevops.site/。物超所值。满满的干货。当然了大佬课程是搭建的7.9.6的版本,我是直接玩8.9.0的lts了。
个人环境是在内网搭建的proxmox虚拟化的服务器上虚拟的centos8.3.并参照https://blog.csdn.net/qq_41570843/article/details/106182073安装了docker环境的初始化主机。
主机ip为:192.168.0.109
关于 lts镜像 为什么用sonarqube:8.9.0-community image呢?可以到dockerhub看下两个镜像的tag
## 创建数据目录
mkdir -p /data/sonarqube/{sonarqube_conf,sonarqube_extensions,sonarqube_logs,sonarqube_data}
chmod 777 -R /data/sonarqube/
## 运行
docker run -itd --name sonarqube \
-p 9000:9000 \
-v /data/sonarqube/sonarqube_conf:/opt/sonarqube/conf \
-v /data/sonarqube/sonarqube_extensions:/opt/sonarqube/extensions \
-v /data/sonarqube/sonarqube_logs:/opt/sonarqube/logs \
-v /data/sonarqube/sonarqube_data:/opt/sonarqube/data \
sonarqube:8.9.0-community
## 验证
docker logs -f sonarqube
登陆web管理页面初始用户名密码dmin修改密码。7.9的版本应该是没有默认修改密码的这一步的,会直接登陆控制台页面。初始化修改密码这步在安全性上我个人觉得这也是一个进步。
Adminstration-Marketplace-Plugins
先提示一条风险l understand the risk
我了解风险。(这一步应该也是新的版本增加的7.9.6的lts貌似是没有的)然后install 搜索chinese install插件,然后重启。(网络经常抽筋安装不了)
https://github.com/xuhuisheng/sonar-l10n-zh/releases/tag/sonar-l10n-zh-plugin-8.9
上传到/data/sonarqube/sonarqube_extensions/downloads目录,然后
cd /data/sonarqube/sonarqube_extensions/downloads
wget https://github.com/xuhuisheng/sonar-l10n-zh/releases/download/sonar-l10n-zh-plugin-8.9/sonar-l10n-zh-plugin-8.9.jar
chmod +x sonar-l10n-zh-plugin-1.29.jar
docker restart sonarqube
其实是加深下docker cp的用法了
## lib目录
mkdir -p /data/sonarqube/sonarqube_lib
cd /data/sonarqube/sonarqube_lib
docker cp sonarqube://opt/sonarqube/lib/. /data/sonarqube/sonarqube_lib/
## 销毁旧的容器,重新挂载本地目录
docker stop sonarqube
docker rm sonarqube
docker run -itd --name sonarqube \
-p 9000:9000 \
-v /data/sonarqube/sonarqube_conf:/opt/sonarqube/conf \
-v /data/sonarqube/sonarqube_extensions:/opt/sonarqube/extensions \
-v /data/sonarqube/sonarqube_logs:/opt/sonarqube/logs \
-v /data/sonarqube/sonarqube_data:/opt/sonarqube/data \
-v /data/sonarqube/sonarqube_lib:/opt/sonarqube/lib \
sonarqube:8.9.0-community
在lib目录下新建一个文件,登陆容器挂载目录内验证加载成功
注:这一步后web登陆sonarqube应该又要重新初始化一遍密码。因为数据库没有整外部的也没有挂载数据目录。使用的默认的数据库内部的。生产环境应该起码配置外部的数据库的嗯大部分用的是postgresql…
在sonarqube7.9版本中 常用的插件举个例子:
8.9版本中很多不需要安装了….参照:https://docs.sonarqube.org/latest/instance-administration/plugin-version-matrix/。凡是提示Bundled的都已经默认集成了:
Gradle - SonarScanner for Gradle .NET - SonarScanner for .NET Maven - use the SonarScanner for Maven Jenkins - SonarScanner for Jenkins Azure DevOps - SonarQube Extension for Azure DevOps Ant - SonarScanner for Ant anything else (CLI) - SonarScanner
选择anything else了,cli的方式。直接在192.168.0.173这台搭建了gitlab的主机上面搭建了(这台主机我也搞了jenkins slave。安装了jdk的1.8)
关于主机已经运行的gitlab环境参照:https://cloud.tencent.com/developer/article/1818427
https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/一般是安装最新的我个人。但是下载的时候貌似没有看好…选择了sonar-scanner-cli-4.6.1.2450-linux.zip。反正大同小异的就拿这个来演示了……
wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.6.1.2450-linux.zip
unzip sonar-scanner-cli-4.6.1.2450-linux.zip
mv sonar-scanner-4.6.1.2450-linux /usr/local/
vim /etc/profile
export SCANNER_HOME=/usr/local/sonar-scanner-4.6.1.2450-linux
export PATH=$PATH:$SCANNER_HOME/bin
source/etc/profile
确认版本安装成功生效
sonar-scanner -v
what嗯 我本地的环境是jdk1.8d 为什么我的sonar-scanner java版本是java11呢?这是因为sonar-scanner中集成了jre环境。默认是使用自己的jre的.
vim /usr/local/sonar-scanner-4.6.1.2450-linux/bin/sonar-scanner
###修改use_embedded_jre参数
use_embedded_jre=false
sonar-scanner -v 验证java版本
只是简单验证使用下sonnarscanner的使用
注:其实在安装jenkins的时候已经安装了maven了。但是这里没有写jenkins的部署。所以这里就补写一下了。
### 下载
wget https://mirrors.bfsu.edu.cn/apache/maven/maven-3/3.8.1/binaries/apache-maven-3.8.1-bin.tar.gz
tar zxf apache-maven-3.8.1-bin.tar.gz -C /usr/local/
cd /usr/local/apache-maven-3.8.1/
pwd /usr/local/apache-maven-3.8.1
### 配置环境变量
vi /etc/profile
export M2_HOME=/usr/local/apache-maven-3.8.1
export PATH=$M2_HOME/bin:$PATH
source /etc/profile
### 验证
mvn -v
Apache Maven 3.8.1 (05c21c65bdfed0f71a2f2ada8b84da59348c4c5d)
Maven home: /usr/local/apache-maven-3.8.1
Java version: 1.8.0_292, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.292.b10-0.el8_3.x86_64/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "4.18.0-240.22.1.el8_3.x86_64", arch: "amd64", family: "unix"
** **https://start.spring.io/的maven项目
其实是跟着泽阳大佬的步骤做的一个devops-maven-service gitlab项目。反正就是那么的一个demo没有做什么复杂的设置。其实如果只是只sonarqube集成也可以不先整合到gitlab的,但是为了尽量还原自己的环境,故上传到gitlab了。
git clone http://192.168.0.173/devops/devops-maven-service
mvn clean package
一定记得mvn打包。自己脑袋糊涂了。不maven打包哪里会有target class目录呢……
执行扫描会报错的(扫描代码详见下一步)
sonar-scanner -Dsonar.host.url=http://192.168.0.209:9000 \
-Dsonar.projectKey=devops-maven-service \
-Dsonar.projectName=devops-maven-service \
-Dsonar.projectVersion=1.0 \
-Dsonar.login=admin \
-Dsonar.password=abc@1234 \
-Dsonar.ws.timeout=30 \
-Dsonar.projectDescription="my first project!" \
-Dsonar.links.homepage=http://192.168.0.173/devops/devops-maven-service \
-Dsonar.links.ci=http://192.168.0.205:8080/job/demo-pipeline-service/ \
-Dsonar.sources=src \
-Dsonar.sourceEncoding=UTF-8 \
-Dsonar.java.binaries=target/classes \
-Dsonar.java.test.binaries=target/test-classes \
-Dsonar.java.surefire.report=target/surefire-reports
嗯配置参数基本字面意思homepage ci都是乱写的可以忽略。
具体参数实例可以参考: https://docs.sonarqube.org/latest/analysis/analysis-parameters/
各种语言的扫描示例:https://docs.sonarqube.org/latest/analysis/languages/
反正正常扫描完了就是下面专业的
介绍后登陆sonarqubeweb管理页面查看:
嗯 貌似就是这样的。拿自己内部的一个tts的项目测试下(起名是个学问,这样的名字我也很无语。其实就是一个使用阿里云tts文字转语音的服务)。
mvn clean package
讲真出现那么多Positive matches 我有点强迫症。都是大佬写的。就抛砖引玉了……
sonar-scanner -Dsonar.host.url=http://192.168.0.209:9000 \
-Dsonar.projectKey=tts \
-Dsonar.projectName=tts \
-Dsonar.projectVersion=1.0 \
-Dsonar.login=admin \
-Dsonar.password=abc@1234 \
-Dsonar.ws.timeout=30 \
-Dsonar.projectDescription="my first project!" \
-Dsonar.links.homepage=http://192.168.0.173/devops/devops-maven-service \
-Dsonar.links.ci=http://192.168.0.205:8080/job/demo-pipeline-service/ \
-Dsonar.sources=src \
-Dsonar.sourceEncoding=UTF-8 \
-Dsonar.java.binaries=target/classes \
-Dsonar.java.test.binaries=target/test-classes \
-Dsonar.java.surefire.report=target/surefire-reports
扫描完成登陆sonarqube查看 嗯 tts的应用也有了
对于我来说和鬼东西段时间还是用不起来。只能算是扩展下自己的知识面,了解下人家的思想和流程……。然后再准备搞一下与jenkins的流程。就为了体验一下正常的cicd工具流过程。
历史遗留问题。公司有一个古老的共享文件系统。权限的管理比较混轮也没有版本的管理。跟总办的同事商量了一下给他们迁移到了svn。文件大概有100多个G吧。搭建了一个svnmanager管理的svn系统。至于不用git或者其他的版本管理系统….是因为我觉得svn对于他们来说容易操作吧。
开始文件夹目录有三个,其中两个的文件夹一个20G一个 500多M,另外一个文件夹目录有80G左右。我就三个目录分别add commit了。20 G 和500M的两个文件夹很容易就加入了svn了。80多g的项目等待上传了一个晚上。早上到公司一看报错……
svn sqliteS13:database or disk is full
没有搞明白怎么回事….怎么还有sqlite?是不是我的硬盘小了呢?看了下我分配的svn硬盘是250G。我的总文件也就120G理论上来说不应该的。抱着司马当活马医的态度。我扩容了硬盘到了400G,嗯还是出现了这个问题。这样也让我确认应该不是硬盘的问题了。
然后我就把repo下这个svn项目删除了。重新建了项目然后重新add commit两个小的文件夹上传观察:
svn服务下项目文件夹下有一下几个目录
看了一眼db目录是最大的。而且个人理解应该也确实在db目录下的
版本1 提交500M文件夹的时候发现上传过程中txn-protorevs目录不断增加。上传完了以后txn-protorevs目录就空了,染然后revs目录下就有了一个0的目录。
然后上传20G文件目录试试:
然后这样的话个人就基本能够明白了:
svn在上传的过程中再txn-protorevs目录下生成对应版本tag的rev rev-lock文件。等待上传完成在revs目录下生成对应版本的文件.
既然出现了sqlite那我是不是可以理解txn-protorevs目录下 rev 文件是一个sqlite文件呢?这个文件的大小超出了限制呢?
我把大文件夹拆分成四次add commit 上传…….最后总算成功了。通过百度或者Google没有能获取svn 的sqlite临时保存的这个rev文件的最大大小是多。不知道有没有大佬能够帮忙解惑解答一下呢。20G的资源上传我是没有出什么问题的。大于50G是出现了问题。具体的最大文件大小也没有能确认。反正就是尽量不一次性上传太大的文件了。
内网有一台项目组用的jenkins,ip 192.168.0.170.版本为1.235.3的版本。部署方式为 tomcat war包+nginx代理。正好有时间想把jenkins升级到最新版本。说干就干,下面记录一下升级的痛苦过程……
按照官方的文档也一般的安装过程就是下载最新jar包替换这样的流程。故:
####远古项目centos7还是默认的service
service tomcat stop
###centos 8 可以systemctl
systemctl stop tomcat
当然了 如果是jar的方式启动的 可以kill了 jar进程。
先备份jenkins数据目录文件和版本部署文件
我的集成环境使用的oneinstck安装的java nginx环境。配置文件在/home/www./jenkins目录下
jar包部署在/data/wwwroot/default目录。先做个备份
####
cd /home/www/
cp -Ra .jenkins/ .jenkinsold/
cd /data/wwwroot
cp -Ra default defaultold
https://get.jenkins.io/war-stable/下载了最新的2.277.3版本,关于 lts版本与weekly版本:
默认反正我个人是tls稳定版了。
我tomcat的目录在/data/wwwroot/default。 将jar包加压到目录下(war包可以直接解压的)。重新启动tomcat服务:
service tomcat start
web访问http://192.168.0.170
what?出现异常了。不能访问……。看了一眼tomcat的日志:
更新到最新版本以失败告终……..,log中截取了报错信息如下:
enkins.model.Jenkins.save An attempt to save Jenkins'' global configuration before it has been loaded has been made during milestone Configuration for all jobs updated. This is indicative of a bug in the caller and may lead to full or partial loss of configuration
将log中报错复制到了百度搜索,找到了stackoverflow中的一个类似的更新失败案例:
按照这里面的方案试一下了……
重复1.1-1.4过程。当然了 只是变成了下载war包下载2.263.1的war包。嗯更新完可以正常进入:
任务就忽略了,瞎写着测试的……
接着把版本升级到1.263.4的版本看一眼,嗯 也成功了
这个时候如果想抱着直接升级到2.277.3就能成功的侥幸还是打错特错的…..
仔细观察我的jenkins中右上角提示信息里面有那么一堆,看了一眼
这几个插件我也是没有用的。还有一些插件也都过时了….我就把能看到的这些插件都卸载了……
其他插件类似….不相干的插件还是少安装了……
然后下载role-straegy.hpi并上传到jenkins:
系统管理-插件管理-高级-上传插件。整完以后重启tomcat
重新执行1.1-1.4流程,嗯版本总算更新成功了
查看tomcat log:
通过这次更新个人的总结:
本来吧gitlab都是搞在kubernetes上面的。公司内网环境需要一个内部的gitlab.然后就准备搭建一个。另外跟着阳明大佬的课程做gitlab触发jenkins任务的时候我的jenkins想拿内网的去做,没法去触发啊。正好搞一个内网的去玩一下呢。线上的都是on kubernetes 的不想太随意去各种玩了……
很多可以下载的。另外gitlab成立了中国的独立的公司极狐?也可以玩一下。不过最近的极狐都被华为造车的的极狐的风头盖过去了吧……
下载源选择了清华的源下载了当前最新的版本gitlab-ce-13.9.6-ce.0.el8.x86_64.rpm
wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el8/gitlab-ce-13.9.6-ce.0.el8.x86_64.rpm
rpm -ivh gitlab-ce-13.9.6-ce.0.el8.x86_64.rpm
显示缺少依赖
yum install policycoreutils-python-utils
rpm -ivh gitlab-ce-13.9.6-ce.0.el8.x86_64.rpm
gitlab的配置文件是/etc/gitlab/gitlab.rb
。我个人是修改了域名还有存储位置(系统盘太小了。挂载了数据盘)
修改/etc/gitlab/gitlab.rb文件:
external_url 'http://192.168.0.173'
git_data_dirs({ "default" => { "path" => "/data/gitlab" } })
当然了文件夹我已经建好了:
mkdir /data/gitlab
加载配置:
gitlab-ctlreconfigure
关于服务的运行控制:
## 启动服务
gitlab-ctl start
## 重启服务
gitlab-ctl restart
## 查看状态
gitlab-ctl status
## 停止
gitlab-ctl stop
注意:external_url貌似没有那么重要…..我开始吧ip输入错了 仍能正常访问。没有那么严格校验的
浏览器访问http://192.168.0.173
嗯 账号密码要求大于8位
正常的gitlab on kubernetes 都搭建了postgresql。分离下搭建个postgresql用一下。参照https://blog.csdn.net/weixin_43431593/article/details/106252231进行了搭建。但是后面权限什么的 吃不下。postgresql自己没有系统玩过。放弃了。选择了docker的安装方式…..毕竟docker的可以偷懒一下……
可参照:https://blog.csdn.net/qq_41570843/article/details/106182073。基本都是大同小异。设置阿里云仓库配置加速器。启动docker服务。不做复杂描述:
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
这个地方应该会报错的
找不到 yum-config-manager?嗯安装一下
yum -y install yum-utils
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce docker-ce-cli containerd.io -y
当然了 也可以配置下镜像加速器:
cat /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors": [
"https://fz5yth0r.mirror.aliyuncs.com",
"http://hub-mirror.c.163.com/",
"https://docker.mirrors.ustc.edu.cn/",
"https://registry.docker-cn.com"
],
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
systemctl daemon-reload
systemctl restart docker
postgresql选择了了11版本。住:支持是到gitlab14.0。故其实也可以安装更高版本的postgresql。
mkdir /data/pgsql
docker run --name dockerPG11 \
-e POSTGRES_PASSWORD=postgres \
-v /data/pgsql:/var/lib/postgresql/data \
-p 54322:5432 \
-d postgres:11.5
## 创建数据库
psql -U postgres -h localhost -p 54322
psql (11.5 (Debian 11.5-3.pgdg90+1))
Type "help" for help.
postgres=# create role gitlab login encrypted password 'gitlab';
CREATE ROLE
postgres=# create database gitlabhq_production owner=gitlab ENCODING = 'UTF8';
CREATE DATABASE
postgres=# \c gitlabhq_production
You are now connected to database "gitlabhq_production" as user "postgres".
gitlabhq_production=# CREATE EXTENSION IF NOT EXISTS btree_gist;
CREATE EXTENSION
gitlabhq_production=# CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION
postgres=# \q
/etc/gitlab/gitlab.rb
gitlab_rails['db_adapter'] = "postgresql"
gitlab_rails['db_encoding'] = "utf8"
# gitlab_rails['db_collation'] = nil
gitlab_rails['db_database'] = "gitlabhq_production"
gitlab_rails['db_username'] = "gitlab"
gitlab_rails['db_password'] = "gitlab"
gitlab_rails['db_host'] = "127.0.0.1"
gitlab_rails['db_port'] = 54322
postgresql['enable'] = false
重载配置文件:
gitlab-ctl reconfigure
cat /opt/gitlab/embedded/service/gitlab-rails/config/database.yml
# This file is managed by gitlab-ctl. Manual changes will be
# erased! To change the contents below, edit /etc/gitlab/gitlab.rb
# and run `sudo gitlab-ctl reconfigure`.
production:
adapter: postgresql
encoding: utf8
collation:
database: gitlabhq_production
username: "gitlab"
password: "gitlab"
host: "127.0.0.1"
port: 54322
socket:
sslmode:
sslcompression: 0
sslrootcert:
sslca:
load_balancing: {"hosts":[]}
prepared_statements: false
statement_limit: 1000
connect_timeout:
keepalives:
keepalives_idle:
keepalives_interval:
keepalives_count:
tcp_user_timeout:
application_name:
variables:
statement_timeout:
继续登陆gitlab页面
修改默认语言为中文:
ok。基本算是完成了。这里要特别说一下postgresql的安装登陆个人真的是没有太搞明白。有时间要好好学习下postgresql。和正常自己了解的mysql等数据库比是完全的知识盲区了。有盲区,那就有时间学习一下了。加油……