【kubernetes】持久卷PV、PVC

目錄

PV和PVC之間的相互作用遵循這個生命周期

根據這 5 個階段,PV 的狀態有以下 4 種

一個PV從創建到銷毀的具體流程如下

靜態PV創建

1、配置nfs存儲

2、定義PV

3、定義PVC

4、測試訪問

動態PV創建

1、在stor01節點上安裝nfs,并配置nfs服務

2、創建 Service Account,用來管理 NFS Provisioner 在 k8s 集群中運行的權限,設置 nfs-client 對 PV,PVC,StorageClass 等的規則

3、使用 Deployment 來創建 NFS Provisioner

方法一

方法二

創建 NFS Provisioner

4、創建 StorageClass,負責建立 PVC 并調用 NFS provisioner 進行預定的工作,并讓 PV 與 PVC 建立關聯

5、創建 PVC 和 Pod 測試


PV 全稱叫做 Persistent Volume,持久化存儲卷。它是用來描述或者說用來定義一個存儲卷的,這個通常都是由運維工程師來定義。

PVC 的全稱是 Persistent Volume Claim,是持久化存儲的請求。它是用來描述希望使用什么樣的或者說是滿足什么條件的 PV 存儲。

PVC 的使用邏輯:在 Pod 中定義一個存儲卷(該存儲卷類型為 PVC),定義的時候直接指定大小,PVC 必須與對應的 PV 建立關系,PVC 會根據配置的定義去 PV 申請,而 PV 是由存儲空間創建出來的。PV 和 PVC 是 Kubernetes 抽象出來的一種存儲資源。


上面介紹的PV和PVC模式是需要運維人員先創建好PV,然后開發人員定義好PVC進行一對一的Bond,但是如果PVC請求成千上萬,那么就需要創建成千上萬的PV,對于運維人員來說維護成本很高,Kubernetes提供一種自動創建PV的機制,叫StorageClass,它的作用就是創建PV的模板。

創建 StorageClass 需要定義 PV 的屬性,比如存儲類型、大小等;另外創建這種 PV 需要用到的存儲插件,比如 Ceph 等。 有了這兩部分信息,Kubernetes 就能夠根據用戶提交的 PVC,找到對應的 StorageClass,然后 Kubernetes 就會調用 StorageClass 聲明的存儲插件,自動創建需要的 PV 并進行綁定。


PV是集群中的資源。 PVC是對這些資源的請求,也是對資源的索引檢查。?

PV和PVC之間的相互作用遵循這個生命周期

Provisioning(配置)---> Binding(綁定)---> Using(使用)---> Releasing(釋放) ---> Recycling(回收)

●Provisioning:即 PV 的創建,可以直接創建 PV(靜態方式),也可以使用 StorageClass 動態創建
●Binding:將 PV 分配給 PVC
●Using:Pod 通過 PVC 使用該 Volume,并可以通過準入控制StorageProtection(1.9及以前版本為PVCProtection) 阻止刪除正在使用的 PVC
●Releasing:Pod 釋放 Volume 并刪除 0PVC
●Reclaiming:回收 PV,可以保留 PV 以便下次使用,也可以直接從云存儲中刪除

根據這 5 個階段,PV 的狀態有以下 4 種

●Available(可用):表示可用狀態,還未被任何 PVC 綁定
●Bound(已綁定):表示 PV 已經綁定到 PVC
●Released(已釋放):表示 PVC 被刪掉,但是資源尚未被集群回收
●Failed(失敗):表示該 PV 的自動回收失敗

一個PV從創建到銷毀的具體流程如下

1、一個PV創建完后狀態會變成Available,等待被PVC綁定。
2、一旦被PVC邦定,PV的狀態會變成Bound,就可以被定義了相應PVC的Pod使用。
3、Pod使用完后會釋放PV,PV的狀態變成Released。
4、變成Released的PV會根據定義的回收策略做相應的回收工作。有三種回收策略,Retain、Delete和Recycle。Retain就是保留現場,K8S集群什么也不做,等待用戶手動去處理PV里的數據,處理完后,再手動刪除PV。Delete策略,K8S會自動刪除該PV及里面的數據。Recycle方式,K8S會將PV里的數據刪除,然后把PV的狀態變成Available,又可以被新的PVC綁定使用。

kubectl explain pv ? ?#查看pv的定義方式
FIELDS:apiVersion: v1kind: PersistentVolumemetadata: ? ?#由于 PV 是集群級別的資源,即 PV 可以跨 namespace 使用,所以 PV 的 metadata 中不用配置 namespacename:?spec
kubectl explain pv.spec ? ?#查看pv定義的規格
spec:nfs:(定義存儲類型)path:(定義掛載卷路徑)server:(定義服務器名稱)accessModes:(定義訪問模型,有以下三種訪問模型,以列表的方式存在,也就是說可以定義多個訪問模式)- ReadWriteOnce ? ? ? ? ?#(RWO)卷可以被一個節點以讀寫方式掛載。 ReadWriteOnce 訪問模式也允許運行在同一節點上的多個 Pod 訪問卷。- ReadOnlyMany ? ? ? ? ? #(ROX)卷可以被多個節點以只讀方式掛載。- ReadWriteMany ? ? ? ? ?#(RWX)卷可以被多個節點以讀寫方式掛載。
#nfs 支持全部三種;iSCSI 不支持 ReadWriteMany(iSCSI 就是在 IP 網絡上運行 SCSI 協議的一種網絡存儲技術);HostPath 不支持 ReadOnlyMany 和 ReadWriteMany。capacity:(定義存儲能力,一般用于設置存儲空間)storage: 2Gi (指定大小)storageClassName: (自定義存儲類名稱,此配置用于綁定具有相同類別的PVC和PV)persistentVolumeReclaimPolicy: Retain ? ?#回收策略(Retain/Delete/Recycle)
#Retain(保留):當用戶刪除與之綁定的PVC時候,這個PV被標記為released(PVC與PV解綁但還沒有執行回收策略)且之前的數據依然保存在該PV上,但是該PV不可用,需要手動來處理這些數據并刪除該PV。
#Delete(刪除):刪除與PV相連的后端存儲資源。對于動態配置的PV來說,默認回收策略為Delete。表示當用戶刪除對應的PVC時,動態配置的volume將被自動刪除。(只有 AWS EBS, GCE PD, Azure Disk 和 Cinder 支持)
#Recycle(回收):如果用戶刪除PVC,則刪除卷上的數據,卷不會刪除。(只有 NFS 和 HostPath 支持)
kubectl explain pvc ? #查看PVC的定義方式
KIND: ? ? PersistentVolumeClaim
VERSION: ?v1
FIELDS:apiVersion?? ?<string>kind?? ?<string> ?metadata?? ?<Object>spec?? ?<Object>
#PV和PVC中的spec關鍵字段要匹配,比如存儲(storage)大小、訪問模式(accessModes)、存儲類名稱(storageClassName)
kubectl explain pvc.spec
spec:accessModes: (定義訪問模式,必須是PV的訪問模式的子集)resources:requests:storage: (定義申請資源的大小)storageClassName: (定義存儲類名稱,此配置用于綁定具有相同類別的PVC和PV)

靜態PV創建

1、配置nfs存儲

mkdir z{1,2,3,4,5}
vim /etc/exports
/opt/z1 192.168.110.0/24(rw,no_root_squash)
/opt/z2 192.168.110.0/24(rw,no_root_squash)
/opt/z3 192.168.110.0/24(rw,no_root_squash)
/opt/z4 192.168.110.0/24(rw,no_root_squash)
/opt/z5 192.168.110.0/24(rw,no_root_squash)
exportfs -arvshowmount -e

2、定義PV

?這里定義5個PV,并且定義掛載的路徑以及訪問模式,還有PV劃分的大小。

vim pv-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:name: pv001labels:name: pv001
spec:nfs:path: /data/volumes/v1server: 192.168.110.60accessModes: ["ReadWriteMany","ReadWriteOnce"]capacity:storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv002labels:name: pv002
spec:nfs:path: /data/volumes/v2server: 192.168.110.60accessModes: ["ReadWriteOnce"]capacity:storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv003labels:name: pv003
spec:nfs:path: /data/volumes/v3server: 192.168.110.60accessModes: ["ReadWriteMany","ReadWriteOnce"]capacity:storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv004labels:name: pv004
spec:nfs:path: /data/volumes/v4server: 192.168.110.60accessModes: ["ReadWriteMany","ReadWriteOnce"]capacity:storage: 4Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv005labels:name: pv005
spec:nfs:path: /data/volumes/v5server: 192.168.110.60accessModes: ["ReadWriteMany","ReadWriteOnce"]capacity:storage: 5Gi
kubectl apply -f pv-demo.yaml
kubectl get pv
NAME ? ? ?CAPACITY ? ACCESS MODES ? RECLAIM POLICY ? STATUS ? ? ?CLAIM ? ? STORAGECLASS ? REASON ? ?AGE
pv001 ? ? 1Gi ? ? ? ?RWO,RWX ? ? ? ?Retain ? ? ? ? ? Available ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?7s
pv002 ? ? 2Gi ? ? ? ?RWO ? ? ? ? ? ?Retain ? ? ? ? ? Available ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?7s
pv003 ? ? 2Gi ? ? ? ?RWO,RWX ? ? ? ?Retain ? ? ? ? ? Available ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?7s
pv004 ? ? 4Gi ? ? ? ?RWO,RWX ? ? ? ?Retain ? ? ? ? ? Available ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?7s
pv005 ? ? 5Gi ? ? ? ?RWO,RWX ? ? ? ?Retain ? ? ? ? ? Available ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ??? ??? ?7s

3、定義PVC

這里定義了pvc的訪問模式為多路讀寫,該訪問模式必須在前面pv定義的訪問模式之中。定義PVC申請的大小為2Gi,此時PVC會自動去匹配多路讀寫且大小為2Gi的PV,匹配成功獲取PVC的狀態即為Bound

vim pod-vol-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: mypvcnamespace: default
spec:accessModes: ["ReadWriteMany"]resources:requests:storage: 2Gi
---
apiVersion: v1
kind: Pod
metadata:name: pod-vol-pvcnamespace: default
spec:containers:- name: myappimage: ikubernetes/myapp:v1volumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlvolumes:- name: htmlpersistentVolumeClaim:claimName: mypvc
kubectl apply -f pod-vol-pvc.yaml
kubectl get pv
NAME ? ? ?CAPACITY ? ACCESS MODES ? RECLAIM POLICY ? STATUS ? ? ?CLAIM ? ? ? ? ? STORAGECLASS ? REASON ? ?AGE
pv001 ? ? 1Gi ? ? ? ?RWO,RWX ? ? ? ?Retain ? ? ? ? ? Available ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?19m
pv002 ? ? 2Gi ? ? ? ?RWO ? ? ? ? ? ?Retain ? ? ? ? ? Available ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?19m
pv003 ? ? 2Gi ? ? ? ?RWO,RWX ? ? ? ?Retain ? ? ? ? ? Bound ? ? ? default/mypvc ? ? ? ? ? ? ? ? ? ? ? ? ? ?19m
pv004 ? ? 4Gi ? ? ? ?RWO,RWX ? ? ? ?Retain ? ? ? ? ? Available ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?19m
pv005 ? ? 5Gi ? ? ? ?RWO,RWX ? ? ? ?Retain ? ? ? ? ? Available ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?19m
kubectl get pvc
NAME ? ? ?STATUS ? ?VOLUME ? ?CAPACITY ? ACCESS MODES ? STORAGECLASS ? AGE
mypvc ? ? Bound ? ? pv003 ? ? 2Gi ? ? ? ?RWO,RWX ? ? ? ? ? ? ? ? ? ? ? 22s

4、測試訪問

在存儲服務器上創建index.html,并寫入數據,通過訪問Pod進行查看,可以獲取到相應的頁面。

cd /opt/v3/
echo "ggl" > index.html
kubectl get pods -o wide
pod-vol-pvc ? ? ? ? ? ? 1/1 ? ? ? Running ? 0 ? ? ? ? ?3m ? ? ? ?10.244.2.39 ? k8s-node02
curl ?10.244.2.39
ggl

動態PV創建

搭建 StorageClass + nfs-client-provisioner ,實現 NFS 的動態 PV 創建

Kubernetes 本身支持的動態 PV 創建不包括 NFS,所以需要使用外部存儲卷插件分配PV。詳見:https://kubernetes.io/zh/docs/concepts/storage/storage-classes/

卷插件稱為 Provisioner(存儲分配器),NFS 使用的是 nfs-client,這個外部卷插件會使用已經配置好的 NFS 服務器自動創建 PV。
Provisioner:用于指定 Volume 插件的類型,包括內置插件(如 kubernetes.io/aws-ebs)和外部插件(如 external-storage 提供的 ceph.com/cephfs)。

1、在stor01節點上安裝nfs,并配置nfs服務

?

yum install -y rpcbind nfs-utils
mkdir /opt/ycx
chmod 777 /opt/ycx/
vim /etc/exports
/opt/k8s 192.168.110.0/24(rw,no_root_squash,sync)
systemctl restart nfs

2、創建 Service Account,用來管理 NFS Provisioner 在 k8s 集群中運行的權限,設置 nfs-client 對 PV,PVC,StorageClass 等的規則

vim nfs-client-rbac.yaml
#創建 Service Account 賬戶,用來管理 NFS Provisioner 在 k8s 集群中運行的權限
apiVersion: v1
kind: ServiceAccount
metadata:name: nfs-client-provisioner
---
#創建集群角色
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:name: nfs-client-provisioner-clusterrole
rules:- apiGroups: [""]resources: ["persistentvolumes"]verbs: ["get", "list", "watch", "create", "delete"]- apiGroups: [""]resources: ["persistentvolumeclaims"]verbs: ["get", "list", "watch", "update"]- apiGroups: ["storage.k8s.io"]resources: ["storageclasses"]verbs: ["get", "list", "watch"]- apiGroups: [""]resources: ["events"]verbs: ["list", "watch", "create", "update", "patch"]- apiGroups: [""]resources: ["endpoints"]verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
---
#集群角色綁定
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: nfs-client-provisioner-clusterrolebinding
subjects:
- kind: ServiceAccountname: nfs-client-provisionernamespace: default
roleRef:kind: ClusterRolename: nfs-client-provisioner-clusterroleapiGroup: rbac.authorization.k8s.io
kubectl apply -f nfs-client-rbac.yaml

3、使用 Deployment 來創建 NFS Provisioner

NFS Provisioner(即 nfs-client),有兩個功能:一個是在 NFS 共享目錄下創建掛載點(volume),另一個則是將 PV 與 NFS 的掛載點建立關聯。

#由于 1.20 版本啟用了 selfLink,所以 k8s 1.20+ 版本通過 nfs provisioner 動態生成pv會報錯,解決方法如下:

vim /etc/kubernetes/manifests/kube-apiserver.yaml
spec:containers:- command:- kube-apiserver- --feature-gates=RemoveSelfLink=false ? ? ? #添加這一行- --advertise-address=192.168.80.20
......

方法一

kubectl apply -f /etc/kubernetes/manifests/kube-apiserver.yaml
kubectl delete pods kube-apiserver -n kube-system?
kubectl get pods -n kube-system | grep apiserver

方法二

mv?/etc/kubernetes/manifests/kube-apiserver.yaml /opt
mv /opt/kube-apiserver.yaml?/etc/kubernetes/manifests

創建 NFS Provisioner

vim nfs-client-provisioner.yaml
kind: Deployment
apiVersion: apps/v1
metadata:name: nfs-client-provisioner
spec:replicas: 1selector:matchLabels:app: nfs-client-provisionerstrategy:type: Recreatetemplate:metadata:labels:app: nfs-client-provisionerspec:serviceAccountName: nfs-client-provisioner ? ?? ? ?#指定Service Account賬戶containers:- name: nfs-client-provisionerimage: quay.io/external_storage/nfs-client-provisioner:latestimagePullPolicy: IfNotPresentvolumeMounts:- name: nfs-client-rootmountPath: /persistentvolumesenv:- name: PROVISIONER_NAMEvalue: nfs-storage ? ? ? #配置provisioner的Name,確保該名稱與StorageClass資源中的provisioner名稱保持一致- name: NFS_SERVERvalue: 192.168.110.60 ? ? ? ? #配置綁定的nfs服務器- name: NFS_PATHvalue: /opt/ycx ? ? ? ? ?#配置綁定的nfs服務器目錄volumes: ? ? ? ? ? ? ?#申明nfs數據卷- name: nfs-client-rootnfs:server: 192.168.110.60path: /opt/ycx
kubectl apply -f nfs-client-provisioner.yaml?
kubectl get pod
NAME ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? READY ? STATUS ? ?RESTARTS ? AGE
nfs-client-provisioner-cd6ff67-sp8qd ? 1/1 ? ? Running ? 0 ? ? ? ? ?14s

4、創建 StorageClass,負責建立 PVC 并調用 NFS provisioner 進行預定的工作,并讓 PV 與 PVC 建立關聯

vim nfs-client-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: nfs-client-storageclass
provisioner: nfs-storage ? ? #這里的名稱要和provisioner配置文件中的環境變量PROVISIONER_NAME保持一致
parameters:archiveOnDelete: "false" ? #false表示在刪除PVC時不會對數據目錄進行打包存檔,即刪除數據;為ture時就會自動對數據目錄進行打包存檔,存檔文件以archived開頭
kubectl apply -f nfs-client-storageclass.yaml
kubectl get storageclass
NAME ? ? ? ? ? ? ? ? ? ? ?PROVISIONER ? RECLAIMPOLICY ? VOLUMEBINDINGMODE ? ALLOWVOLUMEEXPANSION ? AGE
nfs-client-storageclass ? nfs-storage ? Delete ? ? ? ? ?Immediate ? ? ? ? ? false ? ? ? ? ? ? ? ? ?43s

5、創建 PVC 和 Pod 測試

vim test-pvc-pod.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: test-nfs-pvc#annotations: volume.beta.kubernetes.io/storage-class: "nfs-client-storageclass" ? ? #另一種SC配置方式
spec:accessModes:- ReadWriteManystorageClassName: nfs-client-storageclass ? ?#關聯StorageClass對象resources:requests:storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:name: test-storageclass-pod
spec:containers:- name: busyboximage: busybox:latestimagePullPolicy: IfNotPresentcommand:- "/bin/sh"- "-c"args:- "sleep 3600"volumeMounts:- name: nfs-pvcmountPath: /mntrestartPolicy: Nevervolumes:- name: nfs-pvcpersistentVolumeClaim:claimName: test-nfs-pvc ? ? ?#與PVC名稱保持一致
kubectl apply -f test-pvc-pod.yaml

PVC 通過 StorageClass 自動申請到空間

kubectl get pvc
NAME ? ? ? ? ? ?STATUS ? VOLUME ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? CAPACITY ? ACCESS MODES ? STORAGECLASS ? ? ? ? ? ? ?AGE
test-nfs-pvc ? Bound ? ?pvc-11670f39-782d-41b8-a842-eabe1859a456 ? 1Gi ? ? ? ?RWX ? ? ? ? ? ?nfs-client-storageclass ? 2s

查看 NFS 服務器上是否生成對應的目錄,自動創建的 PV 會以

${namespace}-${pvcName}-${pvName} 的目錄格式放到 NFS 服務器上
ls /opt/ycx/
default-test-nfs-pvc-pvc-11670f39-782d-41b8-a842-eabe1859a456

進入 Pod 在掛載目錄 /mnt 下寫一個文件,然后查看 NFS 服務器上是否存在該文件

kubectl exec -it test-storageclass-pod sh
/ # cd /mnt/
/mnt # echo 'ggl' > test.txt

發現 NFS 服務器上存在,說明驗證成功

cat /opt/ycx/test.txt
ggl


?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/41074.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/41074.shtml
英文地址,請注明出處:http://en.pswp.cn/news/41074.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

計算機視覺之三維重建(二)(攝像機標定)

標定示意圖 標定目標 P ′ M P w K [ R T ] P w P^{}MP_wK[R \space T]P_w P′MPw?K[R T]Pw? 其中 K K K為內參數&#xff0c; [ R T ] [R \space T] [R T]為外參數。該式子需要使用至少六對內外點對進行求解內外參數&#xff08;11個未知參數&#xff09;。 其中 R 3 3 …

windows系統丟失mfc120u.dll的解決方法

1.mfc120u.dll是什么 mfc120u.dll是Windows操作系統中的一個動態鏈接庫&#xff08;Dynamic Link Library&#xff0c;簡稱DLL&#xff09;文件。它包含了一些用于運行C程序的函數和其他資源。這個特定的DLL文件是Microsoft Foundation Classes&#xff08;MFC&#xff09;庫的…

freeswitch的mod_xml_curl模塊動態獲取configuration

概述 freeswitch是一款簡單好用的VOIP開源軟交換平臺。 mod_xml_curl模塊支持從web服務獲取xml配置&#xff0c;本文介紹如何動態獲取acl配置。 環境 centos&#xff1a;CentOS release 7.0 (Final)或以上版本 freeswitch&#xff1a;v1.6.20 GCC&#xff1a;4.8.5 web…

第2章 性能測量

理解應用程序性能的第一步是學會對它進行測量。 與絕大多數功能問題相比&#xff0c;性能問題通常很難跟蹤和復現。 任何關注過性能評估的人可能都知道公允地進行性能測量并從中得到準確結論是多么困難。 因為在測量中存在誤差&#xff0c;性能分析通常需要統計方法進行處理…

ThreadLocal(超詳細介紹!!)

關于ThreadLocal&#xff0c;可能很多同學在學習Java的并發編程部分時&#xff0c;都有所耳聞&#xff0c;但是如果要仔細問ThreadLocal是個啥&#xff0c;我們可能也說不清楚&#xff0c;所以這篇博客旨在幫助大家了解ThreadLocal到底是個啥&#xff1f; 1.ThreadLocal是什么&…

Android設備通過藍牙HID技術模擬鍵盤實現

目錄 一&#xff0c;背景介紹 二&#xff0c;技術方案 2.1 獲取BluetoothHidDevice實例 2.2 注冊/解除注冊HID實例 2.3 Hid report description描述符生成工具 2.4 鍵盤映射表 2.5 通過HID發送鍵盤事件 三&#xff0c;實例 一&#xff0c;背景介紹 日常生活中&#xff0…

AndroidStudio中修改打包生成的apk名稱

1.配置手機架構 splits {abi {enable truereset()include armeabi-v7a,arm64-v8auniversalApk false} } 2.多渠道 productFlavors {normal {applicationId "*****"manifestPlaceholders [appName: "string/app_name_normal"]}driver {applicationId &qu…

圖片轉換成pdf格式?這幾種轉換格式方法了解一下

圖片轉換成pdf格式&#xff1f;將圖片轉換成PDF格式的好處有很多。首先&#xff0c;PDF格式具有通用性&#xff0c;可以在幾乎任何設備上查看。其次&#xff0c;PDF格式可以更好地保護文件&#xff0c;防止被篡改或者復制。此外&#xff0c;PDF格式還可以更好地壓縮文件大小&am…

使用Kaptcha生成驗證碼

說明&#xff1a;驗證碼&#xff0c;是登錄流程中必不可少的一環&#xff0c;一般企業級的系統&#xff0c;使用都是專門制作驗證碼、審核校驗的第三方SDK&#xff08;如極驗&#xff09;。本文介紹&#xff0c;使用谷歌提供的Kaptcha技術&#xff0c;制作一個簡單的驗證碼。 …

sqlserver數據庫導出到mysql

愛到分才顯珍貴&#xff0c;很多人都不懂珍惜擁有&#xff0c;只到失去才看到&#xff0c;其實那最熟悉的才最珍貴的。 這里只介紹一種方式&#xff0c;有很多的方式。 1.使用Navicat 安裝 下載 2.工具 數據傳輸 3.選擇源和目標 然后開始 4.最好導入前備份一下庫

【KVM虛擬化環境部署】

環境部署 KVM虛擬化環境 1、裝系統時手動選擇安裝 2、CentOS 7 最小化安裝 yum install qemu-kvm qemu-img libvirt -y yum install virt-install libvirt-python virt-manager python-virtinst libvirt-client -y安裝好CentOS 7后&#xff0c;去設置里面點擊處理器&#x…

4.0 Spring Boot入門

1. Spring Boot概述 Spring Boot介紹 Spring Boot是Pivotal團隊在2014年推出的全新框架&#xff0c;主要用于簡化Spring項目的開發過程&#xff0c;可以使用最少的配置快速創建Spring項目。 Spring Boot版本 2014年4月v1.0.0.RELEASE發布。 ? 2.Spring Boot特性 約定優于配…

docker-compose部署可道云

文章目錄 一. Mac1.1 下載源碼1.2 部署1.2.1 修改密碼部署(可忽略)1.2.2 直接部署 1.3 卸載1.4 訪問 二. Win2.1 下載源碼2.2 部署2.2.1 修改密碼部署(可忽略)2.2.2 直接部署 2.3 卸載 一. Mac 1.1 下載源碼 mkdir -p /Users/wanfei/docker-compose && cd /Users/wan…

mysql 數據備份和恢復

操作系統&#xff1a;22.04.1-Ubuntu mysql 版本&#xff1a;8.033 binlog 介紹 binlog 是mysql 二進制日志 binary log的簡稱&#xff0c;可以簡單理解為數據的修改記錄。 需要開啟binlog,才會產生文件&#xff0c;mysql 8.0 默認開啟,開啟后可以在 /var/lib/mysql &#xff…

技術債 筆記

目錄 1. 技術債 筆記1.1. 什么是技術債1.2. 討論1.3. 國內技術從業者怎么看? 1. 技術債 筆記 1.1. 什么是技術債 1992 年, Ward Cunningham 在敏捷宣言中首次提出了"技術債"概念, 主要指有意或無意地做了錯誤的或不理想的技術決策所累積的債務。隨后, 《重構》一書…

sql中union all、union、intersect、minus的區別圖解,測試

相關文章 sql 的 join、left join、full join的區別圖解總結&#xff0c;測試&#xff0c;注意事項 1. 結論示意圖 對于intersect、minus&#xff0c;oracle支持&#xff0c;mysql不支持&#xff0c;可以變通&#xff08;in或exists&#xff09;實現 2.測試 2.1.創建表和數…

vue pc端項目el-upload上傳圖片時加水印

html代碼&#xff1a; <a-uploadclass"avatar-uploader"list-type"picture-card":file-list"uploadFileList":custom-request"uploadDoneHandle":before-upload"beforeUpload":remove"removeHandle"v-decorat…

案例21 基于Spring Boot+Redis實現圖書信息按書號存儲案例

1. 案例需求 基于Spring BootRedis實現圖書信息按書號存儲和取出功能&#xff0c;數據存儲至Redis。 2. 創建Spring Boot項目 創建Spring Boot項目&#xff0c;項目名稱為springboot-redis02。 3. 選擇依賴 ? pom.xml文件內容如下所示&#xff1a; <?xml version&quo…

瀏覽器控制臺調試代碼和JavaScript控制臺方法介紹

瀏覽器控制臺調試代碼和JavaScript控制臺方法介紹 瀏覽器控制臺調試代碼 瀏覽器控制臺&#xff08;Console&#xff09;是瀏覽器提供的一個開發工具&#xff0c;用于在瀏覽器中執行和調試 JavaScript 代碼。它提供了一個交互式環境&#xff0c;可以輸入 JavaScript 代碼&#…

Qt:隱式內存共享

隱式內存共享 Many C classes in Qt use implicit data sharing to maximize resource usage and minimize copying. Implicitly shared classes are both safe and efficient when passed as arguments, because only a pointer to the data is passed around, and the data i…