当前位置: 首页 > news >正文

如何建独立网站/seo关键词排名优化手机

如何建独立网站,seo关键词排名优化手机,wordpress的第三方登录插件,广州最好的网站建设在 Kubernetes 生态系统中,持久化存储是支撑业务应用稳定运行的基石,对于维护整个系统的健壮性至关重要。对于选择自主搭建 Kubernetes 集群的运维架构师来说,挑选合适的后端持久化存储解决方案是关键的选型决策。目前,Ceph、Glus…

在 Kubernetes 生态系统中,持久化存储是支撑业务应用稳定运行的基石,对于维护整个系统的健壮性至关重要。对于选择自主搭建 Kubernetes 集群的运维架构师来说,挑选合适的后端持久化存储解决方案是关键的选型决策。目前,Ceph、GlusterFS、NFS、Longhorn 和 openEBS 等解决方案已在业界得到广泛应用。

为了丰富技术栈,并为容器云平台的持久化存储设计提供更广泛的灵活性和选择性,今天,我将带领大家一起探索,如何将 Ceph 集成到由 KubeSphere 管理的 Kubernetes 集群中。

集成 Ceph 至 Kubernetes 集群主要有两种方案:

  • 利用 Rook Ceph 直接在 Kubernetes 集群上部署 Ceph 集群,这种方式更贴近云原生的应用特性。
  • 手动部署独立的 Ceph 集群,并配置 Kubernetes 集群与之对接,实现存储服务的集成。

本文将重点实战演示使用 Rook Ceph 在 Kubernetes 集群上直接部署 Ceph 集群的方法,让您体验到云原生环境下 Ceph 部署的便捷与强大。

实战服务器配置(架构 1:1 复刻小规模生产环境,配置略有不同)

主机名IPCPU内存系统盘数据盘用途
ksp-registry192.168.9.904840200Harbor 镜像仓库
ksp-control-1192.168.9.914840100KubeSphere/k8s-control-plane
ksp-control-2192.168.9.924840100KubeSphere/k8s-control-plane
ksp-control-3192.168.9.934840100KubeSphere/k8s-control-plane
ksp-worker-1192.168.9.9441640100k8s-worker/CI
ksp-worker-2192.168.9.9541640100k8s-worker
ksp-worker-3192.168.9.9641640100k8s-worker
ksp-storage-1192.168.9.974840400+Containerd、OpenEBS、ElasticSearch/Longhorn/Ceph/NFS
ksp-storage-2192.168.9.984840300+Containerd、OpenEBS、ElasticSearch/Longhorn/Ceph
ksp-storage-3192.168.9.994840300+Containerd、OpenEBS、ElasticSearch/Longhorn/Ceph
ksp-gpu-worker-1192.168.9.10141640100k8s-worker(GPU NVIDIA Tesla M40 24G)
ksp-gpu-worker-2192.168.9.10241640100k8s-worker(GPU NVIDIA Tesla P100 16G)
ksp-gateway-1192.168.9.1032440自建应用服务代理网关/VIP:192.168.9.100
ksp-gateway-2192.168.9.1042440自建应用服务代理网关/VIP:192.168.9.100
ksp-mid192.168.9.1054840100部署在 k8s 集群之外的服务节点(Gitlab 等)
合计15561526002100+

实战环境涉及软件版本信息

  • 操作系统:openEuler 22.03 LTS SP3 x86_64
  • KubeSphere:v3.4.1
  • Kubernetes:v1.28.8
  • KubeKey: v3.1.1
  • Containerd:1.7.13
  • Rook:v1.14.9
  • Ceph: v18.2.4

1. Rook 部署规划

为了更好地满足生产环境的实际需求,在规划和部署存储基础设施时,我增加了以下策略:

  • 节点扩展:向 Kubernetes 集群中新增三个专用节点,这些节点将专门承载 Ceph 存储服务,确保存储操作的高效性和稳定性。
  • 组件隔离:所有 Rook 和 Ceph 组件以及数据卷将被部署在这些专属节点上,实现组件的清晰隔离和专业化管理。
  • 节点标签化:为每个存储节点设置了专门的标签 node.kubernetes.io/storage=rook,以便 Kubernetes 能够智能地调度相关资源。同时,非存储节点将被标记为 node.rook.io/rook-csi=true,这表明它们将承载 Ceph CSI 插件,使得运行在这些节点上的业务 Pod 能够利用 Ceph 提供的持久化存储。
  • 存储介质配置:在每个存储节点上,我将新增一块 100G 的 Ceph 专用数据盘 /dev/sdd。为保证最佳性能,该磁盘将采用裸设备形态直接供 Ceph OSD 使用,无需进行分区或格式化

重要提示:

  • 本文提供的配置和部署经验对于理解 Rook-Ceph 的安装和运行机制具有参考价值。然而,强烈建议不要将本文描述的配置直接应用于任何形式的生产环境
  • 在生产环境中,还需进一步考虑使用 SSD、NVMe 磁盘等高性能存储介质;细致规划故障域;制定详尽的存储节点策略;以及进行细致的系统优化配置等。

2. 前置条件

2.1 Kubernetes 版本

  • Rook 可以安装在任何现有的 Kubernetes 集群上,只要它满足最低版本,并且授予 Rook 所需的特权

  • 早期 v1.9.7 版本的 Rook 支持 Kubernetes v1.17 或更高版本

  • 现在的 v1.14.9 版本支持 Kubernetes v1.25 到 v1.30 版本(可能支持更低的版本,可以自己验证测试)

2.2 CPU Architecture

支持的 CPU 架构包括: amd64 / x86_64 and arm64

2.3 Ceph 先决条件

为了配置 Ceph 存储集群,至少需要以下任意一种类型的本地存储:

  • Raw devices (no partitions or formatted filesystems,没有分区和格式化文件系统,本文选择)
  • Raw partitions (no formatted filesystem,已分区但是没有格式化文件系统)
  • LVM Logical Volumes (no formatted filesystem)
  • PVs available from a storage class in block mode

使用以下命令确认分区或设备是否使用文件系统并进行了格式化:

$ lsblk -f
NAME               FSTYPE      FSVER    LABEL  UUID                                   FSAVAIL FSUSE% MOUNTPOINTS
sda
├─sda1             ext4        1.0             b5e46d67-426b-476f-bd89-18137af7ff59    682.5M    23% /boot
└─sda2             LVM2_member LVM2 001        NepB96-M3ux-Ei6Q-V7AX-BCy1-e2RN-Lzbecn├─openeuler-root ext4        1.0             0495bb1d-16f7-4156-ab10-5bd837b24de5     29.9G     7% /└─openeuler-swap swap        1               837d3a7e-8aac-4048-bb7a-a6fdd8eb5931
sdb                LVM2_member LVM2 001        Dyj93O-8zKr-HMah-hxjd-8IZP-IxVE-riWf3O
└─data-lvdata      xfs                         1e9b612f-dbd9-46d2-996e-db74073d6648       86G    14% /data
sdc                LVM2_member LVM2 001        LkTCe2-0vp7-e3SJ-Xxzb-UzN1-sd2T-74TF3L
└─longhorn-data    xfs                         30a13ac0-6eef-433c-8d7e-d6776ec669ff     99.1G     1% /longhorn
sdd
  • 如果 FSTYPE 字段不为空,说明该设备已经格式化为文件系统,对应的值就是文件系统类型
  • 如果 FSTYPE 字段为空,说明该设备还没有被格式化,可以被 Ceph 使用
  • 本例中可以使用的设备为 sdd

如果需要清理已有磁盘给 Ceph 使用,请使用下面的命令(生产环境请谨慎):

yum install gdisk
sgdisk --zap-all /dev/sdd

2.4 LVM 需求

Ceph OSDs 在以下场景依赖 LVM。

  • If encryption is enabled (encryptedDevice: "true" in the cluster CR)
  • A metadata device is specified
  • osdsPerDevice is greater than 1

Ceph OSDs 在以下场景不需要 LVM。

  • OSDs are created on raw devices or partitions
  • Creating OSDs on PVCs using the storageClassDeviceSets

openEuler 默认已经安装 lvm2,如果没有装,使用下面的命令安装。

yum install -y lvm2

2.5 Kernel 需求

  • RBD 需求

Ceph 需要使用构建了 RBD 模块的 Linux 内核。许多 Linux 发行版都有这个模块,但不是所有发行版都有。例如,GKE Container-Optimised OS (COS) 就没有 RBD。

在 Kubernetes 节点使用 lsmod | grep rbd 命令验证,如果没有任何输出,请执行下面的命令加载 rbd 模块。

# 在当前环境加载 rbd 和 nbd 模块
modprobe rbd
modprobe nbd# 开机自动加载 rbd 和 nbd 模式(适用于 openEuler)
echo "rbd" >> /etc/modules-load.d/rook-ceph.conf
echo "nbd" >> /etc/modules-load.d/rook-ceph.conf# 再次执行命令验证
lsmod | grep rbd# 正确的输出结果如下
$ lsmod | grep rbd
rbd                   135168  0
libceph               413696  1 rbd
  • CephFS 需求

如果您将从 Ceph shared file system (CephFS) 创建卷,推荐的最低内核版本是 4.17。如果内核版本小于 4.17,则不会强制执行请求的 PVC sizes。存储配额只会在更新的内核上执行。

注意: openEuler 22.03 SP3 目前最新的内核为 5.10.0-218.0.0.121,虽然大于 4.17 但是有些过于高了,在安装 Ceph CSI Plugin 的时候可能会遇到 CSI 驱动无法注册的问题。

3. 扩容集群节点

3.1 扩容存储专用 Worker 节点

将新增的三台存储专用节点加入已有的 Kubernetes 集群,详细的扩容操作请参考 KubeKey 扩容 Kubernetes Worker 节点实战指南。

3.2 设置节点标签

按规划给三个存储节点和其它 Worker 节点打上专属标签。

  • 存储节点标签
# 设置 rook-ceph 部署和存储Osd 节点标签
kubectl label nodes ksp-storage-1 node.kubernetes.io/storage=rook
kubectl label nodes ksp-storage-2 node.kubernetes.io/storage=rook
kubectl label nodes ksp-storage-3 node.kubernetes.io/storage=rook
  • Worker 节点标签
# 安装 ceph csi plugin 节点
# kubectl label nodes ksp-control-1 node.rook.io/rook-csi=true
# kubectl label nodes ksp-control-2 node.rook.io/rook-csi=true
# kubectl label nodes ksp-control-3 node.rook.io/rook-csi=true
kubectl label nodes ksp-worker-1 node.rook.io/rook-csi=true
kubectl label nodes ksp-worker-2 node.rook.io/rook-csi=true
kubectl label nodes ksp-worker-3 node.rook.io/rook-csi=true
  • 控制(Control)节点

不做任何设置,Ceph 的服务组件和 CSI 插件都不会安装在控制节点。网上也有人建议把 Ceph 的管理组件部署在 K8s 的控制节点,我是不赞同的。个人建议把 Ceph 的所有组件独立部署

4. 安装配置 Rook Ceph Operator

4.1 下载部署代码

# git clone --single-branch --branch v1.14.9 https://github.com/rook/rook.git
cd /srv
wget https://github.com/rook/rook/archive/refs/tags/v1.14.9.tar.gz
tar xvf v1.14.9.tar.gz
cd rook-1.14.9/deploy/examples/

4.2 修改镜像地址

可选配置,当 DockerHub 访问受限时,可以将 Rook-Ceph 需要的镜像离线下载到本地仓库,部署时修改镜像地址。

# 取消镜像注释
sed -i '125,130s/^.*#/ /g' operator.yaml
sed -i '506,506s/^.*#/ /g' operator.yaml# 替换镜像地址前缀
sed -i 's#registry.k8s.io#registry.opsxlab.cn:8443/k8sio#g' operator.yaml
sed -i 's#quay.io#registry.opsxlab.cn:8443/quayio#g' operator.yaml
sed -i 's#rook/ceph:v1.14.9#registry.opsxlab.cn:8443/rook/ceph:v1.14.9#g' operator.yaml
sed -i '24,24s#quay.io#registry.opsxlab.cn:8443/quayio#g' cluster.yaml

注意:上面的镜像仓库是我内部离线仓库,参考我文档的读者不要直接照抄,一定要换成自己的镜像仓库。

4.3 修改自定义配置

修改配置文件 operator.yaml 实现以下需求:

  • rook-ceph 所有管理组件部署在指定标签节点
  • k8s 其他节点安装 Ceph CSI Plugin
CSI_PROVISIONER_NODE_AFFINITY: "node.kubernetes.io/storage=rook"
CSI_PLUGIN_NODE_AFFINITY: "node.rook.io/rook-csi=true,node.kubernetes.io/storage=rook"

4.4 部署 Rook Operator

  • 部署 Rook operator
kubectl create -f crds.yaml -f common.yaml -f operator.yaml
  • 验证 rook-ceph-operator Pod 的状态是否为 Running
kubectl -n rook-ceph get pod -o wide

执行成功后,输出结果如下:

$ kubectl -n rook-ceph get pod -o wide
NAME                                 READY   STATUS    RESTARTS   AGE   IP              NODE            NOMINATED NODE   READINESS GATES
rook-ceph-operator-9bd897ff8-426mq   1/1     Running   0          40s   10.233.77.255   ksp-storage-3   <none>           <none>

4.5 KubeSphere 控制台查看 Operator 资源

登录 KubeSphere 控制台查看创建的 Rook Ceph Operator Deployment 资源。

5. 创建 Ceph 集群

5.1 修改集群配置文件

  • 修改集群配置文件 cluster.yaml,增加节点亲和配置
placement:all:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: node.kubernetes.io/storageoperator: Invalues:- rook
  • 修改集群配置文件 cluster.yaml,增加存储节点和 OSD 磁盘配置
storage: # cluster level storage configuration and selectionuseAllNodes: false  # 生产环境,一定要修改,默认会使用所有节点useAllDevices: false # 生产环境,一定要修改,默认会使用所有磁盘#deviceFilter:config:storeType: bluestorenodes:- name: "ksp-storage-1"devices:- name: "sdd"- name: "ksp-storage-2"devices:- name: "sdd"- name: "ksp-storage-3"devices:- name: "sdd"

5.2 创建 Ceph 集群

  • 创建集群
kubectl create -f cluster.yaml
  • 查看资源状态,确保所有相关 Pod 均为 Running
$ kubectl -n rook-ceph get pod -o wide
NAME                                                      READY   STATUS      RESTARTS   AGE     IP             NODE            NOMINATED NODE   READINESS GATES
csi-cephfsplugin-5mrxf                                    2/2     Running     0          2m25s   192.168.9.96   ksp-worker-3    <none>           <none>
csi-cephfsplugin-5s4kz                                    2/2     Running     0          2m25s   192.168.9.95   ksp-worker-2    <none>           <none>
csi-cephfsplugin-kgd48                                    2/2     Running     0          2m25s   192.168.9.94   ksp-worker-1    <none>           <none>
csi-cephfsplugin-provisioner-7f595d6cc4-5xpm8             5/5     Running     0          2m25s   10.233.64.1    ksp-storage-1   <none>           <none>
csi-cephfsplugin-provisioner-7f595d6cc4-q7q4v             5/5     Running     0          2m25s   10.233.77.26   ksp-storage-3   <none>           <none>
csi-cephfsplugin-q7rqj                                    2/2     Running     0          2m25s   192.168.9.97   ksp-storage-1   <none>           <none>
csi-cephfsplugin-x6tfj                                    2/2     Running     0          2m25s   192.168.9.99   ksp-storage-3   <none>           <none>
csi-cephfsplugin-z72tl                                    2/2     Running     0          2m25s   192.168.9.98   ksp-storage-2   <none>           <none>
csi-rbdplugin-2f8db                                       2/2     Running     0          2m25s   192.168.9.97   ksp-storage-1   <none>           <none>
csi-rbdplugin-6dtwt                                       2/2     Running     0          2m25s   192.168.9.94   ksp-worker-1    <none>           <none>
csi-rbdplugin-82jrf                                       2/2     Running     0          2m25s   192.168.9.95   ksp-worker-2    <none>           <none>
csi-rbdplugin-dslkj                                       2/2     Running     0          2m25s   192.168.9.96   ksp-worker-3    <none>           <none>
csi-rbdplugin-gjmmw                                       2/2     Running     0          2m25s   192.168.9.98   ksp-storage-2   <none>           <none>
csi-rbdplugin-hfv4k                                       2/2     Running     0          2m25s   192.168.9.99   ksp-storage-3   <none>           <none>
csi-rbdplugin-provisioner-c845669bc-dp6q4                 5/5     Running     0          2m25s   10.233.64.4    ksp-storage-1   <none>           <none>
csi-rbdplugin-provisioner-c845669bc-f2s6n                 5/5     Running     0          2m25s   10.233.77.24   ksp-storage-3   <none>           <none>
rook-ceph-crashcollector-ksp-storage-1-7b4cf6c8fb-7s85r   1/1     Running     0          68s     10.233.64.7    ksp-storage-1   <none>           <none>
rook-ceph-crashcollector-ksp-storage-2-cc76b86dc-vb4gl    1/1     Running     0          53s     10.233.73.85   ksp-storage-2   <none>           <none>
rook-ceph-crashcollector-ksp-storage-3-67bf8cf566-6rcjg   1/1     Running     0          52s     10.233.77.39   ksp-storage-3   <none>           <none>
rook-ceph-exporter-ksp-storage-1-646fb48465-5mfcx         1/1     Running     0          68s     10.233.64.14   ksp-storage-1   <none>           <none>
rook-ceph-exporter-ksp-storage-2-79fd64549d-rbcnt         1/1     Running     0          50s     10.233.73.86   ksp-storage-2   <none>           <none>
rook-ceph-exporter-ksp-storage-3-7877646d8c-7h2wc         1/1     Running     0          48s     10.233.77.32   ksp-storage-3   <none>           <none>
rook-ceph-mgr-a-c89b4f8bd-psdwl                           3/3     Running     0          86s     10.233.73.80   ksp-storage-2   <none>           <none>
rook-ceph-mgr-b-7ffd8dcb85-jpj5x                          3/3     Running     0          86s     10.233.77.29   ksp-storage-3   <none>           <none>
rook-ceph-mon-a-654b4f677-fmqhx                           2/2     Running     0          2m15s   10.233.73.79   ksp-storage-2   <none>           <none>
rook-ceph-mon-b-74887d5b9c-4mb62                          2/2     Running     0          109s    10.233.77.28   ksp-storage-3   <none>           <none>
rook-ceph-mon-c-5fb5489c58-7hj6n                          2/2     Running     0          99s     10.233.64.16   ksp-storage-1   <none>           <none>
rook-ceph-operator-9bd897ff8-6z45z                        1/1     Running     0          29m     10.233.77.18   ksp-storage-3   <none>           <none>
rook-ceph-osd-0-65ccb887ff-bjtbs                          2/2     Running     0          54s     10.233.64.19   ksp-storage-1   <none>           <none>
rook-ceph-osd-1-c689d9f57-x6prx                           2/2     Running     0          53s     10.233.73.84   ksp-storage-2   <none>           <none>
rook-ceph-osd-2-776bb9cbd6-vmxxp                          2/2     Running     0          52s     10.233.77.37   ksp-storage-3   <none>           <none>
rook-ceph-osd-prepare-ksp-storage-1-tj6rk                 0/1     Completed   0          64s     10.233.64.18   ksp-storage-1   <none>           <none>
rook-ceph-osd-prepare-ksp-storage-2-rds4q                 0/1     Completed   0          63s     10.233.73.83   ksp-storage-2   <none>           <none>
rook-ceph-osd-prepare-ksp-storage-3-hpzgs                 0/1     Completed   0          63s     10.233.77.41   ksp-storage-3   <none>           <none>

5.3 KubeSphere 控制台查看 Ceph 集群资源

  • Deployment(部署,17个)

  • Daemonsets(守护进程集,2个)

6. 创建 Rook toolbox

通过 Rook 提供的 toolbox,我们可以实现对 Ceph 集群的管理。

6.1 创建 toolbox

  • 创建 toolbox
kubectl apply -f toolbox.yaml
  • 等待 toolbox pod 下载容器镜像,并进入 Running 状态:
kubectl -n rook-ceph rollout status deploy/rook-ceph-tools

6.2 常用命令

  • 登录 Toolbox
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash
  • 验证 Ceph 集群状态
$ kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash
bash-5.1$ ceph -scluster:id:     e7913148-d29f-46fa-87a6-1c38ddb1530ahealth: HEALTH_OKservices:mon: 3 daemons, quorum a,b,c (age 6m)mgr: a(active, since 5m), standbys: bosd: 3 osds: 3 up (since 5m), 3 in (since 5m)data:pools:   1 pools, 1 pgsobjects: 2 objects, 577 KiBusage:   81 MiB used, 300 GiB / 300 GiB availpgs:     1 active+clean

观察 Ceph 集群状态,需要满足下面的条件才会认为集群状态是健康的。

  • health 的值为 HEALTH_OK
  • Mons 的数量和状态
  • Mgr 一个 active,一个 standbys
  • OSD 3 个,状态都是 up
  • 其他常用的 Ceph 命令
# 查看 OSD 状态
ceph osd status
ceph osd df
ceph osd utilization
ceph osd pool stats
ceph osd tree# 查看 Ceph 容量
ceph df# 查看 Rados 状态
rados df# 查看 PG 状态
ceph pg stat
  • 删除 toolbox(可选)
kubectl -n rook-ceph delete deploy/rook-ceph-tools

7. Block Storage

7.1 Storage 介绍

Rock Ceph 提供了三种存储类型,请参考官方指南了解详情:

  • Block Storage(RBD): Create block storage to be consumed by a pod (RWO)
  • Filesystem Storage(CephFS): Create a filesystem to be shared across multiple pods (RWX)
  • Object Storage(RGW): Create an object store that is accessible inside or outside the Kubernetes cluster

本文使用比较稳定、可靠的 Block Storage(RBD)的方式作为 Kubernetes 的持久化存储。

7.2 创建存储池

Rook 允许通过自定义资源定义 (crd) 创建和自定义 Block 存储池。支持 Replicated 和 Erasure Coded 类型。本文演示 Replicated 的创建过程。

  • 创建一个 3 副本的 Ceph 块存储池,编辑 CephBlockPool CR 资源清单,vi ceph-replicapool.yaml
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:name: replicapoolnamespace: rook-ceph
spec:failureDomain: hostreplicated:size: 3
  • 创建 CephBlockPool 资源
kubectl create -f ceph-replicapool.yaml
  • 查看资源创建情况
$ kubectl get cephBlockPool -n rook-ceph -o wide
NAME          PHASE   TYPE         FAILUREDOMAIN   REPLICATION   EC-CODINGCHUNKS   EC-DATACHUNKS   AGE
replicapool   Ready   Replicated   host            3             0                 0               16s
  • 在 ceph toolbox 中查看 Ceph 集群状态
# 登录
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash# 查看集群
bash-5.1$ ceph -scluster:id:     e7913148-d29f-46fa-87a6-1c38ddb1530ahealth: HEALTH_OKservices:mon: 3 daemons, quorum a,b,c (age 10m)mgr: a(active, since 8m), standbys: bosd: 3 osds: 3 up (since 9m), 3 in (since 9m)data:pools:   2 pools, 2 pgsobjects: 3 objects, 577 KiBusage:   81 MiB used, 300 GiB / 300 GiB availpgs:     2 active+clean# 查看集群存储池 
bash-5.1$ ceph osd pool ls
.mgr
replicapoolbash-5.1$ rados df
POOL_NAME       USED  OBJECTS  CLONES  COPIES  MISSING_ON_PRIMARY  UNFOUND  DEGRADED  RD_OPS      RD  WR_OPS       WR  USED COMPR  UNDER COMPR
.mgr         1.7 MiB        2       0       6                   0        0         0     106  91 KiB     137  1.8 MiB         0 B          0 B
replicapool   12 KiB        1       0       3                   0        0         0       0     0 B       2    2 KiB         0 B          0 Btotal_objects    3
total_used       81 MiB
total_avail      300 GiB
total_space      300 GiB# 查看存储池的 pg number
bash-5.1$ ceph osd pool get replicapool pg_num
pg_num: 32

7.3 创建 StorageClass

  • 编辑 StorageClass 资源清单,vi storageclass-rook-ceph-block.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: rook-ceph-block
# Change "rook-ceph" provisioner prefix to match the operator namespace if needed
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:# clusterID is the namespace where the rook cluster is runningclusterID: rook-ceph# Ceph pool into which the RBD image shall be createdpool: replicapool# RBD image format. Defaults to "2".imageFormat: "2"# RBD image features. Available for imageFormat: "2". CSI RBD currently supports only `layering` feature.imageFeatures: layering# The secrets contain Ceph admin credentials.csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisionercsi.storage.k8s.io/provisioner-secret-namespace: rook-cephcsi.storage.k8s.io/controller-expand-secret-name: rook-csi-rbd-provisionercsi.storage.k8s.io/controller-expand-secret-namespace: rook-cephcsi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-nodecsi.storage.k8s.io/node-stage-secret-namespace: rook-ceph# Specify the filesystem type of the volume. If not specified, csi-provisioner# will set default as `ext4`. Note that `xfs` is not recommended due to potential deadlock# in hyperconverged settings where the volume is mounted on the same node as the osds.csi.storage.k8s.io/fstype: ext4# Delete the rbd volume when a PVC is deleted
reclaimPolicy: Delete# Optional, if you want to add dynamic resize for PVC.
# For now only ext3, ext4, xfs resize support provided, like in Kubernetes itself.
allowVolumeExpansion: true
  • 创建 StorageClass 资源
kubectl create -f storageclass-rook-ceph-block.yaml

注意: examples/csi/rbd 目录中有更多的参考用例。

  • 验证资源
$ kubectl get sc
NAME               PROVISIONER                                   RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
local              openebs.io/local                              Delete          WaitForFirstConsumer   false                  76d
nfs-sc (default)   k8s-sigs.io/nfs-subdir-external-provisioner   Delete          Immediate              false                  22d
rook-ceph-block    rook-ceph.rbd.csi.ceph.com                    Delete          Immediate              true                   11s

8. 创建测试应用

8.1 使用 Rook 提供的测试案例

我们使用 Rook 官方提供的经典的 Wordpress 和 MySQL 应用程序创建一个使用 Rook 提供块存储的示例应用程序,这两个应用程序都使用由 Rook 提供的块存储卷。

  • 创建 MySQL 和 Wordpress
kubectl create -f mysql.yaml
kubectl create -f wordpress.yaml
  • 查看 PVC 资源
$ kubectl get pvc
NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGE
mysql-pv-claim   Bound    pvc-938fc531-cff8-452b-b89a-0040ac0aaa02   20Gi       RWO            rook-ceph-block   31s
wp-pv-claim      Bound    pvc-d94118de-7105-4a05-a4e7-ebc5807cc5c1   20Gi       RWO            rook-ceph-block   13s
  • 查看 SVC 资源
$ kubectl get svc
NAME              TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)           AGE
kubernetes        ClusterIP      10.233.0.1      <none>        443/TCP           76d
wordpress         LoadBalancer   10.233.25.187   <pending>     80:31280/TCP      33s
wordpress-mysql   ClusterIP      None            <none>        3306/TCP          50s
  • 查看 Pod 资源
$ kubectl get pod -o wide
NAME                               READY   STATUS    RESTARTS   AGE    IP              NODE            NOMINATED NODE   READINESS GATES
wordpress-6678b8879f-ql6sm         1/1     Running   0          49s    10.233.73.89    ksp-storage-2   <none>           <none>
wordpress-mysql-5d69d6696b-fwttl   1/1     Running   0          67s    10.233.64.15    ksp-storage-1   <none>           <none>

8.2 指定节点创建测试应用

Wordpress 和 MySQL 测试用例中,pod 创建在了存储专用节点。为了测试集群中其它 Worker 节点是否可以使用 Ceph 存储,我们再做一个测试,在创建 Pod 时指定 nodeSelector 标签,将 Pod 创建在非 rook-ceph 专用节点的 ksp-worker-1 上。

  • 编写测试 PVC 资源清单,vi test-pvc-rbd.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: test-pvc-rbd
spec:storageClassName: rook-ceph-blockaccessModes:- ReadWriteOnceresources:requests:storage: 2Gi
  • 创建 PVC
kubectl apply -f test-pvc-rbd.yaml
  • 查看 PVC
$ kubectl get pvc -o wide
NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGE   VOLUMEMODE
mysql-pv-claim   Bound    pvc-00c09bac-cee2-4a0e-9549-56f05b9c6965   20Gi       RWO            rook-ceph-block   77s   Filesystem
test-pvc-rbd     Bound    pvc-ad475b29-6730-4c9a-8f8d-a0cd99b12781   2Gi        RWO            rook-ceph-block   5s    Filesystem
wp-pv-claim      Bound    pvc-b3b2d6bc-6d62-4ac3-a50c-5dcf076d501c   20Gi       RWO            rook-ceph-block   76s   Filesystem
  • 编写测试 Pod 资源清单,vi test-pod-rbd.yaml
kind: Pod
apiVersion: v1
metadata:name: test-pod-rbd
spec:containers:- name: test-pod-rbdimage: busybox:stablecommand:- "/bin/sh"args:- "-c"- "touch /mnt/SUCCESS && sleep 3600"volumeMounts:- name: rbd-pvcmountPath: "/mnt"restartPolicy: "Never"nodeSelector:kubernetes.io/hostname: ksp-worker-1volumes:- name: rbd-pvcpersistentVolumeClaim:claimName: test-pvc-rbd
  • 创建 Pod
kubectl apply -f test-pod-rbd.yaml
  • 查看 Pod( Pod 按预期创建在了 ksp-worker-1 节点,并正确运行
$ kubectl get pods -o wide
NAME                               READY   STATUS    RESTARTS   AGE   IP              NODE            NOMINATED NODE   READINESS GATES
test-pod-rbd                       1/1     Running   0          5s    10.233.94.210   ksp-worker-1    <none>           <none>
wordpress-6678b8879f-ql6sm         1/1     Running   0          10m   10.233.73.89    ksp-storage-2   <none>           <none>
wordpress-mysql-5d69d6696b-fwttl   1/1     Running   0          10m   10.233.64.15    ksp-storage-1   <none>           <none>
  • 查看 Pod 挂载的存储
$ kubectl exec test-pod-rbd -- df -h
Filesystem                Size      Used Available Use% Mounted on
overlay                  99.9G     14.0G     85.9G  14% /
tmpfs                    64.0M         0     64.0M   0% /dev
tmpfs                     7.6G         0      7.6G   0% /sys/fs/cgroup
/dev/rbd0                 1.9G     24.0K      1.9G   0% /mnt
/dev/mapper/openeuler-root34.2G      2.3G     30.1G   7% /etc/hosts
/dev/mapper/openeuler-root34.2G      2.3G     30.1G   7% /dev/termination-log
/dev/mapper/data-lvdata99.9G     14.0G     85.9G  14% /etc/hostname
/dev/mapper/data-lvdata99.9G     14.0G     85.9G  14% /etc/resolv.conf
shm                      64.0M         0     64.0M   0% /dev/shm
tmpfs                    13.9G     12.0K     13.9G   0% /var/run/secrets/kubernetes.io/serviceaccount
tmpfs                     7.6G         0      7.6G   0% /proc/acpi
tmpfs                    64.0M         0     64.0M   0% /proc/kcore
tmpfs                    64.0M         0     64.0M   0% /proc/keys
tmpfs                    64.0M         0     64.0M   0% /proc/timer_list
tmpfs                    64.0M         0     64.0M   0% /proc/sched_debug
tmpfs                     7.6G         0      7.6G   0% /proc/scsi
tmpfs                     7.6G         0      7.6G   0% /sys/firmware
  • 测试存储空间读写
# 写入 1GB 的数据
$ kubectl exec test-pod-rbd -- dd if=/dev/zero of=/mnt/test-disk.img bs=1M count=1000
1000+0 records in
1000+0 records out
1048576000 bytes (1000.0MB) copied, 4.710019 seconds, 212.3MB/s# 查看结果
$ kubectl exec test-pod-rbd -- ls -lh /mnt/
total 1000M
-rw-r--r--    1 root     root           0 Aug  5 20:11 SUCCESS
drwx------    2 root     root       16.0K Aug  5 20:11 lost+found
-rw-r--r--    1 root     root     1000.0M Aug  5 20:14 test-disk.img# 测试超限(再写入 1GB 数据,只能写入 929.8MB)
$ kubectl exec test-pod-rbd -- dd if=/dev/zero of=/mnt/test-disk2.img bs=1M count=1000
dd: error writing '/mnt/test-disk2.img': No space left on device
930+0 records in
929+0 records out
974987264 bytes (929.8MB) copied, 3.265758 seconds, 284.7MB/s
command terminated with exit code 1# 再次查看结果
$ kubectl exec test-pod-rbd -- ls -lh /mnt/
total 2G
-rw-r--r--    1 root     root           0 Aug  5 20:11 SUCCESS
drwx------    2 root     root       16.0K Aug  5 20:11 lost+found
-rw-r--r--    1 root     root     1000.0M Aug  5 20:14 test-disk.img
-rw-r--r--    1 root     root      929.8M Aug  5 20:18 test-disk2.img

注意: 测试时,我们写入了 2G 的数据量,当达过我们创建的 PVC 2G 容量上限时会报错(实际使用写不满 2G)。说明,Ceph 存储可以做到容量配额限制

9. Ceph Dashboard

Ceph 提供了一个 Dashboard 工具,我们可以在上面查看集群的状态,包括集群整体运行状态、Mgr、Mon、OSD 和其他 Ceph 进程的状态,查看存储池和 PG 状态,以及显示守护进程的日志等。

部署集群的配置文件 cluster.yaml ,默认已经开启了 Dashboard 功能,Rook Ceph operator 部署集群时将启用 ceph-mgr 的 Dashboard 模块。

9.1 获取 Dashboard 的 service 地址

$ kubectl -n rook-ceph get service
NAME                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
rook-ceph-exporter        ClusterIP   10.233.4.126    <none>        9926/TCP            46m
rook-ceph-mgr             ClusterIP   10.233.49.41    <none>        9283/TCP            46m
rook-ceph-mgr-dashboard   ClusterIP   10.233.7.182    <none>        8443/TCP            46m
rook-ceph-mon-a           ClusterIP   10.233.45.222   <none>        6789/TCP,3300/TCP   47m
rook-ceph-mon-b           ClusterIP   10.233.52.144   <none>        6789/TCP,3300/TCP   47m
rook-ceph-mon-c           ClusterIP   10.233.57.144   <none>        6789/TCP,3300/TCP   47m

9.2 配置在集群外部访问 Dashboard

通常我们需要在 K8s 集群外部访问 Ceph Dashboard,可以通过 NodePort 或是 Ingress 的方式。

本文演示 NodePort 方式。

  • 创建资源清单文件, vi ceph-dashboard-external-https.yaml
apiVersion: v1
kind: Service
metadata:name: rook-ceph-mgr-dashboard-external-httpsnamespace: rook-cephlabels:app: rook-ceph-mgrrook_cluster: rook-ceph
spec:ports:- name: dashboardport: 8443protocol: TCPtargetPort: 8443nodePort: 31443selector:app: rook-ceph-mgrmgr_role: activerook_cluster: rook-cephtype: NodePort
  • 创建资源
kubectl create -f ceph-dashboard-external-https.yaml
  • 验证创建的资源
$ kubectl -n rook-ceph get service rook-ceph-mgr-dashboard-external-https
NAME                                     TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
rook-ceph-mgr-dashboard-external-https   NodePort   10.233.5.136   <none>        8443:31443/TCP   5s

9.3 获取 Login Credentials

登陆 Dashboard 时需要身份验证,Rook 创建了一个默认用户,用户名 admin。创建了一个名为 rook-ceph-dashboard-password 的 secret 存储密码,使用下面的命令获取随机生成的密码。

$ kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}" | base64 --decode && echo
6W6#Y3PvI~=CVq0f'@Yo

9.4 通过浏览器打开 Dashboard

访问 K8s 集群中任意节点的 IP,https://192.168.9.91:31443,默认用户名 admin,密码通过上面的命令获取。

9.5 Ceph Dashboard 概览

Ceph Dashboard 虽然界面简单,但是常用的管理功能都具备,能实现图形化管理存储资源。下面展示几张截图,作为本文的结尾。

  • Dashboard

  • 集群-主机

  • 集群-OSD

  • 存储池

免责声明:

  • 笔者水平有限,尽管经过多次验证和检查,尽力确保内容的准确性,但仍可能存在疏漏之处。敬请业界专家大佬不吝指教。
  • 本文所述内容仅通过实战环境验证测试,读者可学习、借鉴,但严禁直接用于生产环境由此引发的任何问题,作者概不负责

    本文由博客一文多发平台 OpenWrite 发布!

相关文章:

探索 Kubernetes 持久化存储之 Rook Ceph 初窥门径

在 Kubernetes 生态系统中&#xff0c;持久化存储是支撑业务应用稳定运行的基石&#xff0c;对于维护整个系统的健壮性至关重要。对于选择自主搭建 Kubernetes 集群的运维架构师来说&#xff0c;挑选合适的后端持久化存储解决方案是关键的选型决策。目前&#xff0c;Ceph、Glus…...

今日(2024 年 8 月 13 日)科技新闻

我国成功发射卫星互联网高轨卫星&#xff1a;该卫星的成功发射将助力我国卫星互联网的发展。中国首台中子全散射谱仪运行 3 年成果丰硕&#xff1a;由粤港科技合作打造的多物理谱仪&#xff0c;在中国散裂中子源上运行 3 年来&#xff0c;已完成 300 多项用户实验。该谱仪的关键…...

Unity大场景切换进行异步加载时,如何设计加载进度条,并配置滑动条按照的曲线给定的速率滑动

一、异步加载场景的过程 1、异步加载场景用到的API LoadSceneAsync 2、异步加载的参数说明 &#xff08;1&#xff09;默认参数&#xff1a;SceneManagement.LoadSceneAsync(“SceneName”); AsyncOperation task SceneManager.LoadSceneAsync("SceneName");&a…...

Selenium + Python 自动化测试16(Python基础复习)

我们的目标是&#xff1a;按照这一套资料学习下来&#xff0c;大家可以独立完成自动化测试的任务。 上一篇我们讨论了使用模块化测试的测试模型&#xff0c;从某一程度也反映出熟练掌握一门编程语言的重要性。 为了后续进一步深入学习。本篇文章主要做下Python基础知识的复习。…...

2024新型数字政府综合解决方案(六)

新型数字政府综合解决方案通过融合人工智能、大数据、区块链和云计算技术&#xff0c;构建了一个全方位智能化的政务平台&#xff0c;旨在提升政府服务的效率、透明度和公众参与度。该方案实现了跨部门的数据互联互通与实时更新&#xff0c;利用先进的数据分析和自动化处理技术…...

vscode的C/C++环境配置和调试技巧

目录 1.背景 2.下载编译器 3.配置环境变量 4.安装C/C插件 5.写C语言代码并且编译成功 5.1文件操作 5.2对于两个窗口的解释 5.3C语言编译环境配置 6.创建执行文件 7.编译运行过程 8.写其他的代码的解决方案一 9.写其他的代码的解决方案二 10.同时编译多个.c文件 10…...

Python制作《扫雷》游戏-附源码,轻松看懂,简单易学

今天介绍另一款经典小游戏&#xff0c;扫雷&#xff0c;这个应该是很多人windows电脑里玩的最多的游戏了&#xff0c;乐趣很多&#xff0c;而且还有一定的技术含量在里面&#xff0c;今天我们就来通过python实现这个小游戏。 创建扫雷文件 打开pycharm&#xff0c;创建一个名…...

8路VBO转HDMI2.0支持4K60频率ITE6265芯片方案心得分享

在此之前&#xff0c;有人找到我这边询问能不能将智能电视主板改成机顶盒&#xff0c;将VBO信号转换输出位HDMI进行投屏&#xff0c;具体应用奇奇怪怪&#xff01;但是奈何是甲方大佬。认命照做。从网上也有搜索了解过这类芯片&#xff0c;发现资料很少&#xff0c;所以有了这篇…...

【问题解决3】【已解决】Cannot determine path to‘tools.jar‘libraryfor17

前几天在IDEA运行JAVA项目时&#xff0c;出现这个报错。 这是因为是这个笔记本上安装的IDEA版本是“IntelliJ IDEA 2020.3.1”&#xff0c;与JDK17版本不兼容&#xff0c;这种情况下要想使得IDEA版本与JDK版本兼容&#xff0c;就需要升级IDEA版本或者使用JDK较低版本&#xff…...

基于Spring Boot的高效宠物购物平台

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…...

【Vue3】路由基础

【Vue3】路由基础 背景简介开发环境开发步骤及源码总结 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗的日子。本…...

掌握网络数据的钥匙:Python Requests-HTML库深度解析

文章目录 掌握网络数据的钥匙&#xff1a;Python Requests-HTML库深度解析背景&#xff1a;为何选择Requests-HTML&#xff1f;什么是Requests-HTML&#xff1f;如何安装Requests-HTML&#xff1f;5个简单库函数的使用方法3个场景下库的使用示例常见Bug及解决方案总结 掌握网络…...

网络安全: 模型的脆弱性,鲁棒性和隐私性

在网络安全领域&#xff0c;通常描述模型安全性时&#xff0c;会提到以下三个特性&#xff1a; 脆弱性&#xff08;Vulnerability&#xff09;&#xff1a;指模型在某些情况下容易受到攻击或被利用的弱点。例如&#xff0c;模型可能对对抗性攻击或梯度泄露攻击敏感。 鲁棒性&a…...

【go语言】go-webview2用法(持续更新)

文章目录 背景核心接口和方法扩展接口遗憾的是 背景 目前为止&#xff0c;已经有很多优秀的electron应用。但其特点也很明显&#xff1a;使用htmlcssjs构建的布局很精致&#xff0c;但是体积不容小觑&#xff08;最新版electron-egg打包出来的程序已经300MB&#xff09;。 vs…...

KNN 图像识别

KNN&#xff08;K-Nearest Neighbors&#xff0c;K最近邻&#xff09;算法是一种简单而有效的分类算法&#xff0c;也可以用于图像识别。它的基本思想是通过计算样本之间的距离&#xff0c;将待分类的样本归为其在训练集中最相近的K个样本所属的类别中最常见的类别 1. 准备工作…...

基于STM32和云平台的花卉养护系统设计(微信小程序)(209)

文章目录 一、前言1.1 项目介绍【1】项目功能介绍【2】设计实现的功能【3】项目硬件模块组成1.2 设计思路【1】整体设计思路【2】ESP8266工作模式配置1.3 项目开发背景【1】选题的意义【2】可行性分析【3】参考文献【4】摘要【5】选题背景【6】国内外技术发展现状1.4 开发工具的…...

编程语言进化史

编程语言多到你想象不到。 图片来自: 程序设计语言概念 发展历史 自从1946年冯诺依曼原理被提出&#xff0c;计算机数据和指令是通过二进制形式以及后来的汇编语言(二进制助记符)&#xff0c;但依然没有改变容易出错的本质。1951年Rutishauser提出的用编译程序实现高级语言的思…...

vuex的原理和使用方法

简介 Vuex 是 Vue.js 应用的状态管理模式&#xff0c;它为应用内的所有组件提供集中式的状态&#xff08;数据&#xff09;管理。可以帮我们管理 Vue 通用的数据 (多组件共享的数据)。 Vuex的构成 state&#xff1a;state 是 Vuex 的数据中心&#xff0c;也就是说state是用来…...

(javaweb)SpringBootWeb案例(毕业设计)案例--文件上传

1.简介 前端程序和服务端程序 对于前端 html文件放在static目录下 location---文件提交的位置 右键--copy value -------------c盘目录下 2.本地上传--文件存储 1. 2. 使用uuid&#xff1a;保证文件名是唯一的 此时 并没有文件的拓展名--所以需要---写后缀 用字符串截取 此时图…...

数据库之存储过程和函数

目录 一、存储过程和函数概述 二、创建并调用存储过程和函数 1.创建存储过程 2.创建存储函数 3.调用存储过程和函数 三、关于存储过程和函数的表达式 1.变量 1.变量的分类 2.在存储过程和函数中应用变量 2.定义条件和处理程序 1.定义条件 2.定义处理程序 3.游标的…...

《SPSS零基础入门教程》学习笔记——02.数据管理

文章目录 2.1 连续变量的离散化2.2 自动重编码、编秩与数值计数2.3 几个常用过程2.4 多个数据文件的操作2.5 数据字典2.6 数据核查&#xff08;1&#xff09;数据验证模块&#xff08;2&#xff09;数据检验 2.7 数据准备 计算新变量&#xff08;转换 -> 计算变量&#xff0…...

嵌入式软件的一些常用调试测试方法

嵌入式软件的仿真调试测试是确保软件质量和功能正确性的关键步骤。以下是几种常见的仿真调试测试方式&#xff1a; 1.集成开发环境&#xff08;IDE&#xff09;调试&#xff1a; 使用IDE&#xff08;如IAR EWARM、Keil MDK、Eclipse等&#xff09;内置的调试器进行断点设置、单…...

Android T about screen rotation(二)

需求:客户因为模具问题,屏幕方向需要动态的变动.(方向: 0 , 90 , 180 ,270) 拆分:设备开机过程中图像显示可分为三个阶段,boot logo(1)->kernel logo(2),这一段的处理需要驱动层,所以暂时忽略. 开机动画 Bootanimation(3)阶段 和 Home Launcher应用显示(4)阶段是需要修改的…...

qt反射之类反射、方法反射、字段反射

话不多说&#xff0c;直接上代码&#xff1a; main.cpp: #include < QCoreApplication > #include “fstudent.h” #include “manage.h” int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); //注册类型 qRegisterMetaType(“FStudent”); Manage m…...

服务器数据恢复—raid5阵列离线硬盘强制上线失败如何恢复数据?

服务器数据恢复环境&#xff1a; 某品牌2850服务器上有一组由6块SCSI硬盘组建的raid5磁盘阵列&#xff0c;上层操作系统为Redhat linuxext3文件系统。 服务器故障&初检&#xff1a; 服务器在运行过程中突然瘫痪&#xff0c;管理员对服务器中的raid进行检查后发现有两块硬盘…...

FastAPI+Vue3零基础开发ERP系统项目实战课 20240815上课笔记 列表和字典相关方法的学习和练习

昨日回顾 1、大小写转换2、去除空格3、判断是否为数字4、前缀后缀 昨日练习题进度 练习&#xff1a;判断验证码是否正确 1、生成一个由四个字符组成的验证码字符串&#xff0c;要求有大写有小写&#xff0c;要求左右两边有空格2、打印到控制台3、让用户输入这个验证码&…...

基于微信小程序的诗词智能学习系统的设计与实现(全网独一无二,24年最新定做)

文章目录 前言&#xff1a; 博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为…...

httplib库:用C++11搭建轻量级HTTP服务器

目录 引言 一. httplib库概述 二. httplib核心组件 2.1 数据结构 2.2 类和函数 2.3 服务器搭建 ​编辑 结语 引言 在现代软件开发中&#xff0c;HTTP服务是网络应用的基础。对于需要快速搭建HTTP服务器或客户端的场景&#xff0c;使用成熟的第三方库可以极大提高开发效…...

基于嵌入式C++、SQLite、MQTT、Modbus和Web技术的工业物联网网关:从边缘计算到云端集成的全栈解决方案设计与实现

一、项目概述 1.1 项目目标与用途 随着工业4.0时代的到来&#xff0c;传统工业设备与现代信息技术的结合越来越紧密。物联网工业网关作为连接工业设备与云端平台的桥梁&#xff0c;在工业自动化、设备监控、远程运维等方面发挥着至关重要的作用。本项目旨在设计并实现一个能够…...

Chapter 38 设计模式

欢迎大家订阅【Python从入门到精通】专栏&#xff0c;一起探索Python的无限可能&#xff01; 文章目录 前言一、单例模式二、工厂模式 前言 在软件开发中&#xff0c;设计模式提供了一种可重用的解决方案&#xff0c;以应对在特定环境中反复出现的问题。这些模式是基于经验总结…...