基础镜像支持

Longhorn supports creation of block devices backed by a base image. Longhorn base images are packaged as Docker images. Public or private registries may be used as a distribution mechanism for your Docker base images.

Usage

Volumes backed by a base image can be created in three ways.

  1. UI - Create Longhorn volumes exposed as block device or iSCSI target
  2. Flexvolume Driver - Create Longhorn block devices and consume in Kubernetes pods
  3. CSI Driver - (Newer) Create Longhorn block devices and consume in Kubernetes pods

UI

On the Volume tab, click the Create Volume button. The Base Image field expects a Docker image name such as rancher/vm-ubuntu:16.04.4-server-amd64.

Flexvolume Driver

The flexvolume driver supports volumes backed by base image. Below is a sample Flexvolume definition including baseImage option.

  1. flexVolume:
  2. driver: "rancher.io/longhorn"
  3. fsType: "ext4"
  4. options:
  5. size: "32Mi"
  6. numberOfReplicas: "3"
  7. staleReplicaTimeout: "20"
  8. fromBackup: ""
  9. baseImage: "rancher/longhorn-test:baseimage-ext4"

You do not need to (and probably shouldn’t) explicitly set filesystem type fsType when base image is present. If you do, it must match the base image’s filesystem or the flexvolume driver will return an error.

Try it out for yourself. Make sure the Longhorn driver deployer specifies flag --driver flexvolume, otherwise a different driver may be deployed. The following example creates an nginx pod serving content from a flexvolume with a base image and is accessible from a service.

  1. kubectl --kubeconfig=kube_configxxx.yml create -f https://raw.githubusercontent.com/rancher/longhorn-manager/master/examples/flexvolume/example_baseimage.yml

Wait until the pod is running.

  1. kubectl --kubeconfig=kube_configxxx.yml get po/flexvol-baseimage -w

Query for the service you created.

  1. kubectl --kubeconfig=kube_configxxx.yml get svc/flexvol-baseimage

Your service should look similar.

  1. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  2. service/flexvol-baseimage LoadBalancer 10.43.153.186 <pending> 80:31028/TCP 2m

Now let’s access something packaged inside the base image through the Nginx webserver, exposed by the LoadBalancer service. If you have LoadBalancer support and EXTERNAL-IP is set, navigate to the following URL.

  1. http://<EXTERNAL-IP>/guests/hd/party-wizard.gif

Otherwise, navigate to the following URL where NODE-IP is the external IP address of any Kubernetes node and NODE-PORT is the second port in the service (31028 in the example service above).

  1. http://<NODE-IP>:<NODE-PORT>/guests/hd/party-wizard.gif

Finally, tear down the pod and service.

  1. kubectl --kubeconfig=kube_configxxx.yml delete -f https://raw.githubusercontent.com/rancher/longhorn-manager/master/examples/flexvolume/example_baseimage.yml

CSI Driver

The CSI driver supports volumes backed by base image. Below is a sample StorageClass definition including baseImage option.

  1. kind: StorageClass
  2. apiVersion: storage.k8s.io/v1
  3. metadata:
  4. provisioner: rancher.io/longhorn
  5. parameters:
  6. numberOfReplicas: '3'
  7. staleReplicaTimeout: '30'
  8. fromBackup: ''
  9. baseImage: rancher/longhorn-test:baseimage-ext4

Let’s walk through an example. First, ensure the CSI Plugin is deployed.

  1. kubectl --kubeconfig=kube_configxxx.yml -n longhorn-system get daemonset.apps/longhorn-csi-plugin

The following example creates an nginx statefulset with two replicas serving content from two csi-provisioned volumes backed by a base image. The statefulset is accessible from a service.

  1. kubectl --kubeconfig=kube_configxxx.yml create -f https://raw.githubusercontent.com/rancher/longhorn-manager/master/examples/provisioner_with_baseimage.yml

Wait until both pods are running.

  1. kubectl -l app=provisioner-baseimage get po -w

Query for the service you created.

  1. kubectl --kubeconfig=kube_configxxx.yml get svc/csi-baseimage

Your service should look similar.

  1. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  2. csi-baseimage LoadBalancer 10.43.47.129 <pending> 80:32768/TCP 4m

Now let’s access something packaged inside the base image through the Nginx webserver, exposed by the LoadBalancer service. If you have LoadBalancer support and EXTERNAL-IP is set, navigate to the following URL.

  1. http://<EXTERNAL-IP>/guests/hd/party-wizard.gif

Otherwise, navigate to the following URL where NODE-IP is the external IP address of any Kubernetes node and NODE-PORT is the second port in the service (32768 in the example service above).

  1. http://<NODE-IP>:<NODE-PORT>/guests/hd/party-wizard.gif

Finally, tear down the pod and service.

  1. kubectl --kubeconfig=kube_configxxx.yml delete -f https://raw.githubusercontent.com/rancher/longhorn-manager/master/examples/provisioner_with_baseimage.yml

Building

Creating and packaging an empty base image is a very simple process.

  1. Install QEMU基础镜像支持 - 图1.
  2. Create a qcow2 image.
  1. qemu-img create -f qcow2 example.qcow2 4G
  1. Create the Dockerfile file with the following contents:
  1. FROM busybox
  2. COPY example.qcow2 /base_image/example.qcow2
  1. Build and publish the image:
  1. DOCKERHUB_ACCT=rancher
  2. docker build -t ${DOCKERHUB_ACCT}/longhorn-example:baseimage .
  3. docker push ${DOCKERHUB_ACCT}/longhorn-example:baseimage

That’s it! Your (empty) base image is ready for (no) use. Let’s now explore some use cases for a base image and what we should do to our example.qcow2 before building and publishing.

Simple Filesystem

Suppose we want to store some static web assets in a volume. We have our qcow2 image and the web assets, but how to put the assets in the image?

On a Linux machine, load the network block device module.

  1. sudo modprobe nbd

Use qemu-nbd to expose the image as a network block device.

  1. sudo qemu-nbd -f qcow2 -c /dev/nbd0 example.qcow2

The raw block device needs a filesystem. Consider your infrastructure and choose an appropriate filesystem. We will use EXT4 filesystem.

  1. sudo mkfs -t ext4 /dev/nbd0

Mount the filesystem.

  1. mkdir -p example
  2. sudo mount /dev/nbd0 example

Copy web assets to filesystem.

  1. cp /web/images/* example/

Unmount the filesystem, shutdown qemu-nbd, cleanup.

  1. sudo umount example
  2. sudo killall qemu-nbd
  3. rmdir example

Optionally, compress the image.

  1. qemu-img convert -c -O qcow2 example.qcow2 example.compressed.qcow2

Follow the build and publish image steps and you are done. Example script基础镜像支持 - 图2.

Virtual Machine

See this document基础镜像支持 - 图3 for the basic procedure of preparing Virtual Machine images.