上一篇文章我们尝试了在Oracle Cloud的容器云里创建了持久化卷,并且使用该卷创建了一个MySQL数据库的容器。这样数据库里的数据就保存在了容器外部,如果容器崩溃,那么Kubernetes会根据Deployment的定义,重新创建一个容器,而数据则不会丢失。
对于企业在使用存储来说,除了上述的数据持久性保存之外,共享性也是通常会考虑的一个因素,也就是一份存储上的数据同时被多个应用共享读写。
本文阐述如何在Oracle Cloud的容器云中创建和使用共享存储,在这篇文章中我们使用NFS的方式来实现共享。
创建文件系统
首先需要在Oracle Cloud的管理后台创建一个文件系统,菜单项位于File Storage->File Systems。
点击页面中的“Create File System”按钮,在新建文件系统的页面中点击“Edit Details”,可以对名字进行修改,实际上直接全部使用默认值也是可以的。
为了表意更清晰,我们将文件系统的名字修改为FileSystem-for-OKE,将Export路径修改为“/oke-export”,Mount Target名称不做变化。
这些Oracle Cloud中文件系统的术语的解释,可以参看官方文档。注意的是:其中Export路径在后续的容器配置中会使用到,不过这个路径的名称跟容器中会挂载到的路径没有任何关系,可以随意命名。
修改后的并且创建成功的文件系统,可以在管理后台中看到详细情况。
同样,通过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,可以在管理后台中看到详细情况。
注意这里的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!