上一篇文章,提到了如何在Oracle Cloud中创建和访问Kubernetes Cluster。
接下来,这篇文章我们在这个Kubernetes Cluster中创建一个MySQL数据库,并且要使用到容器外的持久化卷来存储数据。
概念介绍
在Kubernetes的存储使用中,至少有两个概念需要了解,一个是Persistent Volumes(PV),另外一个是PersistentVolumeClaims(PVC)。我们可以这样理解,PV就像是真正的资源,就像CPU、内存一样的,只是PV是存储资源;而PVC则是任何一个容器要使用这些资源必须指定的纽带,对于容器来说,只看得到PVC。PVC在定义阶段并不会指明绑定到哪一个PV上,但是在创建之后则会由Kubernetes Controller来在有效的PV中寻找合适的绑定对象,一旦绑定,PV和PVC就形成了一对一的关系。从而,容器->PVC-PV,这样就完成了在容器中使用存储的目的。
前面说,PVC在创建之后会由Controller在有效的PV中寻找合适的绑定对象,实际上也可以在需要的时候自动创建PV然后自动绑定,这被称为Dynamic Volume Provisioning,要实现这一点,需要在Kubernetes中先定义StorageClass。StorageClass中定义了存储提供者(provisioner)还有重分配策略(reclaimPolicy)等,而provisioner实际上就是各种Kubernetes支持的存储类型,分别由各个存储厂家自己制定的,以volume plugin的方式加入到Kubernetes中,比如三大云厂商都提供了自己的存储,微软提供了Azure File和Azure Disk,AWS提供了AWS EBS,Google提供了GCE PD,另外还有其它各种存储类型,比如Ceph,Openstack Cinder,Glusterfs,ScaleIO,vSphere都有相应的provisioner。
同样Oracle Cloud也提供了自己的provisioner,并且在OKE中已经预先创建好了默认的StorageClass。
$ kubectl get StorageClass
NAME PROVISIONER AGE
oci (default) oracle.com/oci 4d6h
$ kubectl describe StorageClass/oci
Name: oci
IsDefaultClass: Yes
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"storage.k8s.io/v1beta1","kind":"StorageClass","metadata":{"annotations":{"storageclass.beta.kubernetes.io/is-default-class":"true"},"name":"oci","namespace":""},"provisioner":"oracle.com/oci"}
,storageclass.beta.kubernetes.io/is-default-class=true
Provisioner: oracle.com/oci
Parameters: <none>
AllowVolumeExpansion: <unset>
MountOptions: <none>
ReclaimPolicy: Delete
VolumeBindingMode: Immediate
Events: <none>
因此,只需要在创建PVC的时候,指定StorageClass=oci,就可以实现Dynamic Volume Provisioning。
定义配置文件
配置文件的命名可以随意,这里我们起名为:pvc-dynamic.yaml
$ cat pvc-dynamic.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc1
spec:
accessModes:
- ReadWriteOnce
storageClassName: "oci"
resources:
requests:
storage: 50Mi
创建PVC(同时自动创建PV)
$ kubectl create -f pvc-dynamic.yaml
persistentvolumeclaim/pvc1 created
可以看到pvc1在创建以后,已经处于Bound状态,也就是已经跟PV绑定了,而VOLUME列就是自动创建的PV
$ kubectl get pvc pvc1
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc1 Bound ocid1.volume.oc1.ap-tokyo-1.abxhiljro7qdtft2mo7jukuhk7hvtpvtwbb6z5zrpkz55zq4lxozorfn7pwq 50Gi RWO oci 73s
查看这个自动创建的PV,可以看到即使我们在配置文件中只要求了50MB,创建的PV容量却是50GB,这是Oracle Cloud中最小的PV尺寸,50GB起步。
$ kubectl describe persistentvolume/ocid1.volume.oc1.ap-tokyo-1.abxhiljro7qdtft2mo7jukuhk7hvtpvtwbb6z5zrpkz55zq4lxozorfn7pwq
Name: ocid1.volume.oc1.ap-tokyo-1.abxhiljro7qdtft2mo7jukuhk7hvtpvtwbb6z5zrpkz55zq4lxozorfn7pwq
Labels: failure-domain.beta.kubernetes.io/region=ap-tokyo-1
failure-domain.beta.kubernetes.io/zone=AP-TOKYO-1-AD-1
Annotations: ociAvailabilityDomain: AP-TOKYO-1-AD-1
ociCompartment: ocid1.tenancy.oc1..aaaaaaaaqxee2wwzpx3s6usguambydweb2q5yfx2y5ux3lwlrpaao4gdun7a
ociProvisionerIdentity: ociProvisionerIdentity
ociVolumeID: ocid1.volume.oc1.ap-tokyo-1.abxhiljro7qdtft2mo7jukuhk7hvtpvtwbb6z5zrpkz55zq4lxozorfn7pwq
pv.kubernetes.io/provisioned-by: oracle.com/oci
Finalizers: [kubernetes.io/pv-protection]
StorageClass: oci
Status: Bound
Claim: default/pvc1
Reclaim Policy: Delete
Access Modes: RWO
VolumeMode: Filesystem
Capacity: 50Gi
Node Affinity: <none>
Message:
Source:
Type: FlexVolume (a generic volume resource that is provisioned/attached using an exec based plugin)
Driver: oracle/oci
FSType: ext4
SecretRef: nil
ReadOnly: false
Options: map[]
Events: <none>
在Oracle Cloud中,自动创建的PV是以Block Storage服务中的Block Volumes方式来提供的。
在管理界面中可以看到Block Volumes的名字就是指定创建的PVC的名字:pvc1。同时还能注意到,这个卷已经Attach到一个虚拟机实例中,实际上这个实例就是Kubernetes集群中的一个Work Node。这些全部都是在一条kubectl create命令之后,Oracle Cloud自动完成的工作。
我们还可以通过oci命令行检查存储卷的情况。如何配置OCI命令行我们也在上一篇文章中提过。
$ oci bv volume get --volume-id ocid1.volume.oc1.ap-tokyo-1.abxhiljro7qdtft2mo7jukuhk7hvtpvtwbb6z5zrpkz55zq4lxozorfn7pwq
{
"data": {
"availability-domain": "lOnA:AP-TOKYO-1-AD-1",
"compartment-id": "ocid1.tenancy.oc1..aaaaaaaaqxee2wwzpx3s6usguambydweb2q5yfx2y5ux3lwlrpaao4gdun7a",
"defined-tags": {},
"display-name": "pvc1",
"freeform-tags": {},
"id": "ocid1.volume.oc1.ap-tokyo-1.abxhiljro7qdtft2mo7jukuhk7hvtpvtwbb6z5zrpkz55zq4lxozorfn7pwq",
"is-hydrated": true,
"kms-key-id": null,
"lifecycle-state": "AVAILABLE",
"size-in-gbs": 50,
"size-in-mbs": 51200,
"source-details": null,
"system-tags": {},
"time-created": "2019-10-21T16:09:10.178000+00:00",
"volume-group-id": null
},
"etag": "432d18081fd598a1ddacddfd8982f8cb"
}
创建MySQL数据库的服务和pod
接下来就是常见的创建MySQL容器的方法了。我们在volumes中指定了pvc1(claimName: pvc1),并且将pvc1绑定的PV挂载到容器中的/var/lib/mysql目录下(mountPath: /var/lib/mysql),从而实现整个MySQL的数据文件都保存在了容器之外的持久化存储卷中。
$ cat mysql-deployment.yaml
apiVersion: v1
kind: Service
metadata:
name: mysql-service
labels:
app: mysql
spec:
selector:
app: mysql
ports:
- port: 3306
clusterIP: None
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:8.0
name: mysql
env:
# Use secret in real usage
- name: MYSQL_ROOT_PASSWORD
value: welcome1
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-pv-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-pv-storage
persistentVolumeClaim:
claimName: pvc1
$ kubectl apply -f mysql-deployment.yaml
service/mysql-service created
deployment.apps/mysql created
$ kubectl get pods --selector=app=mysql
NAME READY STATUS RESTARTS AGE
mysql-749cb8f84b-d5qxm 1/1 Running 0 97s
登入到容器中,检查结果显示:挂载正常,数据文件创建正常。
$ kubectl exec -it mysql-749cb8f84b-d5qxm -- /bin/bash
root@mysql-749cb8f84b-d5qxm:/# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 39G 4.1G 35G 11% /
tmpfs 64M 0 64M 0% /dev
tmpfs 5.8G 0 5.8G 0% /sys/fs/cgroup
/dev/sda3 39G 4.1G 35G 11% /etc/hosts
shm 64M 0 64M 0% /dev/shm
/dev/sdb 50G 228M 47G 1% /var/lib/mysql
tmpfs 5.8G 12K 5.8G 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 5.8G 0 5.8G 0% /proc/acpi
tmpfs 5.8G 0 5.8G 0% /proc/scsi
tmpfs 5.8G 0 5.8G 0% /sys/firmware
root@mysql-749cb8f84b-d5qxm:/# cd /var/lib/mysql
root@mysql-749cb8f84b-d5qxm:/var/lib/mysql# ls -l
total 178208
drwxr-x---. 2 mysql mysql 4096 Oct 21 16:41 #innodb_temp
-rw-r-----. 1 mysql mysql 56 Oct 21 16:41 auto.cnf
-rw-r-----. 1 mysql mysql 3084516 Oct 21 16:41 binlog.000001
-rw-r-----. 1 mysql mysql 155 Oct 21 16:41 binlog.000002
-rw-r-----. 1 mysql mysql 32 Oct 21 16:41 binlog.index
-rw-------. 1 mysql mysql 1676 Oct 21 16:41 ca-key.pem
-rw-r--r--. 1 mysql mysql 1112 Oct 21 16:41 ca.pem
-rw-r--r--. 1 mysql mysql 1112 Oct 21 16:41 client-cert.pem
-rw-------. 1 mysql mysql 1676 Oct 21 16:41 client-key.pem
-rw-r-----. 1 mysql mysql 5416 Oct 21 16:41 ib_buffer_pool
-rw-r-----. 1 mysql mysql 50331648 Oct 21 16:41 ib_logfile0
-rw-r-----. 1 mysql mysql 50331648 Oct 21 16:41 ib_logfile1
-rw-r-----. 1 mysql mysql 12582912 Oct 21 16:41 ibdata1
-rw-r-----. 1 mysql mysql 12582912 Oct 21 16:41 ibtmp1
drwx------. 2 mysql root 16384 Oct 21 16:41 lost+found
drwxr-x---. 2 mysql mysql 4096 Oct 21 16:41 mysql
-rw-r-----. 1 mysql mysql 30408704 Oct 21 16:41 mysql.ibd
drwxr-x---. 2 mysql mysql 4096 Oct 21 16:41 performance_schema
-rw-------. 1 mysql mysql 1680 Oct 21 16:41 private_key.pem
-rw-r--r--. 1 mysql mysql 452 Oct 21 16:41 public_key.pem
-rw-r--r--. 1 mysql mysql 1112 Oct 21 16:41 server-cert.pem
-rw-------. 1 mysql mysql 1676 Oct 21 16:41 server-key.pem
drwxr-x---. 2 mysql mysql 4096 Oct 21 16:41 sys
-rw-r-----. 1 mysql mysql 12582912 Oct 21 16:41 undo_001
-rw-r-----. 1 mysql mysql 10485760 Oct 21 16:41 undo_002
下一篇文章计划介绍,如何在Oracle Cloud的容器云中创建和使用共享磁盘。