基于K8S的CICD系统实现 前情提要 在此声明,这个项目需要有32G+以上的运行内存,不然继续不了,32G运行内存电脑勉强能(阉割版流畅)运行,而且也是关了一台harbor2才能勉强运行,关了没事的,因为harbor是高可用集群,有一台harbor1就行了
系统拓扑图 运行内存严格按照我的以下的内存规格来填写,这是勉强能运行的配置参数,如果内存多的话自行加多即可
K8S集群
主机名
ip1(NAT)
系统
磁盘1
磁盘2
内存
cpu
master1
192.168.48.101
OpenEuler-22.04-LTS
100G
100G
6.2G
2v2c
master2
192.168.48.102
OpenEuler-22.04-LTS
100G
100G
6.2G
2v2c
master3
192.168.48.103
OpenEuler-22.04-LTS
100G
100G
6.2G
2v2c
node01
192.168.48.104
OpenEuler-22.04-LTS
100G
9.9G
2v2c
高可用ip
192.168.48.200
harbor集群
角色
主机名
ip
系统
资源最低要求
Harbor1 nginx Keepalived1
harbor1
192.168.48.106
OpenEuler-22.04-LTS
CPU:1核 内存:1G 硬盘:40G
Harbor2 nginx Keepalived2
harbor2
192.168.48.107
OpenEuler-22.04-LTS
CPU:1核 内存:1G 硬盘:40G
postgresql Redis NFS共享
zujian
192.168.48.108
OpenEuler-22.04-LTS
CPU:1核 内存:1G 硬盘:40G
高可用ip
192.168.48.100
系统架构图
系统流程图
部署K8S高可用集群 OpenEuler-部署K8S高可用集群(内部etcd) - 严千屹博客 (qianyios.top)
部署ceph集群
注意:原文章是部署在master1,node01,node02,由于硬件原因,现在需要部署在三台master,所以原文章开头加硬盘,你也只需要加在三台master上,请自己注意在2.1-2位置修改集群名称和硬盘名称。包括要下载的镜像,就在三台master下载就行了,接着你就可以继续做了
基于K8S1.28.2实验rook部署ceph - 严千屹博客 (qianyios.top)
以下进行cephfs存储做存储声明即Storageclass,方便后续jenkins和gitlab调用
创建cephfs文件系统 操作节点[master1]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 cd cd rook/deploy/examples cat >rook-cephfs.yaml << "EOF" apiVersion: ceph.rook.io/v1 kind: CephFilesystem metadata: name: rook-cephfs #修改名字 namespace: rook-ceph spec: metadataPool: replicated: size: 3 requireSafeReplicaSize: true # 参数指示是否要求副本数量必须是偶数 parameters: compression_mode: none dataPools: - name: replicated failureDomain: host replicated: size: 3 requireSafeReplicaSize: false parameters: compression_mode: none preserveFilesystemOnDelete: true #当删除CephFilesystem资源时,是否保留Ceph集群中的实际文件系统。若设为true则保留,方便后续恢复使用。 metadataServer: activeCount: 3 activeStandby: true placement: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - rook-ceph-mds topologyKey: topology.kubernetes.io/zone priorityClassName: system-cluster-critical livenessProbe: disabled: false startupProbe: disabled: false EOF kubectl apply -f rook-cephfs.yaml kubectl get pod -n rook-ceph | grep rook-cephfs
可能要一分钟才会创建好
为什么我能直接在k8s直接运行ceph指令,而不进入pod,自行去第二步开通看部署ceph集群的
快捷链接:在K8S中直接调用出ceph命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [root@master1 examples]# ceph fs status rook-cephfs - 0 clients =========== RANK STATE MDS ACTIVITY DNS INOS DIRS CAPS 0 active rook-cephfs-f Reqs: 0 /s 10 13 12 0 1 active rook-cephfs-c Reqs: 0 /s 0 0 0 0 2 active rook-cephfs-d Reqs: 0 /s 10 12 11 0 0-s standby-replay rook-cephfs-a Evts: 0 /s 0 0 0 0 2-s standby-replay rook-cephfs-b Evts: 0 /s 0 0 0 0 1-s standby-replay rook-cephfs-e Evts: 0 /s 0 0 0 0 POOL TYPE USED AVAIL rook-cephfs-metadata metadata 0 94.9G rook-cephfs-replicated data 0 94.9G MDS version: ceph version 17.2.6 (d7ff0d10654d2280e08f1ab989c7cdf3064446a5) quincy (stable) [root@master1 examples]# ceph fs ls name: rook-cephfs, metadata pool: rook-cephfs-metadata, data pools: [rook-cephfs-replicated ] [root@master1 examples]#
rook-cephfs-replicated
是下面存储声明需要用到的 pool
创建Storageclass 是k8s调用ceph的声明,通过这个Storageclass才能去调用ceph
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 cd cd rook/deploy/examples cat > rook-cephfs-sc.yaml <<"EOF" apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: rook-cephfs-sc provisioner: rook-ceph.cephfs.csi.ceph.com parameters: clusterID: rook-ceph fsName: rook-cephfs pool: rook-cephfs-replicated csi.storage.k8s.io/provisioner-secret-name: rook-csi-cephfs-provisioner csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph csi.storage.k8s.io/controller-expand-secret-name: rook-csi-cephfs-provisioner csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph csi.storage.k8s.io/node-stage-secret-name: rook-csi-cephfs-node csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph reclaimPolicy: Delete allowVolumeExpansion: true EOF kubectl apply -f rook-cephfs-sc.yaml kubectl get sc
部署harbor进群 Harbor共享存储高可用 - 严千屹博客 (qianyios.top)
配置仓库地址 部署好后,需要将K8s各个节点,和harbor各个节点都要进行配置仓库地址
操作节点:[所有节点]
1 vim /etc/docker/daemon.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 # 客户端默认使用的是https协议,所以需要对docker做以下修改,在文件末尾添加insecure-registries [root@qianyios ~]# vim /etc/docker/daemon.json { ................ "registry-mirrors": [],#无关紧要,不用看, "insecure-registries": [ "192.168.48.100" ],#重要加这行,别忘了如果他不是最后一行一定要在末尾加逗号 ................ } # 修改后,重启docker使其生效 systemctl daemon-reload systemctl restart docker # 利用docker info查看是否添加上 [root@qianyios ~]# docker info Containers: 10 Running: 1 Paused: 0 Stopped: 9 Images: 37 ... Experimental: false Insecure Registries: 192.168.48.100 ###要确保有这个才行 127.0.0.0/8 Registry Mirrors:
测试免密登入 接下来测试免密登入,第一次登入要密码,第二次登入就不用了,第二次之后就是免密登入
1 docker login 192.168.48.100
免密登入成功!
部署jenkins 操作节点:[masetr1]
创建rabc验证 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 cd cd jenkins cat > jenkins-rabc.yaml << "EOF" apiVersion: v1 kind: ServiceAccount metadata: name: jenkins-admin namespace: jenkins --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: jenkins-admin roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: jenkins-admin namespace: jenkins EOF kubectl apply -f jenkins-rabc.yaml
创建jenkins用户的secret 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 cd cd jenkins cat >jenkins-admin-secret.yaml << "EOF" apiVersion: v1 kind: Secret metadata: name: jenkins-admin-secret namespace: jenkins annotations: kubernetes.io/service-account.name: jenkins-admin type: kubernetes.io/service-account-token EOF kubectl apply -f jenkins-admin-secret.yaml kubectl get secret -n jenkins [root@master1 jenkins ] NAME TYPE DATA AGE jenkins-admin-secret kubernetes.io/service-account-token 3 15s
创建pvc 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 cd kubectl create namespace jenkins mkdir jenkins cd jenkins cat > pvc.yaml << EOF kind: PersistentVolumeClaim apiVersion: v1 metadata: name: jenkins-pvc namespace: jenkins spec: storageClassName: rook-cephfs-sc resources: requests: storage: 3Gi accessModes: - ReadWriteMany EOF kubectl apply -f pvc.yaml kubectl get pvc -n jenkins
部署jenkins 自行在harbor仓库创建好cicd仓库
构建jenkins镜像
1 docker pull jenkins/jenkins
可能会出现拉取缓慢现象,也可以用以下方法进行构建
基于阿里云容器服务构建私人docker镜像 - 严千屹博客 (qianyios.top)
构建之后就要进行拉取下载打标签,以下是我自己构建的,你可以用这个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #下载镜像 docker pull registry.cn-hangzhou.aliyuncs.com/qianyios/jenkins:latest #打标签 docker tag registry.cn-hangzhou.aliyuncs.com/qianyios/jenkins:latest 192.168.48.100/cicd/jenkins:latest #查看镜像 [root@master1 jenkins]# docker images | grep jenk 192.168.48.100/cicd/jenkins latest 786c9e8a0cb8 6 days ago 472MB registry.cn-hangzhou.aliyuncs.com/qianyios/jenkins latest 786c9e8a0cb8 6 days ago 472MB [root@master1 jenkins]# #推送镜像到harbor仓库 docker push 192.168.48.100/cicd/jenkins:latest
1 2 3 4 #给所有master节点打上master标签 kubectl label node master1 k8s-type=master kubectl label node master2 k8s-type=master kubectl label node master3 k8s-type=master
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 cd cd jenkins cat >jenkins-deploy.yaml << "EOF" apiVersion: apps/v1 kind: Deployment metadata: name: jenkins namespace: jenkins spec: replicas: 1 selector: matchLabels: app: jenkins-server template: metadata: labels: app: jenkins-server spec: securityContext: fsGroup: 995 runAsUser: 1000 serviceAccountName: jenkins-admin nodeSelector: k8s-type: master containers: - name: jenkins image: 192.168 .48 .100 /cicd/jenkins:latest imagePullPolicy: IfNotPresent resources: limits: memory: "2Gi" cpu: "1000m" requests: memory: "500Mi" cpu: "500m" ports: - name: httpport containerPort: 8080 - name: jnlpport containerPort: 50000 livenessProbe: httpGet: path: "/login" port: 8080 initialDelaySeconds: 90 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 5 readinessProbe: httpGet: path: "/login" port: 8080 initialDelaySeconds: 60 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 volumeMounts: - name: jenkins-data mountPath: /var/jenkins_home - name: kubectl mountPath: /usr/bin/kubectl - name: kube-config mountPath: /root/.kube - name: docker mountPath: /usr/bin/docker - name: docker-sock mountPath: /var/run/docker.sock volumes: - name: jenkins-data persistentVolumeClaim: claimName: jenkins-pvc - name: kubectl hostPath: path: /usr/bin/kubectl - name: kube-config hostPath: path: /root/.kube - name: docker hostPath: path: /usr/bin/docker - name: docker-sock hostPath: path: /var/run/docker.sock EOF kubectl apply -f jenkins-deploy.yaml kubectl get pods -n jenkins
创建svc 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 cd cd jenkins cat >jenkins-svc.yaml << "EOF" apiVersion: v1 kind: Service metadata: name: jenkins-service namespace: jenkins annotations: prometheus.io/scrape: 'true' prometheus.io/path: / prometheus.io/port: '8080' spec: selector: app: jenkins-server type: NodePort ports: - port: 8080 targetPort: 8080 nodePort: 32000 name: httpport - name: jnlpport port: 50000 targetPort: 50000 EOF kubectl apply -f jenkins-svc.yaml kubectl get svc -n jenkins
访问页面 1 http://192.168.48.200:32000/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 kubectl get pods -n jenkins #查看你的pod名字替换下面的名字即可(jenkins-799dc7cd88-d2n4k) #进入容器 kubectl exec -it -n jenkins jenkins-799dc7cd88-d2n4k -- bash #修改Update Center源 sed -i 's#https://updates.jenkins.io/update-center.json#http://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json#g' /var/jenkins_home/hudson.model.UpdateCenter.xml #替换插件源地址: sed -i 's#https://updates.jenkins.io/download#http://mirrors.aliyun.com/jenkins#g' /var/jenkins_home/updates/default.json #替换谷歌地址: sed -i 's#http://www.google.com#http://www.baidu.com#g' /var/jenkins_home/updates/default.json #查看网页密码 jenkins@jenkins-546cf958bd-kq5f2:~$ cat /var/jenkins_home/secrets/initialAdminPassword ebfc1b12835f43c8a8c2677728e4aa55
先点无,这里先不安装,后面再安装
使用admin账户继续
默认下一步
自行去设置修改admin密码
配置k8s等插件和实现功能 安装插件 1 安装插件:Git / Git Parameter/Pipeline/Config File Provider/Gitlab/Generic Webhook Trigger/Blue Ocean/Localization: Chinese /Kubernetes
在首页点击系统管理然后点击插件管理—–安装Kubernetes插件
安装之后需要等待他重启
配置K8s代理节点 配置jenkins连接kubernetes
点击系统管理-cloud
点击Clouds-添加New cloud
点击create
查看Kubernetes 服务证书 key
[root@master1 jenkins]# cat /etc/kubernetes/pki/ca.crt
-----BEGIN CERTIFICATE-----
MIIDBTCCAe2gAwIBAgIIcJ+z+Wx0m20wDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE
AxMKa3ViZXJuZXRlczAeFw0yNDA5MjgxMTI5NDJaFw0zNDA5MjYxMTM0NDJaMBUx
EzARBgNVBAMTCmt1YmVybmV0ZXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQDYeRyEbAJRMqWyAmQf0LfK9wecWoQSyKYX+gHDUvZMaQK/nkAfrEme5Wot
J8lcODlNAj0OImRRKkCzfBwlZl5WMYH3Roonn8z9j4hkUAX/EgTwMun1q0G/D1yV
zxcRSUxxiFDKlRCVsPxIsuHIUvTrAHkU0qpz1S4cITisF9o9hCvqZZZ/5fCudn7I
sLlDhxzL1TAI5R2hqZKFdondpoGxYF5oc2wuk+0g/3GJZeaGEO/9p5ySX/glamil
e5npU/EvLsG4er2UQqB7dc9wfxOT2p0Qlj7UjHcqgY8E6ufhd7GqYVKNDXSmKXiP
BZI5ba6/kZJj0nsSz3GnVdhFxUD1AgMBAAGjWTBXMA4GA1UdDwEB/wQEAwICpDAP
BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBT5qTcFwRrY/VSJtfAZK85ZCp2ViTAV
BgNVHREEDjAMggprdWJlcm5ldGVzMA0GCSqGSIb3DQEBCwUAA4IBAQDX+1q8NXKb
HWnfR75MORrQJ898B9M1FBoHfLRdsmmCJVrSQXbBbKn1zVoJL6YLdjDOx2NfWa8o
f1Y7KSme9Z6B4j57tGFQ/4LST4Cwk4PPh1v6nrwVesW6xE6ClHVZ0N1S4ggZi8ll
Wcv3ZCgdGrjSQm15xsRr4oN7XGY/B1kAZWU4defpcxhtIMtLQ7/m74hfYo/P5L/b
Wu1knzRSs1/Cna2GFkWx3BYfbG78ZPBIh17mN4vFAt/x8ZOZCJ+bb0Ey6upYnhjP
H2jiNrHcyJVnnDO4N6kMII9sh2n+gYvK45u+/Vw8nPElf72LkHFHOyQc8QD9opXF
LC9bmhoJuU9v
-----END CERTIFICATE-----
获取凭证
不是低版本,请跳到下一步!!!!
低版本获取凭证方法,低版本会自动生成一个secret
[root@master1 ~]# SECRET_NAME=$(kubectl get serviceaccount jenkins-admin -o=jsonpath='{.secrets[0].name}' -n jenkins)
[root@master1 ~]# kubectl get secrets $SECRET_NAME -o=jsonpath='{.data.token}' -n jenkins | base64 -d
k8s1.28获取凭证方法,需要手动创建secret
使用kubectl create token获取的token会过期
这里手动创建secret,并查看相关token值
编写jenkins-admin用户secret清单,并创建
cd /root/jenkins
cat >jenkins-admin-secret.yaml<< "EOF"
apiVersion: v1
kind: Secret
metadata:
name: jenkins-admin-secret
namespace: jenkins
annotations:
kubernetes.io/service-account.name: jenkins-admin
type: kubernetes.io/service-account-token
EOF
kubectl apply -f jenkins-admin-secret.yaml
查看secret
kubectl get secret -n jenkins
获取token
[root@master1 jenkins]# kubectl get secrets jenkins-admin-secret -o=jsonpath='{.data.token}' -n jenkins | base64 -d
eyJhbGciOiJSUzI1NiIsImtpZCI6ImpaNkJTN3d0M0pFblBCSVBaaGFoNzdUTVNLMHZiTERxY09Ibmg4WEtFNTQifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJqZW5raW5zIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImplbmtpbnMtYWRtaW4tc2VjcmV0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImplbmtpbnMtYWRtaW4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI3MTg2Mzg1Mi1jNDkwLTQyMDEtYTA2OS1lM2ZhOTcyNTgwODYiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6amVua2luczpqZW5raW5zLWFkbWluIn0.sfofmctQos9fcEAf0hZEfEKN2WiG7GklOW6NMEdXbiJHkg5SNe8-MuJK4c4JtubyIA9IFhHo6PfQoFl8-2smuFaojjSKZKn2esJJ5enT_WNsbIdXmu4tg8a2571EikotiGKLpGHuLEZOLdTyswTsQW-FSQH7K16VmfUSzHCkKjV5eXNK3gpRj9p3voGWlBRQ3Jqfm6NWSKp_1_XZqFyi_KM8DOaMHhffN24ejwC2lvIzKNcZp80yY2rW4BkCI0dLN2GqUNlzB9QXYUslLtsigObukCdjY8EefCc34Rh68kq2UQVpXb9eTkyK50J9HEFJtLiuameD3Yx8gNE9xWJ4Vw
配置kubernetes相关信息
Name : 这个自定义, 默认的是kubernetes
Kubernetes URL : https://kubernetes.default
- 这个一般是从你的 service account 自动配置的
Kubernetes 服务证书 key : 如果您有 Kubernetes 集群 CA 证书,您可以添加它以实现安全连接。您可以从 pod 位置获取证书/var/run/secrets/kubernetes.io/serviceaccount/ca.crt。如果您没有证书,您可以启用“ disable https certificate check”(禁用HTTPS证书检查)选项
Kubernetes Namespace : 一般是 default
除非你要在一个特殊的命名空间 ,否则不要动他.因为我的jenkins部署在了jenkin命名空间,就用了jenkins
Credentials(凭据) : 为了让 Jenkins 与 Kubernetes 集群通信,我们需要一个服务帐户令牌,该令牌具有在设置的命名空间中部署 pod 的权限
Jenkins URL : http://<your_jenkins_hostname>:port
Jenkins tunnel : <your_jenkins_hostname>:50000
- 这就是用来和 Jenkins 启动的 agent 进行交互的端口
修改名称和kubernetes地址及服务证书key
此Kubernetes由于Jenkins 服务器在同一个 Kubernetes 集群中运行,这里直接通过service进行通讯
此服务证书key就是前几步获取的key
添加凭证
点击添加->jenkins
选择Domain为全局凭据
类型选择为secret txt
范围选择为全局
secret就是刚才获取的凭据
描述 就是凭据的名称
点击添加
选择凭据为刚才添加的,点击测试链接,验证 Kubernetes 集群的连接性
配置 Jenkins URL 详细信息
对于在k8s集群内部运行的 Jenkins master,您可以使用 Kubernetes 集群的 Service 端点作为 Jenkins URL,因为代理 pod 可以通过内部服务 DNS 连接到集群
url语法:http://.:8080
jenkins-service.jenkins:8080
注意:Jenkins 通道(Jenkins tunnel)链接不需要加http://,否则无法正常通讯
创建成功
创建Jenkins代理镜像 拉取jenkins代理镜像并上传到harbor仓库
docker pull jenkins/inbound-agent
#如果下不到可以用我的
docker pull registry.cn-hangzhou.aliyuncs.com/qianyios/inbound-agent:latest
docker tag registry.cn-hangzhou.aliyuncs.com/qianyios/inbound-agent:latest 192.168.48.100/library/inbound-agent:latest
docker push 192.168.48.100/library/inbound-agent:latest
docker images | grep inbound
部署gitlab 创建gitlab的secret 1 2 3 4 #长度为8个字符 [root@master1 ~]# echo -n 'qianyios' | base64 cWlhbnlpb3M= #qianyios将会成为gitlab页面的登入密码
1 2 3 4 mkdir /root/gitlab cd /root/gitlab #创建namespace kubectl create namespace gitlab
1 2 3 4 5 6 7 8 9 10 11 12 cat >gitlab-secret-pwd.yaml << "EOF" apiVersion: v1 data: password: cWlhbnlpb3M= kind: Secret metadata: creationTimestamp: null name: gitlab-pwd namespace: gitlab EOF kubectl apply -f gitlab-secret-pwd.yaml kubectl get secret -n gitlab
创建pvc 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 cat > gitlab-pvc.yaml <<"EOF" kind: PersistentVolumeClaim apiVersion: v1 metadata: name: gitlab-pvc-logs namespace: gitlab spec: storageClassName: rook-cephfs-sc resources: requests: storage: 5Gi accessModes: - ReadWriteOnce --- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: gitlab-pvc-config namespace: gitlab spec: storageClassName: rook-cephfs-sc resources: requests: storage: 1Gi accessModes: - ReadWriteOnce --- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: gitlab-pvc-data namespace: gitlab spec: storageClassName: rook-cephfs-sc resources: requests: storage: 10Gi accessModes: - ReadWriteOnce EOF kubectl apply -f gitlab-pvc.yaml kubectl get pvc -n gitlab
部署gitlab 1 2 3 4 5 6 7 8 9 10 11 #下载gitlab-ce镜像,镜像很大要1个G多 docker pull gitlab/gitlab-ce # 如果下不了用我构建的镜像 docker pull registry.cn-hangzhou.aliyuncs.com/qianyios/gitlab:latest #镜像打标签#这个里我用了自己构建的镜像,你要是用这个gitlab/gitlab-ce自行替换 docker tag registry.cn-hangzhou.aliyuncs.com/qianyios/gitlab:latest 192.168.48.100/cicd/gitlab:latest #推送镜像 docker push 192.168.48.100/cicd/gitlab:latest
1 2 给node节点打上k8s-type=node标签 kubectl label nodes node01 k8s-type=node
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 cat > gitlab-deploy.yaml << "EOF" apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: gitlab name: gitlab namespace: gitlab spec: replicas: 1 selector: matchLabels: app: gitlab strategy: {} template: metadata: creationTimestamp: null labels: app: gitlab spec: nodeSelector: k8s-type: node containers: - image: 192.168.48.100/cicd/gitlab:latest #更换镜像 imagePullPolicy: IfNotPresent name: gitlab-ce env: - name: GITLAB_ROOT_PASSWORD valueFrom: secretKeyRef: name: gitlab-pwd key: password - name: GITLAB_ROOT_MAIL value: xiaoohu2002@126.com ports: - name: gitlab80 containerPort: 80 - name: gitlab22 containerPort: 22 - name: gitlab443 containerPort: 443 volumeMounts: - name: gitlab-logs mountPath: /var/log/gitlab - name: gitlab-config mountPath: /etc/gitlab - name: gitlab-data mountPath: /var/opt/gitlab volumes: - name: gitlab-logs persistentVolumeClaim: claimName: gitlab-pvc-logs - name: gitlab-config persistentVolumeClaim: claimName: gitlab-pvc-config - name: gitlab-data persistentVolumeClaim: claimName: gitlab-pvc-data status: {} EOF kubectl apply -f gitlab-deploy.yaml kubectl get pod -n gitlab
创建svc 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 cat > gitlab-svc.yaml << "EOF" apiVersion: v1 kind: Service metadata: creationTimestamp: null labels: app: gitlab name: gitlab namespace: gitlab spec: ports: - name: 80-80 port: 80 protocol: TCP targetPort: 80 nodePort: 30880 - name: 443-443 port: 443 protocol: TCP targetPort: 443 - name: 22-22 port: 22 protocol: TCP targetPort: 22 selector: app: gitlab type: NodePort status: loadBalancer: {} EOF kubectl apply -f gitlab-svc.yaml kubectl get svc -n gitlab
访问页面
1 http://192.168.48.200:30880/
页面测试 设置中文
创建项目
项目推送 操作节点:[master1]
1 2 3 4 yum install -y git mkdir /root/cicd/ cd /root/cicd/ mkdir chatgpt && cd chatgpt/
上传Chatgpt镜像站源码
项目地址:ChatGPTNextWeb
1 2 cd /root/cicd/chatgpt/ wget https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web/archive/refs/heads/main.zip
1 [root@master1 chatgpt]# ls main.zip
解压源代码压缩包
1 2 3 unzip /root/cicd/chatgpt/main.zip mv ChatGPT-Next-Web-main/* ./ rm -rf ChatGPT-Next-Web-main main.zip
Git全局设置
1 2 git config --global user.name "Administrator" git config --global user.email "XiaooHu2002@163.com"
添加版本库
1 2 cd /root/cicd/chatgpt/ git init
添加远程仓库
要注意是哪个主分支哦!这里的是main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 git remote add origin http://192.168.48.200:30880/root/chatgpt.git git add . git commit -m "first commit" git branch -m master main git push -u origin main Username for 'http://192.168.48.200:30880' : root Password for 'http://root@192.168.48.200:30880' :
Jenkins对接gitlab 创建gitlab Secret令牌 进入gitlab创建Secret令牌
创建成功Secret令牌,并复制令牌
此令牌需要保存好,后面jenkins还需要用到
glpat-vLZgV6Z1nbC_96yyZdyp
Jenkins创建流水线 点击新建任务,输入名称并选择为流水线,并点击确定
在general中找到Generic Webhook Trigger 并勾选且复制webhook链接
http://JENKINS_URL/generic-webhook-trigger/invoke
添加gitlab凭据
配置Webhook 配置允许Webhook和服务对本地网络的请求
进入管理员-设置-网络
勾选允许来自 webhooks 和集成对本地网络的请求并保存更改即可
接下来配置webhooks
进入到项目中
填写相关信息
网址:就是刚才jenkins创建项目的时候复制的链接,这里只是对其进行修改了,因为jenkins和gitlab都是部署在同一个k8s集群中我这里将域名修改成了service的地址
原地址:http://JENKINS_URL/generic-webhook-trigger/invoke
修改后的地址:http://jenkins-service.jenkins:8080/generic-webhook-trigger/invoke
Secret 令牌:就是刚创建的个人令牌
推送事件:指定只有推送到某个仓库时才触发,留空则全部分支
先看更改地址,这一步不需要操作什么,看清楚,替换了啥JENKINS_URL➡️jenkins-service.jenkins:8080
部署webhook
然后添加webhook即可,然后测试推送事件
配置jenkins流水线 添加harbor用户
输入相关信息并点击create创建
类型选择Username with password
范围选择全局
用户名为Harbor仓库用户名
密码为Harbor仓库用户密码
描述为此凭据的名称
创建好后,接下来配置流水线
先获取项目仓库地址
但是我们要对其中的地址改一下,改成
http://gitlab.gitlab/root/chatgpt.git
回到jenkins任务
点击Dashboard->ChatGPT->设置->并点击流水线
点击添加凭据
Domain 选择全局凭据
类型选择Username with password
范围选择全局
用户名即是gitlab账号
密码即是gitlab账号密码
描述为此凭据的名称
往下滑
保存即可
harbor新建项目 输入相关信息并点击确定
用于存放业务镜像
访问级别设置成公开
存储容量为-1即代表不限制存储容量
项目镜像准备 1 2 3 4 5 docker pull node:18-alpine #如果下载不了可以用我的 docker pull registry.cn-hangzhou.aliyuncs.com/qianyios/node:18-alpine docker tag registry.cn-hangzhou.aliyuncs.com/qianyios/node:18-alpine 192.168.48.100/library/node:18-alpine docker push 192.168.48.100/library/node:18-alpine
编写业务部署清单 1 2 3 4 5 6 [root@master1 ~]# echo -n "https://xiaoai.plus" | base64 aHR0cHM6Ly94aWFvYWkucGx1cw== [root@master1 ~]# echo -n "sk-K19c1kSqZZ92sXp13d042aD4E2B74a60B749E717Ed69449e" | base64 c2stSzE5YzFrU3FaWjkyc1hwMTNkMDQyYUQ0RTJCNzRhNjBCNzQ5RTcxN0VkNjk0NDll
key是ChatGPTkey,这里已经对其base64加密
baseurl是chatgpt第三方服务商提供的代理地址,这里已经对其base64加密
1 2 3 4 cd /root/cicd/chatgpt kubectl create deploy chatgpt --image=chatgpt-next-web --dry-run=client -oyaml kubectl create svc nodeport chatgpt --tcp=3000:3000 --dry-run=client -oyaml >> deploy.yaml vim deploy.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 apiVersion: v1 data: key: c2stSzE5YzFrU3FaWjkyc1hwMTNkMDQyYUQ0RTJCNzRhNjBCNzQ5RTcxN0VkNjk0NDll baseurl: aHR0cHM6Ly94aWFvYWkucGx1cw== kind: Secret metadata: creationTimestamp: null name: chat-config --- apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: chatgpt name: chatgpt spec: replicas: 1 selector: matchLabels: app: chatgpt strategy: {} template: metadata: creationTimestamp: null labels: app: chatgpt spec: containers: - image: chatgpt-next-web name: chatgpt ports: - containerPort: 3000 imagePullPolicy: IfNotPresent env: - name: OPENAI_API_KEY valueFrom: secretKeyRef: name: chat-config key: key - name: BASE_URL valueFrom: secretKeyRef: name: chat-config key: baseurl --- apiVersion: v1 kind: Service metadata: creationTimestamp: null labels: app: chatgpt name: chatgpt spec: ports: - name: 3000-3000 port: 3000 protocol: TCP targetPort: 3000 selector: app: chatgpt type: NodePort status: loadBalancer: {}
编写镜像构建文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 cd /root/cicd/chatgpt sed -i 's|https://registry.yarnpkg.com/|https://registry.npmmirror.com/|g' yarn.lock cat > Dockerfile <<"EOF" # 基础镜像 FROM 192.168.48.100/library/node:18-alpine AS base # 设置国内镜像源 RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories RUN apk add --no-cache libc6-compat proxychains-ng WORKDIR /app # 依赖阶段 COPY package.json yarn.lock ./ RUN npm config set registry https://registry.npmmirror.com RUN yarn config set registry https://registry.npmmirror.com --global # 替换 yarn.lock 文件中的源地址 RUN sed -i 's|https://registry.yarnpkg.com/|https://registry.npmmirror.com/|g' yarn.lock RUN sed -i 's|https://registry.npmjs.org/|https://registry.npmmirror.com/|g' yarn.lock # 清除缓存并安装依赖 RUN yarn config list # 查看当前的 Yarn 配置 RUN yarn install # 更新 caniuse-lite RUN npx update-browserslist-db@latest # 构建阶段 FROM base AS builder RUN apk update && apk add --no-cache git ENV OPENAI_API_KEY="" ENV BASE_URL="" WORKDIR /app COPY . . RUN yarn add @svgr/webpack@latest --frozen-lockfile RUN yarn add sharp # 添加 sharp 包 RUN yarn build # 运行阶段 FROM base AS runner WORKDIR /app RUN apk add proxychains-ng ENV PROXY_URL="" ENV OPENAI_API_KEY="" ENV BASE_URL="" COPY --from=builder /app/public ./public COPY --from=builder /app/.next/standalone ./ COPY --from=builder /app/.next/static ./.next/static COPY --from=builder /app/.next/server ./.next/server EXPOSE 3000 CMD if [ -n "$PROXY_URL" ]; then \ export HOSTNAME="127.0.0.1"; \ protocol=$(echo $PROXY_URL | cut -d: -f1); \ host=$(echo $PROXY_URL | cut -d/ -f3 | cut -d: -f1); \ port=$(echo $PROXY_URL | cut -d: -f3); \ conf=/etc/proxychains.conf; \ echo "strict_chain" > $conf; \ echo "proxy_dns" >> $conf; \ echo "remote_dns_subnet 224" >> $conf; \ echo "tcp_read_time_out 15000" >> $conf; \ echo "tcp_connect_time_out 8000" >> $conf; \ echo "localnet 127.0.0.0/255.0.0.0" >> $conf; \ echo "localnet ::1/128" >> $conf; \ echo "[ProxyList]" >> $conf; \ echo "$protocol $host $port" >> $conf; \ cat /etc/proxychains.conf; \ proxychains -f $conf node server.js; \ else \ node server.js; \ fi EOF
编写流水线脚本
withCredentials
块来引用一个名为 my-credentials
的凭据,该凭据的类型是用户名密码。usernameVariable
和 passwordVariable
参数分别指定了在代码块中使用凭据时的变量名。
在 withCredentials
块内部,你可以执行需要使用凭据的操作,比如在 Shell 脚本中使用用户名和密码进行身份验证。
请注意,credentialsId
参数需要指定你在 Jenkins 中创建的凭据的 ID。确保凭据 ID 正确,并且具有访问该凭据的权限。
使用 withCredentials
块可以确保凭据的安全性,因为凭据的值不会明文显示在日志中,而是以变量的形式传递给代码块中的操作。这样可以避免凭据泄露的风险。
以下内容,自行修改,对照,每一行都去看
Harbor-passwd是jenkins创建的harbor的用户凭据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 cd /root/cicd/chatgpt cat > Jenkinsfile<<"EOF" pipeline{ agent { kubernetes { inheritFrom "jenkins-slave" yaml ''' apiVersion: v1 kind: Pod metadata: name: jenkins-slave spec: securityContext: fsGroup: 0 runAsUser: 0 nodeSelector: k8s-type: master containers: - name: jnlp image: "192.168.48.100/library/inbound-agent:latest" imagePullPolicy: IfNotPresent volumeMounts: - name: kubectl mountPath: /usr/bin/kubectl - name: kube-config mountPath: /root/.kube - name: docker mountPath: /usr/bin/docker - name: docker-sock mountPath: /var/run/docker.sock volumes: - name: kubectl hostPath: path: /usr/bin/kubectl - name: kube-config hostPath: path: /root/.kube - name: docker hostPath: path: /usr/bin/docker - name: docker-sock hostPath: path: /var/run/docker.sock ''' } } environment { NPM_REGISTRY = "https://registry.npmmirror.com/" YARN_REGISTRY = "https://registry.npmmirror.com/" } stages{ stage('git clone') { steps { sh 'git version' } } stage('image-build'){ steps{ withCredentials([usernamePassword(credentialsId: 'Harbor-passwd', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) { sh 'docker build -t 192.168.48.100/chatgpt/chatgpt:v1-$BUILD_NUMBER -f Dockerfile .' sh 'docker login 192.168.48.100 -u $USERNAME -p $PASSWORD' sh 'docker push 192.168.48.100/chatgpt/chatgpt:v1-$BUILD_NUMBER' } } } stage('cloud-deploy'){ steps{ sh 'sed -i "s#chatgpt-next-web#192.168.48.100/chatgpt/chatgpt:v1-$BUILD_NUMBER#g" deploy.yaml' sh 'cat deploy.yaml' sh 'kubectl get pod -A' sh 'kubectl get secret,deploy,svc -A' sh 'kubectl apply -f deploy.yaml' sh 'kubectl get -f deploy.yaml' } } } } EOF
通过git上传代码 1 2 3 4 5 6 cd /root/cicd/chatgpt git add . git commit -m "add Jenkinsfile Dockerfile and deploy.yaml" git push -u origin main Username for 'http://192.168.48.200:30880': root Password for 'http://root@192.168.48.200:30880':
测试 通过刚刚的上传deploy.yaml,流水线已经开始执行
进入jenkins页面可以看到jenkins建的项目正在执行,并且可以看到右下角有一个jenkins代理,说明新建了一个jenkins代理执行
Harbor仓库也有构建好的镜像
测试项目部署成功
jenkins部署日志也显示成功
千屹博客旗下的所有文章,是通过本人课堂学习和课外自学所精心整理的知识巨著 难免会有出错的地方 如果细心的你发现了小失误,可以在下方评论区告诉我,或者私信我! 非常感谢大家的热烈支持!