k8s集群中安裝rook-ceph


容器的持久化存儲

容器的持久化存儲是保存容器存儲狀態的重要手段,存儲插件會在容器里掛載一個基於網絡或者其他機制的遠程數據卷,使得在容器里創建的文件,實際上是保存在遠程存儲服務器上,或者以分布式的方式保存在多個節點上,而與當前宿主機沒有任何綁定關系。這樣,無論你在其他哪個宿主機上啟動新的容器,都可以請求掛載指定的持久化存儲卷,從而訪問到數據卷里保存的內容。由於 Kubernetes 本身的松耦合設計,絕大多數存儲項目,比如 Ceph、GlusterFS、NFS 等,都可以為 Kubernetes 提供持久化存儲能力。

Rook 、ceph簡介

Ceph分布式存儲系統

Ceph是一種高度可擴展的分布式存儲解決方案,提供對象、文件和塊存儲。在每一個存儲節點上,您將找到Ceph存儲對象的文件系統和Ceph OSD(對象存儲守護程序)進程。在Ceph集群上,您還能夠找到Ceph MON(監控)守護程序,它們確保Ceph集群保持高可用性。

Rook

Rook 是一個開源的cloud-native storage編排, 提供平台和框架;為各類存儲解決方案提供平台、框架和支持,以便與雲原生環境本地集成。
Rook 將存儲軟件轉變為自我管理、自我擴展和自我修復的存儲服務,它經過自動化部署、引導、配置、置備、擴展、升級、遷移、災難恢復、監控和資源管理來實現此目的。
Rook 使用底層雲本機容器管理、調度和編排平台提供的工具來實現它自身的功能。
Rook 目前支持Ceph、NFS、Minio Object Store和CockroachDB。
Rook使用Kubernetes原語使Ceph存儲系統能夠在Kubernetes上運行。下圖說明了Ceph Rook如何與Kubernetes集成:

隨着Rook在Kubernetes集群中運行,Kubernetes應用程序可以掛載由Rook管理的塊設備和文件系統,或者可以使用S3 / Swift API提供對象存儲。Rook oprerator自動配置存儲組件並監控群集,以確保存儲處於可用和健康狀態。
Rook oprerator是一個簡單的容器,具有引導和監視存儲集群所需的全部功能。oprerator將啟動並監控ceph monitor pods和OSDs的守護進程,它提供基本的RADOS存儲。oprerator通過初始化運行服務所需的pod和其他組件來管理池,對象存儲(S3 / Swift)和文件系統的CRD。
oprerator將監視存儲后台駐留程序以確保群集正常運行。Ceph mons將在必要時啟動或故障轉移,並在群集增長或縮小時進行其他調整。oprerator還將監視api服務請求的所需狀態更改並應用更改。
Rook oprerator還創建了Rook agent。這些agent是在每個Kubernetes節點上部署的pod。每個agent都配置一個Flexvolume插件,該插件與Kubernetes的volume controller集成在一起。處理節點上所需的所有存儲操作,例如附加網絡存儲設備,安裝卷和格式化文件系統。

該rook容器包括所有必需的Ceph守護進程和工具來管理和存儲所有數據 - 數據路徑沒有變化。 rook並沒有試圖與Ceph保持完全的忠誠度。 許多Ceph概念(如placement groups和crush maps)都是隱藏的,因此您無需擔心它們。 相反,Rook為管理員創建了一個簡化的用戶體驗,包括物理資源,池,卷,文件系統和buckets。 同時,可以在需要時使用Ceph工具應用高級配置。
Rook在golang中實現。Ceph在C ++中實現,其中數據路徑被高度優化。

前期准備

1.已有一個能夠正常跑應用的k8s集群
2.在集群中至少有三個節點可用,滿足ceph高可用要求,而且每個服務器具有一塊未格式化未分區的硬盤。
我這邊使用的環境是VMware workstation,一個msater倆worker,每個主機各新增一個100G的磁盤。(已配置master節點使其支持運行pod。)
不重啟系統,重新掃描scsi總線查看到新添加的磁盤。詳看文章:https://www.cnblogs.com/sanduzxcvbnm/p/14841818.html

3.rook-ceph項目地址:https://github.com/rook/rookbash
部署文檔: https://github.com/rook/rook/blob/master/Documentation/ceph-quickstart.md
4.rook使用存儲方式
rook默認使用全部節點的全部資源,rook operator自動在全部節點上啟動OSD設備,Rook會用以下標准監控並發現可用設備:

  • 設備沒有分區
  • 設備沒有格式化的文件系統
  • Rook不會使用不知足以上標准的設備。另外也能夠經過修改配置文件,指定哪些節點或者設備會被使用。
    5.無另外說明,以下全部操作都在master節點執行。

添加新磁盤

在所有節點添加1塊100GB的新磁盤:/dev/sdc,作為OSD盤,提供存儲空間,添加完成后掃描磁盤,確保主機能夠正常識別到: (新添加的磁盤不用掛載配置到/etc/fstab上)

#掃描 SCSI總線並添加 SCSI 設備
for host in $(ls /sys/class/scsi_host) ; do echo "- - -" > /sys/class/scsi_host/$host/scan; done

#重新掃描 SCSI 總線
for scsi_device in $(ls /sys/class/scsi_device/); do echo 1 > /sys/class/scsi_device/$scsi_device/device/rescan; done

#查看已添加的磁盤,能夠看到sdb說明添加成功
lsblk

本次搭建的基本原理圖:

事先准備好使用的鏡像

須要用到的鏡像,部署服務前首先得將鏡像導入
rook/ceph:v1.6.3
ceph/ceph:v15.2.11
quay.io/cephcsi/cephcsi:v3.1.1.4

# 如下這些鏡像會從k8s.gcr.io中拉取,網絡的問題拉取不到,這里采用從其他地方拉取,然后重新tag的方法
k8s.gcr.io/sig-storage/csi-snapshotter:v4.0.0  
docker pull antmoveh/csi-snapshotter:v4.0.0
docker tag antmoveh/csi-snapshotter:v4.0.0 k8s.gcr.io/sig-storage/csi-snapshotter:v4.0.0 

k8s.gcr.io/sig-storage/csi-provisioner:v2.0.4
docker pull antmoveh/csi-provisioner:v2.0.4
docker tag antmoveh/csi-provisioner:v2.0.4 k8s.gcr.io/sig-storage/csi-provisioner:v2.0.4

k8s.gcr.io/sig-storage/csi-resizer:v1.0.1
docker pull antmoveh/csi-resizer:v1.0.1
docker tag antmoveh/csi-resizer:v1.0.1 k8s.gcr.io/sig-storage/csi-resizer:v1.0.1

k8s.gcr.io/sig-storage/csi-attacher:v3.0.2
docker pull antmoveh/csi-attacher:v3.0.2
docker tag antmoveh/csi-attacher:v3.0.2 k8s.gcr.io/sig-storage/csi-attacher:v3.0.2

k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.0.1
docker pull antmoveh/csi-node-driver-registrar:v2.0.1 
docker tag  antmoveh/csi-node-driver-registrar:v2.0.1 k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.0.1

部署Rook Operator

安裝

# 克隆指定版本
git clone --single-branch --branch v1.6.3 https://github.com/rook/rook.git

# 進入到目錄
cd rook/cluster/examples/kubernetes/ceph

#全部的pod都會在rook-ceph命名空間下建立
kubectl create -f common.yaml

# k8s1.15版本及其以上的需要這個
kubectl create -f crds.yaml 

#部署Rook操做員
kubectl create -f operator.yaml

# 在繼續操作之前,驗證 rook-ceph-operator 是否處於“Running”狀態:
kubectl get pod -n rook-ceph

創建 Rook Ceph 集群

kubectl create -f cluster.yaml

# 通過 kubectl 來查看 rook-ceph 命名空間下面的 Pod 狀態
kubectl get pods -n rook-ceph
# OSD Pod 的數量將取決於集群中的節點數量以及配置的設備和目錄的數量

# 如果要刪除已創建的Ceph集群,可執行命令:kubectl delete -f cluster.yaml

Rook 工具箱---Ceph toolbox 命令行工具

# 驗證集群是否處於正常狀態,可以使用 Rook 工具箱,Rook 工具箱是一個用於調試和測試 Rook 的常用工具容器,該工具基於 CentOS 鏡像,所以可以使用 yum 來輕松安裝更多的工具包。
# 默認啟動的Ceph集群,是開啟Ceph認證的,這樣你登錄Ceph組件所在的Pod里,是無法去獲取集群狀態,以及執行CLI命令,這時須要部署Ceph toolbox,命令如下
kubectl create -f toolbox.yaml

# 一旦 toolbox 的 Pod 運行成功后,就可以使用下面的命令進入到工具箱內部進行操作:
# 進入ceph tool容器
kubectl exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') -n rook-ceph -- bash

#查看ceph狀態
# ceph status

  cluster:
    id:     b0228f2b-d0f4-4a6e-9c4f-9d826401fac2
    health: HEALTH_WARN
            mons are allowing insecure global_id reclaim
 
  services:
    mon: 3 daemons, quorum a,b,c (age 90m)
    mgr: a(active, since 87m)
    mds: myfs:1 {0=myfs-b=up:active} 1 up:standby-replay
    osd: 3 osds: 3 up (since 88m), 3 in (since 5h)
 
  data:
    pools:   4 pools, 97 pgs
    objects: 22 objects, 2.2 KiB
    usage:   3.2 GiB used, 297 GiB / 300 GiB avail
    pgs:     97 active+clean
 
  io:
    client:   852 B/s rd, 1 op/s rd, 0 op/s wr

#查看osd狀態
# ceph osd status

ID  HOST               USED  AVAIL  WR OPS  WR DATA  RD OPS  RD DATA  STATE      
 0  develop-worker-2  1089M  98.9G      0        0       0        0   exists,up  
 1  develop-worker-1  1089M  98.9G      0        0       1      105   exists,up  
 2  develop-master-1  1089M  98.9G      0        0       0        0   exists,up 

# ceph df

--- RAW STORAGE ---
CLASS  SIZE     AVAIL    USED     RAW USED  %RAW USED
hdd    300 GiB  297 GiB  195 MiB   3.2 GiB       1.06
TOTAL  300 GiB  297 GiB  195 MiB   3.2 GiB       1.06
 
--- POOLS ---
POOL                   ID  PGS  STORED   OBJECTS  USED     %USED  MAX AVAIL
device_health_metrics   1    1      0 B        0      0 B      0     94 GiB
replicapool             2   32      0 B        0      0 B      0     94 GiB
myfs-metadata           3   32  2.2 KiB       22  1.5 MiB      0     94 GiB
myfs-data0              4   32      0 B        0      0 B      0     94 GiB

# rados df

POOL_NAME                 USED  OBJECTS  CLONES  COPIES  MISSING_ON_PRIMARY  UNFOUND  DEGRADED  RD_OPS       RD  WR_OPS      WR  USED COMPR  UNDER COMPR
device_health_metrics      0 B        0       0       0                   0        0         0       0      0 B       0     0 B         0 B          0 B
myfs-data0                 0 B        0       0       0                   0        0         0       0      0 B       0     0 B         0 B          0 B
myfs-metadata          1.5 MiB       22       0      66                   0        0         0    2496  1.2 MiB      45  13 KiB         0 B          0 B
replicapool                0 B        0       0       0                   0        0         0       0      0 B       0     0 B         0 B          0 B

total_objects    22
total_used       3.2 GiB
total_avail      297 GiB
total_space      300 GiB

#至此已經部署完成了,查看rook-ceph命名空間下的pod,首先看pod的狀況,有operator、mgr、agent、discover、mon、osd、tools,且osd-prepare是completed的狀態,其它是running的狀態
![](https://img2020.cnblogs.com/blog/794174/202106/794174-20210603114332076-345391793.png)

比如現在我們要查看集群的狀態,需要滿足下面的條件才認為是健康的:

  • 所有 mons 應該達到法定數量
  • mgr 應該是激活狀態
  • 至少有一個 OSD 處於激活狀態
  • 如果不是 HEALTH_OK 狀態,則應該查看告警或者錯誤信息

Ceph Dashboard

Ceph 有一個 Dashboard 工具,可以在上面查看集群的狀態,包括總體運行狀態,mgr、osd 和其他 Ceph 進程的狀態,查看池和 PG 狀態,以及顯示守護進程的日志等等。

可以在上面的 cluster CRD 對象中開啟 dashboard,設置 dashboard.enable=true即可,這樣 Rook Operator 就會啟用 ceph-mgr dashboard 模塊,(默認這個是開啟的)並將創建一個 Kubernetes Service 來暴露該服務,將啟用端口 8443進行 https 訪問,如果 Ceph 集群部署成功了,可以使用下面的命令來查看 Dashboard 的 Service:kubectl get service -n rook-ceph

這里的 rook-ceph-mgr 服務用於報告 Prometheus metrics 指標數據的,而后面的的 rook-ceph-mgr-dashboard 服務就是我們的 Dashboard 服務,如果在集群內部我們可以通過 DNS 名稱 http://rook-ceph-mgr-dashboard.rook-ceph:8443或者 CluterIP http://10.3.255.193:8443來進行訪問,但是如果要在集群外部進行訪問的話,我們就需要通過 Ingress 或者 NodePort 類型的 Service 來暴露了。
有如下兩種方式

# 暴露方式有多種選擇適合本身的一個便可
https://github.com/rook/rook/blob/master/Documentation/ceph-dashboard.md

第一種方式是修改rook-ceph-mgr-dashboard,原先是cluster ip,修改成nodeport形式就可以訪問了。
#執行完cluster.yaml后rook會自動幫咱們建立ceph的Dashboard,pod及service以下圖,默認dashboard為ClusterIP,須要咱們改成NodePort對外暴露服務。
kubectl  edit svc rook-ceph-mgr-dashboard -n rook-ceph

在訪問的時候需要登錄才能夠訪問,Rook 創建了一個默認的用戶 admin,並在運行 Rook 的命名空間中生成了一個名為 rook-ceph-dashboard-admin-password 的 Secret,要獲取密碼,可以運行以下命令:
kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}" | base64 --decode && echo

訪問地址,注意是https,http會訪問不成功
用上面獲得的密碼和用戶名 admin 就可以登錄 Dashboard 了,在 Dashboard 上面可以查看到整個集群的狀態


注意:使用后面的那個端口號,這個是節點端口
https://nodeip:32111

第二種方式
執行如下這個,根據實際情況修改,默認的8443端口已被占用
kubectl create -f  dashboard-external-https.yaml
創建完成后我們可以查看到新創建的 rook-ceph-mgr-dashboard-external 這個 Service 服務:

https://nodeip:32009

訪問Web Ceph Dashboard

Ceph Dashboard首頁,點擊admin修改登錄密碼


配置 Dashboard

除此之外在使用上面的 CRD 創建 ceph 集群的時候我們還可以通過如下的配置來配置 Dashboard:

spec:
  dashboard:
    urlPrefix: /ceph-dashboard
    port: 8443
    ssl: true
  • urlPrefix:如果通過反向代理訪問 Dashboard,則可能希望在 URL 前綴下來訪問,要讓 Dashboard 使用包含前綴的的鏈接,可以設置 urlPrefix
  • port:可以使用端口設置將為 Dashboard 提供服務的端口從默認值修改為其他端口,K8S 服務暴露的端口也會相應的更新
  • ssl:通過設置 ssl=false,可以在不使用 SSL 的情況下為 Dashboard 提供服務

監控

每個 Rook 群集都有一些內置的指標 collectors/exporters,用於使用 Prometheus 進行監控。

存儲

對於 Rook 暴露的三種存儲類型可以查看對應的文檔:

ceph分布式存儲使用

RBD

1.安裝rbd插件storageclass
# kubectl apply -f rook/cluster/examples/kubernetes/ceph/csi/rbd/storageclass.yaml

2.查看建立rbd結果
# kubectl  get storageclasses.storage.k8s.io
NAME              PROVISIONER                  RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
rook-ceph-block   rook-ceph.rbd.csi.ceph.com   Delete          Immediate              true                   11s

3.建立pvc指定storageClassName為rook-ceph-block框
![](https://img2020.cnblogs.com/blog/794174/202106/794174-20210603111234449-625695428.png)

CEPHFS安裝使用

1.安裝cephfs元數據存儲池及插件storageclass
kubectl  apply -f rook/cluster/examples/kubernetes/ceph/filesystem.yaml
kubectl  apply -f rook/cluster/examples/kubernetes/ceph/csi/cephfs/storageclass.yaml

2.以pod的形式部署在rook-ceph命名空間中,會有兩個pod。
kubectl -n rook-ceph get pod -l app=rook-ceph-mds

NAME                                    READY   STATUS    RESTARTS   AGE
rook-ceph-mds-myfs-a-54f64f7d6f-rgrv6   1/1     Running   0          19s
rook-ceph-mds-myfs-b-94f87f777-fd6fv    1/1     Running   0          17s

3.查看建立rbd結果
kubectl get storageclasses.storage.k8s.io

NAME              PROVISIONER                     RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
rook-ceph-block   rook-ceph.rbd.csi.ceph.com      Delete          Immediate              true                   12m
rook-cephfs       rook-ceph.cephfs.csi.ceph.com   Delete          Immediate              true                   57s

4.cephfs使用和rbd同樣指定storageClassName的值便可,須要注意的是rbd只支持ReadWriteOnce,cephfs能夠支持ReadWriteMany。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  namespace: default
  name: airflow-service-log-pvc
spec:
  accessModes:
    #- ReadWriteOnce
    - ReadWriteMany
  resources:
    requests:
      storage: 2Gi
  storageClassName: rook-cephfs

測試

安裝一個MySQL,使用storageClassName: rook-cephfs,可以查看到這個這次擴容

還能安裝CSI插件給PVC創建快照

故障修復

1.rook-ceph-crashcollector-k8s-master3-offline-217-d9ff847442ng7p  一直處於init狀態,輸入命令查看pod啟動狀態 kubectl  describe  pod rook-ceph-crashcollector-k8s-master3-offline-217-d9ff847442ng7p -n rook-ceph報錯信息如下:
MountVolume.SetUp failed for volume "rook-ceph-crash-collector-keyring" : secret "rook-ceph-crash-collector-keyring" not foun
修復過程:
刪除集群 
 kubectl  delete -f cluster.yaml
之后會一直卡在刪除的階段。
kubectl  edit customresourcedefinitions.apiextensions.k8s.io cephclusters.ceph.rook.io 
刪除文件中狀態兩行

每個節點都需要執行
rm -rf /var/lib/rook/*
rm -rf /var/lib/kubelet/plugins/rook-ceph.*
rm -rf /var/lib/kubelet/plugins_registry/rook-ceph.*

重新安裝,再次查看
kubectl create -f common.yaml
kubectl create -f operator.yaml
kubectl create -f cluster.yaml

2.現象:rook-ceph部分容器為一直創建的狀態
排查過程:查看pod狀態后發現缺少rook-ceph-csi-config文件,github相關資料https://github.com/rook/rook/issues/6162。大概原因是由於服務器重啟或者是服務器發生抖動,導致pod飄逸重建。重建失敗

解決方法:
kubectl delete -f rook/cluster/examples/kubernetes/ceph/operator.yaml 
kubectl apply -f rook/cluster/examples/kubernetes/ceph/common.yaml
kubectl apply -f rook/cluster/examples/kubernetes/ceph/operator.yaml

3.清理ceph集群

每個節點都需要執行
rm -rf /var/lib/rook/*
rm -rf /var/lib/kubelet/plugins/rook-ceph.*
rm -rf /var/lib/kubelet/plugins_registry/rook-ceph.*

https://rook.io/docs/rook/v1.4/ceph-teardown.html

ceph 歷史報錯回收

使用ceph -s查看集群狀態,發現一直有如下報錯,且數量一直在增加.經查當前系統運行狀態正常,判斷這里顯示的應該是歷史故障,處理方式如下:

查看歷史crash
ceph crash ls-new

根據ls出來的id查看詳細信息
ceph crash info <crash-id>

將歷史crash信息進行歸檔,即不再顯示
ceph crash archive <crash-id>

歸檔所有信息
ceph crash archive-all

ceph基礎運維命令

進入rook-ceph命令行工具pod
kubectl exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') -n rook-ceph -- bash

檢查Ceph集群狀態
ceph -s

如果需要實時觀察Ceph集群狀態變化,可使用如下命令
ceph -w 

檢查集群容量使用情況
ceph df

查看集群OSD配置
ceph osd df

查看OSD在集群布局中的設計分布
ceph osd tree

列式pool列表
ceph osd lspools

rook-ceph開啟S3 API接口

創建過程:
cd /opt/k8s-install/rook/cluster/examples/kubernetes/ceph
創建對象存儲,Rook操作員將創建啟動服務所需的所有池和其他資源。這可能需要三四分鍾才能完成
kubectl create -f object.yaml 
kubectl -n rook-ceph get pod -l app=rook-ceph-rgw

創建存儲桶,客戶端可以在其中讀取和寫入對象。可以通過定義存儲類來創建存儲桶,類似於塊存儲和文件存儲所使用的模式。首先,定義允許對象客戶端創建存儲桶的存儲類。存儲類定義對象存儲系統,存儲桶保留策略以及管理員所需的其他屬性
kubectl create -f storageclass-bucket-delete.yaml 

創建申請聲明。基於此存儲類,對象客戶端現在可以通過創建對象存儲桶聲明(OBC)來請求存儲桶。創建OBC后,Rook-Ceph存儲桶配置程序將創建一個新存儲桶。請注意,OBC引用了上面創建的存儲類。
kubectl create -f object-bucket-claim-delete.yaml 

創建集群外部訪問
Rook設置了對象存儲,因此Pod可以訪問群集內部。如果您的應用程序在集群外部運行,則需要通過來設置外部服務NodePort。
首先,請注意將RGW公開到群集內部的服務。我們將保留該服務不變,並為外部訪問創建一個新服務。
創建之前修改rgw-external.yaml,配置一個固定的nodeport端口例如38000
kubectl create -f rgw-external.yaml 

創建一個用戶 
如果您需要創建一組獨立的用戶憑據來訪問S3端點,請創建一個CephObjectStoreUser。該用戶將使用S3 API連接到集群中的RGW服務。用戶將獨立於您可能在本文檔前面的說明中創建的任何對象存儲桶聲明。

kubectl create -f object-user.yaml 

獲取用戶的AccessKey和SecretKey
這里建議先print 打印出來,之后再echo "xxxx"  | base64 --decode
kubectl -n rook-ceph get secret rook-ceph-object-user-my-store-my-user -o yaml | grep AccessKey | awk '{print $2}' | base64 --decode 
kubectl -n rook-ceph get secret rook-ceph-object-user-my-store-my-user -o yaml | grep SecretKey | awk '{print $2}' | base64 --decode

最終提供訪問的地址及認證信息

例如:
access_key = 'BMXG3WP8JA9D1GSD2AJJ'
secret_key = 'vl32x2t0sBxy0BEgcY9Iz442HK2HobPTNw4T99yK'
host = '192.168.10.237:38000'

rook-ceph1.4.1 升級到1.4.8

只需要導入兩個鏡像,之后重新apply operator.yaml即可,rook會自動檢查並升級重啟
docker load -i cephcsi.tar
docker load -i rook-ceph.tar
kubectl apply -f operator.yaml

問題

1.進入ceph tool容器后查看ceph狀態,會發現狀態是HEALTH_WARN,下面有一行提示:mons are allowing insecure global_id reclaim
解決辦法:禁用不安全模式

進入ceph tool容器后執行如下命令:
ceph config set mon auth_allow_insecure_global_id_reclaim false

稍后再次查看,ceph status就變成HEALTH_OK了

額外知識點

pv的三種訪問模式

ReadWriteOnce,RWO,僅可被單個節點讀寫掛載
ReadOnlyMany,ROX,可被多節點同時只讀掛載
ReadWriteMany,RWX,可被多節點同時讀寫掛載

pv回收策略

Retain,保持不動,由管理員手動回收
Recycle,空間回收,刪除全部文件,僅NFS和hostPath支持
Delete,刪除存儲卷,僅部分雲端存儲支持


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM