最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

kubernetes?volume數(shù)據(jù)存儲的使用解讀

 更新時間:2025年12月22日 09:11:37   作者:sxpnp  
文章介紹了Kubernetes中容器的生命周期、持久化存儲的實現(xiàn)方式,以及常見的存儲卷類型,包括EmptyDir、HostPath、NFS、PV、PVC、ConfigMap和Secret等,通過這些存儲卷和配置,可以實現(xiàn)Pod中容器之間的數(shù)據(jù)共享、持久化存儲以及敏感信息的管理

 寫在前面:如有問題,以你為準(zhǔn)

概述

容器的生命周期可能很短,會被頻繁的創(chuàng)建和銷毀

保存在容器中的數(shù)據(jù)也會被清除,所以要實現(xiàn)持久化存儲(Volume)

通過將本地目錄掛載到pod,一個目錄可以掛載到多個pod中的容器

Volume是Pod中能夠被多個容器訪問的共享目錄

通過Volume實現(xiàn)同一個Pod中不同容器之間的數(shù)據(jù)共享以及數(shù)據(jù)的持久化存儲

Volume的生命周期不和Pod中的單個容器的生命周期有關(guān),當(dāng)容器終止或者重啟的時候,Volume中的數(shù)據(jù)也不會丟失

kubernetes的Volume支持多種類型,比較常見的有下面的幾個:

  • 簡單存儲:EmptyDir、HostPath、NFS。
  • 高級存儲:PV、PVC。
  • 配置存儲:ConfigMap、Secret。

EmptyDir:pod中臨時存儲空間可以被多個容器掛載,實現(xiàn)共享目錄,pod刪除其也刪除

HostPath:將node上的目錄掛載到pod里面的容器里面,實現(xiàn)了持久化存儲,但是沒有實現(xiàn)存儲高可用

Kubernetes 目前支持多達(dá) 28 種數(shù)據(jù)卷類型(其中大部分特定于具體的云環(huán)境如 GCE/AWS/Azure 等)

非持久性存儲:

  • emptyDir
  • HostPath

網(wǎng)絡(luò)連接性存儲:

  • SAN:iSCSI、ScaleIO Volumes、FC (Fibre Channel)
  • NFS:nfs,cfs

分布式存儲

  • Glusterfs
  • RBD (Ceph Block Device)
  • CephFS
  • Portworx Volumes
  • Quobyte Volumes

云端存儲

  • GCEPersistentDisk
  • AWSElasticBlockStore
  • AzureFile
  • AzureDisk
  • Cinder (OpenStack block storage)
  • VsphereVolume
  • StorageOS

自定義存儲

  • FlexVolume

基本存儲

EmptyDir

EmptyDir是最基礎(chǔ)的Volume類型,一個EmptyDir就是Host上的一個空目錄。

不是持久化數(shù)據(jù)存儲,生命周期跟pod一樣,一般是用于多容器共享目錄

EmptyDir是在Pod被分配到Node時創(chuàng)建的,它的初始內(nèi)容為空,并且無須指定宿主機(jī)上對應(yīng)的目錄文件,因為kubernetes會自動分配一個目錄,當(dāng)Pod銷毀時,EmptyDir中的數(shù)據(jù)也會被永久刪除。

EmptyDir的用途如下:

  • 臨時空間,例如用于某些應(yīng)用程序運行時所需的臨時目錄,且無須永久保留。
  • 一個容器需要從另一個容器中獲取數(shù)據(jù)的目錄(多容器共享目錄)。

示例

接下來,通過一個容器之間的共享案例來使用描述一個EmptyDir。

在一個Pod中準(zhǔn)備兩個容器nginx和busybox,然后聲明一個volume分別掛載到兩個容器的目錄中,然后nginx容器負(fù)責(zé)向volume中寫日志,busybox中通過命令將日志內(nèi)容讀到控制臺。

apiVersion: v1

kind: Pod

metadata:

  name: volume-emptydir

  namespace: study

spec:

  containers:

    - name: nginx

      image: nginx:1.17.1

      imagePullPolicy: IfNotPresent

      command: ["/bin/sh","-c","tail -f /var/log/nginx/access.log"]

      ports:

        - containerPort: 80

      volumeMounts: # 將logs-volume掛載到nginx容器中對應(yīng)的目錄,該目錄為/var/log/nginx

        - name: logs-volume # 卷名

          mountPath: /var/log/nginx # 要掛載到容器的目錄,該目錄且要容器必須存在

    - name: busybox

      image: busybox:1.30

      imagePullPolicy: IfNotPresent

      command: ["/bin/sh","-c","tail -f /logs/access.log"] # 初始命令,持續(xù)讀取指定文件

      # 讀取的時候是前臺,而kubectl logs命令就是讀取前臺日志/dev/stdout和/dev/stderr

      volumeMounts: # 將logs-volume掛載到busybox容器中的對應(yīng)目錄,該目錄為/logs

        - name: logs-volume

          mountPath: /logs

  volumes: # 聲明volume,name為logs-volume,類型為emptyDir

    - name: logs-volume # 用于掛載時指定的volume名字

      emptyDir: {} # 指定volume類型
[root@master k8s]# kubectl apply -f emptydir.yaml

pod/volume-emptydir created

[root@master k8s]# kubectl get pod volume-emptydir -n study -o wide

NAME              READY   STATUS    RESTARTS   AGE    IP              NODE    NOMINATED NODE   READINESS GATES

volume-emptydir   2/2     Running   0          142m   10.244.104.44   node2   <none>           <none>
[root@master k8s]# kubectl describe pod -n study

# 訪問nginx,查看busybox掛載的目錄是否有信息,有則說明nginx的日志在logs-volume,且busybox也掛載了目錄

[root@master k8s]# curl 10.244.104.44

<!DOCTYPE html>

<html>

<head>

<title>Welcome to nginx!</title>

[root@master k8s]# kubectl logs -f volume-emptydir -n study -c busybox

192.168.100.53 - - [19/Feb/2023:08:15:33 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.61.1" "-"

HostPath

HostPath就是將Node主機(jī)中的一個實際目錄掛載到Pod中,以供容器使用,這樣的設(shè)計就可以保證Pod銷毀了,但是數(shù)據(jù)依舊可以保存在Node節(jié)點主機(jī)上

但是一旦Node節(jié)點故障了,Pod如果轉(zhuǎn)移到別的Node節(jié)點上,又會出現(xiàn)問題

還有就是將容器的日志導(dǎo)出等場景

  volumes:

  - name: test-volume

    hostPath:

      # directory location on host

      path: /data

      # this field is optional

      type: Directory # 目錄必須存在指定路徑

      # FileOrCreate 不會創(chuàng)建文件的父目錄,如果掛載文件的父目錄不存在,則pod啟動失敗

      # DirectoryOrCreate 如果不存在就創(chuàng)建,且權(quán)限為0755,與 Kubelet 具有相同的組和所有權(quán)

      # File 文件必須存在于給定路徑

      # 如果不寫type就跳過檢測,則如果目錄不存在,yaml創(chuàng)建時候也不會報錯,類似于可選項

示例

apiVersion: v1

kind: Pod

metadata:

  name: volume-hostpath

  namespace: study

spec:

  containers:

    - name: nginx

      image: nginx:1.17.1

      imagePullPolicy: IfNotPresent

      ports:

        - containerPort: 80

      volumeMounts: # 將logs-volume掛載到nginx容器中對應(yīng)的目錄,該目錄為/var/log/nginx

        - name: logs-volume

          mountPath: /var/log/nginx

    - name: busybox

      image: busybox:1.30

      imagePullPolicy: IfNotPresent

      command: ["/bin/sh","-c","tail -f /logs/access.log"] # 初始命令,動態(tài)讀取指定文件

      volumeMounts: # 將logs-volume掛載到busybox容器中的對應(yīng)目錄,該目錄為/logs

        - name: logs-volume

          mountPath: /logs

  volumes: # 聲明volume,name為logs-volume,類型為hostPath

    - name: logs-volume

      hostPath:

        path: /root/logs

        type: DirectoryOrCreate # 目錄存在就使用,不存在就先創(chuàng)建再使用

  nodeName: master # 測試方便查看hostPath被掛載的目錄
[root@master k8s]# kubectl apply -f emptydir.yaml

pod/volume-hostpath created

[root@master k8s]# kubectl get pod -n study -o wide

NAME              READY   STATUS    RESTARTS   AGE   IP              NODE     NOMINATED NODE   READINESS GATES

volume-hostpath   2/2     Running   0          58s   10.244.219.71   master   <none>           <none>

[root@master k8s]# curl 10.244.219.71

<!DOCTYPE html>

<html>

<head>

<title>Welcome to nginx!</title>

[root@master k8s]# cat /root/logs/access.log

192.168.100.53 - - [20/Feb/2023:06:23:56 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.61.1" "-"

subPath

subpath 主要是為了防止覆蓋

使用 mountPath 掛載 /etc/nginx ,但是我告訴 kubernetes 我掛載那個文件,此時就可以使用 subPath 了,此時 Kubernetes 就只會覆蓋 /etc/nginx/nginx.conf 文件

換言之,mountPath 告訴 Kubernetes 我需要覆蓋容器中的那個目錄,但是有了 subPath ,Kubernetes 就知道了,哦,原來你只需要覆蓋 mountPath 下邊的子文件?。╯ubPath )

apiVersion: v1

kind: Pod

metadata:

  name: my-lamp-site

spec:

    containers:

    - name: mysql

      image: mysql

      env:

      - name: MYSQL_ROOT_PASSWORD

        value: "rootpasswd"

      volumeMounts:

      - mountPath: /var/lib/mysql

        name: site-data

        subPath: m

    - name: php

      image: php:7.0-apache

      volumeMounts:

      - mountPath: /var/www/html

        name: site-data

        subPath: m

    volumes:

    - name: site-data

      emptyDir: {}

NFS

hostpath可以實現(xiàn)持久化,但是沒有實現(xiàn)高可用,但是一旦Node節(jié)點故障了,Pod如果轉(zhuǎn)移到別的Node節(jié)點上,又會出現(xiàn)問題,而NFS就是為解決持久化存儲高可用

常用的有:NFS CIFS 等

NFS是一個網(wǎng)絡(luò)文件存儲系統(tǒng),可以搭建一臺NFS服務(wù)器,然后將Pod中的存儲直接連接到NFS系統(tǒng)上,這樣,無論P(yáng)od在節(jié)點上怎么轉(zhuǎn)移,只要Node和NFS的對接沒有問題,數(shù)據(jù)就可以成功訪問。

Master 搭建 NFS

首先需要準(zhǔn)備NFS服務(wù)器,這里為了簡單,直接在Master節(jié)點做NFS服務(wù)器。

在Master節(jié)點上安裝NFS服務(wù)器:

yum install -y nfs-utils rpcbind

mkdir -pv /root/data/k8s-nfs

vim /etc/exports

# 將共享目錄以讀寫權(quán)限暴露給192.168.100.0/24網(wǎng)段中的所有主機(jī)

/root/data/k8s-nfs 192.168.100.0/24(rw,no_root_squash)

# 讀寫權(quán)限,不使用root權(quán)限

systemctl start rpcbind

systemctl enable rpcbind

systemctl start nfs-server

systemctl enable nfs-server

在Node節(jié)點上都安裝NFS服務(wù)器,目的是為了Node節(jié)點可以驅(qū)動NFS設(shè)備

# 在Node節(jié)點上安裝NFS服務(wù),不需要啟動

yum -y install nfs-utils

showmount -e 192.168.100.53

mount -t  nfs 192.168.100.53:/root/data/k8s-nfs /mnt #關(guān)機(jī)后

mount -t  nfs 192.168.100.53:/root/data/k8s-nfs/mnt

示例

apiVersion: v1

kind: Pod

metadata:

  name: volume-nfs

  namespace: dev

spec:

  containers:

    - name: nginx

      image: nginx:1.17.1

      imagePullPolicy: IfNotPresent

      ports:

        - containerPort: 80

      volumeMounts: # 將logs-volume掛載到nginx容器中對應(yīng)的目錄,該目錄為/var/log/nginx

        - name: logs-volume

          mountPath: /var/log/nginx

    - name: busybox

      image: busybox:1.30

      imagePullPolicy: IfNotPresent

      command: ["/bin/sh","-c","tail -f /logs/access.log"] # 初始命令,動態(tài)讀取指定文件

      volumeMounts: # 將logs-volume掛載到busybox容器中的對應(yīng)目錄,該目錄為/logs

        - name: logs-volume

          mountPath: /logs

  volumes: # 聲明volume

    - name: logs-volume

      nfs:

        server: 192.168.100.53 # NFS服務(wù)器地址

        path: /root/data/k8s-nfs # 共享文件路徑
[root@master k8s]# kubectl apply -f  emptydir.yaml

pod/volume-hostpath created

[root@master k8s]# kubectl get pod -n study -o wide

NAME              READY   STATUS    RESTARTS   AGE   IP              NODE    NOMINATED NODE   READINESS GATES

volume-hostpath   2/2     Running   0          64s   10.244.104.53   node2   <none>           <none>

[root@master k8s]# curl 10.244.104.53

[root@master k8s]# cat /root/data/k8s-nfs/access.log

192.168.100.53 - - [20/Feb/2023:07:15:55 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.61.1" "-"

192.168.100.53 - - [20/Feb/2023:07:49:20 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.61.1" "-"

高級存儲(pv pvc)

概述架構(gòu)

此時就要求用戶會搭建NFS系統(tǒng)等,并且會在yaml配置nfs

由于kubernetes支持的存儲系統(tǒng)有很多,要求客戶全部掌握,顯然不現(xiàn)實。為了能夠屏蔽底層存儲實現(xiàn)的細(xì)節(jié),方便用戶使用,kubernetes引入了PV和PVC兩種資源對(類似于資源池化,pv和pvc是抽象的存儲資源)

使用了PV和PVC之后,工作可以得到進(jìn)一步的提升:

  1. 存儲:存儲工程師維護(hù)。
  2. PV:kubernetes管理員維護(hù)。
  3. PVC:kubernetes用戶維護(hù)。

下面實操的架構(gòu):pod-pvc-pv-NFS

生命周期

PVC和PV是一一對應(yīng)的,PV和PVC之間的相互作用遵循如下的生命周期。

1.資源供應(yīng):管理員手動創(chuàng)建底層存儲和PV。

2.資源綁定

用戶創(chuàng)建PVC,kubernetes負(fù)責(zé)根據(jù)PVC聲明去尋找PV,并綁定在用戶定義好PVC之后,系統(tǒng)將根據(jù)PVC對存儲資源的請求在以存在的PV中選擇一個滿足條件的。

  • 一旦找到,就將該P(yáng)V和用戶定義的PVC進(jìn)行綁定,用戶的應(yīng)用就可以使用這個PVC了。
  • 如果找不到,PVC就會無限期的處于Pending狀態(tài),直到系統(tǒng)管理員創(chuàng)建一個符合其要求的PV。

PV一旦綁定到某個PVC上,就會被這個PVC獨占,不能再和其他的PVC進(jìn)行綁定了。

3.資源使用

  • 用戶可以在Pod中像volume一樣使用PVC,Pod使用Volume的定義,將PVC掛載到容器內(nèi)的某個路徑進(jìn)行使用。

4.資源釋放

  • 上一個 pod還有東西存在目錄中
  • 用戶刪除PVC來釋放PV。
  • 當(dāng)存儲資源使用完畢后,用戶可以刪除PVC,和該P(yáng)VC綁定的PV將會標(biāo)記為“已釋放”,但是還不能立刻和其他的PVC進(jìn)行綁定。通過之前PVC寫入的數(shù)據(jù)可能還留在存儲設(shè)備上,只有在清除之后該P(yáng)V才能再次使用。

5.資源回收

  • kubernetes根據(jù)PV設(shè)置的回收策略進(jìn)行資源的回收。
  • 對于PV,管理員可以設(shè)定回收策略,用于設(shè)置與之綁定的PVC釋放資源之后如何處理遺留數(shù)據(jù)的問題。只有PV的存儲空間完成回收,才能供新的PVC綁定和使用。

理論與使用 PV

類似于linux lvm 中的 vg

一般由kubernetes運維管理人員創(chuàng)建,然后提供給需要使用的人創(chuàng)建pvc

apiVersion: v1

kind: PersistentVolume

metadata:

  name: pv2

  # 沒有namespace 是集群級別的資源,跨namespace使用

spec:

  nfs: # 存儲類型,和底層正則的存儲對應(yīng)

    path:

    server:

  capacity: # 存儲能力,目前只支持存儲空間的設(shè)置

    storage: 2Gi

  accessModes: # 訪問模式

    - ReadWriteOnce

    # ReadOnlyMany

    # ReadWriteMany

  storageClassName: # 存儲類別

  persistentVolumeReclaimPolicy: # 回收策略

pv的關(guān)鍵配置參數(shù)說明:

1.存儲類型:底層實際存儲的類型,kubernetes支持多種存儲類型,每種存儲類型的配置有所不同。

2.存儲能力(capacity):目前只支持存儲空間的設(shè)置(storage=1Gi),不過未來可能會加入IOPS、吞吐量等指標(biāo)的配置。

3.訪問模式(accessModes)

用來描述用戶應(yīng)用對存儲資源的訪問權(quán)限,訪問權(quán)限包括下面幾種方式:

  • ReadWriteOnce(RWO):讀寫權(quán)限,但是只能被單個節(jié)點掛載(單pvc掛載)。
  • ReadOnlyMany(ROX):只讀權(quán)限,可以被多個節(jié)點掛載。
  • ReadWriteMany(RWX):讀寫權(quán)限,可以被多個節(jié)點掛載。

需要注意的是,底層不同的存儲類型可能支持的訪問模式不同

4.回收策略( persistentVolumeReclaimPolicy)

當(dāng)PV不再被使用之后,對其的處理方式,目前支持三種策略:

  • Retain(保留):保留數(shù)據(jù),需要管理員手動清理數(shù)據(jù)。
  • Recycle(回收):清除PV中的數(shù)據(jù),效果相當(dāng)于 rm -rf /volume/*。
  • Delete(刪除):和PV相連的后端存儲完成volume的刪除操作,常見于云服務(wù)器廠商的存儲服務(wù)。

需要注意的是,底層不同的存儲類型可能支持的回收策略不同

5.存儲類別(storageClassName):PV可以通過storageClassName參數(shù)指定一個存儲類別。

  • 具有特定類型的PV只能和請求了該類別的PVC進(jìn)行綁定。
  • 未設(shè)定類別的PV只能和不請求任何類別的PVC進(jìn)行綁定。

6.狀態(tài)(status):一個PV的生命周期,可能會處于4種不同的階段。

  • Available(可用):表示可用狀態(tài),還未被任何PVC綁定。
  • Bound(已綁定):表示PV已經(jīng)被PVC綁定。
  • Released(已釋放):表示PVC被刪除,但是資源還沒有被集群重新釋放。
  • Failed(失?。罕硎驹揚(yáng)V的自動回收失敗。

示例

mkdir -pv /root/data/{pv1,pv2,pv3}

chmod 777 -R /root/data

# 修改 NFS 的配置文件

vim /etc/exports

    /root/data/pv1     192.168.18.0/24(rw,no_root_squash)

    /root/data/pv2     192.168.18.0/24(rw,no_root_squash)

    /root/data/pv3     192.168.18.0/24(rw,no_root_squash)

systemctl restart nfs-server
apiVersion: v1

kind: PersistentVolume

metadata:

  name: pv1

spec:

  nfs: # 存儲類型,和底層正則的存儲對應(yīng)

    path: /root/data/pv1

    server: 192.168.100.53

  capacity: # 存儲能力,目前只支持存儲空間的設(shè)置

    storage: 1Gi

  accessModes: # 訪問模式

    - ReadWriteMany

  persistentVolumeReclaimPolicy: Retain # 回收策略



---

apiVersion: v1

kind: PersistentVolume

metadata:

  name: pv2

spec:

  nfs: # 存儲類型,和底層正則的存儲對應(yīng)

    path: /root/data/pv2

    server: 192.168.100.53

  capacity: # 存儲能力,目前只支持存儲空間的設(shè)置

    storage: 2Gi

  accessModes: # 訪問模式

    - ReadWriteMany

  persistentVolumeReclaimPolicy: Retain # 回收策略

 

---

apiVersion: v1

kind: PersistentVolume

metadata:

  name: pv3

spec:

  nfs: # 存儲類型,和底層正則的存儲對應(yīng)

    path: /root/data/pv3

    server: 192.168.100.53

  capacity: # 存儲能力,目前只支持存儲空間的設(shè)置

    storage: 3Gi

  accessModes: # 訪問模式

    - ReadWriteMany

  persistentVolumeReclaimPolicy: Retain # 回收策略
[root@master k8s]# kubectl apply -f pv.yaml

persistentvolume/pv1 created

persistentvolume/pv2 created

persistentvolume/pv3 created

[root@master k8s]# kubectl get pv

NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE

pv1    1Gi        RWX            Retain           Available                                   27s

pv2    2Gi        RWX            Retain           Available                                   27s

pv3    3Gi        RWX            Retain           Available                                   27s

 CLAIM 如果被使用這里會顯示pvc的名字

理論與使用 PVC

PVC是對 PV 資源的申請,用來聲明對存儲空間、訪問模式、存儲類別需求信息

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

  name: pvc

  namespace: dev

spec:

  accessModes: # 訪客模式

    - ReadWriteMany

  selector: # 采用標(biāo)簽對PV選擇

  storageClassName: # 存儲類別

  resources: # 請求空間

    requests:

      storage: 5Gi

PVC的關(guān)鍵配置參數(shù)說明:

1.訪客模式(accessModes):用于描述用戶應(yīng)用對存儲資源的訪問權(quán)限。

必須和要連接的pv聲明的訪問模式要一樣

  • ReadWriteOnce(RWO):讀寫權(quán)限,但是只能被單個節(jié)點掛載(單pvc掛載)。
  • ReadOnlyMany(ROX):只讀權(quán)限,可以被多個節(jié)點掛載。
  • ReadWriteMany(RWX):讀寫權(quán)限,可以被多個節(jié)點掛載。

2.用于描述用戶應(yīng)用對存儲資源的訪問權(quán)限:

  • 選擇條件(selector):通過Label Selector的設(shè)置,可使PVC對于系統(tǒng)中已存在的PV進(jìn)行篩選。
  • 存儲類別(storageClassName):PVC在定義時可以設(shè)定需要的后端存儲的類別,只有設(shè)置了該class的pv才能被系統(tǒng)選出。
  • 資源請求(resources):描述對存儲資源的請求。

優(yōu)先級為

  •  pvc(1Gi)= pv(1Gi)
  • 同等容量的pv沒有了則申請比自己大即可 pvc(1Gi)= pv(2Gi)
  • 如果沒有比自己大的,也沒有相等的即失敗

3.狀態(tài)(status)

  • Bound(已綁定):表示PVC已經(jīng)綁定PV。

創(chuàng)建PVC后一直綁定不了PV的原因

  • ①PVC的空間申請大小比PV的空間要大。
  • ②PVC的storageClassName和PV的storageClassName不一致。
  • ③PVC的accessModes和PV的accessModes不一致。

上面 pv 申請pv1:1g pv2:2g pv3:3g

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

  name: pvc1

  namespace: study

spec:

  accessModes: # 訪客模式

    - ReadWriteMany # 和pv一樣

  resources: # 請求空間

    requests:

      storage: 1Gi #申請pv1



---

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

  name: pvc2

  namespace: study

spec:

  accessModes: # 訪客模式

    - ReadWriteMany

  resources: # 請求空間

    requests:

      storage: 1Gi # 上面pv1已經(jīng)被申請了沒有同等容量的pv,所以申請pv2(2G)



---

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

  name: pvc3

  namespace: study

spec:

  accessModes: # 訪客模式

    - ReadWriteMany

  resources: # 請求空間

    requests:

      storage: 5Gi # 沒有與這個相等也沒有比他大的,所以申請失敗
[root@master k8s]# kubectl apply -f pvc.yaml

persistentvolumeclaim/pvc1 created

persistentvolumeclaim/pvc2 created

persistentvolumeclaim/pvc3 created

[root@master k8s]# kubectl get pvc -n study

NAME   STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE

pvc1   Bound     pv1      1Gi        RWX                           54s

pvc2   Bound     pv2      2Gi        RWX                           54s

pvc3   Pending                                                     54s

# Bound 被使用

# pvc3 沒找到存儲容量相等或大于所以一直在ping,可以另外創(chuàng)建新的pv

[root@master k8s]# kubectl get pv

NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM        STORAGECLASS   REASON   AGE

pv1    1Gi        RWX            Retain           Bound       study/pvc1                           23m

pv2    2Gi        RWX            Retain           Bound       study/pvc2                           23m

pv3    3Gi        RWX            Retain           Available                                        23m

創(chuàng)建pod連接 PVC

apiVersion: v1

kind: Pod

metadata:

  name: pod1

  namespace: study

spec:

  containers:

  - name: busybox

    image: busybox:1.30

    command: ["/bin/sh","-c","while true;do echo pod1 >> /root/out.txt; sleep 10; done;"]

    volumeMounts:

    - name: volume

      mountPath: /root/

  volumes:

    - name: volume

      persistentVolumeClaim: # 這個字段是pvc的kind: PersistentVolumeClaim

        claimName: pvc1

        readOnly: false # 只讀



---

apiVersion: v1

kind: Pod

metadata:

  name: pod2

  namespace: study

spec:

  containers:

    - name: busybox

      image: busybox:1.30

      command: ["/bin/sh","-c","while true;do echo pod1 >> /root/out.txt; sleep 10; done;"]

      volumeMounts:

        - name: volume

          mountPath: /root/

  volumes:

    - name: volume

      persistentVolumeClaim:

        claimName: pvc2

        readOnly: false
[root@master k8s]# kubectl apply -f pod-pvc.yaml

pod/pod1 created

pod/pod2 created

[root@master k8s]# ls /root/data/pv1/out.txt

/root/data/pv1/out.txt

刪除

[root@master k8s]# kubectl delete -f pod-pvc.yaml

pod "pod1" deleted

pod "pod2" deleted

[root@master k8s]# kubectl get pvc -n study

NAME   STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE

pvc1   Bound     pv1      1Gi        RWX                           123m

pvc2   Bound     pv2      2Gi        RWX                           123m

pvc3   Pending                                                     123m

[root@master k8s]# kubectl get pv

NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM        STORAGECLASS   REASON   AGE

pv1    1Gi        RWX            Retain           Bound       study/pvc1                           126m

pv2    2Gi        RWX            Retain           Bound       study/pvc2                           126m

pv3    3Gi        RWX            Retain           Available                                        126m

[root@master k8s]# kubectl delete -f pvc.yaml

persistentvolumeclaim "pvc1" deleted

persistentvolumeclaim "pvc2" deleted

persistentvolumeclaim "pvc3" deleted

[root@master k8s]# kubectl get pv -n study

NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM        STORAGECLASS   REASON   AGE

pv1    1Gi        RWX            Retain           Released    study/pvc1                           127m

pv2    2Gi        RWX            Retain           Released    study/pvc2                           127m

pv3    3Gi        RWX            Retain           Available                                        127m

# persistentVolumeReclaimPolicy:Retain 所以要手動釋放,并重新聲明

persistentVolumeReclaimPolicy:Retain

將pv從Released 變?yōu)?Available

使用edit命令刪除pv中的pvc的綁定信息即可變?yōu)閍vailable

注意:先將資源拿出來備份,反正數(shù)據(jù)還沒備份就被pvc使用了

[root@master k8s]# kubectl get pv -n study

NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM        STORAGECLASS   REASON   AGE

pv1    1Gi        RWX            Retain           Released    study/pvc1                           129m

pv2    2Gi        RWX            Retain           Released    study/pvc2                           129m

pv3    3Gi        RWX            Retain           Available                                        129m

[root@master k8s]# kubectl edit pv pv2 # pv1
# 刪除下面字段

  claimRef:

    apiVersion: v1

    kind: PersistentVolumeClaim

    name: pvc2

    namespace: study

    resourceVersion: "849619"

    uid: fac30e1d-90a5-4e8b-9092-e6b83fd55d62

persistentvolume/pv2 edited
[root@master k8s]# kubectl get pv -n study

NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE

pv1    1Gi        RWX            Retain           Available                                   134m

pv2    2Gi        RWX            Retain           Available                                   134m

pv3    3Gi        RWX            Retain           Available                                   134m

問題

pv創(chuàng)建不會檢測nfs的路徑是否連上,哪怕nfs都沒有這個配置也連不上也能創(chuàng)建,不會報錯,甚至后續(xù)的pvc和pod連接pvc都不會報錯

動態(tài)供應(yīng)

  • 靜態(tài)供應(yīng):集群管理員創(chuàng)建若干 PV 卷。這些卷對象帶有真實存儲的細(xì)節(jié)信息,并且對集群用戶可用(可見)。PV 卷對象存在于 Kubernetes API 中,可供用戶消費(使用)。
  • 動態(tài)供應(yīng):集群自動根據(jù) PVC 創(chuàng)建出對應(yīng) PV 進(jìn)行使用

① 集群管理員預(yù)先創(chuàng)建存儲類(StorageClass)。

② 用戶創(chuàng)建使用存儲類的持久化存儲聲明(PVC:PersistentVolumeClaim)。

③ 存儲持久化聲明通知系統(tǒng),它需要一個持久化存儲(PV: PersistentVolume)。

④ 系統(tǒng)讀取存儲類的信息。

⑤ 系統(tǒng)基于存儲類的信息,在后臺自動創(chuàng)建 PVC 需要的 PV 。

⑥ 用戶創(chuàng)建一個使用 PVC 的 Pod 。

⑦ Pod 中的應(yīng)用通過 PVC 進(jìn)行數(shù)據(jù)的持久化。

⑧ PVC 使用 PV 進(jìn)行數(shù)據(jù)的最終持久化處理。

https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner

設(shè)置 NFS 動態(tài)供應(yīng)

apiVersion: storage.k8s.io/v1

kind: StorageClass

metadata:

  name: nfs-client

provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # 指定一個供應(yīng)商的名字

# or choose another name, 必須匹配 deployment 的 env PROVISIONER_NAME'

parameters:

  archiveOnDelete: "false" # 刪除 PV 的時候,PV 中的內(nèi)容是否備份

---

apiVersion: apps/v1

kind: Deployment

metadata:

  name: nfs-client-provisioner

  labels:

    app: nfs-client-provisioner

  namespace: default

spec:

  replicas: 1

  strategy:

    type: Recreate

  selector:

    matchLabels:

      app: nfs-client-provisioner

  template:

    metadata:

      labels:

        app: nfs-client-provisioner

    spec:

      serviceAccountName: nfs-client-provisioner

      containers:

        - name: nfs-client-provisioner

          image: ccr.ccs.tencentyun.com/gcr-containers/nfs-subdir-external-provisioner:v4.0.2

          volumeMounts:

            - name: nfs-client-root

              mountPath: /persistentvolumes

          env:

            - name: PROVISIONER_NAME

              value: k8s-sigs.io/nfs-subdir-external-provisioner

            - name: NFS_SERVER

              value: 192.168.65.100 # NFS 服務(wù)器的地址

            - name: NFS_PATH

              value: /nfs/data # NFS 服務(wù)器的共享目錄

      volumes:

        - name: nfs-client-root

          nfs:

            server: 192.168.65.100

            path: /nfs/data

---

apiVersion: v1

kind: ServiceAccount

metadata:

  name: nfs-client-provisioner

  namespace: default

---

kind: ClusterRole

apiVersion: rbac.authorization.k8s.io/v1

metadata:

  name: nfs-client-provisioner-runner

rules:

  - apiGroups: [""]

    resources: ["nodes"]

    verbs: ["get", "list", "watch"]

  - 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: ["create", "update", "patch"]

---

kind: ClusterRoleBinding

apiVersion: rbac.authorization.k8s.io/v1

metadata:

  name: run-nfs-client-provisioner

subjects:

  - kind: ServiceAccount

    name: nfs-client-provisioner

    namespace: default

roleRef:

  kind: ClusterRole

  name: nfs-client-provisioner-runner

  apiGroup: rbac.authorization.k8s.io

---

kind: Role

apiVersion: rbac.authorization.k8s.io/v1

metadata:

  name: leader-locking-nfs-client-provisioner

  namespace: default

rules:

  - apiGroups: [""]

    resources: ["endpoints"]

    verbs: ["get", "list", "watch", "create", "update", "patch"]

---

kind: RoleBinding

apiVersion: rbac.authorization.k8s.io/v1

metadata:

  name: leader-locking-nfs-client-provisioner

  namespace: default

subjects:

  - kind: ServiceAccount

    name: nfs-client-provisioner

    namespace: default

roleRef:

  kind: Role

  name: leader-locking-nfs-client-provisioner

  apiGroup: rbac.authorization.k8s.io

測試動態(tài)供應(yīng)

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

  name: nginx-pvc

  namespace: default

  labels:

    app: nginx-pvc

spec:

  storageClassName: nfs-client # 注意此處

  accessModes:

  - ReadWriteOnce

  resources:

    requests:

      storage: 2Gi

---

apiVersion: v1

kind: Pod

metadata:

  name: nginx

  namespace: default

  labels:

    app: nginx

spec:

  containers:

  - name: nginx

    image: nginx:1.20.2

    resources:

      limits:

        cpu: 200m

        memory: 500Mi

      requests:

        cpu: 100m

        memory: 200Mi

    ports:

    - containerPort:  80

      name:  http

    volumeMounts:

    - name: localtime

      mountPath: /etc/localtime

    - name: html

      mountPath: /usr/share/nginx/html/

  volumes:

    - name: localtime

      hostPath:

        path: /usr/share/zoneinfo/Asia/Shanghai

    - name: html   

      persistentVolumeClaim:

        claimName:  nginx-pvc

        readOnly: false 

  restartPolicy: Always

設(shè)置 SC 為默認(rèn)驅(qū)動

kubectl patch storageclass <your-class-name> -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

kubectl patch storageclass nfs-client -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

  name: nginx-pvc

  namespace: default

  labels:

    app: nginx-pvc

spec:

  # storageClassName: nfs-client 不寫,就使用默認(rèn)的

  accessModes:

  - ReadWriteOnce

  resources:

    requests:

      storage: 2Gi

---

apiVersion: v1

kind: Pod

metadata:

  name: nginx

  namespace: default

  labels:

    app: nginx

spec:

  containers:

  - name: nginx

    image: nginx:1.20.2

    resources:

      limits:

        cpu: 200m

        memory: 500Mi

      requests:

        cpu: 100m

        memory: 200Mi

    ports:

    - containerPort:  80

      name:  http

    volumeMounts:

    - name: localtime

      mountPath: /etc/localtime

    - name: html

      mountPath: /usr/share/nginx/html/

  volumes:

    - name: localtime

      hostPath:

        path: /usr/share/zoneinfo/Asia/Shanghai

    - name: html   

      persistentVolumeClaim:

        claimName:  nginx-pvc

        readOnly: false 

  restartPolicy: Always

展望

目前,只需要運維人員部署好各種 storageclass,開發(fā)人員在使用的時候,創(chuàng)建 PVC 即可;但是,存儲系統(tǒng)太多太多,運維人員也未必會一一掌握,此時就需要 Rook 來統(tǒng)一管理了。

特殊存儲卷

ConfigMap

ConfigMap是一個比較特殊的存儲卷,它的主要作用是用來存儲配置信息的

創(chuàng)建configmap

apiVersion: v1

kind: ConfigMap

metadata:

  name: configmap-test

  namespace: study

data: # 下面都是要存儲的數(shù)據(jù)

  info: # 會創(chuàng)建一個名為info文件,文件內(nèi)容如下

    username:admin

    password:123456

# 如果更新ConfigMap中的內(nèi)容,容器中的值也會動態(tài)更新

# 更改后重新 apply 或 使用 edit命令

# 注意:需要一定時間
[root@master k8s]# kubectl apply  -f configmap.yaml

configmap/configmap-test created

[root@master k8s]# kubectl get cm -n study

NAME               DATA   AGE

configmap-test     1      22s

kube-root-ca.crt   1      4d21h

創(chuàng)建pod掛載configmap

apiVersion: v1

kind: Pod

metadata:

  name: pod-configmap

  namespace: study

spec:

  containers:

    - name: nginx

      image: nginx:1.17.1

      volumeMounts:

        - mountPath: /configmap/config

          name: config

  volumes:

    - name: config

      configMap:

        name: configmap-test # 綁定 configmap
[root@master k8s]# kubectl apply -f configmap.yaml

pod/pod-configmap created

[root@master k8s]# kubectl get pod -n study

NAME            READY   STATUS    RESTARTS   AGE

pod-configmap   1/1     Running   0          11s

[root@master k8s]# kubectl exec -it -n study pod-configmap -c nginx /bin/sh
# ls /configmap/config

info

# cat /configmap/config/info

username:admin password:123456

Secret

在kubernetes中,還存在一種和ConfigMap非常類似的對象,稱為Secret對象,它主要用來存儲敏感信息,例如密碼、密鑰、證書等等

Secret 是一個用于存儲敏感數(shù)據(jù)的資源,所有的數(shù)據(jù)要經(jīng)過base64編碼,數(shù)據(jù)實際會存儲在K8s中Etcd,然后通過創(chuàng)建Pod時引用該數(shù)據(jù)。

查詢 Secret 的時候是加密,在pod容器里面顯示的是解密后的內(nèi)容

Pod 使用 secret 數(shù)據(jù)有兩種方式:

  • 變量注入
  • 數(shù)據(jù)卷掛載

kubectl create secret 支持三種數(shù)據(jù)類型:

  • docker--registry:存儲鏡像倉庫認(rèn)證信息
  • generic:從文件、目錄或者字符串創(chuàng)建,例如存儲用戶名密碼
  • ts:存儲證書,例如HTTPS證書

type字段

內(nèi)置類型

用法

Opaque

用戶定義的任意數(shù)據(jù)

kubernetes.io/service-account-token

服務(wù)賬號令牌

kubernetes.io/dockercfg

~/.dockercfg

文件的序列化形式

kubernetes.io/dockerconfigjson

~/.docker/config.json

文件的序列化形式

kubernetes.io/basic-auth

用于基本身份認(rèn)證的憑據(jù)

kubernetes.io/ssh-auth

用于 SSH 身份認(rèn)證的憑據(jù)

kubernetes.io/tls

用于 TLS 客戶端或者服務(wù)器端的數(shù)據(jù)

bootstrap.kubernetes.io/token

啟動引導(dǎo)令牌數(shù)據(jù)

yaml 解析

# 準(zhǔn)備base64加密數(shù)據(jù)

echo -n "admin" | base64

echo -n "123456" | base64
apiVersion: v1

kind: Secret

metadata:

  name: secret

  namespace: dev

type: Opaque

data: # 下面存存儲敏感信息,已base64加密

  # 這里 username 是一個文件名,這里 password 是一個文件名

  username: YWRtaW4=

  password: MTIzNDU2

  # mysql-root-password:"MTIzNDU2"

stringData: #如果不手動進(jìn)行編碼加密,可以將這個操作讓k8s來做,使用stringdata

  username: admin

  password: "123456"

# 不能直接寫數(shù)字,不然會報錯 cannot convert int64 to string,如果要寫數(shù)字就加""

注:如果同時使用data和stringData,那么data會被忽略

[root@master k8s]# kubectl apply -f secret.yaml

secret/secret created

[root@master k8s]# kubectl describe secrets -n study

Name:         secret

Namespace:    study

Labels:       <none>

Annotations:  <none>



Type:  Opaque



Data

====

password:  6 bytes

username:  5 bytes

數(shù)據(jù)卷掛載

apiVersion: v1

kind: Pod

metadata:

  name: pod-secret

  namespace: study

spec:

  containers:

    - name: nginx

      image: nginx:1.17.1

      volumeMounts:

        - mountPath: /secret/config

          name: secret-config

  volumes:

    - name: secret-config

      secret:

        secretName: secret
kubectl exec -it -n study pod-secret -c nginx /bin/sh

# cat /secret/config/password

123456

解碼 Secret

kubectl get secret db-user-pass -o jsonpath='{.data}' | base64

變量注入

示例:將Mysql用戶密碼保存到Secret中存儲

[root@master cks]# echo -n "123456" | base64

MTIzNDU2
apiVersion: v1

kind: Secret

metadata:

  name: mysql

type: Opaque

data:

  mysql-root-password: "MTIzNDU2"

---

apiVersion: apps/v1

kind: Deployment

metadata:

  name: mysql

spec:

  selector:

    matchLabels:

      app: mysql

  template:

    metadata:

      labels:

        app: mysql

    spec:

      containers:

      - name: mysql-db

        image: mysql:5.7.30

        env:

        - name: MYSQL_ROOT_PASSWORD

          valueFrom:

            secretKeyRef:

              name: mysql

              key: mysql-root-password

將 secret 的mysql中的mysql-root-passwd變量注入到 容器中的 MYSQL_ROOT_PASSWORD 變量

[root@master cks]# kubectl exec -it mysql-6c8b6c4d74-vbflz /bin/sh

# mysql -uroot -p123456

mysql: [Warning] Using a password on the command line interface can be insecure.

Welcome to the MySQL monitor.  Commands end with ; or \g.

Your MySQL connection id is 4

Server version: 5.7.30 MySQL Community Server (GPL)



Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.



Oracle is a registered trademark of Oracle Corporation and/or its

affiliates. Other names may be trademarks of their respective

owners.



Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.



mysql>

鏡像拉取密碼

imagePullSecret:Pod拉取私有鏡像倉庫的時使用的賬戶密碼,會傳遞給kubelet,然后kubelet就可以拉取有密碼的倉庫里面的鏡像

kubectl create secret docker-registry docker-harbor-registrykey --docker-server=192.168.18.119:85 \

          --docker-username=admin --docker-password=Harbor12345 \

          --docker-email=1900919313@qq.com

apiVersion: v1

kind: Pod

metadata:

  name: redis

spec:

  containers:

    - name: redis

      image: 192.168.18.119:85/yuncloud/redis # 這是Harbor的鏡像私有倉庫地址

  imagePullSecrets:

    - name: docker-harbor-registrykey

總結(jié)以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 訪問k8s集群部署的微服務(wù)內(nèi)部服務(wù)接口問題

    訪問k8s集群部署的微服務(wù)內(nèi)部服務(wù)接口問題

    文章介紹了在Kubernetes集群中訪問微服務(wù)內(nèi)部服務(wù)接口的幾種方法,包括通過Pod的localhost訪問、使用服務(wù)名和DNS解析、以及通過注冊中心的地址訪問
    2026-02-02
  • 詳解Kubernetes 中容器跨主機(jī)網(wǎng)絡(luò)

    詳解Kubernetes 中容器跨主機(jī)網(wǎng)絡(luò)

    這篇文章主要為大家介紹了Kubernetes中容器跨主機(jī)網(wǎng)絡(luò)是怎么樣的,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • IPVS下CoreDNS滾動更新解析失敗原理探究

    IPVS下CoreDNS滾動更新解析失敗原理探究

    這篇文章主要為大家介紹了IPVS下CoreDNS滾動更新解析失敗原理探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • kubenetes集群版本升級方式

    kubenetes集群版本升級方式

    本文詳細(xì)介紹了使用kubeadm和二進(jìn)制方式搭建及升級Kubernetes集群的方法,介紹了版本控制、升級步驟、備份ETCD數(shù)據(jù)、升級各節(jié)點組件等關(guān)鍵操作,并提供了操作示例和注意事項,幫助理解和實施Kubernetes集群的搭建和升級過程
    2024-09-09
  • k8s中pod不停重啟問題定位原因與解決方法

    k8s中pod不停重啟問題定位原因與解決方法

    這篇文章主要給大家介紹了關(guān)于k8s中pod不停重啟問題定位原因與解決方法的相關(guān)資料,Kubernetes是一款高度可擴(kuò)展、可靠的容器編排和管理系統(tǒng),它簡化了容器的部署、管理和自動化操作,需要的朋友可以參考下
    2023-08-08
  • kubernetes?k8s?CRD自定義資源學(xué)習(xí)筆記

    kubernetes?k8s?CRD自定義資源學(xué)習(xí)筆記

    這篇文章主要介紹了kubernetes?k8s?CRD自定義資源學(xué)習(xí)筆記,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • Kubernetes刪除ns實現(xiàn)方式(namespace)

    Kubernetes刪除ns實現(xiàn)方式(namespace)

    文章介紹了在Kubernetes中刪除無法正常刪除的命名空間(namespace)的幾種方法,首先,通過查看和修改命名空間的JSON文件來刪除`finalizers`,然后使用`kubectl proxy`命令來繞過Kubernetes的安全機(jī)制,最終成功刪除了命名空間
    2026-01-01
  • k8s:pod has unbound PersistentVolumeClaims問題及解決方案

    k8s:pod has unbound PersistentVolumeClaims問題及

    部署redis-ha時,Pod因PVC未綁定報錯,原因在于value.yaml中storageClassName為空,且未啟用DefaultDefaultStorageClass,解決方法是手動指定PVC的StorageClassName為現(xiàn)有存儲類,確保PV分配成功
    2025-07-07
  • 普通人如何在區(qū)塊鏈行業(yè)賺錢

    普通人如何在區(qū)塊鏈行業(yè)賺錢

    區(qū)塊鏈?zhǔn)且豁椥录夹g(shù)。之所以快速吸引人們的關(guān)注,是因為比特幣在2017年的暴漲,迅速吸引了大眾的視線。而比特幣的底層技術(shù),主要是區(qū)塊鏈技術(shù)
    2018-03-03
  • k8s如何給node添加標(biāo)簽(最新推薦)

    k8s如何給node添加標(biāo)簽(最新推薦)

    k8s集群如果由大量節(jié)點組成,可將節(jié)點打上對應(yīng)的標(biāo)簽,然后通過標(biāo)簽進(jìn)行篩選及查看,更好的進(jìn)行資源對象的相關(guān)選擇與匹配,這篇文章主要介紹了k8s如何給node添加標(biāo)簽,需要的朋友可以參考下
    2023-02-02

最新評論

宁陵县| 江川县| 安泽县| 图们市| 潞城市| 沙雅县| 清河县| 苗栗县| 海宁市| 承德市| 师宗县| 灵武市| 泸溪县| 吉安市| 阿克陶县| 灵丘县| 治多县| 色达县| 启东市| 宜兴市| 黄龙县| 金山区| 广州市| 普定县| 辽源市| 乐清市| 樟树市| 沂源县| 阳谷县| 无棣县| 福建省| 靖安县| 夏津县| 杨浦区| 张北县| 新乐市| 阿克| 藁城市| 石泉县| 卓尼县| 托克托县|