kubernetes集群部署GlusterFS分布式文件系统

server/2024/9/23 23:21:49/

关于GlusterFS和Heketi

GlusterFS Heketi 组合提供了一个强大、灵活和易于管理的分布式存储解决方案,适用于各种规模和需求的应用场景。GlusterFS 提供了高性能和可靠性的分布式文件系统,而 Heketi 则简化了 GlusterFS 的部署和管理流程,使得用户可以更轻松地搭建和管理存储基础设施。

GlusterFS 是一个开源的分布式文件系统,旨在提供可扩展性、高性能和高可靠性的存储解决方案。它基于分布式存储和对象存储的概念,允许将多个存储服务器汇聚成一个统一的文件系统,并提供了数据冗余、负载均衡、弹性伸缩等功能。

以下是 GlusterFS 的一些主要特点和功能:

  1. 可扩展性:GlusterFS 可以轻松地扩展到成百上千台服务器,从而支持 PB 级别的数据存储需求。

  2. 高性能:GlusterFS 具有并行 I/O、缓存和负载均衡等特性,可以实现高并发、高吞吐量的数据访问。

  3. 数据冗余:GlusterFS 支持多种数据冗余方式,包括复制、条带化和分布式条带化,可以保障数据的安全性和可靠性。

  4. 透明性:GlusterFS 提供了统一的命名空间,使得用户无需关心数据存储在哪个节点上,可以透明地访问整个文件系统。

  5. 弹性伸缩:GlusterFS 可以动态地添加或删除存储节点,从而实现存储容量的动态扩展和收缩。

  6. 灵活性:GlusterFS 支持多种存储协议,包括 NFS、CIFS、FTP 等,可以与各种应用和操作系统无缝集成。

Heketi(以前称为 GlusterFS Manager)是一个用于管理 GlusterFS 的管理器,旨在简化 GlusterFS 的部署、管理和维护。它提供了一个 RESTful API,通过该 API 可以轻松地创建、删除、调整存储卷,以及动态地分配存储资源。

以下是 Heketi 的一些主要功能:

  1. 自动化管理:Heketi 可以自动化地管理 GlusterFS 集群,包括存储卷的创建、删除、调整大小等操作。

  2. 动态分配资源:Heketi 可以根据需求动态地分配存储资源,从而最大化资源利用率。

  3. 简化部署:Heketi 提供了一组命令行工具和 RESTful API,可以简化 GlusterFS 的部署和管理流程。

  4. 故障恢复:Heketi 可以自动检测和处理存储节点的故障,从而保障数据的可靠性和可用性。

  5. 集成性:Heketi 可以与其他管理工具和自动化平台集成,例如 Kubernetes、OpenShift 等,从而实现存储资源的自动化管理和调度。

搭建前准备工作

首先需要搭建一套Kubernetes集群环境,因Heketi要求GlusterFS至少有3个节点,所以,最好kubernetes集群的节点有4个(当然3个也可以),我准备了6个节点(所有节点都要配置时间同步,确保时间一致性):

类型节点名分区情况标签
master节点linshi-k8s-52/dev/sda1 / /dev/sda1 /var
普通node节点linshi-k8s-54/dev/sda1 / /dev/sda1 /varlabel=commnode
普通node节点linshi-k8s-57/dev/sda1 / /dev/sda1 /varlabel=commnode
gluserfs用node节点linshi-k8s-clusterfs-55/dev/sda1 / /dev/sdb 裸盘(不格式化)storagenode=glusterfs
gluserfs用node节点linshi-k8s-clusterfs-56/dev/sda1 / /dev/sdb 裸盘(不格式化)storagenode=glusterfs
gluserfs用node节点linshi-k8s-clusterfs-58/dev/sda1 / /dev/sdb 裸盘(不格式化)storagenode=glusterfs

为了能够使用GlusterFS,需要在计划使用GlusterFS的Node上安装GlusterFS客户端(普通node节点也要装)

yum -y install glusterfs glusterfs-fuse

GlusterFS管理服务容器需要以特权模式运行,需要kubernetes启用特权模式

 ~]# systemctl cat kube-apiserver# /usr/lib/systemd/system/kube-apiserver.serviceExecStart=/opt/kubernetes/server/bin/kube-apiserver \--allow-privileged=true  

准备部署GlusterFS管理服务的节点上,需要打上标签,例如:“storagenode=glusterfs”

kubectl label node linshi-k8s-clusterfs-55 storagenode=glusterfs
kubectl label node linshi-k8s-clusterfs-56 storagenode=glusterfs
kubectl label node linshi-k8s-clusterfs-58 storagenode=glusterfs

创建GlusterFS管理服务容器集群

GlusterFS管理服务容器以DaemonSet方式进行部署,即:每个Node上都运行一个GlusterFS管理服务。glusterfs-daemonset.yaml内容如下:

---
kind: DaemonSet
apiVersion: apps/v1
metadata:name: glusterfslabels:glusterfs: daemonsetannotations:description: GlusterFS DaemonSettags: glusterfs
spec:selector:matchLabels:glusterfs-node: podtemplate:metadata:name: glusterfslabels:glusterfs-node: podspec:nodeSelector:storagenode: glusterfshostNetwork: truecontainers:- image: 192.168.XXXX/library/gluster-centosimagePullPolicy: IfNotPresentname: glusterfsvolumeMounts:- name: glusterfs-heketimountPath: "/var/lib/heketi"- name: glusterfs-runmountPath: "/run"- name: glusterfs-lvmmountPath: "/run/lvm"- name: glusterfs-etcmountPath: "/etc/glusterfs"- name: glusterfs-logsmountPath: "/var/log/glusterfs"- name: glusterfs-configmountPath: "/var/lib/glusterd"- name: glusterfs-devmountPath: "/dev"- name: glusterfs-miscmountPath: "/var/lib/misc/glusterfsd"- name: glusterfs-cgroupmountPath: "/sys/fs/cgroup"readOnly: true- name: glusterfs-sslmountPath: "/etc/ssl"readOnly: truesecurityContext:capabilities: {}privileged: truereadinessProbe:timeoutSeconds: 3initialDelaySeconds: 40exec:command:- "/bin/bash"- "-c"- systemctl status glusterd.serviceperiodSeconds: 25successThreshold: 1failureThreshold: 15livenessProbe:timeoutSeconds: 3initialDelaySeconds: 40exec:command:- "/bin/bash"- "-c"- systemctl status glusterd.serviceperiodSeconds: 25successThreshold: 1failureThreshold: 15volumes:- name: glusterfs-heketihostPath:path: "/var/lib/heketi"- name: glusterfs-run- name: glusterfs-lvmhostPath:path: "/run/lvm"- name: glusterfs-etchostPath:path: "/etc/glusterfs"- name: glusterfs-logshostPath:path: "/var/log/glusterfs"- name: glusterfs-confighostPath:path: "/var/lib/glusterd"- name: glusterfs-devhostPath:path: "/dev"- name: glusterfs-mischostPath:path: "/var/lib/misc/glusterfsd"- name: glusterfs-cgrouphostPath:path: "/sys/fs/cgroup"- name: glusterfs-sslhostPath:path: "/etc/ssl"
 ~]# docker pull gluster/gluster-centos:latest~]# docker tag gluster/gluster-centos 192.168.XXXX/library/gluster-centos~]# kubectl apply -f glusterfs-daemonset.yaml ~]# kubectl get po -o wideNAME                             READY   STATUS    RESTARTS   AGE     IP               NODE                      NOMINATED NODE   READINESS GATESglusterfs-2lzr7                  1/1     Running   0          2d19h   192.XXXX.56   linshi-k8s-clusterfs-56   <none>           <none>glusterfs-6qzdc                  1/1     Running   0          2d19h   192.XXXX.55   linshi-k8s-clusterfs-55   <none>           <none>glusterfs-lr9ff                  1/1     Running   0          2d19h   192.XXXX.58   linshi-k8s-clusterfs-58   <none>           <none>

创建Heketi服务

在部署Heketi之前需要给它授权,否则无法访问GlusterFS管理服务。首先,创建一个ServiceAccount对象(heketi-service-account.yaml):

apiVersion: v1
kind: ServiceAccount
metadata:name: heketi-service-account

给heketi-service-account绑定权限:

 ~]# kubectl create clusterrole heketi-gluster-role --verb=get,list,watch,create 
--resource=pods,pods/status,pods/exec~]# kubectl create clusterrolebinding heketi-gluster-admin 
--clusterrole=heketi-gluster-role --serviceaccount=default:heketi-service-account​~]# kubectl create -f heketi-service-account.yaml ~]# kubectl get sa|grep heketiNAME                     SECRETS   AGEheketi-service-account   1         3d1h

部署Heketi服务(heketi-deployment-svc.yaml )

heketi服务的环境变量HEKETI_ADMIN_KEY,请自行修改(最好不要用默认的)

kind: Deployment
apiVersion: apps/v1
metadata:name: deploy-heketilabels:glusterfs: heketi-deploymentdeploy-heketi: heketi-deploymentannotations:description: Defines how to deploy Heketi
spec:selector:matchLabels:name: deploy-heketireplicas: 1template:metadata:name: deploy-heketilabels:name: deploy-heketiglusterfs: heketi-podspec:serviceAccountName: heketi-service-accountcontainers:- image: 192.168.XXXX/library/heketiname: deploy-heketienv:- name: HEKETI_EXECUTORvalue: kubernetes- name: HEKETI_FSTABvalue: "/var/lib/heketi/fstab"- name: HEKETI_SNAPSHOT_LIMITvalue: '14'- name: HEKETI_CLI_SERVERvalue: "http://localhost:8080"- name: HEKETI_ADMIN_KEYvalue: "admin123"- name: HEKETI_KUBE_GLUSTER_DAEMONSETvalue: "y"ports:- containerPort: 8080volumeMounts:- name: dbmountPath: "/var/lib/heketi"readinessProbe:timeoutSeconds: 3initialDelaySeconds: 3httpGet:path: "/hello"port: 8080livenessProbe:timeoutSeconds: 3initialDelaySeconds: 30httpGet:path: "/hello"port: 8080volumes:- name: dbhostPath:path: "/heketi-data"
---
kind: Service
apiVersion: v1
metadata:name: deploy-heketilabels:glusterfs: heketi-servicedeploy-heketi: supportannotations:description: Exposes Heketo Service
spec:type: NodePortselector:name: deploy-heketiports:- name: deploy-heketiport: 8080targetPort: 8080nodePort: 38080
 ~]# kubectl apply -f heketi-deployment-svc.yaml ~]# kubectl get po |grep heketideploy-heketi-64558d59d7-vz56v   1/1     Running   0          2d22h

为Heketi设置GlusterFS集群

在Heketi能够管理GlusterFS集群之前,需要为其设置GlusterFS集群的信息。可以通过topology.json文件完成GlusterFS集群的定义。

Heketi要求GlusterFS集群至少有3个节点。

topology.json配置文件:

clusters.nodes.node.hostnames.manage:设置nodename或hostname

clusters.nodes.node.hostnames.storage:设置nodeip

clusters.nodes.node.devices:设置存储裸设备,可以设置多块,以供Heketi自动完成PV、VG 、LV的创建。

{ "clusters": [{"nodes": [{"node": {"hostnames": {"manage": ["linshi-k8s-clusterfs-55"],"storage": ["192.XXXX.55"]},"zone": 1},"devices": ["/dev/sdb"]},{"node": {"hostnames": {"manage": ["linshi-k8s-clusterfs-56"],"storage": ["192.XXXX.56"]},"zone": 1},"devices": ["/dev/sdb"]},{"node": {"hostnames": {"manage": ["linshi-k8s-clusterfs-58"],"storage": ["192.XXXX.58"]},"zone": 1},"devices": ["/dev/sdb"]} ]}]
}

进入到heketi容器,使用命令行工具heketi-cli完成GlusterFS集群的配置:

~]# kubectl exec -it deploy-heketi-64558d59d7-vz56v -- /bin/bash
~]# export HEKETI_CLI_SERVER=http://192.XXXX.54:38080
~]# cd /var/lib/heketi/
~]# heketi-cli topology load --json=topology.json --user admin --secret admin123
Creating cluster ... ID: 145a1f5fd81b8299deb2f885efeefa4cAllowing file volumes on cluster.Allowing block volumes on cluster.Creating node linshi-k8s-clusterfs-55 ... ID: dded86116e8092e7034193b17db89e7cAdding device /dev/sdb ... OKCreating node linshi-k8s-clusterfs-56 ... ID: b87c03ec7f0879979b46cdaaf52b7b11Adding device /dev/sdb ... OKCreating node linshi-k8s-clusterfs-58 ... ID: 8c49ae684daf6806e0fd8d3e71e1768bAdding device /dev/sdb ... OK

经过上面的操作,Heketi完成了GlusterFS集群的创建,并在GlusterFS集群各个节点的/dev/sdb盘上成功创建了PV和VG。

~]# pvsPV         VG                                  Fmt  Attr PSize   PFree  /dev/sda2  centos_linshi-k8s-clusterfs-55      lvm2 a--  <29.00g      0 /dev/sdb   vg_49f62450516d6cfd0280d994b40b70ca lvm2 a--   39.87g <38.86g
~]# vgsVG                                  #PV #LV #SN Attr   VSize   VFree  centos_linshi-k8s-clusterfs-55        1   1   0 wz--n- <29.00g      0 vg_49f62450516d6cfd0280d994b40b70ca   1   2   0 wz--n-  39.87g <38.86g

通过下面的命令,查看Heketi的topology信息,可以看到Node和Device的详细信息,包括磁盘空间大小和剩余空间。此时,Volume和Brick还未创建。

~]# heketi-cli topology info --user admin --secret admin123 Cluster Id: 145a1f5fd81b8299deb2f885efeefa4cFile:  trueBlock: trueVolumes:Nodes:Node Id: 8c49ae684daf6806e0fd8d3e71e1768bState: onlineCluster Id: 145a1f5fd81b8299deb2f885efeefa4cZone: 1Management Hostnames: linshi-k8s-clusterfs-58Storage Hostnames: 192.XXXX.58Devices:Id:7679bedee4b8208721f5d3bc71c31948   State:online    Size (GiB):39      Used (GiB):0       Free (GiB):39      Known Paths: /dev/sdbBricks:Node Id: b87c03ec7f0879979b46cdaaf52b7b11State: onlineCluster Id: 145a1f5fd81b8299deb2f885efeefa4cZone: 1Management Hostnames: linshi-k8s-clusterfs-56Storage Hostnames: 192.XXXX.56Devices:Id:2e3aaa5d446899a751d086005e57a361   State:online    Size (GiB):39      Used (GiB):0       Free (GiB):39      Known Paths: /dev/sdbBricks:Node Id: dded86116e8092e7034193b17db89e7cState: onlineCluster Id: 145a1f5fd81b8299deb2f885efeefa4cZone: 1Management Hostnames: linshi-k8s-clusterfs-55Storage Hostnames: 192.XXXX.55Devices:Id:6d1ce90e0ff01dc926f630a955f90ccc   State:online    Size (GiB):39      Used (GiB):0       Free (GiB):39      Known Paths: /dev/sdbBricks:

定义StorageClass

创建secret对象

##1.
cat > glusterfs_secret.yaml <<EOF
apiVersion: v1
kind: Secret
metadata:name: heketi-secretnamespace: default
data:# base64 encoded password. E.g.: echo -n "admin123" | base64key: YWRtaW4xMjM=
type: kubernetes.io/glusterfs
EOF##2.
kubectl apply -f glusterfs_secret.yaml

storageclass-gluster-heketi.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: gluster-heketi
provisioner: kubernetes.io/glusterfs
reclaimPolicy: Delete
allowVolumeExpansion: true
parameters:volumeMode: Blockresturl: "http://192.XXXX.54:38080"restauthenabled: "true"restuser: "admin"secretNamespace: "default"secretName: "heketi-secret"~]# kubectl apply -f storageclass-gluster-heketi.yaml 
~]# kubectl get sc
NAME             PROVISIONER               RECLAIMPOLICY   VOLUMEBINDINGMODE   
ALLOWVOLUMEEXPANSION   AGE
gluster-heketi   kubernetes.io/glusterfs   Delete          Immediate           
true                   2d23h

定义PVC

定义文件如下,该PVC申请1G空间,StorageClass使用gluster-heketi。PVC一旦生成,系统便触发Heketi进行相应操作:

1、GlusterFS集群上创建Brick,再创建Volume。

2、PVC创建成功后会自动创建PV

3、PV的Endpoint和Path也由Heketi自动关联到GlusterFS上

pvc-gluster-heketi.yaml

kind: PersistentVolumeClaim
apiVersion: v1
metadata:name: pvc-gluster-heketi
spec:storageClassName: gluster-heketivolumeMode: FilesystemaccessModes:- ReadWriteOnceresources:requests:storage: 1Gi

~]# kubectl apply -f pvc-gluster-heketi.yaml 
~]# kubectl get pvc
查看PVC,状态Pending了好长时间
NAME                 STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS     AGE
pvc-gluster-heketi   Bound    pvc-b8cf1063-122f-436d-ac5a-ff5862d66846   1Gi        RWO            gluster-heketi   2d23h
~]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                        STORAGECLASS     REASON   AGE
pvc-b8cf1063-122f-436d-ac5a-ff5862d66846   1Gi        RWO            Delete           Bound    default/pvc-gluster-heketi   gluster-heketi            2d23h
~]# kubectl describe pv pvc-b8cf1063-122f-436d-ac5a-ff5862d66846 
Name:            pvc-b8cf1063-122f-436d-ac5a-ff5862d66846
Labels:          <none>
Annotations:     Description: Gluster-Internal: Dynamically provisioned PV
                 gluster.kubernetes.io/heketi-volume-id: 20bd5715aed57741c866152bc1a00835
                 gluster.org/type: file
                 kubernetes.io/createdby: heketi-dynamic-provisioner
                 pv.beta.kubernetes.io/gid: 2000
                 pv.kubernetes.io/bound-by-controller: yes
                 pv.kubernetes.io/provisioned-by: kubernetes.io/glusterfs
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    gluster-heketi
Status:          Bound
Claim:           default/pvc-gluster-heketi
Reclaim Policy:  Delete
Access Modes:    RWO
VolumeMode:      Filesystem
Capacity:        1Gi
Node Affinity:   <none>
Message:         
Source:
    Type:                Glusterfs (a Glusterfs mount on the host that shares a pod's lifetime)
    EndpointsName:       glusterfs-dynamic-b8cf1063-122f-436d-ac5a-ff5862d66846
    EndpointsNamespace:  default
    Path:                vol_20bd5715aed57741c866152bc1a00835
    ReadOnly:            false
Events:                  <none>

定义Pod使用PVC资源

定义Pod centos-demo使用PVC:pvc-gluster-heketi,挂载到容器内/host/gluster。

apiVersion: v1
kind: Pod
metadata:name: centos-demolabels:type: os-demo version: 1.0.0namespace: 'default'
spec:restartPolicy: OnFailurenodeName: linshi-k8s-54containers:- name: centosimage: 192.XXXX.101/library/centosimagePullPolicy: IfNotPresentresources:requests:cpu: 100mmemory: 128Milimits:cpu: 200mmemory: 256MisecurityContext:privileged: truevolumeMounts:- name: "proc-dir"mountPath: "/host/proc"- name: "opt-dir"mountPath: "/host/opt"- name: "etc-dir"mountPath: "/host/etc"- name: gluster-volumemountPath: "/host/gluster"volumes:- name: "proc-dir"hostPath:path: /proc- name: "opt-dir"hostPath:path: /opt- name: "etc-dir"hostPath:path: /etc- name: gluster-volumepersistentVolumeClaim:claimName: pvc-gluster-heketi

~]# kubectl apply -f centos-demo.yaml
~]# kubectl exec -it centos-demo -- /bin/bash
/]# df -hT
Filesystem                                          Type            Size  Used Avail Use% Mounted on
overlay                                             overlay          39G  2.3G   37G   6% /
tmpfs                                               tmpfs            64M     0   64M   0% /dev
tmpfs                                               tmpfs           3.9G     0  3.9G   0% /sys/fs/cgroup
/dev/mapper/centos_linshi--k8s--54-root             xfs              20G  7.5G   13G  38% /host/etc
192.XXXX.56:vol_20bd5715aed57741c866152bc1a00835 fuse.glusterfs 1014M   43M  972M   5% /host/gluster
/dev/mapper/centos_linshi--k8s--54-var              xfs              39G  2.3G   37G   6% /etc/hosts
shm                                                 tmpfs            64M     0   64M   0% /dev/shm
tmpfs                                               tmpfs           256M   12K  256M   1% /run/secrets/kubernetes.io/serviceaccount
[root@centos-demo /]# cd /host/gluster/
[root@centos-demo gluster]# touch test-file
[root@centos-demo gluster]# echo "hello-glusterfs">test-file 
[root@centos-demo gluster]# cat test-file 
hello-glusterfs

FAQ

Heketi加载GlusterFS配置报token丢失错误

heketi-cli topology load --json=topology.json Error: Unable to get topology information: Invalid JWT token: Token missing iss claim 因为clusterfs访问需要认证,所以换成命令: heketi-cli topology load --json=topology.json --user admin --secret admin123

Heketi加载GlusterFS配置创建node失败错误

heketi-cli topology load --json=topology.json --user admin --secret admin123 Creating cluster ... ID: 18a2b447ded26ac0b169efc2d3703150 Allowing file volumes on cluster. Allowing block volumes on cluster. Creating node linshi-k8s-clusterfs-55 ... Unable to create node: New Node doesn't have glusterd running Creating node linshi-k8s-clusterfs-56 ... Unable to create node: New Node doesn't have glusterd running Creating node linshi-k8s-clusterfs-58 ... Unable to create node: New Node doesn't have glusterd running 因为heketi-service-account没有权限: kubectl create clusterrolebinding heketi-gluster-admin --clusterrole=edit --serviceaccount=default:heketi-service-account

创建pvc一直处于pending状态

# kubectl get persistentvolumeclaim -o wide NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE pvc-gluster-heketi Pending gluster-heketi 8s Filesystem 查看pvc的日志: Operation for "provision-default/pvc-gluster-heketi[2ee4f999-95fd-4982-a36d-88ec0c7c35ba]" failed. No retries permitted until 2024-04-15 14:06:21.357227113 +0800 CST m=+252629.514399927 (durationBeforeRetry 500ms). Error: failed to create volume: failed to create volume: see kube-controller-manager.log for details 但是,通过heketi-cli topology info --user admin --secret admin123 查看,一直在创建Brick。 后来将Heketi的数据目录删掉,将GlusterFS服务容器以及Heketi服务容器重新创建了一遍,然后通过topology.json重新创建了集群和StorageClass,再创建PV就可以了。

定义挂载GlusterFS的Volume,使用命令kubectl apply -f centos-demo.yaml创建Pod失败

 mount gluster 报错:unknown filesystem type 'glusterfs'  ​  centos-demo被调度的node上没有安装GlusterFS客户端

http://www.ppmy.cn/server/46255.html

相关文章

【缓存】框架层常见问题和对策

缓存是为了加快读写速度&#xff0c;再了解redis这类框架层的缓存应用之前&#xff0c;我们不妨先思考下操作系统层面的缓存解决方案&#xff0c;这样有助于我们更深的理解缓存&#xff0c;哪些是系统层面的&#xff0c;哪些是服务层面。 以下是一些常见的缓存问题及其解决方案…

linux服务器配置GroundingDINO 详细过程

linux服务器配置GroundingDINO 详细过程 1. 参考帖子2. 配置流程&#xff1a;环境配置&#xff1a;py310, cuda118, pytorch2.12.1 设置相关的环境变量&#xff1a;2.2 配置conda下载anaconda 配置相对应的环境 1. 参考帖子 已经跑通了&#xff0c;该踩的坑也都踩过来了&#…

【计算机网络】——物理层(图文并茂)

物理层 一.物理层概述1.物理层要实现的功能2.物理层接口特征1.机械特性2.电气特性3.功能特性4.过程特性 二.物理层下面的传输媒体1.传输媒体的分类2.导向型传输媒体1.同轴电缆2.双绞线3.光纤 3.非导向型传输媒体1.无线电波2.微波3.红外线4.激光5.可见光 三.传输方式1.串行传输与…

如何搭建一款成功的淘宝扭蛋机小程序

随着移动互联网的飞速发展&#xff0c;小程序因其轻量级、即用即走的特点&#xff0c;迅速成为各行业追逐的热点。在电商领域&#xff0c;淘宝扭蛋机小程序以其独特的互动性和趣味性&#xff0c;吸引了大量用户的关注。那么&#xff0c;如何搭建一款成功的淘宝扭蛋机小程序呢&a…

新人硬件工程师,工作中遇到的问题list

新人硬件工程师能够通过面试&#xff0c;已经证明是能够胜任硬件工程师职责&#xff0c;当然胜任的时间会延迟&#xff0c;而不是当下&#xff0c;为什么呢&#xff1f;因为学校学习和公司做产品&#xff0c;两者之间有差异&#xff0c;会需要适应期。今天来看看新人硬件工程师…

UE5 使用外置摄像头进行拍照并保存到本地

连接外置摄像头功能&#xff1a;https://docs.unrealengine.com/4.27/zh-CN/WorkingWithMedia/IntegratingMedia/MediaFramework/HowTo/UsingWebCams/ 核心功能&#xff1a;UE4 相机拍照功能&#xff08;图片保存&#xff09;_ue 移动端保存图片-CSDN博客 思路是&#xff1a; …

生产力工具推荐:AI Video To Blog-根据视频自动生成博客

#AI 其实这个项目有点多余&#xff0c;我个人习惯制作素材合成文案文稿后再去制作视频&#xff0c;但是这个工具肯定有应用场景。比如那些对着镜头可以一顿扯淡&#xff0c;后期生成文案博客再广而告之的情形。 所以这是一个视频生成博客的项目&#xff0c;你可以上传一个视频…

9秒爬取庆余年2分集剧情

版本一: 要创建一个Python爬虫程序来爬取指定网站的分集剧情,我们需要使用requests库来发送HTTP请求,以及BeautifulSoup库来解析HTML内容。以下是一个简单的示例,展示了如何爬取你提供的网站的分集剧情,并将每集剧情保存到本地的.txt文件中。 首先,确保你已经安装了req…