GlusterFS 深度洞察:从架构原理到案例实践的全面解读(上)
文章目录
- 一.GlusterFS简介
- 二.GlusterFS原理架构
- 三.适用场景
- 四.Glusterfs与其他存储产品对比
- 五.部署GlusterFS集群
- 六. 使用heketi将glusterfs接入k8s作为后端存储
一.GlusterFS简介
GlusterFS是一个免费的开源分布式文件系统,具有无中心节点、堆栈式设计、全局统一命名空间、高可用、高性能和横向扩展等特点,在业界被广泛使用。
GlusterFS是一种全对称的开源分布式文件系统,所谓全对称是指GlusterFS采用弹性哈希算法,没有中心节点,所有节点平等。GlusterFS配置方便,稳定性好,可轻松扩展至PB级数量,数千个节点。
优势:
- 容量扩展至数PB
- 处理上千并发
- POSIX兼容
- 使用廉价硬件,几乎可以在所有硬件设备运行
- 可使用NFS和SMB等行业标准协议访问
- 提供复制、配额、异地复制、快照和比特检测
- 允许针对不同的工作负载进行优化
专业术语
名称 | 解释 |
---|---|
Brick | 最基本的存储单元,表示为trusted storage pool中输出的目录,供客户挂载使用 |
Volume | 一个卷。在逻辑上由N个bricks组成 |
Glusterd | 管理进程,要在trusted storage pool中所有服务器中运行 |
FUSE | 一个可加载的内核模块,和内核VFS交互进行文件系统的操作 |
POSIX | 一个标准,全名是可移植操作系统接口,GlusterFS兼容 |
Translators | 转换器,GlusterFS的功能都是通过转换器实现的,例如处理请求,加密解密,锁,异地复制等等,详细介绍https://docs.gluster.org/en/latest/Quick-Start-Guide/Architecture/ |
二.GlusterFS原理架构
如下图,管理守护进程(glusterd)运行在每一台服务器上,并管理服务器上的一个brick进程(glusterfsd),该进程又管理底层文件系统(xfs,ext4…)。客户端进程挂载卷(Volume)到本地,并将所有的Brick作为统一存储公开给应用程序。客户端(Clients)和brick进程加载了各种转换器(Translators)。来自应用程序的I/O通过这些转换器路由到不同的brick进行文件访问。
当客户端访问GlusterFS存储时,首先程序通过访问挂载点的形式读写数据,对于用户和程序而言,集群文件系统是透明的,用户和程序根本感觉不到文件系统是本地还是在远程服务器上。读写操作将会被交给VFS(Virtual File System)来处理,VFS会将请求交给FUSE内核模块,而FUSE又会通过设备/dev/fuse将数据交给GlusterFS Client。最后经过GlusterFS Client的计算,并最终经过网络将请求或数据发送到GlusterFS Server上。
GlusterFS采用独特的无中心对称式架构,没有元数据的存储,在文件定位问题上,GlusterFS中DHT模块目前使用一致性哈希算法(Davies-Meyer)计算文件名hash值,并将文件存储到其中一个DHT子卷,而目录是GlusterFS中哈希分布(layout)的基本单位,会在所有DHT子卷的目录都会分配一个哈希子空间,即32位哈希空间(十六进制表示为0x00000000~0xffffffff
)中的一段哈希范围,例如,0x00000000~0x55555554
。
根据以上介绍,可以概括GlusterFS中文件访问的一般流程如下:
- 首先,DHT根据文件名称计算出一个哈希值(假设图1中file1哈希值为0x23333333);
- 其次,根据该哈希值找到其所在的目录哈希子空间(即0x00000000~0x55555554),也就是找到了对应的DHT子卷(即subvolume1);
- 最后,访问对应的DHT子卷(即subvolume1)
GlusterFS目前使用Davies-Meyer算法计算文件名hash值,获得一个32位整数。Davies-Meyer算法具有非常好的hash分布性,计算效率很高,假设逻辑卷中的存储单元Brick有N个,则32位整数空间被平均划分为N个连续子空间,每个空间分别映射到一个存储单元Brick,计算得到的32位hash值就会被投射到一个存储单元Brick。
GlusterFS的哈希分布是以目录为基本单位的,文件的父目录利用扩展属性记录了子卷映射信息,其下面子文件目录在父目录所属存储单元中进行分布。由于文件目录事先保存了分布信息,因此新增节点不会影响现有文件存储分布,它将从此后的新创建目录开始参与存储分布调度。这种设计,新增节点不需要移动任何文件,但是负载均衡没有平滑处理,老节点负载较重。GlusterFS在设计中考虑了这一问题,在新建文件时会优先考虑容量负载最轻的节点,在目标存储节点上创建文件链接直向真正存储文件的节点。另外,GlusterFS弹性卷管理工具可以在后台以人工方式来执行负载平滑,将进行文件移动和重新分布,此后所有存储服务器都会均会被调度。
文件快速Hash映射
现在我们将test-file1、test-file2、test-file3、test-file4四个文件通过快速Hash函数计算出对应的key值(2^32范围的数值),然后散列到服务器的brick上。这里需要注意的是两点,GlusterFS里面在处理文件名时候会忽略扩展名,如file.txt,file.pdf。在计算过程其实都是file;GlusterFS是可以忽略分布式算法指定文件落到客户指定的节点上,基本格式是file@client_brick,这样指定了file落到client_brick节点上。在没有特殊处理情况下Hash过程。
处理节点分布不均衡
根据分层目录划分区间,虽然极大的使文件平衡的分布到各个节点上,但是在各种应用场景下,文件名很多是类似而且是在一层目录下,Hash算法是概率性。出现一个brick容量满而其他brick节点还剩余大量空间容量的情况,目前算法还是无法百分百避免。
GlusterFS在处理出现节点分布不均衡利用链接技术,假设一个大文件定位了某个brick,而这个brick剩余磁盘容量小于文件大小,这时候文件会在落点区间创建一个T文件(链接文件),然后在其他节点真实得创建文件,写入文件。磁盘在超过90%容量时候,性能会出现断崖式的下跌,所以在GlusterFS会设置一个阈值,当节点容量超过这个阈值,文件会使用链接方式存储文件。File文件在读写时候,会首先定位到/sda/brcik0上,根据文件属性发现是一个T文件,客户端根据返回的扩展属性获取真实文件所在brick节点/sdb/brick1,客户端则会在真实得brick节点上读写。
文件查找流程
Xlator是GlusterFS中使用实现每一个功能层的结构体,在网络连接层,xlator结构体包含了服务端brick的ip以及挂载目录,这里把xlator简单的成代表指向一个服务器的brick。从上一小节知道layout包含了集群里面的所以指向服务器的brick。在集群当中一个layout保存了完整的分布区间而一个xlator保存了一个区间,比如一个集群有5个brick节点,这时候分成了5个区间,一个xlator指向一个区间,在GlusterFS里面一个区间可以称作一个hash卷,一个服务端brick为一个子卷。一个layout包含了整个区间。
根据上面的的知识,现在看看GlusterFS是如何查找一个文件的。这个在代码对应的是lookup函数。
文件查找过程:
- 根据文件目录名获取其hash卷;
- 若不是第一次查询且是目录,则向所有子卷下发lookup操作,比对与inode中的信息是否一致,若不一致则更新。
- 若不是第一次查询但不是目录,则向cached下发lookup操作,若不存在,则需调用dht_lookup_everywhere.,找到后为其创建DHTLINKFILE。
- 若是第一次查询且是目录,则会向其hashed卷下发lookup操作,然后再向其它子卷下发lookup操作,合并后返回。
- 若是第一次查询但不是目录,则会向其hashed卷下发lookup操作,若返回的是DHT_LINKFILE,则还有向其cached卷下发lookup操作,将其属性返回。
从上面具体去分析,首先分析根节点文件的查找,可以知道GlusterFS有对hash节点做缓存的,在先前查找之后会有缓存一个hash卷,下次访问时候就会根据inode的ctx获取从而缩短了时间。但是缓存是有时间限制,现在我们分析一下GlusterFS列目录(即ls)动作为什么会这么慢。假设操作都是第一次查找而且文件处于几层目录下面,在查询目录需要检测集群中每一个目录,而且这些动作是一个一个目录去查询的,也就是需要跟整个集群的机器去通信。当出现缓存不一致时候或者目录损坏(被删除,或者扩展属性不一致),这时候还会先修复目录,在访问该目录下文件的时候,还需要把所有的机器的全部文件查找一遍。在GlusterFS挂载点上做一次ls,这个时候基本会调用lookup,stat,getxattr,opendir等函数,这些每调用一次这个函数都需要进行一次通信而且在需要访问整个集群上面得机器。这样就会导致ls出现过于慢的情况。
根据ls去分析简单分析小文件读写为什么这么慢的原因。我们假设一次需要写入一万个64Kb的小文件,集群规模为10台60个brick节点,那么一万个文件就会散落到整个集群的60个brcik节点上面。GusterFS对一个文件读写的基本操作是lookup->stat->open->read/write,假设集群整体状态是正常的,文件目录都是健康的情况下,分布区间都是正确的,目录是三层目录。这一万文件在读写时候,首先需要把集群的两层目录整体都遍历一遍,也就说需要依次对60个节点上的目录进行访问,检测状态时候正常。当这些工作执行结束之后开始对每个文件进行读写,而一个读写过程需要多个操作,也就是多次的网络通信。但是读写过程其实只是进行了一次的通信。也就是说基本一次的读写,需要去多次的网络通信。这样当大量的小文件就会出现比大量的lookup->stat->open->read/write操作从而进行了很多次网络通信而正真意义上的read/write只是占了一小部分。这里需要介绍GlusterFS一个针对小文件设置的参数performance.quick-read,这个参数开启之后会在一次lookup时候会把小于64Kb的小文件读出来即合并lookup->stat->open->read/write多个操作为一个lookup操作。
提到glusterfs就不得不说存储卷(Volume)的类型,Glusterfs根据需求支持不同类型的卷。一些卷有利于扩展存储大小,一些有利于提高性能,有一些两者兼而有之。
1.分布式卷
如果没有指定卷类型,这是默认创建的卷类型。在这里,文件分布在卷中的各个块中。所以File1可能存储在brick1或者brick2中,但不能同时存储在两者中。因此没有数据冗余。这种存储卷的目的是轻松且廉价地扩展卷大小。然而,这也意味着brick故障将导致数据完全丢失,必须依靠底层硬件来保护数据丢失。类似于Raid0
分布式卷也可看成哈希卷,多个文件以文件为单位在多个brick上,使用哈希算法随机存储
创建分布式卷
gluster volume create NEW-VOLNAME [transport [tcp | rdma | tcp,rdma]] NEW-BRICK...
例如,创建具有四个存储服务器的分布式卷。
# gluster volume create test-volume server1:/exp1 server2:/exp2 server3:/exp3 server4:/exp4
volume create: test-volume: success: please start the volume to access data
显示volume信息
# gluster volume info
Volume Name: test-volume
Type: Distribute
Status: Created
Number of Bricks: 4
Transport-type: tcp
Bricks:
Brick1: server1:/exp1
Brick2: server2:/exp2
Brick3: server3:/exp3
Brick4: server4:/exp4
2.复制卷
在本卷中,我们克服了分布式卷中存在的数据丢失风险。数据通过定义多个副本保证高可用性。卷的副本数量可以在创建卷时指定。实现了更好的可靠性和数据冗余。类似于Raid 1
创建复制卷
gluster volume create NEW-VOLNAME [replica COUNT] [transport [tcp |rdma | tcp,rdma]] NEW-BRICK...
例如,要创建具有三个存储服务器的复制卷:
# gluster volume create test-volume replica 3 transport tcp \server1:/exp1 server2:/exp2 server3:/exp3
volume create: test-volume: success: please start the volume to access data
3.分布式复制卷
在此卷中,文件分布在复制的brick中,brick数量必须是副本数的倍数。此外,我们指定brick的顺序也很重要,因为相邻的brick会相互复制。当由于冗余和扩展数据需要数据的高可用时,适合使用这种类型的卷。因此,如果有8个brick且副本数为2,那么前两个brick将成为彼此的副本,然后是接下来的两个brick。类似地,如果有8个brick且副本数为4,则4个brick成为彼此的副本。类似于Raid 10
创建分布式复制卷:
gluster volume create NEW-VOLNAME [replica COUNT] [transport [tcp | rdma | tcp,rdma]] NEW-BRICK…
例如,创建3副本数且6节点的分布式复制卷
# gluster volume create test-volume replica 3 transport tcp server1:/exp1 server2:/exp2 server3:/exp3 server4:/exp4 server5:/exp5 server6:/exp6
volume create: test-volume: success: please start the volume to access data
4.条带卷
分散的卷基于纠删码,它将文件的数据条带化,并在卷中的多个brick中添加一些冗余。您可以使用条带卷获得一定的可靠性级别,同时最大限度减少空间浪费。卷中冗余brick的数量可以在创建卷中指定。冗余brick决定了在不中断卷操作的情况下可以丢失多少brick。默认条带大小128k。类似于Raid 5
创建条带卷
# gluster volume create test-volume [disperse [<COUNT>]] [disperse-data <COUNT>] [redundancy <COUNT>] [transport tcp | rdma | tcp,rdma] <NEW-BRICK>
例如,创建,冗余级别为1的三节点条带卷(2+1)
# gluster volume create test-volume disperse 3 redundancy 1 server1:/exp1 server2:/exp2 server3:/exp3
volume create: test-volume: success: please start the volume to access data
5.分布式条带卷
分布式条带卷类似于分布式复制卷,只不过数据冗余依靠的不是数据副本,而是数据条带化
Brick的数量必须是第一个子卷的倍数。
创建分布式条带卷
# gluster volume create [disperse [<COUNT>]] [disperse-data <COUNT>] [redundancy <COUNT>] [transport tcp | rdma | tcp,rdma] <NEW-BRICK>
例如,冗余级别为1,2x(2+1)=6的六节点分布式条带卷
# gluster volume create test-volume disperse 3 redundancy 1 server1:/exp1 server2:/exp2 server3:/exp3 server4:/exp4 server5:/exp5 server6:/exp6
volume create: test-volume: success: please start the volume to access data
GlusterFS卷应用对比图
三.适用场景
GlusterFS目前主要适用大文件存储场景,对于小文件尤其是海量小文件,存储效率和访问性能表现不佳。海量小文件LOSF问题是工业界和学术界公认的难题,GlusterFS作为通用的分布式文件系统,并没有对小文件做额外的优化措施,性能不好也是可以理解的。
四.Glusterfs与其他存储产品对比
五.部署GlusterFS集群
-
安装yum源
对于可公网访问环境,推荐使用yum安装方式,简单便捷,解决依赖;对于内网限制环境,可将RPM包提前下载准备好,进行自行安装。
以centos7为例:
yum install centos-release-gluster -y -
准备服务器
1) 准备至少两台centos7服务器,数量越多可实现的卷类型越丰富
2) 主机之间网络互通
3) 每台主机至少两块硬盘,一块用于操作系统安装,另一块用于Gluster数据存储(数据盘可挂载多个,提高性能),防止系统盘损坏数据丢失,也是避免系统盘和数据盘发生IO抢占。注意:GlusterFS将其动态生成的配置文件存储在/var/lib/glusterd中,如果在任何时间点GlusterFS无法写入这些文件,它会导致您的GlusterFS系统出现问题,或者让系统脱机,建议为/var/lib/glusterd,/var/log等这些目录单独创建分区以防发生这种问题。
-
添加本地解析
添加服务器本地解析192.168.1.2 server1192.168.1.3 server2192.168.1.4 server3
- 关闭防火墙及selinux
Cenos6: systemctl stop iptables ;chkconfig iptables offCentos7: systemctl stop firewalld;systemctl disable firewalld/etc/selinux/configSELINUX=disabled
- 加载内核模块
modprobe dm_snapshotmodprobe dm_mirrormodprobe dm_thin_pool
-
格式化分区和挂载brick
对于文件系统类型,推荐使用性能更好的xfs或者ext4
以下命令在每台节点上操作
fdisk /dev/sdb
mkfs.xfs -i size=512 /dev/sdb1
mkdir -p /bricks/brick1
echo -n /dev/sdb1 /bricks/brick1 xfs defaults 1 2 >> /etc/fstab
mount -a && mount
现在看到sdb1 挂载到/bricks/brick1
注意:在centos6上,需要安装xfsprogs包以支持格式化XFS文件系统
yum install xfsprogs -
安装GlusterFS
在每台节点上安装
yum install glusterfs-server -y
在centos8上安装时需要启动PowerTools源
dnf --enablerepo=powertools install glusterfs-server
启动GlusterFS进程
systemctl start glusterd && systemctl enable glusterd -
iptables配置
您可以使用iptables规则运行glusterFS,但需要注意的是,默认情况下,glusterd将在tcp/24007上侦听,但在glusterd节点上打开该端口是不够的,每次添加brick时,它都会打开一个新端口(您可以通过“gluster volume status”查看)
根据您的设计,最好为 gluster/存储流量使用专用 NIC,因此通过您的 netfilter 解决方案“信任”nic/subnet/gluster 节点(CentOS 6 的 /etc/sysconfig/iptables 和 firewalld/firewall -cmd)
对于安全性要求不是非常高的使用场景,推荐关闭firewalld -
配置可信任池
在任意一台机器执行以下命令:
gluster peer probe server2
gluster peer probe server3
在其中一台主机添加不在信任池中的其他主机
例如在server1上执行命令添加server2,server3主机
注意:一旦建立了信任池,只有受信任的成员可以将新服务器添加到池中,新服务器无法自行添加到信任池 -
设置GlusterFS卷
在server1和server2上执行以下命令
mkdir /bricks/brick1/gv0
在任意一台服务器执行:
gluster volume create gv0 replica 2 server1:/bricks/brick1/gv0 server2:/bricks/brick1/gv0
gluster volume start gv0
查看volume信息确保volume启动了
gluster volume info
注意:如果卷未启动,则有关出错的线索将在一台或两台服务器上/var/log/glusterfs下的日志文件中 - 通常在etc-glusterfs-glusterd.vol.log
- 测试volume卷
在任意一台主机挂载volume测试mount -t glusterfs server1:/gv0 /mntfor i in `seq -w 1 100`; do cp -rp /var/log/messages /mnt/copy-test-$i; done首先检查挂载点ls -lA /mnt | wc -l
您应该看到返回了 100 个文件。接下来,检查每台服务器上的 GlusterFS 挂载点:ls -lA /bricks/brick1/gv0
六. 使用heketi将glusterfs接入k8s作为后端存储
在上一节安装完glusterfs集群后,我们需要使用heketi将glusterfs接入到k8s,作为后端持久化存储。heketi是一个GlusterFs管理软件,可以管理glusterFS集群的卷创建、删除等操作
heketi管理Glusterfs集群需要注意:
- Glusterfs集群的各peer必须要有未安装文件系统的磁盘设备(磁盘设备未进行格式化)
- Glusterfs集群各peer的端口号不能太少,不然当peer上的brick将端口号用完后,会造成无法创建卷。
- Glusterfs的各peer不能组成集群,heketi可以自创建集群集合。
步骤:
- 准备磁盘
如果是使用的全部磁盘,则磁盘不需要分区,直接使用/dev/sdb
如果使用磁盘的部分空间,则需要对磁盘分区,使用/dev/sdb1
上一节我们使用/dev/sdb并进行了分区,因此我们需要将磁盘分区删除,并将磁盘数据清除,否则heketi将拒绝使用该磁盘
umount /bricks/brick1
fdisk /dev/sdb d w #删除分区
wipefs -a /dev/sdb #清除磁盘数据及信息
注意⚠️:如果您使用的是另一块未格式化的新磁盘,上面的三个命令无需执行
- 安装heketi(在集群中任选一个节点安装)
yum install heketi heketi-client - 生成密钥并配置免密
# ssh-keygen -t rsa -q -f /etc/heketi/private_key -N ""# ssh-copy-id -i /etc/heketi/private_key.pub glusterfs-node01# ssh-copy-id -i /etc/heketi/private_key.pub glusterfs-node02# ssh-copy-id -i /etc/heketi/private_key.pub glusterfs-node03# chown heketi.heketi /etc/heketi/private_key
- 配置heketi
vi /etc/heketi/heketi.json{"_port_comment": "Heketi Server Port Number","port": “48080", #改为48080或其他端口"_use_auth": "Enable JWT authorization. Please enable for deployment","use_auth": true, #改为true"_jwt": "Private keys for access","jwt": {"_admin": "Admin has access to all APIs","admin": {"key": "admin@password" #用于heketi认证的admin用户及密码},"_user": "User only has access to /volumes endpoint","user": {"key": "user@password" #用于heketi认证的user用户及密码,可以不配置}},"_glusterfs_comment": "GlusterFS Configuration","glusterfs": {"_executor_comment": ["Execute plugin. Possible choices: mock, ssh","mock: This setting is used for testing and development."," It will not send commands to any node.","ssh: This setting will notify Heketi to ssh to the nodes."," It will need the values in sshexec to be configured.","kubernetes: Communicate with GlusterFS containers over"," Kubernetes exec api."],"executor": “ssh",#改为ssh"_sshexec_comment": "SSH username and private key file information","sshexec": {"keyfile": "/etc/heketi/private_key","user": "root", #若这里使用root用户,则glusterfs的机器之间不能禁用root"port": "22", "fstab": "/etc/fstab"},"_kubeexec_comment": "Kubernetes configuration","kubeexec": {"host" :"https://kubernetes.host:8443","cert" : "/path/to/crt.file","insecure": false,"user": "kubernetes username","password": "password for kubernetes user","namespace": "OpenShift project or Kubernetes namespace","fstab": "Optional: Specify fstab file on node. Default is /etc/fstab"},"_db_comment": "Database file name","db": "/var/lib/heketi/heketi.db","_loglevel_comment": ["Set log level. Choices are:"," none, critical, error, warning, info, debug","Default is warning"],"loglevel" : "debug"}
}
将默认配置文件参考上述配置进行修改
-
启动heketi
systemctl enable heketi.service && systemctl start heketi.service -
测试
curl http://glusterfs-node01:48080/hello
Hello from Heketi #返回结果 -
配置topology
vi /etc/heketi/topology.json #配置三个节点的使用信息,这里/dev/sdb表示后端存储所要使用的数据盘
{"clusters": [{"nodes": [{"node": {"hostnames": {"manage": [“10.140.55.112”],"storage": ["10.140.55.112"]},"zone": 1},"devices": ["/dev/sdb"]},{"node": {"hostnames": {"manage": ["10.140.55.113"],"storage": ["10.140.55.112"]},"zone": 1},"devices": ["/dev/sdb"]},{"node": {"hostnames": {"manage": ["10.139.55.114"],"storage": ["10.139.55.114"]},"zone": 1},"devices": ["/dev/sdb"]}]}]
}
- 配置环境变量,方便操作
echo “export HEKETI_CLI_SERVER=http://10.140.55.112:48080” >> /etc/profile.d/heketi.sh #heketi地址
echo “alias heketi-cli=‘heketi-cli --server “$HEKETI_CLI_SERVER” --user admin --secret admin@password” >> ~/.bashrc #heketi用户密码
source /etc/profile.d/heketi.sh
source ~/.bashrc
-
创建集群
heketi-cli topology load --json=/etc/heketi/topology.json -
查看集群信息
heketi-cli cluster list
heketi-cli cluster info xxxx #xxxx为上条命令返回的id
heketi-cli node list
创建volume测试
heketi-cli volume create --size=2 --replica=3
heketi-cli volume list
mount -t glusterfs 10.140.55.112:vol_4f1a171ab06adf80460c84f2132e96e0 /mnt
heketi-cli volume delete 4f1a171ab06adf80460c84f2132e96e0
- k8s接入heketi
所有的k8s节点均安装glusterfs-fuse,以保证正常使用
yum install glusterfs-fuse -y
创建secret,heketi的认证密码,或者在kebesphere平台添加密钥apiVersion: v1
kind: Secret
metadata:name: heketi-secretnamespace: kube-system
data:key: YWRtaW5AUEBzc1cwcmQ=
type: kubernetes.io/glusterfskey的值,使用base64转码生成echo -n "admin@password" | base64 这里的用户名密码为heketi配置文件中创建的用户密码创建storageclass(heketi-storageclass.yaml)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: glusterfsnamespace: kube-system
parameters:resturl: “http://10.140.55.112:48080” #heketi的地址clusterid: "cca360f44db482f03297a151886eea19" #在heketi节点使用heketi-cli cluster list命令返回的idrestauthenabled: "true" restuser: "admin" #heketi配置文件中创建的用户密secretName: "heketi-secret" # name/namespace与secret资源中定义一致secretNamespace: "kube-system"volumetype: "replicate:3"
provisioner: kubernetes.io/glusterfs
reclaimPolicy: Delete创建pvc测试
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: heketi-pvcannotations:volume.beta.kubernetes.io/storage-provisioner: kubernetes.io/glusterfs
spec:storageClassName: "glusterfs"accessModes:- ReadWriteOnceresources:requests:storage: 1Gi查看sc和pvc的信息
kubectl get sc
kubectl get pvc
创建Pod挂载pvc(heketi-pod.yaml)
kind: Pod
apiVersion: v1
metadata:name: heketi-pod
spec:containers:- name: heketi-containerimage: busyboxcommand:- sleep- "3600"volumeMounts:- name: heketi-volumemountPath: "/pv-data"readOnly: falsevolumes:- name: heketi-volumepersistentVolumeClaim:claimName: heketi-pvc进入容器测试
kubectl exec -it heketi-pod /bin/sh
相关文章:
GlusterFS 深度洞察:从架构原理到案例实践的全面解读(上)
文章目录 一.GlusterFS简介二.GlusterFS原理架构三.适用场景四.Glusterfs与其他存储产品对比五.部署GlusterFS集群六. 使用heketi将glusterfs接入k8s作为后端存储 一.GlusterFS简介 GlusterFS是一个免费的开源分布式文件系统,具有无中心节点、堆栈式设计、全局统一…...
实现限制同一个账号最多只能在3个客户端(有电脑、手机等)登录(附关键源码)
如上图,我的百度网盘已登录设备列表,有一个手机,2个windows客户端。手机设备有型号、最后登录时间、IP等。windows客户端信息有最后登录时间、操作系统类型、IP地址等。这些具体是如何实现的?下面分别给出android APP中采集手机信…...
C#综合知识点面试集锦
在.NET Core 框架的面试中,可能会涉及基础概念、核心组件、依赖注入、性能优化等多方面的知识点,以下为你详细介绍: 基础概念 .NET Core 概述 定义与特点:解释 .NET Core 是一个跨平台、开源、模块化且高性能的通用开发框架,能在 Windows、Linux、macOS 等操作系统上运行…...
宝珀(Blancpain):机械制表的三项重大创新(中英双语)
宝珀(Blancpain):机械制表的创新先驱 本文灵感来源: 瑞士钟表业决定逆流而上,杀出一条生路,宝珀更是坚定地宣称“我们永远只做机械表”,它拒绝了石英技术。制表师们在提高腕表的技艺和品质、实…...
稠密架构和稀疏架构
稠密架构和稀疏架构 flyfish 稠密架构 参数使用方面:稠密架构中的大部分参数在每次计算时都会被使用。也就是说,对于输入的每一个样本,模型的所有或大部分参数都会参与到计算过程中。计算特点:计算密集,需要对大量的…...
SpringCloud - Gateway 网关
前言 该博客为Sentinel学习笔记,主要目的是为了帮助后期快速复习使用 学习视频:7小快速通关SpringCloud 辅助文档:SpringCloud快速通关 源码地址:cloud-demo 一、简介 官网:https://spring.io/projects/spring-clou…...
【如何掌握CSP-J 信奥赛中的排序算法】
要掌握CSP-J信奥赛中的排序算法,需要系统学习基础排序算法的原理、实现和应用场景。以下是分阶段的学习路径和建议: 一、必掌握的排序算法清单 CSP-J阶段需重点掌握以下算法(按考察频率排序): 冒泡排序(B…...
3. CSS中@scope
说说你对 CSS 中scope 的了解 <style>/* scope规则 */scope (#app) {.box {width: 100px;height: 100px;background-color: red;}} </style> <div id"app"><div class"box"></div> </div>CSS 中的scope 是一个相对较新…...
基于雷达和摄像头的无人机轨迹识别与激光照射控制研究
标题:基于雷达和摄像头的无人机轨迹识别与激光照射控制研究 内容:1.摘要 摘要:本文研究了基于雷达和摄像头的无人机轨迹识别与激光照射控制。通过对雷达和摄像头数据的融合处理,实现了对无人机轨迹的精确识别。同时,利用激光照射技术对无人机…...
Response 和 Request 介绍
怀旧网个人博客网站地址:怀旧网,博客详情:Response 和 Request 介绍 1、HttpServletResponse 1、简单分类 2、文件下载 通过Response下载文件数据 放一个文件到resources目录 编写下载文件Servlet文件 public class FileDownServlet exten…...
读 DeepSeek-R1 论文笔记
DeepSeek-R1:通过强化学习激发大语言模型的推理能力 DeepSeek-AI 摘要 我们推出第一代推理模型DeepSeek-R1-Zero和DeepSeek-R1。DeepSeek-R1-Zero作为无需监督微调(SFT)预训练阶段、直接通过大规模强化学习(RL)训练的基础模型,展现出卓越的推理能力。…...
【算法-动态规划】、魔法卷轴: 两次清零机会整个数组最大累加和
【算法-动态规划】、魔法卷轴: 两次清零机会整个数组最大累加和 文章目录 一、dp1.1 题意理解1.2 整体思路1.3 具体思路1.4 代码 二、多语言解法 一、dp 1.1 题意理解 nums 数组, 有正负0, 使用最多两次魔法卷轴, 希望使数组整体的累加和尽可能大. 求尽可能大的累加和 其实就…...
蓝桥杯C语言组:分治问题研究
蓝桥杯C语言组分治问题研究 摘要 本文针对蓝桥杯C语言组中的分治问题展开深入研究,详细介绍了分治算法的原理、实现方法及其在解决复杂问题中的应用。通过对经典例题的分析与代码实现,展示了分治算法在提高编程效率和解决实际问题中的重要作用ÿ…...
npm介绍(Node Package Manager)(JavaScript生态中最流行的包管理工具,主要用于Node.js项目的依赖管理)
文章目录 **核心功能****常用命令****关键文件****npm vs 其他工具****最佳实践**官方资源 npm(Node Package Manager)是 JavaScript 生态中最流行的包管理工具,主要用于 Node.js 项目的依赖管理。以下是核心要点: 核心功能 依赖管…...
小白零基础如何搭建CNN
1.卷积层 在PyTorch中针对卷积操作的对象和使用的场景不同,如有1维卷积、2维卷积、 3维卷积与转置卷积(可以简单理解为卷积操作的逆操作),但它们的使用方法比较相似,都可以从torch.nn模块中调用,需要调用的…...
【分布式架构理论3】分布式调用(1):负载均衡
文章目录 零、三种不同的负载均衡一、常见行业负载均衡方案1. 电商与互联网服务2. 金融与支付系统3. 云计算与分布式存储 二、负载均衡策略概述1. 无状态负载均衡(强调公平性)2. 有状态的负载均衡(强调正确性) 三、 总结 零、三种…...
QT 5.15.2 开发地图ArcGIS 100.15.6(ArcGIS Runtime SDK for Qt)
QT 5.15.2ArcGIS下载 Downloads | ArcGIS Runtime API for Qt | Esri Developer ArcGIS安装(略)参考 Display a map | ArcGIS Maps SDK for Qt | Esri Developer QT新建工程 步骤1 步骤2 步骤3 步骤4(选择Topographic不需要KEY) 步骤5&a…...
细读 React | React Router 路由切换原理
2022 北京冬奥会开幕式 此前一直在疑惑,明明 pushState()、replaceState() 不触发 popstate 事件,可为什么 React Router 还能挂载对应路由的组件呢? 翻了一下 history.js 源码,终于知道原因了。 源码 假设项目路由设计如下&#…...
kubernetes学习-Helm 包管理器(十二)
一、Helm解释 Helm:Kubernetes 的软件包管理器 Helm 被誉为查找、分享及使用 Kubernetes 软件组件的最佳途径。作为 Kubernetes 包的管理工具,Helm 专注于管理名为 chart 的软件包。以下是 Helm 所具备的核心功能: 创建新 chart࿱…...
PbootCMS最新代码注入漏洞(CNVD-2025-01710、CVE-2024-12789)
PbootCMS是一套高效、简洁、 强悍的可免费商用的CMS源码,使用PHPMySQL开发,能够满足各类企业网站开发建设的需要。 国家信息安全漏洞共享平台于2025-01-14公布该程序存在代码注入漏洞。 漏洞编号:CNVD-2025-01710、CVE-2024-12789 影响产品…...
网络安全与AI:数字经济发展双引擎
在2025年年初,一场科技攻防战引发了全球关注。国产人工智能DeepSeek的爆火,伴随着大规模的网络攻击事件,将网络安全的重要性推上了风口浪尖。 在此背景下,我们计划探讨网络安全与人工智能如何为数字经济发展提供强大动力。网络安…...
【DeepSeek × Postman】请求回复
新建一个集合 在 Postman 中创建一个测试集合 DeepSeek API Test,并创建一个关联的测试环境 DeepSeek API Env,同时定义两个变量 base_url 和 api_key 的步骤如下: 1. 创建测试集合 DeepSeek API Test 打开 Postman。点击左侧导航栏中的 Co…...
如何将网站提交百度收录完整SEO教程
百度收录是中文网站获取流量的重要渠道。本文以我的网站,www.mnxz.fun(当然现在没啥流量) 为例,详细讲解从提交收录到自动化维护的全流程。 一、百度收录提交方法 1. 验证网站所有权 1、登录百度搜索资源平台 2、选择「用户中心…...
【unity实战】实现摄像机跟随效果
考虑到每个人基础可能不一样,且并不是所有人都有同时做2D、3D开发的需求,所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】:主要讲解C#的基础语法,包括变量、数据类型、运算符、流程控制、面向对象等,适合没有编程基础的…...
使用Hexo部署NexT主体网站
一.使用git提交文件 参考: 从零开始搭建个人博客(超详细) - 知乎 致谢! 第一种:本地没有 git 仓库 直接将远程仓库 clone 到本地;将文件添加并 commit 到本地仓库;将本地仓库的内容push到远程仓…...
使用 AlexNet 实现图片分类 | PyTorch 深度学习实战
前一篇文章,CNN 卷积神经网络处理图片任务 | PyTorch 深度学习实战 本系列文章 GitHub Repo: https://github.com/hailiang-wang/pytorch-get-started 本篇文章内容来自于 强化学习必修课:引领人工智能新时代【梗直哥瞿炜】 使用 AlexNet 实现图片分类…...
ES6 Proxy 用法总结以及 Object.defineProperty用法区别
Proxy 是 ES6 引入的一种强大的拦截机制,用于定义对象的基本操作(如读取、赋值、删除等)的自定义行为。相较于 Object.defineProperty,Proxy 提供了更灵活、全面的拦截能力。 1. Proxy 语法 const proxy new Proxy(target, hand…...
初次体验Tauri和Sycamore (2)
原创作者:庄晓立(LIIGO) 原创时间:2025年2月8日(首次发布时间) 原创链接:https://blog.csdn.net/liigo/article/details/145520637 版权所有,转载请注明出处。 关键词:Sy…...
Qt - 地图相关 —— 2、Qt调用百度在线地图功能示例全集,包含线路规划、地铁线路查询等(附源码)
效果:由于录制软件导致exe显示不正常,实际运行没有任何问题。 作者其他相关文章链接: Qt - 地图相关 —— 1、加载百度在线地图(附源码)...
ffmpeg基本用法
一、用法 ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}... 说明: global options:全局选项,应用于整个 FFmpeg 进程,它们通常不受输入或输出部分的限制。 infile options:输入选…...
redis底层数据结构——链表
文章目录 定义内部实现总结 定义 链表提供了高效的节点重排能力,以及顺序性的节点访间方式,并且可以通过增删节点来灵活地调整链表的长度。 作为一种常用数据结构,链表内置在很多高级的编程语言里面,因为Redis使用的C语言并没有…...
Repo命令使用
repo 命令与 git 类似,但它主要用于管理多个 Git 仓库的操作。以下是等效的 repo 命令: 1. 获取新仓库代码 克隆仓库 repo init -u <manifest_url> -b <branch_name> repo sync repo init:初始化 repo,指定远程清单…...
React 高级教程
使用 React 高级组件(HOC)实现的完整项目示例,包含权限控制、数据加载状态处理、性能优化等常见高级功能。创建一个简单的博客系统: // 项目结构: src/ |-- components/ | |-- ArticleList.jsx | |-- Article.jsx | |-- Header.jsx | |-- LoginForm.jsx | |-- U…...
Linux: ASoC 声卡硬件参数的设置过程简析
文章目录 1. 前言2. ASoC 声卡设备硬件参数2.1 将 DAI、Machine 平台的硬件参数添加到声卡2.2 打开 PCM 流时将声卡硬件参数配置到 PCM 流2.3 应用程序对 PCM 流参数进行修改调整 1. 前言 限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失&am…...
网络基础知识与配置
目录 网络基础知识 (一)网络的概念 (二)网络协议 (三)网络拓扑结构 (四)IP地址和子网掩码 显示和配置网络接口 (一)在Windows系统中 (二&a…...
【STM32】ADC|多通道ADC采集
本次实现的是ADC实现数字信号与模拟信号的转化,数字信号时不连续的,模拟信号是连续的。 1.ADC转化的原理 模拟-数字转换技术使用的是逐次逼近法,使用二分比较的方法来确定电压值 当单片机对应的参考电压为3.3v时,0~ 3.3v(模拟信…...
centos 7 关于引用stdatomic.h的问题
问题:/tmp/tmp4usxmdso/main.c:6:23: fatal error: stdatomic.h: No such file or directory #include <stdatomic.h> 解决步骤: 1.这个错误是因为缺少C编译器的标准原子操作头文件 stdatomic.h。在Linux系统中,我们需要安装开发工具…...
用语言模型探索语音风格空间:无需情感标签的情 感TTS
用语言模型探索语音风格空间:无需情感标签的情感TTS 原文:Exploring speech style spaces with language models: Emotional TTS without emotion labels 今天我们要说的是 一种无需情感标签的情感TTS。提出了一个基于FastSpeech2的E-TTS框架࿰…...
将Excel中的图片保存下载并导出
目录 效果演示 注意事项 核心代码 有需要将excel中的图片解析出来保存到本地的小伙子们看过来!!! 效果演示 注意事项 仅支持xlsx格式:此方法适用于Office 2007及以上版本的.xlsx文件,旧版.xls格式无法使用。 图片名…...
2.11日学习总结
题目一 : AC代码 #include <stdio.h> #include <stdlib.h>// 定义长整型 typedef long long ll;// 定义求最大值和最小值的宏函数 #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b))// 定义数组和变量 ll…...
安川伺服控制器MP系列优势特点及行业应用
在工业自动化领域,运动控制器的性能直接决定了设备的精度、效率和可靠性。作为全球领先的运动控制品牌,安川电机伺服控制器凭借其卓越的技术优势和广泛的应用场景,正在为智能制造注入强劲动力! MP3100:主板型运动控制…...
【腾讯地图】录入经纬度功能 - 支持地图选点
目录 效果展示代码引入地图服务地址弹框中输入框 - 支持手动输入经纬度/地图选点按钮地图选点弹框组件 当前文章 - 地图功能与 https://blog.csdn.net/m0_53562074/article/details/143677335 功能类似 效果展示 代码 引入地图服务地址 public/index.html <!-- 互联网地图…...
Mybatis快速入门与核心知识总结
Mybatis 1. 实体类(Entity Class)1.1 实体类的定义1.2 简化编写1.2.1 Data1.2.2 AllArgsConstructor1.2.3 NoArgsConstructor 2. 创建 Mapper 接口2.1 Param2.2 #{} 占位符2.3 SQL 预编译 3. 配置 MyBatis XML 映射文件(可选)3.1 …...
RK3568平台开发系列讲解(调试篇)网卡队列均衡负载
🚀返回专栏总目录 文章目录 一、RPS 的介绍1. RPS 的工作原理2. RPS 配置3. 启用和调优 RPS4. RPS 优势二、下行测试iperf测试沉淀、分享、成长,让自己和他人都能有所收获!😄 RPS(Receive Packet Steering) 是一种用于提高网络接收性能的技术,通常用于多核处理器系统中…...
Matlab机械手碰撞检测应用
本文包含三个部分: Matlab碰撞检测的实现URDF文件的制作机械手STL文件添加夹爪 一.Matlab碰撞检测的实现 首先上代码 %% 检测在结构环境中机器人是否与物体之间发生碰撞情况,如何避免? % https://www.mathworks.com/help/robotics/ug/che…...
【前端】几种常见的跨域解决方案代理的概念
几种常见的跨域解决方案&代理的概念 一、常见的跨域解决方案1. 服务端配置CORS(Cross-Origin Resource Sharing):2. Nginx代理3. Vue CLI配置代理:4 .uni-app在manifest.json中配置代理来解决:5. 使用WebSocket通讯…...
服务器有多少线程?发起一个请求调用第三方服务,是新增加一个请求吗?如果服务器线程使用完了怎么办?
目录 1. 服务器有多少线程? (1)服务器类型 (2)配置参数 (3)硬件资源 2. 发起一个请求调用第三方服务,是新增加一个线程吗? (1)同步调用 (2)异步调用 (3)HTTP 客户端 3. 如果服务器线程使用完了怎么办? (1)请求被拒绝 (2)性能下降 (3)解决方案…...
【Spring AI】基于SpringAI+Vue3+ElementPlus的QA系统实现一
整理不易,请不要吝啬你的赞和收藏。 1. 前言 这是 SpringAI 系列的第二篇文章,这篇文章将介绍如何基于 RAG 技术,使用 SpringAI Vue3 ElementPlus 实现一个 Q&A 系统。本文使用 deepseek 的 DeepSeek-V3 作为聊天模型,使用…...
前端快速生成接口方法
大家好,我是苏麟,今天聊一下OpenApi。 官网 : umijs/openapi - npm 安装命令 npm i --save-dev umijs/openapi 在根目录(项目目录下)创建文件 openapi.config.js import { generateService } from umijs/openapi// 自…...
【Qt 常用控件】多元素控件(QListWidget、QTabelWidgt、QTreeWidget)
**View和**Widget的区别? **View的实现更底层,**Widget是基于**View封装实现的更易用的类型。 **View使用MVC结构 MVC是软件开发中 经典的 软件结构 组织形式,软件设计模式。 M(model)模型。管理应用程序的核心数据和…...