-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Heketi on OpenShift #5364
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Heketi on OpenShift #5364
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,386 @@ | ||
| [[install-config-storage-examples-containerized-heketi-dedicated-gluster]] | ||
| = Example: Containerized Heketi for managing dedicated GlusterFS storage | ||
| {product-author} | ||
| {product-version} | ||
| :data-uri: | ||
| :icons: | ||
| :experimental: | ||
| :toc: macro | ||
| :toc-title: | ||
| :prewrap!: | ||
|
|
||
| toc::[] | ||
|
|
||
| [[containerized-heketi-dedicated-gluster-overview]] | ||
| == Overview | ||
| This example provides information about the integration, deployment, and management of GlusterFS containerized storage nodes by using Heketi running on OpenShift Container Platform. | ||
|
|
||
| This example: | ||
|
|
||
| * Shows how to install and configure a Heketi server on OpenShift to perform dynamic provisioning. | ||
| * Assumes you have familiarity with Kubernetes and the Kubernetes Persistent Storage model. | ||
| * Assumes you have access to an existing, dedicated GlusterFS cluster that has raw devices available for consumption and management by a Heketi server. If you do not have this, you can create a three node cluster using your virtual machine solution of choice. Ensure sure you create a few raw devices and give plenty of space (at least 100GB recommended). See | ||
| link:https://access.redhat.com/documentation/en-US/Red_Hat_Storage/3.1/html/Installation_Guide/[Red Hat Gluster Storage Installation Guide]. | ||
|
|
||
| [[containerized-heketi-dedicated-gluster-prerequisites]] | ||
| == Environment and Prerequisites | ||
| This example uses the following environment and prerequisites: | ||
|
|
||
| * GlusterFS cluster running Red Hat Gluster Storage (RHGS) 3.1. Three nodes, each with at least two 100GB RAW devices: | ||
| ** *gluster23.rhs* (192.168.1.200) | ||
| ** *gluster24.rhs* (192.168.1.201) | ||
| ** *gluster25.rhs* (192.168.1.202) | ||
| * This example uses an all-in-one {product-title} cluster (master and node on a single host), though it can work using a standard, multi-node cluster as well. | ||
| ** *k8dev2.rhs* (192.168.1.208) | ||
|
|
||
| [[containerized-heketi-dedicated-gluster-install-heketi]] | ||
| == Installing and Configuring Heketi | ||
| Heketi is used to manage the Gluster cluster storage (adding volumes, removing volumes, etc.). Download link:https://github.com/heketi/heketi/blob/master/extras/openshift/templates/deploy-heketi-template.json[`deploy-heketi-template`] to install Heketi on OpenShift. | ||
|
|
||
| [NOTE] | ||
| ==== | ||
| This template file places the database in an EmptyDir volume. Adjust the database accordingly for a reliable persistent storage. | ||
| ==== | ||
|
|
||
| . Create a new project: | ||
| + | ||
| [source, bash] | ||
| ---- | ||
| $ oc new-project <project-name> | ||
| ---- | ||
|
|
||
| . Enable privileged containers in the new project: | ||
| + | ||
| [source, bash] | ||
| ---- | ||
| $ oc adm policy add-scc-to-user privileged -z default | ||
| ---- | ||
|
|
||
| . Register the `deploy-heketi` template: | ||
| + | ||
| [source, bash] | ||
| ---- | ||
| $ oc create -f <template-path>/deploy-heketi-template | ||
| ---- | ||
|
|
||
| . Deploy the bootstrap Heketi container: | ||
| + | ||
| [source, bash] | ||
| ---- | ||
| $ oc process deploy-heketi -v \ | ||
| HEKETI_KUBE_NAMESPACE=<project-name> \ | ||
| HEKETI_KUBE_APIHOST=<master-url-and-port> \ | ||
| HEKETI_KUBE_INSECURE=y \ | ||
| HEKETI_KUBE_USER=<cluster-admin-username> \ | ||
| HEKETI_KUBE_PASSWORD=<cluster-admin-password> | oc create -f - | ||
| ---- | ||
|
|
||
| . Wait until the `deploy-heketi` pod starts and all services are running. Then get Heketi service details: | ||
| + | ||
| [source, bash] | ||
| ---- | ||
| $ oc get svc | ||
| NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE | ||
| deploy-heketi 172.30.96.173 <none> 8080/TCP 2m | ||
| ---- | ||
|
|
||
| . Check if Heketi services are running properly, it must return `Hello from Heketi`. | ||
| + | ||
| [source, bash] | ||
| ---- | ||
| $ curl http://<cluster-ip>:8080/hello | ||
| Hello from Heketi | ||
| ---- | ||
|
|
||
| . Set an environment variable for the Heketi server: | ||
| + | ||
| [source, bash] | ||
| ---- | ||
| $ export HEKETI_CLI_SERVER=http://<cluster-ip>:8080 | ||
| ---- | ||
|
|
||
| [[dedicated-glusterfs-dynamic-loading-topology]] | ||
| == Loading Topology | ||
|
|
||
| Topology is used to tell Heketi about the environment and what nodes and devices | ||
| it will manage. | ||
|
|
||
| [NOTE] | ||
| ==== | ||
| Heketi is currently limited to managing raw devices only. If a device is already | ||
| a Gluster volume, it is skipped and ignored. | ||
| ==== | ||
|
|
||
| . Create and load the topology file. There is a sample file located in | ||
| *_/usr/share/heketi/toplogy-sample.json_* by default, or *_/etc/heketi_* | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Didn't see /usr/share/heketi/toplogy-sample.json, may because I just have heketi-client RPM package installed. Should hint customer here.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @wkshi I have updated the docs to include more details around this one by adding following note: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks good to me~ |
||
| depending on how it was installed. | ||
| + | ||
| [NOTE] | ||
| ==== | ||
| Depending upon your method of installation this file may not exist. If it is missing, manually create the *_toplogy-sample.json_* file, as shown in the following example. | ||
| ==== | ||
| + | ||
| [source, json] | ||
| ---- | ||
| { | ||
| "clusters": [ | ||
| { | ||
| "nodes": [ | ||
| { | ||
| "node": { | ||
| "hostnames": { | ||
| "manage": [ | ||
| "gluster23.rhs" | ||
| ], | ||
| "storage": [ | ||
| "192.168.1.200" | ||
| ] | ||
| }, | ||
| "zone": 1 | ||
| }, | ||
| "devices": [ | ||
| "/dev/sde", | ||
| "/dev/sdf" | ||
| ] | ||
| }, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a extra "," here. Remove it then "heketi-cli topology load --json=toplogy-sample.json" could works.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I removed the extra "," from line 179, in the latest commit and also fixed it in the gluster dynamic example. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks good to me~ |
||
| { | ||
| "node": { | ||
| "hostnames": { | ||
| "manage": [ | ||
| "gluster24.rhs" | ||
| ], | ||
| "storage": [ | ||
| "192.168.1.201" | ||
| ] | ||
| }, | ||
| "zone": 1 | ||
| }, | ||
| "devices": [ | ||
| "/dev/sde", | ||
| "/dev/sdf" | ||
| ] | ||
| }, | ||
| { | ||
| "node": { | ||
| "hostnames": { | ||
| "manage": [ | ||
| "gluster25.rhs" | ||
| ], | ||
| "storage": [ | ||
| "192.168.1.202" | ||
| ] | ||
| }, | ||
| "zone": 1 | ||
| }, | ||
| "devices": [ | ||
| "/dev/sde", | ||
| "/dev/sdf" | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ---- | ||
|
|
||
| . Run the following command to load the topology of your | ||
| environment. | ||
| + | ||
| [source, bash] | ||
| ---- | ||
| $ heketi-cli topology load --json=toplogy-sample.json | ||
|
|
||
| Found node gluster23.rhs on cluster bdf9d8ca3fa269ff89854faf58f34b9a | ||
| Adding device /dev/sde ... OK | ||
| Adding device /dev/sdf ... OK | ||
| Creating node gluster24.rhs ... ID: 8e677d8bebe13a3f6846e78a67f07f30 | ||
| Adding device /dev/sde ... OK | ||
| Adding device /dev/sdf ... OK | ||
| ... | ||
| ---- | ||
|
|
||
| . Create a Gluster volume to verify Heketi: | ||
| + | ||
| [source, bash] | ||
| ---- | ||
| $ heketi-cli volume create --size=50 | ||
| ---- | ||
|
|
||
| . View the volume information from one of the the Gluster nodes: | ||
| + | ||
| [source, bash] | ||
| ---- | ||
| $ gluster volume info | ||
|
|
||
| Volume Name: vol_335d247ac57ecdf40ac616514cc6257f <1> | ||
| Type: Distributed-Replicate | ||
| Volume ID: 75be7940-9b09-4e7f-bfb0-a7eb24b411e3 | ||
| Status: Started | ||
| ... | ||
| ---- | ||
| <1> Volume created by `heketi-cli`. | ||
|
|
||
| [[dedicated-glusterfs-dynamic-provision-volume]] | ||
| == Dynamically Provision a Volume | ||
| [NOTE] | ||
| ==== | ||
| If you installed {product-title} by using the link:https://github.com/openshift/openshift-ansible/tree/master/inventory/byo[BYO (Bring your own) OpenShift Ansible inventory configuration files] for either link:https://github.com/openshift/openshift-ansible/blob/master/inventory/byo/hosts.byo.glusterfs.native.example[native] or link:https://github.com/openshift/openshift-ansible/blob/master/inventory/byo/hosts.byo.glusterfs.external.example[external] GlusterFS instance, the GlusterFS StorageClass automatically get created during the installation. For such cases you can skip the following storage class creation steps and directly proceed with creating persistent volume claim instruction. | ||
| ==== | ||
|
|
||
| . Create a `StorageClass` object definition. The following definition is based on the | ||
| minimum requirements needed for this example to work with {product-title}. See | ||
| xref:../../install_config/persistent_storage/dynamically_provisioning_pvs.adoc#install-config-persistent-storage-dynamically-provisioning-pvs[Dynamic | ||
| Provisioning and Creating Storage Classes] for additional parameters and | ||
| specification definitions. | ||
| + | ||
| [source,yaml] | ||
| ---- | ||
| kind: StorageClass | ||
| apiVersion: storage.k8s.io/v1 | ||
| metadata: | ||
| name: gluster-dyn | ||
| provisioner: kubernetes.io/glusterfs | ||
| parameters: | ||
| resturl: "http://glusterclient2.rhs:8080" <1> | ||
| restauthenabled: "false" <2> | ||
| ---- | ||
| <1> The Heketi server from the `HEKETI_CLI_SERVER` environment variable. | ||
| <2> Since authentication is not turned on in this example, set to `false`. | ||
|
|
||
| . From the {product-title} master host, create the storage class: | ||
| + | ||
| [source, bash] | ||
| ---- | ||
| $ oc create -f glusterfs-storageclass1.yaml | ||
| storageclass "gluster-dyn" created | ||
| ---- | ||
|
|
||
| . Create a persistent volume claim (PVC), requesting the newly-created storage | ||
| class. For example: | ||
| + | ||
| [source,yaml] | ||
| ---- | ||
| apiVersion: v1 | ||
| kind: PersistentVolumeClaim | ||
| metadata: | ||
| name: gluster-dyn-pvc | ||
| spec: | ||
| accessModes: | ||
| - ReadWriteMany | ||
| resources: | ||
| requests: | ||
| storage: 30Gi | ||
| storageClassName: gluster-dyn | ||
| ---- | ||
|
|
||
| . From the {product-title} master host, create the PVC: | ||
| + | ||
| [source, bash] | ||
| ---- | ||
| $ oc create -f glusterfs-pvc-storageclass.yaml | ||
| persistentvolumeclaim "gluster-dyn-pvc" created | ||
| ---- | ||
|
|
||
| . View the PVC to see that the volume was dynamically created and bound to the PVC: | ||
| + | ||
| [source, bash] | ||
| ---- | ||
| $ oc get pvc | ||
| NAME STATUS VOLUME CAPACITY ACCESSMODES STORAGECLASS AGE | ||
| gluster-dyn-pvc Bound pvc-78852230-d8e2-11e6-a3fa-0800279cf26f 30Gi RWX gluster-dyn 42s | ||
| ---- | ||
|
|
||
| . Verify and view the new volume on one of the Gluster nodes: | ||
| + | ||
| [source, bash] | ||
| ---- | ||
| $ gluster volume info | ||
|
|
||
| Volume Name: vol_335d247ac57ecdf40ac616514cc6257f <1> | ||
| Type: Distributed-Replicate | ||
| Volume ID: 75be7940-9b09-4e7f-bfb0-a7eb24b411e3 | ||
| Status: Started | ||
| ... | ||
| Volume Name: vol_f1404b619e6be6ef673e2b29d58633be <2> | ||
| Type: Distributed-Replicate | ||
| Volume ID: 7dc234d0-462f-4c6c-add3-fb9bc7e8da5e | ||
| Status: Started | ||
| Number of Bricks: 2 x 2 = 4 | ||
| ... | ||
| ---- | ||
| <1> Volume created by `heketi-cli`. | ||
| <2> New dynamically created volume triggered by Kubernetes and the storage class. | ||
|
|
||
| [[dedicated-glusterfs-dynamic-nginx]] | ||
| == Creating a NGINX Pod That Uses the PVC | ||
|
|
||
| At this point, you have a dynamically created GlusterFS volume bound to a PVC. | ||
| You can now now utilize this PVC in a pod. In this example, create a simple | ||
| NGINX pod. | ||
|
|
||
| . Create the pod object definition: | ||
| + | ||
| [source,yaml] | ||
| ---- | ||
| apiVersion: v1 | ||
| kind: Pod | ||
| metadata: | ||
| name: gluster-pod1 | ||
| labels: | ||
| name: gluster-pod1 | ||
| spec: | ||
| containers: | ||
| - name: gluster-pod1 | ||
| image: gcr.io/google_containers/nginx-slim:0.8 | ||
| ports: | ||
| - name: web | ||
| containerPort: 80 | ||
| securityContext: | ||
| privileged: true | ||
| volumeMounts: | ||
| - name: gluster-vol1 | ||
| mountPath: /usr/share/nginx/html | ||
| volumes: | ||
| - name: gluster-vol1 | ||
| persistentVolumeClaim: | ||
| claimName: gluster-dyn-pvc <1> | ||
| ---- | ||
| <1> The name of the PVC created in the previous step. | ||
|
|
||
| . From the {product-title} master host, create the pod: | ||
| + | ||
| [source, bash] | ||
| ---- | ||
| $ oc create -f nginx-pod.yaml | ||
| pod "gluster-pod1" created | ||
| ---- | ||
|
|
||
| . View the pod. Give it a few minutes, as it might need to download the image if | ||
| it does not already exist: | ||
| + | ||
| [source, bash] | ||
| ---- | ||
| $ oc get pods -o wide | ||
| NAME READY STATUS RESTARTS AGE IP NODE | ||
| gluster-pod1 1/1 Running 0 9m 10.38.0.0 node1 | ||
| ---- | ||
|
|
||
| . Now remote into the container with `oc exec` and create an *_index.html_* file: | ||
| + | ||
| [source, bash] | ||
| ---- | ||
| $ oc exec -ti gluster-pod1 /bin/sh | ||
| $ cd /usr/share/nginx/html | ||
| $ echo 'Hello World from GlusterFS!!!' > index.html | ||
| $ ls | ||
| index.html | ||
| $ exit | ||
| ---- | ||
|
|
||
| . Now `curl` the URL of the pod: | ||
| + | ||
| [source, bash] | ||
| ---- | ||
| $ curl http://10.38.0.0 | ||
| Hello World from GlusterFS!!! | ||
| ---- | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does EmptyDir need mark up? i looked quickly at the docs and there doesn't seem to be consistent usage. Some
EmptyDir, some EmptyDir and some with no mark up.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kubernetes uses
emptyDirmaybe we should use the same markup. I'll check this in our docs and submit a new PR with the changes.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @mburke5678 addressed this in #6084