You are currently viewing How to Use Shared Disk PersistentVolumes for Oracle Kubernetes Engine (OKE) in Oracle Cloud Infrastructure (OCI)

How to Use Shared Disk PersistentVolumes for Oracle Kubernetes Engine (OKE) in Oracle Cloud Infrastructure (OCI)

上一篇文章我们尝试了在Oracle Cloud的容器云里创建了持久化卷,并且使用该卷创建了一个MySQL数据库的容器。这样数据库里的数据就保存在了容器外部,如果容器崩溃,那么Kubernetes会根据Deployment的定义,重新创建一个容器,而数据则不会丢失。

对于企业在使用存储来说,除了上述的数据持久性保存之外,共享性也是通常会考虑的一个因素,也就是一份存储上的数据同时被多个应用共享读写。

本文阐述如何在Oracle Cloud的容器云中创建和使用共享存储,在这篇文章中我们使用NFS的方式来实现共享。

创建文件系统

首先需要在Oracle Cloud的管理后台创建一个文件系统,菜单项位于File Storage->File Systems。
NewImage

点击页面中的“Create File System”按钮,在新建文件系统的页面中点击“Edit Details”,可以对名字进行修改,实际上直接全部使用默认值也是可以的。
NewImage

为了表意更清晰,我们将文件系统的名字修改为FileSystem-for-OKE,将Export路径修改为“/oke-export”,Mount Target名称不做变化。
这些Oracle Cloud中文件系统的术语的解释,可以参看官方文档。注意的是:其中Export路径在后续的容器配置中会使用到,不过这个路径的名称跟容器中会挂载到的路径没有任何关系,可以随意命名。

修改后的并且创建成功的文件系统,可以在管理后台中看到详细情况。
NewImage

同样,通过oci命令行也可以获得创建成功的文件系统的信息。

$ oci fs file-system list \
> --compartment-id ocid1.tenancy.oc1..aaaaaaaaqxee2wwzpx3s6usguambydweb2q5yfx2y5ux3lwlrpaao4gdun7a \
> --availability-domain lOnA:AP-TOKYO-1-AD-1
{
  "data": [
    {
      "availability-domain": "lOnA:AP-TOKYO-1-AD-1",
      "compartment-id": "ocid1.tenancy.oc1..aaaaaaaaqxee2wwzpx3s6usguambydweb2q5yfx2y5ux3lwlrpaao4gdun7a",
      "defined-tags": {},
      "display-name": "FileSystem-for-OKE",
      "freeform-tags": {},
      "id": "ocid1.filesystem.oc1.ap_tokyo_1.aaaaaaaaaaaafictnzzhillqojxwiotboawxi33lpfxs2mjnmfsc2mia",
      "kms-key-id": "",
      "lifecycle-state": "ACTIVE",
      "metered-bytes": 8704,
      "time-created": "2019-10-21T13:26:40+00:00"
    }
  ]
}

在创建文件系统时,Oracle Cloud会自动创建一个Mount Target,可以在管理后台中看到详细情况。
NewImage

注意这里的IP地址,这个地址在后续创建容器持久化卷的时候也会使用到。

同样,通过oci命令行也可以获得创建成功的挂载目标的信息。

$ oci fs mount-target list \
--compartment-id ocid1.tenancy.oc1..aaaaaaaaqxee2wwzpx3s6usguambydweb2q5yfx2y5ux3lwlrpaao4gdun7a \
--availability-domain lOnA:AP-TOKYO-1-AD-1
{
  "data": [
    {
      "availability-domain": "lOnA:AP-TOKYO-1-AD-1",
      "compartment-id": "ocid1.tenancy.oc1..aaaaaaaaqxee2wwzpx3s6usguambydweb2q5yfx2y5ux3lwlrpaao4gdun7a",
      "defined-tags": {},
      "display-name": "MountTarget-20191021-1322",
      "export-set-id": "ocid1.exportset.oc1.ap_tokyo_1.aaaaaa4np2snfy33nzzhillqojxwiotboawxi33lpfxs2mjnmfsc2mia",
      "freeform-tags": {},
      "id": "ocid1.mounttarget.oc1.ap_tokyo_1.aaaaaa4np2snfy34nzzhillqojxwiotboawxi33lpfxs2mjnmfsc2mia",
      "lifecycle-state": "ACTIVE",
      "private-ip-ids": [
        "ocid1.privateip.oc1.ap-tokyo-1.aaaaaaaa34v43wf2b3j73kme2rtho4rlpm6kit3avszgirkpqm5uspbqnrrq"
      ],
      "subnet-id": "ocid1.subnet.oc1.ap-tokyo-1.aaaaaaaafqsuofe2e34mnfkotolakrzktxmwdasj7dyov3u3jixqablc2qgq",
      "time-created": "2019-10-21T13:26:42+00:00"
    }
  ]
}

可以参看创建文件系统的官方文档

创建PV

创建一个PV的定义yaml文件,内容如下。server部分指定上述的Mount Target的IP地址,path部分指定上述的File System的名字。

$ cat pv-nfs.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: 10.0.10.5
    path: "/oke-export"

创建PV,并检查创建结果。

$ kubectl create -f pv-nfs.yaml

$ kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
nfs    1Gi        RWX            Retain           Available                                   8s

$ kubectl describe pv nfs
Name:            nfs
Labels:          <none>
Annotations:     pv.kubernetes.io/bound-by-controller: yes
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:
Status:          Available
Claim:           default/nfs
Reclaim Policy:  Retain
Access Modes:    RWX
VolumeMode:      Filesystem
Capacity:        1Gi
Node Affinity:   <none>
Message:
Source:
    Type:      NFS (an NFS mount that lasts the lifetime of a pod)
    Server:    10.0.10.5
    Path:      /oke-export
    ReadOnly:  false
Events:        <none>

可以看到现在PV的状态是Available,表示可用,在后续我们创建完PVC之后,这里会显示成Bound,表示该PV已经跟PVC绑定。

创建PVC

创建一个PVC的定义yaml文件,内容如下。

$ cat pvc-nfs.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: ""
  resources:
    requests:
      storage: 1Mi

创建PVC,并检查创建结果。

$ kubectl create -f pvc-nfs.yaml

$ kubectl get pvc
NAME   STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nfs    Bound    nfs      1Gi        RWX                           4s

$ kubectl describe pvc nfs
Name:          nfs
Namespace:     default
StorageClass:
Status:        Bound
Volume:        nfs
Labels:        <none>
Annotations:   pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      1Gi
Access Modes:  RWX
VolumeMode:    Filesystem
Events:        <none>
Mounted By:    <none>

创建容器

这里我们使用ReplicationController类型的对象来创建Pod,这样可以指定自动创建多个容器,并共享读写指定的NFS存储。
创建一个RC的定义yaml文件,内容如下。作为测试,我们使用最简单的Nginx镜像,并且指定2个复制。

$ cat rc-nfs.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: rc-nfs-test
spec:
  replicas: 2
  selector:
    app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
          - name: nginx
            containerPort: 80
        volumeMounts:
            - name: nfs
              mountPath: "/usr/share/nginx/html"
      volumes:
      - name: nfs
        persistentVolumeClaim:
          claimName: nfs

创建RC,并检查结果。

$ kubectl create -f rc-nfs.yaml

$ kubectl get rc rc-nfs-test
NAME          DESIRED   CURRENT   READY   AGE
rc-nfs-test   2         2         2       6m56s

$ kubectl describe replicationcontrollers/rc-nfs-test
Name:         rc-nfs-test
Namespace:    default
Selector:     app=nginx
Labels:       app=nginx
Annotations:  <none>
Replicas:     2 current / 2 desired
Pods Status:  2 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:        nginx
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:
      /usr/share/nginx/html from nfs (rw)
  Volumes:
   nfs:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  nfs
    ReadOnly:   false
Events:
  Type    Reason            Age   From                    Message
  ----    ------            ----  ----                    -------
  Normal  SuccessfulCreate  16m   replication-controller  Created pod: rc-nfs-test-bqhm9
  Normal  SuccessfulCreate  16m   replication-controller  Created pod: rc-nfs-test-8h884

$ kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
rc-nfs-test-8h884                   1/1     Running   0          3m16s
rc-nfs-test-bqhm9                   1/1     Running   0          3m16s

到目前为止,我们已经创建好了一组(2个)共享使用磁盘的Nginx容器,共享磁盘在容器内的挂载路径是:/usr/share/nginx/html

接下来,测试一下共享读写的效果。计划在一个容器的共享磁盘中创建index.html文件,并且写入了”test sharing disk”这样的文本,之后从另外一个容器中进行查看。

首先,在其中一个容器里创建index.html文件。

$ kubectl exec rc-nfs-test-8h884 touch /usr/share/nginx/html/index.html

写入一行文本。

$ kubectl exec -it rc-nfs-test-8h884 -- /bin/bash
root@rc-nfs-test-8h884:/# cd /usr/share/nginx/html/
root@rc-nfs-test-8h884:/usr/share/nginx/html# ls
index.html
root@rc-nfs-test-8h884:/usr/share/nginx/html# echo "test sharing disk">>/usr/share/nginx/html/index.html

现在我们登录到另外一个容器中,查看是否能够读取到该内容。

$ kubectl exec rc-nfs-test-bqhm9 cat /usr/share/nginx/html/index.html
test sharing disk

Well Done!

Leave a Reply