How to Deploy Container MySQL Database with Persistent Volumes in Oracle Cloud

上一篇文章,提到了如何在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方式来提供的。
Oci pvc1

在管理界面中可以看到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的容器云中创建和使用共享磁盘。

Leave a Reply

Your email address will not be published. Required fields are marked *