Skip to content

Latest commit

 

History

History
351 lines (248 loc) · 15.9 KB

kubernetes-iscsi-storage.md

File metadata and controls

351 lines (248 loc) · 15.9 KB

Kubernetes iSCSI Dynamic Storage and the Targetd Storage Appliance

The current configuration uses two types of persistent volume storage:

  1. Dynamic (for pre-production)
  2. Static (for production)

Dynamically provisioned volumes are accomplished using the iscsi-provisioner. In a pre-production environment the agility of dynamic provisioning is helpful in support of dynamic feature branch QA deployments. Since it is pre-production, we are less concerned with High Availability and so a single Targetd Storage Appliance can fit the need.

Statically provisioned volumes are pre-allocated iSCSI LUNs on an external production grade storage appliance. In production, data must be cared for and managed for High Availability and Disaster Recovery. In this case, technology like the Amazon Storage Gateway or direct Compellant allocated iSCSI LUNs are the best strategy.

By combining these two approaches we achieve a lightweight, minimalist and robust persistent volume strategy that is not subject to periodic breakage due to complex software interactions like ESXi Kernel module VIBS or 3rd party storage providers.

The Targetd Storage Appliance

cluster-builder supports the automated deployment of dedicated Kubernetes Cluster Targetd storage appliances. As depicted in the diagram above, these can be paired with Kubernetes Clusters to provide controlled dynamic storage.

The Targetd Storage Appliance supports up to 255 persistent volumes per server instance. If this is insufficient, multiple provisioners can be deployed with multiple targetd storage appliance backends in the same Kubernetes cluster.

The default configuration of the appliance is a 1 TB thinly provisioned LVM volume on VMDK. This can be resized as needed but represents a solid initial storage footprint for a pre-production environment.

The Targetd Host Configuration File illustrates the settings required for deploying a targetd storage appliance (it should look familiar):

[all:vars]
cluster_type=targetd-server
cluster_name=targetd
remote_user=admin

vmware_target=esxi
overwrite_existing_vms=true

esxi_net="VM Network"
esxi_net_prefix=192.168.1

network_mask=255.255.255.0
network_gateway=192.168.1.1
network_dns=8.8.8.8
network_dns2=8.8.4.4
network_dn=onprem.idstudios.io

targetd_server=192.168.1.205
targetd_server_iqn=iqn.2003-01.org.linux-iscsi.minishift:targetd
targetd_server_volume_group=vg-targetd
targetd_server_provisioner_name=iscsi-targetd
targetd_server_account_credentials=targetd-account
targetd_server_account_username=admin
targetd_server_account_password=ciao
targetd_server_namespace=default

[targetd_server]
storage-server ansible_host=192.168.1.205 esxi_host=esxi-6 esxi_user=root

[vmware_vms]
storage-server numvcpus=4 memsize=6144 esxi_host=esxi-6 esxi_user=root esxi_ds=datastore6-ssd

targetd_server= The ip address of the targetd server (as per the anisble_host value)

targetd_server_iqn= A valid and unique iSCSI IQN

targetd_server_volume_group= vg-targetd is the default but can be modified.

targetd_server_provisioner_name= A unique name given to the iscsi provisioner

targetd_server_account_credentials= The name of the K8s secret that will store the targetd server credentials

targetd_server_account_username= The username for targetd RPC remote access (used by the provisioner)

targetd_server_account_password= The password for targetd RPC remote access (used by the provisioner)

targetd_server_namespace= This should be default, but may support additional namespaces with configuration

Once the hosts file has been prepared, deployment uses the familiar cluster-builder convention:

bash cluster-deploy <targetd package folder>

Which should result in a deployed Targetd Server Appliance with 1 TB of thinly provisioned LVM storage to be allocated dynamically as K8s PVCs are requested.

The iSCSI Provisioner Configuration

Make sure to copy the targetd configuration into the kubeadm cluster package hosts file:

targetd_server=192.168.1.205
targetd_server_iqn=iqn.2003-01.org.linux-iscsi.minishift:targetd
targetd_server_volume_group=vg-targetd
targetd_server_provisioner_name=iscsi-targetd
targetd_server_account_credentials=targetd-account
targetd_server_account_username=admin
targetd_server_account_password=ciao

These same settings will be used to create the corresponding ISCSI provisioner manifests that will bind the provisioner to the Targetd Storage Appliance.

With the Targetd Storage Appliance configuration values in our cluster configuration file we can run the cluster-builder ansible script to configure k8s for iSCSI direct:

ansible-playbook -i clusters/ids/core ansible/centos-iscsi.yml

At this stage you must setup your kubectl configuration before proceeding - ensure you can connect to your kubeadm cluster

We will then install the iSCSI Provisioner:

./iscsi-secret.sh

This will create the secret credentials that the iSCSI provisioner will use to connect to the Targetd server.

kubectl apply -f iscsi.yml

This will create the necessary roles, as well as install the iscsi-provisioner deployment and the corresponding storage class.

kubectl get sc

Will show the storage class.

kubectl get pods

Will show the running iscsi-provisioner. Check the logs and you should see something like this:

time="2018-05-31T23:30:11Z" level=debug msg="start called"
time="2018-05-31T23:30:11Z" level=debug msg="creating in cluster default kube client config"
time="2018-05-31T23:30:11Z" level=debug msg="kube client config created" config-host="https://10.3.0.1:443"
time="2018-05-31T23:30:11Z" level=debug msg="creating kube client set"
time="2018-05-31T23:30:11Z" level=debug msg="kube client set created"
time="2018-05-31T23:30:11Z" level=debug msg="targed URL http://admin:[email protected]:18700/targetrpc"
time="2018-05-31T23:30:11Z" level=debug msg="iscsi provisioner created"

The iSCSI provisioner is now ready to deploy iSCSI PVC volumes:

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
        name: iscsi-test-volume
        annotations:
        volume.beta.kubernetes.io/storage-class: "iscsi-targetd-vg-targetd"
    spec:
        accessModes:
        - ReadWriteOnce
        resources:
        requests:
            storage: 1Gi

And you can run a benchmark test job on the Targetd iSCSI volumes:

    kubectl apply -f iscsi-bench-pvc.yml
    (wait 10 secs)
    kubectl get pvc
    kubectl get pv
    kubectl apply -f iscsi-bench-job.yml

For better performance consider using Thickly provisioned VMware VMDK volumes.

Once your pod is running and you see the the PVCs are bound, your kubeadm cluster is ready to use dynamic iSCSI PVC provisioning and static iSCSI PVC storage.

Enjoy :)

Viewing the Targetd PVC Volumes

On the Targetd Storage Appliance you can view the allocated volumes using the targetcli ls command (as root).

Targetd targetcli ls example

In the example screenshot we can see four pvc- volumes allocated in the vg-targetd volume group. These map directly to provisioned Kubernetes persistent volumes (PV) and persistent volume claims (PVC):

NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM                                     STORAGECLASS               REASON    AGE
core-drupal-files-volume                   10Gi       RWX            Retain           Bound     web/core-drupal-files-volume-claim                                             2d
ghost-files-volume                         5Gi        RWO            Retain           Bound     idstudios/ghost-files-volume-claim                                             2d
mysql-main-iscsi-volume                    10Gi       RWO            Retain           Bound     idstudios/mysql-main-iscsi-volume-claim                                        2d
pvc-f67ca813-65de-11e8-bcca-000c298174b4   3Gi        RWO            Delete           Bound     web/core-galera-seed-volume-claim         iscsi-targetd-vg-targetd             2d
pvc-f67f1d81-65de-11e8-bcca-000c298174b4   3Gi        RWO            Delete           Bound     web/core-galera-node1-volume-claim        iscsi-targetd-vg-targetd             2d
pvc-f681c73f-65de-11e8-bcca-000c298174b4   3Gi        RWO            Delete           Bound     web/core-galera-node2-volume-claim        iscsi-targetd-vg-targetd             2d
pvc-f6842a73-65de-11e8-bcca-000c298174b4   3Gi        RWO            Delete           Bound     web/core-galera-node3-volume-claim        iscsi-targetd-vg-targetd             2d

If we launch our benchmarking utility job, we will see an iscsi-benchmark-volume-claim created with a corresponding PV, which will map to a dynamically allocated pvc- volume we can verify with targetcli ls.

    kubectl apply -f iscsi-bench.yml

And

    kubectl get pvc

Will show a PVC of:

NAME                                  STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS               AGE
iscsi-benchmark-target-volume-claim   Bound     pvc-f09f473d-6809-11e8-97f1-000c298174b4   3Gi        RWO            iscsi-targetd-vg-targetd   5s

With a corresponding PV of (kubectl get pv):

pvc-f09f473d-6809-11e8-97f1-000c298174b4   3Gi        RWO            Delete           Bound     default/iscsi-benchmark-target-volume-claim   iscsi-targetd-vg-targetd             1m

Note the name of the volume: pvc-f09f473d-6809-11e8-97f1-000c298174b4. We see it has been allocated 3Gi, and using targetcli ls on the Targetd Storage Appliance, we can verify it has in fact been allocated (2nd from the top):

Targetd pvc volume allocated

Going back to the benchmark job we launched, we can check the job (kubectl get jobs) and view the logs:

IDStudios Cluster Toolbox
-------------------------
mode: disk-bench

Performing dd performance test on target volume /target...
-----
WRITE (1st pass bs=1G count=1):
1+0 records in
1+0 records out
1073741824 bytes (1.1 GB) copied, 4.75949 s, 226 MB/s
WRITE (2nd pass):
1+0 records in
1+0 records out
1073741824 bytes (1.1 GB) copied, 4.98027 s, 216 MB/s
WRITE (1st pass bs=1M count=1024):
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 14.2731 s, 75.2 MB/s
WRITE (1st pass bs=1k count=10240):
10240+0 records in
10240+0 records out
10485760 bytes (10 MB) copied, 89.5945 s, 117 kB/s
READ (1st pass bs=1M):
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0.00142444 s, 7.4 GB/s
READ (2nd pass bs=1M):
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0.00136206 s, 7.7 GB/s
sysctl: setting key "vm.drop_caches": Read-only file system
READ (no cache bs=1M):
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0.00126906 s, 8.3 GB/s
LATENCY (seconds / 1000 = latency in ms):
1000+0 records in
1000+0 records out
512000 bytes (512 kB) copied, 0.00142748 s, 359 MB/s
By using 1000 writes, the time in seconds is the latency for a single write in milliseconds.
-----

...

Run status group 0 (all jobs):
   READ: bw=19.3MiB/s (20.2MB/s), 4339KiB/s-9747KiB/s (4443kB/s-9981kB/s), io=528MiB (554MB), run=3749-27388msec
  WRITE: bw=9415KiB/s (9641kB/s), 4401KiB/s-8857KiB/s (4507kB/s-9070kB/s), io=272MiB (285MB), run=3749-29596msec

Disk stats (read/write):
  sdf: ios=135139/64471, merge=0/971, ticks=53341/936230, in_queue=989559, util=99.71%
fio: file hash not empty on exit
-----

IOPing -R /target (disk seek rate (iops, avg))

--- /target (ext4 /dev/sdf) ioping statistics ---
10.1 k requests completed in 3.0 s, 3.4 k iops, 13.3 MiB/s
min/avg/max/mdev = 237 us / 293 us / 8.7 ms / 192 us
-----

IOPing -RL /target (disk sequential speed (MiB/s))

--- /target (ext4 /dev/sdf) ioping statistics ---
2.7 k requests completed in 3.0 s, 929 iops, 232.3 MiB/s
min/avg/max/mdev = 820 us / 1.1 ms / 9.4 ms / 464 us
-----

IOPing for 10 count...
4.0 KiB from /target (ext4 /dev/sdf): request=1 time=8.3 ms
4.0 KiB from /target (ext4 /dev/sdf): request=2 time=1.1 s
4.0 KiB from /target (ext4 /dev/sdf): request=3 time=1.5 ms
4.0 KiB from /target (ext4 /dev/sdf): request=4 time=505 us
4.0 KiB from /target (ext4 /dev/sdf): request=5 time=501 us
4.0 KiB from /target (ext4 /dev/sdf): request=6 time=2.6 ms
4.0 KiB from /target (ext4 /dev/sdf): request=7 time=940 us
4.0 KiB from /target (ext4 /dev/sdf): request=8 time=2.6 ms
4.0 KiB from /target (ext4 /dev/sdf): request=9 time=2.0 ms
4.0 KiB from /target (ext4 /dev/sdf): request=10 time=1.5 ms

--- /target (ext4 /dev/sdf) ioping statistics ---
10 requests completed in 10.1 s, 8 iops, 35.7 KiB/s
min/avg/max/mdev = 501 us / 112.2 ms / 1.1 s / 329.7 ms
-----


Benchmark complete... sleeping 300s (kill me anytime).

Now we will do as suggested, and kill (remove) our benchmark job:

    kubectl delete -f iscsi-bench.yml

This will also remove the 3Gi PVC volume used for the test, which we can verify with targetcli ls:

Targetd pvc volume reclaimed

And we see that the volume pvc-f09f473d-6809-11e8-97f1-000c298174b4 has been removed and the disk space has been reclaimed by LVM.

Extending the Targetd Storage Appliance

You can extend the Targetd Storage Appliance by adding another virtual hard disk to the VM, and then provisioning it manually:

    sudo pvcreate /dev/sd_
    sudo vgcreate vg-targetd-thick /dev/sd_

Where sd_ is the newly added volume. Targetd supports hosting multiple physical disks as block pools.

Edit the /etc/target/target.yaml file to support the additional block volume:

    password: ciao

    # defaults below; uncomment and edit
    # if using a thin pool, use <volume group name>/<thin pool name>
    # e.g vg-targetd/pool
    # Use the multi pool syntax to support multiple volumes:
    block_pools: [vg-targetd, vg-targetd-thick]
    # pool_name: vg-targetd
    user: admin
    ssl: false
    target_name: iqn.2003-01.org.linux-iscsi.minishift:targetd

And then of course you will need to restart the service:

    sudo systemctl restart targetd

And validate the configuration:

    sudo targetcli ls

Create a new storage class that uses the vg-targetd-thick pool (it is easiest to copy the one generated by cluster-builder as it contains the necessary initiator ids):

    kind: StorageClass
    apiVersion: storage.k8s.io/v1
    metadata:
    name: iscsi-targetd-vg-targetd-thick
    provisioner: iscsi-targetd
    parameters:
    # this id where the iscsi server is running
    targetPortal: 192.168.1.205:3260
    iqn: iqn.2003-01.org.linux-iscsi.minishift:targetd
    fsType: ext4
    volumeGroup: vg-targetd-thick

    # this is a comma separated list of initiators that will be give access to the created volumes, they must correspond to what you have configured in your nodes.
    initiators: iqn.2016-04.com.iscsi:1459208749854afebb99c5953e7b2c36,iqn.2016-04.com.iscsi:21dfca155e2940b69824a35fc98ab4be,iqn.2016-04.com.iscsi:b4c735d4d7f545d4907b966947218be5,iqn.2016-04.com.iscsi:3805f9ad51fc40aca73e57c6787dab2e,iqn.2016-04.com.iscsi:4df8a3d976494f56b0405f3a1edcbdb4,iqn.2016-04.com.iscsi:95a1744390d641fe93da94a35fde654c,iqn.2016-04.com.iscsi:39839a9f9d8d480a89107b13cbce9eb1,iqn.2016-04.com.iscsi:6938c01c1b274a40948380063255f274

    ---

And then reference that class when creating PVCs.

The Targetd Storage Appliance has been tuned for ESXi Disk I/O as per the following article, as have all CentOS/RHEL VMs. It makes a remarkable difference.