4 基于Velero的备份和恢复
Velero介绍
Velero是用于备份和恢复 Kubernetes 集群资源和PV的开源项目,由VMWare-Tanzu维护◼ 基于Velero CRD创建备份(Backup)和恢复作业(Restore)◼ 可以备份或恢复集群中的所有对象,也可以按类型、名称空间或标签过滤对象◼ 可基于文件系统备份(File System Backup)备份Pod卷中的数据,并借助restic或kopia上传到对象存储系统◼ 支持基于快照备份PV,这种方式较之FSB能确保文件的一致性;它支持两种操作◆仅创建PV快照◆创建PV快照, 并借助于restic或kopia上传到对象存储系统上◼ 使用对象存储作为备份数据的存储目标,并基于对象存储上的备份对象完成数据恢复◆基于存储提供商插件同各种存储系统集成◆支持的Provider列表:https://velero.io/docs/main/supported-providers/
备份及恢复架构概览
程序组件◼ velero CLI◼ Velero Server◆一款Kubernetes Operator◆两个关键API:Backup和Restore 备份◼ “velero backup create”即可创建备份◼ 新建的备份对象会借助存储插件保存在对应的对象存储系统中◼ Volume的备份不能存储于对象存储系统中,而是要借助于Velero-plugin-for-CSI插件通过相应的CSI Controller创建VolumeSnapshot 恢复◼ “velero restore create”命令用于创建恢复◼ 对于Volume,要将数据源指向VolumeSnapshot
#官网 https://velero.io/Velero的部署:1、安装velero Cli2、使用"velero install"命令,部署velero server至Kubernetes集群上;同时会创建多个CRD#在k8s集群外部准备一台主机,部署minio系统(这里单实例,生产环境要做高可用模式) #9000是控制端口,9001是图形界面端口 #拉取项目,里面有部署minio的docker-compose部署文件 [root@minio ~]#git clone https://github.com/iKubernetes/learning-k8s.git [root@minio ~]#cd learning-k8s/Velero/minio [root@minio minio]#apt install docker [root@minio minio]#apt install docker-compose [root@minio minio]#vim docker-compose.yml version: '3.8'services:minio:image: minio/minio:RELEASE.2024-02-26T09-33-48Zcontainer_name: miniorestart: unless-stoppedenvironment:MINIO_ROOT_USER: 'minioadmin'MINIO_ROOT_PASSWORD: 'magedu.com'MINIO_ADDRESS: ':9000'MINIO_CONSOLE_ADDRESS: ':9001'ports:- "9000:9000"- "9001:9001"networks:- minionetworkvolumes:- ./data:/datahealthcheck:test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]interval: 30stimeout: 20sretries: 3command: server /data #command: server --console-address ":9001" /data networks:minionetwork:driver: bridge -------------------------------------------------- [root@minio minio]#mkdir data #拉镜像(docker配置外网) [root@minio minio]#docker-compose pull #在后台运行服务容器 [root@minio minio]#docker-compose up -d #查看 [root@minio minio]#docker-compose ps Name Command State Ports minio /usr/bin/docker-entrypoint ... Up (health: starting) 0.0.0.0:9000->9000/tcp,:::9000->9000/tcp, 0.0.0.0:9001->9001/tcp,:::9001->9001/tcp#浏览器访问minio内置图形界面 minioadmin/magedu.com http://10.0.0.158:9001/ #创建bucket保存数据,名称为velero#创建credentials-velero(任意名字),用来存放minio的用户名密码,之后给Velero读取 [root@minio minio]#cd .. [root@minio Velero]#vim credentials-velero [default] aws_access_key_id = minioadmin aws_secret_access_key = magedu.com region = minio#master01节点 部署Velero #安装Velero CLI #通过velero官网进入对应github地址: https://github.com/vmware-tanzu/velero/releases/ #下载#velero-v1.13.0-linux-amd64.tar.gz [root@master01 ~]#tar xf velero-v1.13.0-linux-amd64.tar.gz [root@master01 ~]#cd velero-v1.13.0-linux-amd64/ [root@master01 velero-v1.15.0-linux-amd64]#mv velero /usr/local/bin/#切到credentials-velero文件目录下,velero install要加载 [root@master01 ~]#cd learning-k8s/Velero/ #部署Velero (会加载kubeconfig文件) 这里需要每个节点提前配置containerd的外网代理 [root@master01 ~]#velero install \ --secret-file=./credentials-velero \ --provider=aws \ --bucket=velero \ #自己创建的bucket #region地域随便取名;s3ForcePathStyle是否是s3风格路径 --backup-location-config region=minio,s3ForcePathStyle=true,s3Url=http://10.0.0.158:9000 \ --plugins=velero/velero-plugin-for-aws:v1.9.0 \ #镜像路径,在dockerhub上 --use-volume-snapshots=true \ #是否使用卷快照 --snapshot-location-config region=minio \ #如果使用卷快照,快照数据保存到哪 --use-node-agent \ #每个节点上部署一个pod,里面的agent提供上传功能 --uploader-type=kopia #上传时使用的上传器(默认kopia)#查看 [root@master01 Velero]#kubectl get pods -n velero NAME READY STATUS RESTARTS AGE node-agent-f2l9q 1/1 Running 0 6m41s node-agent-f47mv 1/1 Running 0 6m41s node-agent-smzps 1/1 Running 0 6m41s velero-85c8575444-9l757 1/1 Running 0 6m41s
备份
备份存储位置 (Backup Storage Location)Velero系统上用于保存备份信息的目标位置成为Backup Storage Location可由专门的CRD/BackupStorageLocation进行定义和维护Velero部署完成后,会自动创建一个名为default的Backup Storage Location对象#示例: #查看备份存储位置 [root@master01 Velero]#kubectl get BackupStorageLocation -n velero [root@master01 Velero]#kubectl describe BackupStorageLocation default -n velero #或者使用velero查看 [root@master01 Velero]#velero backup-location get NAME PROVIDER BUCKET/PREFIX PHASE LAST VALIDATED ACCESS MODE DEFAULT default aws velero Available 2024-12-17 07:55:18 +0000 UTC ReadWrite true备份Velero使用Backup CRD来管理备份创建Backup: velero backup create列出Backup: velero backup getBackup详情: velero backup describe删除Backup: velero backup delete定制要备份的内容Velero backup create的命令行选项--include-namespaces: 要备份的名称空间列表,默认为"*",代表备份所有的名称空间;--exclude-namespaces: 在备份中要排除的名称空间列表,即不要备份的名称空间列表;--include-resources: 要备份的资源类型列表,格式为"resouce.group",列如"daemonsets.apps",默认为"*";--exclude-resources: 要排除的资源类型列表,格式为"resource.group";--include-cluster-resources: 同时备份集群级别的所有资源;--snapshot-volumes: 是否为PV资源创建快照作为备份作业的一部分,默认为true;--default-volumes-to-fs-backup: 是否使用FSB机制备份Pod卷中的内容;#如果正在写入,有时间点不一致的脏数据#示例 仅备份demo名称空间,且要使用FSB备份机制来备份Pod Volume中的数据velero backup create backup-demo-with-volume --include-namespaces demo --default-volumes-to-fs-backup备份除kube-system、velero以外的所有名称空间velero backup create all-namespaces --exclude-namespaces kube-system,velero --default-volumes-to-fs-backup
恢复 (Restore)
灾难恢复Velero使用Restore CRD来管理恢复,它支持两种数据源--from-backup BACKUP: 从指定的Backup对象进行数据恢复--from-schedule SCHEDULE: 从指定的Schedule对象进行数据恢复其它命令行选项--exclude-namespaces--include-namespaces--exclude-resources--include-resources--restore-volumes: 从snapshot执行卷恢复--allow-partially-failed: 允许部分错误#示例velero restore create --from-backup all-namespaces --allow-partially-failedvelero restore create --from-schedule all-namespaces --exclude-namespaces default,demo --restore-volumes
备份恢复示例
#velero的FSB机制不支持hostPath卷提取,这里用nfs存储,通过csi-driver-nfs #这里minio服务器上安装nfs服务 [root@minio ~]#apt install nfs-kernel-server #暴露路径 [root@minio ~]#mkdir /data/nfs -pv [root@minio ~]#vim /etc/exports /data/nfs 10.0.0.0/16(rw,fsid=0,async,no_subtree_check,no_auth_nlm,insecure,no_root_squash) #重新导出 [root@minio ~]#exportfs -arv#安装NFS CSI Driver (这里用本地部署的方式,才会创建快照crd,用于快照卷备份) [root@master01 ~]#git clone https://github.com/kubernetes-csi/csi-driver-nfs.git [root@master01 ~]#cd csi-driver-nfs/deploy/v4.6.0/ [root@master01 ~]#kubectl apply -f . #查看部署情况(等待pod运行) [root@master01 v4.6.0]#kubectl get pods -n kube-system #查看crd,因为csi-driver-nfs支持快照(必须本地部署方式才会有) [root@master01 v4.6.0]#kubectl get crds ... volumesnapshotclasses.snapshot.storage.k8s.io 2024-12-17T10:27:40Z volumesnapshotcontents.snapshot.storage.k8s.io 2024-12-17T10:27:40Z volumesnapshotlocations.velero.io 2024-12-17T06:16:44Z volumesnapshots.snapshot.storage.k8s.io#k8s每个节点上手动安装程序包,用于访问nfs的客户端组件 [root@master01 ~]#apt install nfs-common -y #主节点创建storageclass [root@master01 ~]#vim nfs-csi.yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata:name: nfs-csi provisioner: nfs.csi.k8s.io parameters:server: 10.0.0.158share: /data/nfs# csi.storage.k8s.io/provisioner-secret is only needed for providing mountOptions in DeleteVolume# csi.storage.k8s.io/provisioner-secret-name: "mount-options"# csi.storage.k8s.io/provisioner-secret-namespace: "default" reclaimPolicy: Delete volumeBindingMode: Immediate[root@master01 ~]#kubectl apply -f nfs-csi.yaml [root@master01 ~]#kubectl get sc NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE nfs-csi nfs.csi.k8s.io Delete Immediate false 20s#创建pvc [root@master01 ~]#cat nfs-pvc-demo.yaml kind: PersistentVolumeClaim apiVersion: v1 metadata:name: nfs-pvcannotations:velero.io/csi-volumesnapshot-class: "nfs-csi" spec:storageClassName: nfs-csiaccessModes:- ReadWriteManyresources:requests:storage: 5Gi [root@master01 ~]#kubectl create -f nfs-pvc-demo.yaml -n demo [root@master01 ~]#kubectl get pvc -n demo NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS nfs-pvc Bound pvc-39cfb435-58d6-46d7-b426-678c3128f677 5Gi RWX nfs-csi #示例: [root@master01 Velero]#kubectl create namespace demo #创建pod [root@master01 Velero]#kubectl create deployment demoapp --image=ikubernetes/demoapp:v1.0 --replicas=3 -n demo #部署redis,后面测试卷中数据能不能备份 (这里用nfs,velero无法读取hostPath卷下的数据) [root@master01 ~]#cd learning-k8s-master/Velero/csi-driver-nfs [root@master01 volumes]#vim redis-with-nfs-pvc.yaml apiVersion: v1 kind: Pod metadata:name: redis-with-nfs-pvc spec:containers:- name: redisimage: redis:7-alpineports:- containerPort: 6379name: redisvolumeMounts:- mountPath: /dataname: data-storagevolumes:- name: data-storagepersistentVolumeClaim:claimName: nfs-pvc[root@master01 csi-driver-nfs]#kubectl apply -f redis-with-nfs-pvc.yaml -n demo #在redis中创建些数据 [root@master01 csi-driver-nfs]#kubectl exec -it redis-with-nfs-pvc -n demo -- /bin/sh /data # redis-cli 127.0.0.1:6379> set hi "hi from magedu" OK 127.0.0.1:6379> BGSAVE #生成dump.rdb文件 Background saving started 127.0.0.1:6379> exit /data # ls dump.rdb#备份,取名demo 只备份demo名称空间,不指定备份所有 (没有备份卷中数据,后面redis数据无法恢复,如果要就指明FSB) [root@master01 volumes]#velero backup create demo --include-namespaces demo #列出已经创建出的备份 (显示为已完成) [root@master01 volumes]#velero backup get NAME STATUS ERRORS WARNINGS CREATED EXPIRES STORAGE LOCATION demo Completed 0 0 2024-12-17 08:03:29 +0000 UTC 29d default #查看备份详细信息 [root@master01 volumes]#velero backup describe demo #在minio网页端能看到对应备份数据#测试 #删除demo名称空间,名称空间下的资源会全部被删除 [root@master01 volumes]#kubectl delete namespace demo#恢复,从指定的备份进行恢复 [root@master01 volumes]#velero restore create --from-backup demo#查看,自动创建了个恢复 [root@master01 volumes]#velero restore get NAME BACKUP STATUS STARTED COMPLETED ERRORS WARNINGS CREATED SELECTOR demo-20241217083347 demo Completed 2024-12-17 08:33:47 +0000 UTC 2024-12-17 08:33:48 +0000 UTC 0 2 2024-12-17 08:33:47 +0000 UTC <none> #查看名称空间 [root@master01 volumes]#kubectl get ns NAME STATUS AGE ... demo Active 3m21s #查看,所有内容都已恢复 [root@master01 volumes]#kubectl get all -n demo #进入redis查看,没有数据,卷中数据没有恢复回来 [root@master01 volumes]#kubectl exec -it redis -n demo -- /bin/sh#可以删除之前的备份,恢复(远端minio也会被删掉) #[root@master01 ~]#velero backup delete --all #[root@master01 ~]#velero restore delete --all#这次备份保存卷中数据 #redis中创建数据 [root@master01 volumes]#kubectl exec -it redis -n demo -- /bin/sh /data # redis-cli 127.0.0.1:6379> set mykey "Hello from MageEdu.com" 127.0.0.1:6379> BGSAVE 127.0.0.1:6379> exit /data # ls dump.rdb#备份(保存卷中数据) [root@master01 volumes]#velero backup create demo02 --include-namespaces demo --default-volumes-to-fs-backup #查看(显示为已完成) [root@master01 volumes]#velero backup get NAME STATUS ERRORS WARNINGS CREATED EXPIRES STORAGE LOCATION SELECTOR demo Completed 0 0 2024-12-17 08:03:29 +0000 UTC 29d default demo02 Completed 0 0 2024-12-17 09:08:14 +0000 UTC 29d default [root@master01 volumes]#velero backup describe demo02Pod Volume Backups - kopia (specify --details for more information): #有保存卷数据Completed: 1 #显示更详细信息 [root@master01 csi-driver-nfs]#velero backup describe demo02 --detailsPod Volume Backups - kopia:Completed: #完成备份demo/redis-with-nfs-pvc: data-storage #minio上bucket下会多出kopia文件夹,里面有demo文件夹(属于demo名称空间的),里面为数据#测试 #删除demo名称空间,名称空间下的资源会全部被删除 [root@master01 volumes]#kubectl delete namespace demo #pv也会同时被删,因为sc的回收策略是delete(删了pvc,pv也会被删) [root@master01 csi-driver-nfs]#kubectl get pv No resources found#恢复,从指定的备份进行恢复 [root@master01 volumes]#velero restore create --from-backup demo02 #查看恢复,有warning [root@master01 volumes]#velero restore get #查看下warning信息是什么 [root@master01 volumes]#velero restore describe demo02-20241217092247#pvc恢复回来了(有了pvc,pv也创建了) [root@master01 csi-driver-nfs]#kubectl get pvc -n demo NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS nfs-pvc Bound pvc-6aa356f1-36d7-4847-931f-23b3bffc0f53 5Gi RWX nfs-csi #在minio服务器上可以看到对应的文件 [root@minio ~]#ls /data/nfs/pvc-6aa356f1-36d7-4847-931f-23b3bffc0f53 dump.rdb [root@master01 ~]#kubectl exec -it redis-with-nfs-pvc -n demo -- /bin/sh /data # ls dump.rdb
Schedule a Backup (创建周期性备份)
Velero支持周期性备份操作基于Schedule CRD进行定义管理命令为 "velero schedule"velero schedule create NAME --schedule="* * * * *" [flags]分 时 日 月 周Schedule也支持 "@every {duration}" 语法也指定备份周期, 常用的时间单位有seconds(s)、minutes(m)和hours(h);例如--schedule= "@every 6h": 每6个小时--schedule="@every 24h"#示例#所有名称空间但排除kube-system,velero, 备份卷中数据, 每24小时执行备份velero schedule create all-namespaces --exclude-namespaces kube-system,velero --default-volumes-to-fs-backup --schedule="@every 24h"#查看 [root@master01 csi-driver-nfs]#velero schedule get NAME STATUS CREATED SCHEDULE BACKUP TTL LAST BACKUP all-namespaces Enabled 2024-12-17 13:28:11 +0000 UTC @every 24h 0s n/a #恢复要用 --from-schedule (其他和前面恢复一样) velero restore create --from-schedule XXX
基于CSI Volume Snapshot (快照) 的PV数据备份和恢复
Velero要使用CSI卷快照,必须实现部署velero-plugin-for-csi插件,且在部署Velero时启用了CSI特性~#velero install \--secret-file=./credentials-velero \--provider=aws \--bucket=velero \--backup-location-config region=minio,s3ForcePathStyle=true,s3Url=http://10.0.0.158:9000 \--plugins=velero/velero-plugin-for-aws:v1.9.0,velero/velero-plugin-for-csi:v0.7.0 \ #加对接csi卷插件--use-volume-snapshots=true \--features=EnableCSI \ #启用CSI功能--snapshot-location-config region=minio \--use-node-agent \--uploader-type=kopia快照创建完成后,Velero也支持将其数据移动至专用的位置进行存储移动数据Velero默认并不移动PV数据需要由 "--snapshot-move-data" 选项明确指定卷数据存储位置可用存储位置可由 "velero snapshot-location get" 命令列出default/VolumeSnapshotLocation通常为默认的位置,也由选项 "--volume-snapshot-locations"进行明确指定VolumeSnapshotClassVelero会基于现有的VolumeSnapshotClass对要备份的PV创建VolumeSnapshot和VolumeSnapshotContent对象在备份作业中为基于CSI卷的PVC创建快照时,Velero CSI plugin遵循如下逻辑查找要使用的VolumeSnapshotClass资源#下面三种方式选择其中之一,下面示例选的第一种1.在默认要使用的VolumeSnapshotClass对象上添加专用的标签 "velero.io/csi-volumesnapshot-class"2.在Backup对象上使用特定格式的注解信息,明确指定要使用的VolumeSnapshotClass例如: velero.io/csi-volumesnapshot-class_nfs.csi.k8s.io: "nfs-csi"3.在PVC对象上使用统一格式的注解信息,即可指定要使用VolumeSnapshotClass例如: velero.io/csi-volumesnapshot-class: "nfs-csi"#实际操作示例 [root@master01 ~]#cd learning-k8s-master/Velero/csi-driver-nfs/ #创建快照卷类 [root@master01 csi-driver-nfs]#vim nfs-csi-volumesnapshotclass.yaml apiVersion: snapshot.storage.k8s.io/v1 kind: VolumeSnapshotClass #资源类型 metadata:name: nfs-csilabels:velero.io/csi-volumesnapshot-class: "true" #基于卷快照执行备份,允许Volume自动在该类创建快照卷 driver: nfs.csi.k8s.io parameters: parameters:server: 10.0.0.158 #nfs服务器地址(对nfs服务器创建快照)share: /data/nfs deletionPolicy: Delete[root@master01 csi-driver-nfs]#kubectl apply -f nfs-csi-volumesnapshotclass.yaml #查看VolumeSnapshotClass [root@master01 csi-driver-nfs]#kubectl get vsclass NAME DRIVER DELETIONPOLICY AGE nfs-csi nfs.csi.k8s.io Delete 39s#卸载此前的velero(此前的备份和恢复不会被删掉) [root@master01 csi-driver-nfs]#velero uninstall #部署Velero [root@master01 csi-driver-nfs]#cd .. [root@master01 Velero]#ls credentials-velero csi-driver-nfs imgs minio tests.md #安装会下载对应插件,插件会复制到velero的pod中 [root@master01 csi-driver-nfs]#velero install \ --secret-file=./credentials-velero \ --provider=aws \ --bucket=velero \ --backup-location-config region=minio,s3ForcePathStyle=true,s3Url=http://10.0.0.158:9000 \ --plugins=velero/velero-plugin-for-aws:v1.9.0,velero/velero-plugin-for-csi:v0.7.0 \ --use-volume-snapshots=true \ --features=EnableCSI \ --snapshot-location-config region=minio \ --use-node-agent \ --uploader-type=kopia #确保pod都正常 [root@master01 Velero]#kubectl get pods -n velero NAME READY STATUS RESTARTS AGE node-agent-6zmp9 1/1 Running 0 12m node-agent-hznjt 1/1 Running 0 10m node-agent-k9pbv 1/1 Running 0 12m velero-96d846bd9-9t9pf 1/1 Running 0 12m#基于快照方式执行备份操作 #该pvc已经创建好了,基于nfs-csi,支持卷快照 [root@master01 csi-driver-nfs]#kubectl get pvc -n demo NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS nfs-pvc Bound pvc-6aa356f1-36d7-4847-931f-23b3bffc0f53 5Gi RWX nfs-csi #备份时velero backup参数--snapshot-volumes:是否为PV资源创建快照作为备份作业的一部分,默认为true; 可以不定义 [root@master01 Velero]#velero backup create demo003 --include-namespaces demo --snapshot-volumes #查看备份完成没,如果inprogress表示正在执行中 [root@master01 Velero]#velero backup get [root@master01 Velero]#velero backup describe demo003 Backup Volumes:Velero-Native Snapshots: <none included>CSI Snapshots:demo/nfs-pvc: #demo名称空间下基于nfs-pvc创建的SnapshotSnapshot: included, specify --details for more informationPod Volume Backups: <none included>#volumesnapshot创建完就会删除,但会保留volumesnapshotcontent [root@master01 Velero]#kubectl get vs -n demo No resources found in demo namespace. #volumesnapshotcontent,万一pod的pvc被删或被清,可以基于该快照把数据恢复回来 [root@master01 Velero]#kubectl get vsc -n demo NAME READYTOUSE RESTORESIZE DELETIONPOLICY DRIVER VOLUMESNAPSHOTCLASS VOLUMESNAPSHOT VOLUMESNAPSHOTNAMESPACE snapcontent-73387383-cd7a-4e91-b590-5154cde9f01e true 0 Retain nfs.csi.k8s.io nfs-csi name-d522a23b-fb8b-48bb-acf8-ddcee83a51eb ns-d522a23b-fb8b-48bb-acf8-ddcee83a51eb#恢复 (--restore-volumes: 从snapshot执行卷恢复) [root@master01 Velero]#velero restore create --from-backup=demo003 --restore-volumes#备份并把卷快照的数据move到minio去 --snapshot-move-data (这里内部报错集群不支持v1betal CRD) [root@master01 Velero]#velero backup create demo004 --include-namespaces demo --snapshot-volumes --snapshot-move-data #查看, WaitingForPluginOperations表示备份上传过程,一旦上传完成会把volumesnapshotcontent也删掉 [root@master01 Velero]#velero backup get#测试,删除数据(名称空间没了,快照也都没了) [root@master01 Velero]#kubectl delete namespace demo #vsc还有是因为保留规则为Retain [root@master01 Velero]#kubectl get vsc#恢复 [root@master01 Velero]#velero restore create --from-backup demo004 #pending可能是pvc正在创建 [root@master01 Velero]#kubectl get pods -n demo [root@master01 Velero]#kubectl get pvc -n demo [root@master01 Velero]#kubectl describe pvc nfs-pvc -n demo
总结
升级集群版本:velero执行一次全量备份,将数据上传保存;支持跨集群恢复:集群迁移:A: 全量备份B: 恢复
1云原生的定义
云原生:微服务架构体系:治理微服务: 微服务治理框架 #下面两种方案1.Spring Cloud: 规范,微服务治理的功能框架 (SDK,和多个后端基础务:Nacos、Spring Cloud Gateway...),限制在Java语言Spring cloud NetflixSpring Cloud AlibabaSpring CLoud TencentSermant(Java Agent,proxyless)#华为提供的agent方案(类网格服务,性能好,局限于java),基于Spring Cloud ...Spring CLoud Kubernetes: 复用Kubernetes的能力(可以直接使用k8s的组件实现微服务功能)2.Service Mesh: 规范,微服务治理的基础设施,没有语言限制,遵循接口契约#服务网格由数据平面和控制平面两部分组成代理: Envoy (C++), 数据平面(对于服务网格来说) #基于sidecar进行注入控制平面: Istio, ... #把envoy以sidecar的形式注入到每个pod中,并给它下发配置,实现流量治理能力 局限: 代理层,存在相当程度的性能损失,15%-30%; #据说蚂蚁金服优化到10%,大部分服务都跑在服务网格了
#项目地址 (对原项目做了改造,更好的适配k8s) https://gitee.com/mageedu/mall-microservicemall-microservice项目实战:微服务化的电子商城 (Spring Cloud)电子商城后台: mall-microservice前台: 移动端 #不做部署测试商家前台: Vue, Web UI, mall-admin-webmall-microservice部署:#后端服务Prometheus Server (http/https,且仅支持prometheus专用的格式的指标)mysql --> mysql exporter部署形式: 同一个Pod中的多个容器mysql-server: 主容器mysql-exporter: adapter容器Nacos: 依赖于特有的jar直接暴露prometheus格式的指标;...MySQLNacos --> MySQL业务数据 --> MySQLNacos:服务注册中心配置中心ElasticSearch #商品搜索服务和日志中心可以各部署一套,这里就节省为共用一套 商品搜索服务:安装中文分词器Image: ikubernetes/elasticsearch:7.17.7-ik #重新构建(内置中文分词器)日志中心: Fluent-bit(常用来收集pod中日志的组件),KibanaFluent-bit: DaemonSet部署Kibana: Web UIRedismaster/slaveMongoDBReplicaSet ClusterRabbitMQMinIOSkyWalking#商城后台mall-gatewaymall-portalmall-search...#商城管理器:mall-admin-web --> API --> mall-gateway#移动端: 用户前台 基础环境:OS: ubuntu 2204, 2 cores (主节点:2g,从节点:7g,nfs服务器:1g)1 master, 3 worker nodes: kubernetes clusterversion: v1.29.3网络插件:Cilium(启动Cilium Ingress Controller)AddONs:Metrics ServerKuboardMetalLBIngress Controller: Cilium存储服务:OpenEBS #项目自己做了数据冗余,所以这里不需要做冗余,不需要用到jiva进行冗余openebs-hostpath #在节点本地保存数据,性能没问题csi-driver-nfs
基础环境部署
[root@ubuntu ~]#git clone https://github.com/iKubernetes/learning-k8s.git #部署好k8s, 网络插件Cilium(启动Cilium Ingress Controller)#部署metrics-server(多实例,高可用方式部署) (promethues会用) [root@master01 ~]#cd learning-k8s-master/metrics-server [root@master01 metrics-server]#kubectl apply -f high-availability-1.21+.yaml #会部署在kube-system名称空间 [root@master01 metrics-server]#kubectl get pods -n kube-system metrics-server-69d8c57977-488pm 1/1 Running 0 91s metrics-server-69d8c57977-hrbh2 1/1 Running 0 91s#会增加metrics.k8s.io/v1beta1的群组,有了这个群组,就可以使用kubectl top命令看pod的资源信息 [root@master01 metrics-server]#kubectl api-versions metrics.k8s.io/v1beta1 [root@master01 metrics-server]#kubectl top pods -n kube-system NAME CPU(cores) MEMORY(bytes) cilium-9f668 11m 85Mi cilium-envoy-k5f2f 2m 13Mi ... #显示每个节点的使用情况 [root@master01 metrics-server]#kubectl top nodes NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% master01 84m 4% 1936Mi 51% node01 18m 0% 1289Mi 34% node02 23m 1% 1233Mi 32% node03 16m 0% 1253Mi 33%#部署metallb [root@master01 metrics-server]#kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.8/config/manifests/metallb-native.yaml #等待pod运行正常 [root@master01 ~]#kubectl get pods -n metallb-system #配置地址池 [root@master01 learning-k8s-master]#cd MetalLB/ [root@master01 MetalLB]#vim metallb-ipaddresspool.yaml apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata:name: localip-poolnamespace: metallb-system spec:addresses:- 10.0.0.51-10.0.0.80autoAssign: trueavoidBuggyIPs: true [root@master01 MetalLB]#kubectl apply -f metallb-ipaddresspool.yaml #配置地址公告方式 [root@master01 MetalLB]#vim metallb-l2advertisement.yaml apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata:name: localip-pool-l2anamespace: metallb-system spec:ipAddressPools:- localip-poolinterfaces:- ens33 [root@master01 MetalLB]#kubectl apply -f metallb-l2advertisement.yaml #此时cilium-ingress获得外部地址 [root@master01 MetalLB]#kubectl get svc -n kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE cilium-ingress LoadBalancer 10.106.124.248 10.0.0.51 80:31735/TCP,443:31545/TCP 68m#部署openebs-hostpath [root@master01 ~]#kubectl apply -f https://openebs.github.io/charts/openebs-operator.yaml #等待 [root@master01 MetalLB]#kubectl get pods -n openebs
后端服务部署
[root@master01 ~]#cd learning-k8s-master/Mall-MicroService/infra-services-with-prometheus/#部署Prometheus [root@master01 infra-services-with-prometheus]#cd 00-Prometheus/ [root@master01 00-Prometheus]#kubectl create namespace prom [root@master01 00-Prometheus]#cat prometheus-server/prometheus-ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata:name: prometheusnamespace: promlabels:app: prometheusannotations:ingress.cilium.io/loadbalancer-mode: 'shared'ingress.cilium.io/service-type: 'Loadbalancer' #默认,可以不写 spec:ingressClassName: 'cilium' #ingressClass指定为cilium,因为这里是cilium提供ingress功能 rules:- host: prom.magedu.comhttp:paths:- path: /pathType: Prefixbackend:service:name: prometheusport:number: 9090- host: prometheus.magedu.comhttp:paths:- path: /pathType: Prefixbackend:service:name: prometheusport: number: 9090 [root@master01 00-Prometheus]#kubectl apply -f prometheus-server/ -n prom #查看生成的ingress [root@master01 00-Prometheus]#kubectl get ingress -n prom NAME CLASS HOSTS ADDRESS PORTS AGE prometheus cilium prom.magedu.com,prometheus.magedu.com 10.0.0.51 80 108m#windows上配置host文件,浏览器输入测试 10.0.0.51 prom.magedu.com#节点级指标 [root@master01 00-Prometheus]#kubectl apply -f node_exporter/ -n prom [root@master01 00-Prometheus]#kubectl get pods -n prom NAME READY STATUS RESTARTS AGE prometheus-node-exporter-js8r2 1/1 Running 0 2m18s prometheus-node-exporter-nsm2v 1/1 Running 0 2m18s prometheus-node-exporter-p49rr 1/1 Running 0 2m18s #暴露k8s上的逻辑组件相关指标 [root@master01 00-Prometheus]#kubectl apply -f kube-state-metrics/ -n prom [root@master01 00-Prometheus]#kubectl get pods -n prom NAME READY STATUS RESTARTS AGE kube-state-metrics-7bfbbcdbb7-rbpfx 1/1 Running 0 3m34s #prometheus会自动发现上述指标会抓取#部署promtheus的告警功能,grafana图形显示promtheus (grafana的ingress也要改成cilium) [root@master01 00-Prometheus]#kubectl apply -f grafana/ -f alertmanager/ -n prom#grafana需要准备卷,需要nfs-csi存储类 (也可以不部署nfs,改成openebs-hostpath存储类) #准备一台机器做nfs服务器 [root@nfs ~]#apt update && apt install -y nfs-kernel-server #创建文件夹用于导出 (用于动态置备) [root@nfs ~]#mkdir /data/nfs -pv [root@nfs ~]#vim /etc/exports /data/nfs 10.0.0.0/16(rw,fsid=0,async,no_subtree_check,no_auth_nlm,insecure,no_root_squash) #执行重新导出 [root@nfs ~]#exportfs -arv #k8s所有节点安装nfs客户端 [root@node01 ~]#apt update && apt install -y nfs-common#部署csi-driver-nfs (动态置备存储) [root@master01 ~]#git clone https://github.com/kubernetes-csi/csi-driver-nfs.git [root@master01 ~]#cd csi-driver-nfs/deploy #直接部署4.6.0版本 (每个节点下载镜像并运行) [root@master01 deploy]#kubectl apply -f v4.6.0/ #查看(默认在kube-system空间下) [root@master01 deploy]#kubectl get pods -n kube-system#准备StroageClass,以完成csi-driver-nfs和nfs-server之间的对接: #要使用nfs上的存储驱动,需要定义storageclass来完成 [root@master01 ~]#vim storageclass-csi-nfs.yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata:name: nfs-csiannotations:storageclass.kubernetes.io/is-default-class: "true" provisioner: nfs.csi.k8s.io parameters:server: 10.0.0.155 #nfs服务器地址share: /data/nfs #nfs对应地址(会在该路径下自动创建子目录作为动态置备存储路径) reclaimPolicy: Delete #生产中用delete回收策略有风险 volumeBindingMode: Immediate [root@master01 ~]#kubectl apply -f storageclass-csi-nfs.yaml #查看存储类 [root@master01 ~]#kubectl get sc #此时grafana的pvc已经bound上了 [root@master01 deploy]#kubectl get pvc -n prom NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS grafana-pvc Bound pvc-f2e296d8... 5Gi RWX nfs-csi #grafana正常启动了 [root@master01 00-Prometheus]#kubectl get pods -n prom NAME READY STATUS RESTARTS AGE grafana-69465f69d6-ntbfc 1/1 Running 0 4m46s [root@master01 00-Prometheus]#kubectl get ingress -n prom NAME CLASS HOSTS ADDRESS PORTS AGE grafana cilium grafana.magedu.com 10.0.0.51 80 13h prometheus cilium prom.magedu.com,prometheus.magedu.com 10.0.0.51 80 16h#windows上配置host,浏览器输入测试 grafana.magedu.com 用户名/密码 admin/admin 10.0.0.51 prom.magedu.com grafana.magedu.com#部署nacos [root@master01 infra-services-with-prometheus]#cd 01-Nacos/ #这里nacos使用外部的mysql,所以先部署mysql(主从复制方式,statefulset编排运行) [root@master01 01-Nacos]#kubectl create namespace nacos [root@master01 01-Nacos]#kubectl apply -f 01-secrets-mysql.yaml -f 02-mysql-persistent.yaml -n nacos #访问入口 #读请求:mysql-read.nacos.svc.cluster.local #写请求:mysql-0.mysql.nacos.svc.cluster.local #mysql-0表示主节点#已创建用户账号,但需要对账号进行授权 #在mysql上创建nacos专用的用户账号,本示例中,Naocs默认使用nacos用户名和"magedu.com"密码访问mysql服务上的nacosdb数据库。 [root@master01 01-Nacos]#kubectl exec -it mysql-0 -n nacos -- mysql -uroot -hlocalhost #在mysql的提示符下运行如下SQL语句后退出即可 mysql> GRANT ALL ON nacosdb.* TO nacos@'%' IDENTIFIED BY 'magedu.com';#部署Nacos(statefulset编排运行) [root@master01 01-Nacos]#kubectl apply -f 03-nacos-cfg.yaml -f 04-nacos-persistent.yaml -f 05-nacos-service.yaml -f 06-nacos-ingress.yaml -n nacos [root@master01 01-Nacos]#kubectl get ingress -n nacos NAME CLASS HOSTS ADDRESS PORTS AGE nacos cilium nacos.magedu.com 10.0.0.51 80 8m46s#确保nacos都运行了,如果有pending,可能是还在创建卷 [root@master01 ~]#kubectl get pvc -n nacos #查看卷是否都创建好绑定了 [root@master01 ~]#kubectl get pods -n nacos#windows上配置host,浏览器输入测试 http://nacos.magedu.com/nacos 10.0.0.51 prom.magedu.com grafana.magedu.com nacos.magedu.com#把配置信息导入nacos #查看nacos的pod的ip地址 [root@master01 examples]#kubectl get pods -n nacos -o wide nacos-0 1/1 Running 1 (21m ago) 148m 10.244.1.6 node01 <none> <none> nacos-1 1/1 Running 0 148m 10.244.2.182 node02 <none> <none> nacos-2 1/1 Running 1 (21m ago) 148m 10.244.3.94 node03 <none> <none> #下面的命令可以导入指定的示例文件中的配置,通过nacos任一ip地址 OVERWRITE如果已有配置就覆盖 [root@master01 01-Nacos]#curl --location -XPOST 'http://10.244.1.6:8848/nacos/v1/cs/configs?import=true&namespace=public' \--form 'policy=OVERWRITE' --form 'file=@"examples/nacos_config_20231029.zip"' #将来电子商城从nacos中加载配置信息#部署ElasticStack [root@master01 infra-services-with-prometheus]#cd 02-ElasticStack/ [root@master01 02-ElasticStack]#kubectl create namespace elastic #先部署elasticsearch(集群化部署,3个实例) [root@master01 02-ElasticStack]#kubectl apply -f 01-elasticsearch-cluster-persistent.yaml -n elastic [root@master01 02-ElasticStack]#kubectl get pods -n elastic#部署fluentbit (会收集日志,简单转换格式存到es中) [root@master01 02-ElasticStack]#kubectl apply -f 02-fluentbit.yaml -n elastic [root@master01 02-ElasticStack]#kubectl get pods -n elastic NAME READY STATUS RESTARTS AGE fluent-bit-96jqh 1/1 Running 0 2m50s fluent-bit-fbxf9 1/1 Running 0 2m50s fluent-bit-ftbnc 1/1 Running 0 2m50s fluent-bit-q4tkh 1/1 Running 0 2m50s #随意找一个k8s节点查看索引,已经有logstash日志信息录入了 [root@master01 02-ElasticStack]#curl 10.244.3.177:9200/_cat/indices green open .geoip_databases 2irGf4quQ8eHb4601ReZyw 1 1 36 0 68.3mb 34.1mb green open logstash-2024.12.20 dD6EUFW1T3C0FdhgIJOdSw 1 1 659 0 927.6kb 463.4kb#部署kibana [root@master01 02-ElasticStack]#kubectl apply -f 03-kibana.yaml -n elastic #等待kibana部署起来 [root@master01 02-ElasticStack]#kubectl get pods -n elastic [root@master01 02-ElasticStack]#kubectl get ingress -n elastic NAME CLASS HOSTS ADDRESS PORTS AGE kibana cilium kibana.magedu.com 10.0.0.51 80 2m3s#windows上配置host,浏览器输入测试 kibana.magedu.com 10.0.0.51 prom.magedu.com grafana.magedu.com nacos.magedu.com kibana.magedu.com #在kibana网页上左侧stack management上创建index,输入logstash-*,选择时间轴 @timestamp #左侧analytics下的discover,就能显示对应pod当中的日志信息了#部署redis(主从复制 1主2从,statefulset) [root@master01 infra-services-with-prometheus]#cd 03-Redis/ #里面sentinel文件是redis的哨兵,会自动监视主从健康状态,并在必要时刻自动切换主从节点信息并重新唤起主/从节点,这里不进行部署 [root@master01 03-Redis]#kubectl create namespace redis #部署redis 密码:bWFnZWR1LmNvbQ== [root@master01 03-Redis]#kubectl apply -f . -n redis [root@master01 03-Redis]#kubectl get pods -n redis#部署RabbitMQ (微服务访问后端服务用到的消息队列) [root@master01 infra-services-with-prometheus]#cd 04-RabbitMQ/ [root@master01 04-RabbitMQ]#kubectl create namespace rabbit #部署 RabbitMQ 超级管理员用户名/密码 admin/magedu.com [root@master01 04-RabbitMQ]#kubectl apply -f ./ -n rabbit [root@master01 04-RabbitMQ]#kubectl get pods -n rabbit [root@master01 04-RabbitMQ]#kubectl get ingress -n rabbit NAME CLASS HOSTS ADDRESS PORTS AGE rabbitmq cilium rabbitmq.magedu.com 10.0.0.51 80 84s #windows上配置host,浏览器输入测试 rabbitmq.magedu.com 用户名/密码 admin/magedu.com 10.0.0.51 rabbitmq.magedu.com#为mall-microservice提供服务时,需要创建新的用户malladmin/magedu.com,并创建新的vhost,名称为/mall,并授权给malladmin用户。 在rabbitmq网页上方admin栏下,添加新用户账号/密码malladmin/magedu.com,标签为management,点击add user 右侧栏选Virtual Hosts,新增一个,名称/mall,Default Queue Type选Classic就行,点add virtual host 点击新加的/mall,在Set permission(授权),admin用户所有权限点set,malladmin用户所有权限点set permission #如果用到消息队列,在下面topic permissions中选malladmin,在(AMQP default)高级消息队列协议,给所有权限,点set#部署MongoDB ReplicaSet集群 [root@master01 infra-services-with-prometheus]#cd 05-MongoDB/ [root@master01 05-MongoDB]#kubectl create namespace mongo [root@master01 05-MongoDB]#kubectl apply -f . -n mongo [root@master01 05-MongoDB]#kubectl get pods -n mongo #查看集群状态 mongodb-0主实例 直接运行mongo客户端命令(交互接口) kubectl exec -it mongodb-0 -n mongo -- mongo mongo> rs.status()#部署minio(4个实例,构建集群) (内置暴露promtheus指标) [root@master01 infra-services-with-prometheus]#cd 06-MinIO/ [root@master01 06-MinIO]#kubectl create namespace minio #部署minio 用户名/密码 minioadmin/magedu.com [root@master01 06-MinIO]#kubectl apply -f . -n minio [root@master01 06-MinIO]#kubectl get pods -n minio [root@master01 06-MinIO]#kubectl get ingress -n minio NAME CLASS HOSTS ADDRESS PORTS AGE minio cilium minio.magedu.com 10.0.0.51 80 21m #windows上配置host,浏览器输入测试 minio.magedu.com 用户名/密码 minioadmin/magedu.com 10.0.0.51 minio.magedu.com #创建一个mall的bucket(后面服务要用)#部署Skywalking (实现分布式链路跟踪) [root@master01 infra-services-with-prometheus]#cd 07-Skywalking/ [root@master01 07-Skywalking]#kubectl create namespace tracing #先部署部署Skywalking OAP(用到的配置文件依赖于部署在elastic名称空间中的elasticsearch服务) [root@master01 07-Skywalking]#kubectl apply -f 01-skywalking-oap.yaml -n tracing [root@master01 07-Skywalking]#kubectl get pods -n tracing #再部署Skywalking UI(前端界面) [root@master01 07-Skywalking]#kubectl apply -f 02-skywalking-ui.yaml -n tracing [root@master01 07-Skywalking]#kubectl get pods -n tracing NAME READY STATUS RESTARTS AGE skywalking-oap-88cc84f5c-4lgmn 0/1 Running 0 10m skywalking-ui-f69f457b6-flqxt 0/1 Running 0 4m41s [root@master01 07-Skywalking]#kubectl get ingress -n tracing NAME CLASS HOSTS ADDRESS PORTS AGE skywalking cilium skywalking.magedu.com 10.0.0.51 80 55 #windows上配置host,浏览器输入测试 skywalking.magedu.com 10.0.0.51 skywalking.magedu.com
部署商城后端
#获取mysql脚本 # 从https://gitee.com/mageedu/mall-microservice下载项目获取msyql脚本 [root@master01 ~]#git clone https://gitee.com/mageedu/mall-microservice.git [root@master01 ~]#cd mall-microservice/document/sql/ [root@master01 sql]#ls mall.sql README.md #为了便于导入,安装mysql的客户端 [root@master01 sql]#apt install -y mysql-client [root@master01 sql]#kubectl get pods -o wide -n nacos NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES mysql-0 3/3 Running 0 3m10s 10.244.3.176 node03 <none> <none> mysql-1 3/3 Running 15 (4m41s ago) 29h 10.244.1.138 node01 <none> <none> ... #输入,没有密码 [root@master01 sql]#mysql -uroot -p -h10.244.3.176 < mall.sql [root@master01 ~]#cd learning-k8s-master/Mall-MicroService/mall-and-skywalking #这里镜像都已经提前编译上传好了 [root@master01 mall-and-skywalking]#kubectl create namespace mall #部署各服务 [root@master01 mall-and-skywalking]#kubectl apply -f . -n mall #等待部署完成 [root@master01 mall-and-skywalking]#kubectl get pods -n mall [root@master01 mall-and-skywalking]#kubectl get ingress -n mall NAME CLASS HOSTS ADDRESS PORTS AGE mall-admin-web cilium mall-admin-web.magedu.com 10.0.0.51 80 79s #前端服务 mall-gateway cilium mall-gateway.magedu.com 10.0.0.51 80 79s #后端服务 mall-monitor cilium mall-monitor.magedu.com 10.0.0.51 80 79s #后端服务#windows上配置host,浏览器输入测试 10.0.0.51 mall-admin-web.magedu.com mall-gateway.magedu.com mall-monitor.magedu.com#Spring Boot admin 用于监控Spring Boot应用程序的状态和各种运行时指标 mall-monitor.magedu.com #用户名/密码 admin/magedu.com #mall-gateway需要登录访问,需要oauth认证;内部文档也不需要认证 http://mall-gateway.magedu.com/doc.html #商家管理端 #用户名/密码 admin/magedu.com mall-admin-web.magedu.com #里面随便点点,形成请求,被sky-walking agent生成跟踪信息并报告到sky-walking中#登录skywalking可以看到后端之间的调用关系,访问时间等信息 skywalking.magedu.com