Introducing “gluster-kubernetes” repo && “gk-deploy” script .

The information to bring Gluster into kubernetes was kind of scattered among few repos and we noticed few concerns on lagging single place to look into! it made the launch of new repo under gluster github account called “glusterfs-kubernetes” . This repo introduced a new tool called “gk-deploy” which helps to deploy the entire solution in kubernetes or Openshift environment.

An excerpt from its run.

[root@master deploy]# ./gk-deploy -g topology.json -n storagens Welcome to the deployment tool for GlusterFS on Kubernetes and OpenShift.

Before getting started, this script has some requirements of the execution environment and of the container platform that you should verify.

The client machine that will run this script must have: * Administrative access to an existing Kubernetes or OpenShift cluster * Access to a python interpreter ‘python’ * Access to the heketi client ‘heketi-cli’

Each of the nodes that will host GlusterFS must also have appropriate firewall
rules for the required GlusterFS ports:

* 2222 – sshd (if running GlusterFS in a pod) * 24007 – GlusterFS Daemon * 24008 – GlusterFS Management * 49152 to 49251 – Each brick for every volume on the host requires its own port. For every new brick, one new port will be used starting at 49152. We recommend a default range of 49152-49251 on each host, though you can adjust this to fit your needs.

In addition, for an OpenShift deployment you must:

* Have ‘cluster_admin’ role on the administrative account doing the deployment * Add the ‘default’ and ‘router’ Service Accounts to the ‘privileged’ SCC * Add the ‘heketi-service-account’ Service Account to the ‘privileged’ SCC * Have a router deployed that is configured to allow apps to access services running in the cluster

Do you wish to proceed with deployment?

[Y]es, [N]o? [Default: Y]: y Multiple CLI options detected. Please select a deployment option. [O]penShift, [K]ubernetes? [O/o/K/k]: o Using OpenShift CLI. NAME STATUS AGE storagens Active 25s Using namespace “storagens”. serviceaccount “heketi-service-account” created

…………

On a successful run, you will have running Gluster pods, Heketi service..etc.

New features ( GID support, Cluster support ) added to GlusterFS dynamic provisioner in Kubernetes.

Always there are asks for RFEs and we are bringing it into GlusterFS dynamic provisioner one by one!

I would like to introduce 2 new features available now in upstream Kube tree which enhance the functionality of GlusterFS provisioner.

1) The GID ( Group ID ) support for dynamically provisioned volume
2) The support for specifying the “Cluster” from which an admin want to provision the volume.

Lets look into these options in detail.

The GID support:Till now, the gluster dynamic provisioner was creating volumes with USERID and GROUPID as root (UID 0 : GID 0 ). So, the access to the volume is restricted to root user. However with the addition of GID support, we now have a GID allocator internal to the provisioner. This allows a storage admin of Openshift/Kubernetes cluster specify a POOL of GIDs for a particular storage class. That said, the provisioner introduced 2 more new parameters called gidMin and gidMax in Storage class. These are optional parameters.

# cat glusterfs-storageclass.yaml

apiVersion: storage.k8s.io/v1beta1 kind: StorageClass metadata: name:gluster-fast provisioner: kubernetes.io/glusterfs parameters: resturl: “http://127.0.0.1:8081” restuser: “admin” secretNamespace: “default” secretName: “heketi-secret” gidMin: “2000” gidMax: “4000”

With the above storage class configuration, if you provision PVs using PV Claim requests, the PVs are created and given access to GID value for ex: 2001 which is a value between mentioned gidMin and gidMax value. If the gidMin and gidMax value are not provided, then the dynamic provisioned volumes will have the GID between 2000 and 2147483647.

If you attach this PVClaim to a pod, the pod get the new GID value in its supplemental group, thus get access to the volume. How this GID is passed to the supplemental group is internally taken care by the provisioner. You can validate that the GID has been reflected in Supplemental Group ID of the pod using ‘id’ command inside the container.

For ex: inside the container where this PVC is attached:

# id

uid=1000060000 gid=0(root) groups=0(root),2001

Now you should be able to write to the volume with the access of this Group. Once the Claim is deleted, previously allocated GID will go back to the GID pool.

Nice feature. Isnt it ?
lets look into the second feature ( Cluster Support ):

As yet, when you dynamically provision a volume, Heketi-the server who create volumes pick any of the cluster according to certain criteria. However there was a request from few users on, there should be a provision to specify a cluster or group of clusters for a storage class , so we added that support. According to me, this can help in scenarios for example, where storage admin want to specify a particular cluster for Dev and another cluster for TEST/QE departments, may be based on the hardware he has allocated for these departments and so on. That said, an admin is left with the choice of grouping nodes with faster disks ( SSDs) in one cluster and thus a storage class called ‘fast’ and other slow speed harddisks in another cluster and a subjected storage class ‘slow’. The PVs will be created based on this classification if you use ‘clusterid’ parameter in the storage class. With that it is possible now in dynamic provisioner to select a cluster from which you want to provision volume. Cool feature, Isnt it ?

apiVersion: storage.k8s.io/v1beta1

kind: StorageClass

metadata:

name: slow

provisioner: kubernetes.io/glusterfs

parameters:

resturl: “http://127.0.0.1:8081”

clusterid: “630372ccdc720a92c681fb928f27b53f”

restuser: “admin”

secretNamespace: “default”

secretName: “heketi-secret”

gidMin: “40000”

gidMax: “50000”

* clusterid: 630372ccdc720a92c681fb928f27b53f is the ID of the cluster which will be used by Heketi when provisioning the volume. It can also be a list of clusterids, for ex:”8452344e2becec931ece4e33c4674e4e,42982310de6c63381718ccfa6d8cf397″. This is an optional parameter.

Please feel free to share your thoughts on these new features and also let me know if you would like to see any further enhancements for the gluster dynamic provisioner.!! I am watching this space for your comments.

Use iscsiadm session command to figure out details about a gluster block share.

Here is an easy way to list details about an ISCSI share or LUN. You have all the required details about the share below. You could also map this information in an iscsi client system to figure out the device map or device file as shown below.

[root@localhost glusterblock]# iscsiadm -m session -P 3 iSCSI Transport Class version 2.0-870 version 6.2.0.873-33 Target: iqn.2016-12.org.gluster-block:5b5b9581-bc66-4d51-8b4e-2befcd30fee7 (non-flash) Current Portal: 10.67.116.64:3260,1 Persistent Portal: 10.67.116.64:3260,1 ********** Interface: ********** Iface Name: default Iface Transport: tcp Iface Initiatorname: iqn.1994-05.com.redhat:8efc1ab116fc Iface IPaddress: 10.67.116.64 Iface HWaddress: Iface Netdev: SID: 41 iSCSI Connection State: LOGGED IN iSCSI Session State: LOGGED_IN Internal iscsid Session State: NO CHANGE ********* Timeouts: ********* Recovery Timeout: 120 Target Reset Timeout: 30 LUN Reset Timeout: 30 Abort Timeout: 15 ***** CHAP: ***** username: 5b5b9581-bc66-4d51-8b4e-2befcd30fee7 password: ******** username_in: password_in: ******** ************************ Negotiated iSCSI params: ************************ HeaderDigest: None DataDigest: None MaxRecvDataSegmentLength: 262144 MaxXmitDataSegmentLength: 262144 FirstBurstLength: 65536 MaxBurstLength: 262144 ImmediateData: Yes InitialR2T: Yes MaxOutstandingR2T: 1 ************************ Attached SCSI devices: ************************ Host Number: 3 State: running scsi3 Channel 00 Id 0 Lun: 0 Attached scsi disk sdb State: running [root@localhost glusterblock]# ll /dev/sdb brw-rw—- 1 root disk 8, 16 May 20 14:24 /dev/sdb [root@localhost glusterblock]# ll /dev/disk/by-path/ip-10.67.116.64:3260-iscsi-iqn.2016-12.org.gluster-block:5b5b9581-bc66-4d51-8b4e-2befcd30fee7-lun-0 lrwxrwxrwx 1 root root 9 May 20 14:24 /dev/disk/by-path/ip-10.67.116.64:3260-iscsi-iqn.2016-12.org.gluster-block:5b5b9581-bc66-4d51-8b4e-2befcd30fee7-lun-0 -> ../../sdb [root@localhost glusterblock]# iscsiadm -m session tcp: [41] 10.67.116.64:3260,1 iqn.2016-12.org.gluster-block:5b5b9581-bc66-4d51-8b4e-2befcd30fee7 (non-flash) [root@localhost glusterblock]#

[How to] GlusterFS Dynamic Volume Provisioner in Kubernetes (>= v1.4 ) / Openshift.

You could have seen or tried the method of using glusterfs volumes in a kubernetes/openshift cluster as discussed in my previous blog post , however this involves more steps or this method is called static provisioning. In this article, I will discuss about a new method called dynamic volume provisioning.

I am happy to share that Gluster Dynamic Volume Provisioner is available in kubernetes tree since 1.4 release !!

This is one of the feature which enables the User/Developer in Kubernetes/Openshift to have Persistent Volume Claim ( PVC ) request to be satisfied dynamically without admin intervention. IMHO, it gives a nice user experience and its a good feature to have in container orchestrators. Till this feature came in, the persistent volumes in the store were created statically.

The static provisioning workflow looks like this:

Eventhough it was easy to perform the static provisioning of volumes, it has few limitations in my view.

*) The admin has to create the persistent volumes upfront and keep it in persistent store.

*) When a claim request comes to the controller, it check for the size of the request against the available PVs in the pool and if the ( available PV size >= size of the request ) it bind the claim.

The latter can lead to wastage of storage in most of the case.

These kinds of limitations have been lifted with Dynamic provisioning. Now the admin defines the storage classes and the user/developer request the persistent volumes using the storage class reference in the PVC request. The storage classes can pass the parameters of the plugin using the storage class key value pairs.

I have created the following diagram to simplify the workflow of dynamic (Ex: GlusterFS) provisioning.

As you can see in the above diagram, the GlusterFS plugin in Kubernetes/Openshift make use of “Heketi” to provision GlusterFS volumes. If you want to know more about Heketi and how it can be used to manage gluster clusters, please refer this Wiki. In short, Heketi is a volume manager for GlusterFS clusters. It manage Gluster trusted pool and create volumes based on demand.

Let us start from Storage Class which allows us to do dynamic provisioning in kubernetes.

Here is an example of the storage class parameters:

apiVersion: storage.k8s.io/v1beta1 kind: StorageClass metadata: name: slow provisioner: kubernetes.io/glusterfs parameters: resturl: “http://127.0.0.1:8081” restuser: “admin” secretNamespace: “default” secretName: “heketi-secret”

Where

resturl : Gluster REST service/Heketi service url which provision gluster volumes on demand. The general format should be IPaddress:Port and this is a mandatory parameter for GlusterFS dynamic provisioner. If Heketi service is exposed as a routable service in openshift/kubernetes setup, this can have a format similar to http://heketi-storage-project.cloudapps.mystorage.com where the fqdn is a resolvable heketi service url.

restuser : Gluster REST service/Heketi user who has access to create volumes in the Gluster Trusted Pool.

secretNamespace + secretName : Identification of Secret instance that containes user password to use when talking to Gluster REST service. These parameters are optional, empty password will be used when both secretNamespace and secretName are omitted.

for more details on these parameters please refer https://github.com/kubernetes/kubernetes/tree/master/examples/experimental/persistent-volume-provisioning

To summarize, the user/developer requests the persistent storage using the claim and mentions the storage class which need to be used/mapped with the claim. As soon as the claim request comes in, the GlusterFS plugin in Kubernetes create a volume with the requested size and BIND the persistent volume to Claim. When there is a request to delete the claim, the subjected volume is deleted from the backend gluster trusted pool. The glusterfs plugin in Kubernetes make use of ‘Heketi’ to provision a volume dynamically.

Here is the demo video of Dynamic GlusterFS provisioner in Kubernetes.

As always comments/suggestions/questions are welcome. ?

[ Berlin ] Gluster Summit 2016 – An awesome event

This year’s gluster summit was held at Berlin ( Oct 6th and 7th – 2016) and I am happy to be part of it. An awesome city and great folks around.

There were lots of presentations about Gluster and its upcoming features. If you would like to catch up with all the presentations please check this account in slideshare # http://www.slideshare.net/GlusterCommunity/

I gave a presentation in the same event with Luis on contenarized storage for cloud applications and received really good feedback about this. \o/

Here is the slide of the presentation.

[slideshare id=67284723&doc=glusterfssummit2016-161017120703]

Gluster Client Containers or containers capable of mounting Gluster Volumes.

I have been receiving lots of queries on whether we can mount GlusterFS from the container ? or Gluster Client containers are available ?
Yes, it is. Today I refreshed this image to fedora24, so the blog.
The process to use gluster client containers are simple as shown below:

[Update: the same docker image can be found at https://hub.docker.com/r/gluster/gluster-client/ ]

#docker pull humble/gluster-client

Then run the container as

[root@localhost gluster-client]# docker run -d -ti –privileged humble/gluster-client bash
7d8dfbf8e4dbb841b240cc196682c77aad7c30cc4511d906cab275cd326b4755

[root@localhost gluster-client]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7d8dfbf8e4db humble/gluster-client "bash" 6 seconds ago Up 2 seconds high_cray
[root@localhost gluster-client]# docker exec -ti 7d8dfbf8e4db bash

[root@7d8dfbf8e4db /]# glusterd –version
glusterfs 3.8.4 built on Sep 10 2016 16:42:36
Repository revision: git://git.gluster.com/glusterfs.git
Copyright (c) 2006-2013 Red Hat, Inc.
GlusterFS comes with ABSOLUTELY NO WARRANTY.It is licensed to you under your choice of the GNU Lesser
General Public License, version 3 or any later version (LGPLv3 or later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation.
[root@7d8dfbf8e4db /]#cat /etc/redhat-release
Fedora release 24 (Twenty Four)
[root@7d8dfbf8e4db /]#

Make sure “FUSE” device exist in the container as shown below.

[root@localhost gluster-client]# ll /dev/fuse
crw-rw-rw-. 1 root root 10, 229 Sep 18 03:03 /dev/fuse
[root@localhost gluster-client]#

I have a gluster volume exported from another server and would like to mount it inside this container.

[root@7d8dfbf8e4db /]# mount -t glusterfs 192.168.43.149:/myVol1 /mnt
WARNING: getfattr not found, certain checks will be skipped..
[root@7d8dfbf8e4db mnt]# mount |grep gluster
192.168.43.149:/myVol1 on /mnt type fuse.glusterfs (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other,max_read=131072)
[root@7d8dfbf8e4db mnt]#
[root@7d8dfbf8e4db /]# cd /mnt
[root@7d8dfbf8e4db mnt]# ls
[root@7d8dfbf8e4db mnt]# touch Hi
[root@7d8dfbf8e4db mnt]#

Thats it.

I will automate the build in docker hub and move this image to gluster official account soon.

Gluster Container Demo Videos on “Gluster as a Persistent Data Store for Containers…. “

Recently I got a chance to consolidate the Demo videos which covers how GlusterFS can be used in Docker, kubernetes and Openshift. I have placed everything in single channel for better tracking.

Here is a brief description about the available videos:

How to run a Gluster Container :

Reference # Blog – bit.ly/2bNobjK Presentation – bit.ly/2bNow5Y

This demo covers the standard process to run Gluster Docker Containers in a Linux system. It shows which directories can be exported when spawning Gluster Containers to make sure data persistence. This demo also talks about the usage of official Gluster Container image.

How to form a Gluster trusted pool using Gluster Containers:

This demo shows how we can create a Gluster trusted pool (cluster) among Gluster containers. This is one of the important building blocks of Running storage in container or to be precise, “Storage as a Service” in my terms.

Gluster Container deployment in Openshift using templates-DaemonSets

Reference # bit.ly/2btsZLQ

Once we are confident that we can run gluster containers and form a trusted pool, the next step would be deploying it in PaaS like offering. Obviously I chose Openshift PaaS for this demo because it is an awesome PaaS based on Kubernetes.

“OpenShift is Red Hat’s Platform-as-a-Service (PaaS) that allows developers to quickly develop, host, and scale applications in a cloud environment. With OpenShift you have a choice of offerings, including online, on-premise, and open source project options.” .

OpenShift has a deployment model called ‘template deployment’ which will be a part of this demo as well. This demo also covers one of the deployment option ‘DaemonSets’ to deploy gluster containers/pods in Openshift.

Gluster Persistent Storage in Kubernetes/Openshift OR PV and PVC using GlusterFS plugin

Reference #

Blog – bit.ly/2boATUK Presentation – bit.ly/2bX5XNZ

This demo shows us a way to use Gluster trusted pool and Gluster volumes in an OpenShift or Kubernetes environment. The trusted pool may or may not be hosted in containers. The demo covers the Endpoint, Service, Persistent Volume and Persistent Volume Claim creation based on GlusterFS trusted pool and volumes. Once we have a ‘BOUND” claim, one can use it in application pod/container for Persistent Data Store.

Gluster Pods deployment with PetSets for consistent pod name

In general the pods get a random name in an Openshift or Kubernetes environment. At times we may need to assign defined names or ordered names for the Gluster Pods. There is a new attribute ‘PetSets‘ in kubernetes which enables this functionality. Here we use “PetSets’ in this demo to show how we can get defined names for Gluster Containers and to show how this PetSet pods can be controlled or scaled as well.

Stay tuned, there’s more to come in this space.

Run Gluster systemd containers [without privileged mode] in Fedora/CentOS

Run Gluster systemd containers [without privileged mode] in Fedora/CentOS

Today we will discuss how to run gluster systemd containers without ‘privilege’ mode !! Awesome .. Isn’t it?

I owe this blog to few people latest being twitter.com/dglushenok/status/740265552258682882
Here is some details about my docker host setup:

Today we will discuss how to run gluster systemd containers without ‘privilege’ mode !! Awesome .. Isn’t it?

I owe this blog to few people latest being twitter.com/dglushenok/status/740265552258682882
Here is some details about my docker host setup:

[root@dhcp35-111 ~]# cat /etc/redhat-release Fedora release 24 (Twenty Four) [root@dhcp35-111 ~]# docker version Client: Version: 1.10.3 API version: 1.22 Package version: docker-1.10.3-21.git19b5791.fc24.x86_64 Go version: go1.6.2 Git commit: 19b5791/1.10.3 Built: OS/Arch: linux/amd64 Server: Version: 1.10.3 API version: 1.22 Package version: docker-1.10.3-21.git19b5791.fc24.x86_64 Go version: go1.6.2 Git commit: 19b5791/1.10.3 Built: OS/Arch: linux/amd64 [root@dhcp35-111 ~]#

I have pulled gluster/gluster-centos image from the docker hub and kept in my docker image registry.

[root@dhcp35-111 ~]# docker images |grep gluster docker.io/gluster/gluster-centos latest 759691b0beca 4 days ago 406.1 MB gluster/gluster-centos experiment fd8cd51f47fb 2 weeks ago 351.2 MB gluster/gluster-centos latest 9b46174d3366 3 weeks ago 351.1 MB gluster/gluster-centos gluster_3_7_centos_7 5809addca906 4 weeks ago 351.1 MB

The beauty is that we don’t need any extra steps to be performed in our host system.

NOTE: We haven’t submitted ‘privileged’ flag/option with below ‘docker run’ command. The volume mounts like ‘/etc/glusterfs’, ‘/var/lib/glusterd’, ‘/var/log/glusterfs’..etc are kept for glusterfs metadata and logs to be persistent across container spawning.

[root@dhcp35-111 docker-host]# docker run -d –name gluster3 -v /etc/glusterfs:/etc/glusterfs:z -v /var/lib/glusterd:/var/lib/glusterd:z -v /var/log/glusterfs:/var/log/glusterfs:z -v /sys/fs/cgroup:/sys/fs/cgroup:ro gluster/gluster-centos 8b1dd6f0aa88197bdcd022802f7c0c16d642630a21b2b43accfa5ed8023c197a [root@dhcp35-111 docker-host]#

As we now have the container id ( 8b1dd6f0aa88197bdcd022802f7c0c16d642630a21b2b43accfa5ed8023c197a), let’s get inside the container and examine the service and its behavior.

[root@dhcp35-111 docker-host]# docker exec -ti 8b1dd6f0aa88197bdcd022802f7c0c16d642630a21b2b43accfa5ed8023c197a /bin/bash [root@8b1dd6f0aa88 /]# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 122764 4688 ? Ss 13:34 0:00 /usr/sbin/init root 22 0.0 0.0 36832 6348 ? Ss 13:34 0:00 /usr/lib/systemd/systemd-journald root 23 0.0 0.0 118492 2744 ? Ss 13:34 0:00 /usr/sbin/lvmetad -f root 29 0.0 0.0 24336 2884 ? Ss 13:34 0:00 /usr/sbin/crond -n rpc 42 0.0 0.0 64920 3244 ? Ss 13:34 0:00 /sbin/rpcbind -w root 44 0.0 0.2 430272 17300 ? Ssl 13:34 0:00 /usr/sbin/glusterd -p /var/run/glusterd.pid –log-level INFO root 68 0.0 0.0 82572 6212 ? Ss 13:34 0:00 /usr/sbin/sshd -D root 197 0.0 0.0 11788 2952 ? Ss 13:35 0:00 /bin/bash root 219 0.0 0.0 47436 3360 ? R+ 13:44 0:00 ps aux [root@8b1dd6f0aa88 /]# [root@8b1dd6f0aa88 /]# systemctl status glusterd ● glusterd.service – GlusterFS, a clustered file-system server Loaded: loaded (/usr/lib/systemd/system/glusterd.service; enabled; vendor preset: disabled) Active: active (running) since Tue 2016-06-28 13:34:53 UTC; 27s ago Process: 43 ExecStart=/usr/sbin/glusterd -p /var/run/glusterd.pid –log-level $LOG_LEVEL $GLUSTERD_OPTIONS (code=exited, status=0/SUCCESS) Main PID: 44 (glusterd) CGroup: /system.slice/docker-8b1dd6f0aa88197bdcd022802f7c0c16d642630a21b2b43accfa5ed8023c197a.scope/system.slice/glusterd.service └─44 /usr/sbin/glusterd -p /var/run/glusterd.pid –log-level INFO Jun 28 13:34:51 8b1dd6f0aa88 systemd[1]: Starting GlusterFS, a clustered file-system server… Jun 28 13:34:53 8b1dd6f0aa88 systemd[1]: Started GlusterFS, a clustered file-system server. Jun 28 13:35:15 8b1dd6f0aa88 systemd[1]: Started GlusterFS, a clustered file-system server. [root@8b1dd6f0aa88 /]# [root@8b1dd6f0aa88 /]# glusterd –version glusterfs 3.7.11 built on Apr 18 2016 13:20:46 Repository revision: git://git.gluster.com/glusterfs.git Copyright (c) 2006-2013 Red Hat, Inc. GlusterFS comes with ABSOLUTELY NO WARRANTY. It is licensed to you under your choice of the GNU Lesser General Public License, version 3 or any later version (LGPLv3 or later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. [root@8b1dd6f0aa88 /]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) [root@8b1dd6f0aa88 /]# rpm -qa |grep glusterfs glusterfs-3.7.11-1.el7.x86_64 glusterfs-fuse-3.7.11-1.el7.x86_64 glusterfs-cli-3.7.11-1.el7.x86_64 glusterfs-libs-3.7.11-1.el7.x86_64 glusterfs-client-xlators-3.7.11-1.el7.x86_64 glusterfs-api-3.7.11-1.el7.x86_64 glusterfs-server-3.7.11-1.el7.x86_64 glusterfs-geo-replication-3.7.11-1.el7.x86_64 [root@8b1dd6f0aa88 /]#

Let’s examine this container from docker host and verify these containers are running without privileged mode.

[root@dhcp35-111 docker-host]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8b1dd6f0aa88 gluster/gluster-centos “/usr/sbin/init” 6 minutes ago Up 6 minutes 111/tcp, 245/tcp, 443/tcp, 2049/tcp, 2222/tcp, 6010-6012/tcp, 8080/tcp, 24007/tcp, 38465-38466/tcp, 38468-38469/tcp, 49152-49154/tcp, 49156-49162/tcp gluster3 [root@dhcp35-111 docker-host]# docker inspect 8b1dd6f0aa88|grep -i privil “Privileged”: false, [root@dhcp35-111 docker-host]#

All is well, but what will be missing if you run these containers without ‘privilged’ mode? Not much! However, if you want to create gluster snapshots from the container we may need to export ‘/dev/’ to the container and operations to create devices from containers need privileged mode.

Possible configurations of GlusterFS in Kubernetes/OpenShift setup

In previous blog posts, we discussed, how to use GlusterFS as a persistent storage in Kubernetes and Openshift. In nutshell, the GlusterFS can be deployed/used in a Kubernetes/openshift environment as :

*) Contenarized GlusterFS ( Pod ) *) GlusterFS as Openshift service and Endpoint (Service and Endpoint). *) GlusterFS volume as Persistent Volume (PV) and using GlusterFS volume plugin to bind this PV to a Persistent Volume Claim ( PVC) *) GlusterFS template to deploy GlusterFS pods in an Openshift Environment.

All the configuration files that can be used to deploy GlusterFS can be found @ github.com/humblec/glusterfs-kubernetes-openshift/ or github.com/gluster/glusterfs-kubernetes-openshift. Let’s see how to use these files to deploy GlusterFS in Kubernetes and Openshift. We will start with Deploying GlusterFS pods in an Openshift/Kubernetes Environment. Deploying GlusterFS Pod:

[Update] The pod file is renamed to gluster-pod.yaml in the mentioned repo. More details about Gluster Containers can be found @http://www.slideshare.net/HumbleChirammal/gluster-containers

GlusterFS pods can be deployed in Kubernetes/Openshift, so that Gluster Nodes are deployed in containers and it can provide persistent storage for Openshift/Kubernetes setup. The examples files in this repo are used for this demo.

Step 1: Create GlusterFS pod

[root@atomic-node2 gluster_pod]# oc create -f gluster-1.yaml

Step 2: Get details about the GlusterFS pod.

[root@atomic-node2 gluster_pod]# oc describe pod gluster-1

Name: gluster-1 Namespace: default Image(s): gluster/gluster-centos Node: atomic-node1/10.70.43.174 Start Time: Tue, 17 May 2016 10:19:17 +0530 Labels: name=gluster-1 Status: Running Reason: Message: IP: 10.70.43.174 Replication Controllers: Containers: glusterfs: Container ID: docker://ff8f4af700d725dfe0e08939ec011c34ddf9dedc7204e0ced1cc355a56150742 Image: gluster/gluster-centos Image ID: docker://033de9c44a8aabde55ce8a2b751ccf5bc345fdb534ea30e79a8fa70b82dc7761 QoS Tier: cpu: BestEffort memory: BestEffort State: Running Started: Tue, 17 May 2016 10:20:35 +0530 Ready: True Restart Count: 0 Environment Variables: Conditions: Type Status Ready True Volumes: brickpath: Type: HostPath (bare host directory volume) Path: /mnt/brick1 default-token-72d89: Type: Secret (a secret that should populate this volume) SecretName: default-token-72d89 Events: FirstSeen LastSeen Count From SubobjectPath Reason Message ───────── ──────── ───── ──── ───────────── ────── ─────── 1m 1m 1 {scheduler } Scheduled Successfully assigned gluster-1 to atomic-node1 1m 1m 1 {kubelet atomic-node1} implicitly required container POD Pulled Container image “openshift3/ose-pod:v3.1.1.6” already present on machine 1m 1m 1 {kubelet atomic-node1} implicitly required container POD Created Created with docker id f55ce55e6ea3 1m 1m 1 {kubelet atomic-node1} implicitly required container POD Started Started with docker id f55ce55e6ea3 1m 1m 1 {kubelet atomic-node1} spec.containers{glusterfs} Pulling pulling image “gluster/gluster-centos” 8s 8s 1 {kubelet atomic-node1} spec.containers{glusterfs} Pulled Successfully pulled image “gluster/gluster-centos” 8s 8s 1 {kubelet atomic-node1} spec.containers{glusterfs} Created Created with docker id ff8f4af700d7 8s 8s 1 {kubelet atomic-node1} spec.containers{glusterfs} Started Started with docker id ff8f4af700d7

From above logs, you can see it pulled gluster/gluster-centos container image and deployed containers from it.

[root@atomic-node2 gluster_pod]# oc get pods NAME READY STATUS RESTARTS AGE gluster-1 1/1 Running 0 1m

Examine the container and make sure it has a running GlusterFS daemon.

[root@atomic-node2 gluster_pod]# oc exec -ti gluster-1 /bin/bash Examine the processes running in this container and the glusterd service information.

[root@atomic-node1 /]# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.4 0.0 40780 2920 ? Ss 04:50 0:00 /usr/sbin/init root 20 0.3 0.0 36816 4272 ? Ss 04:50 0:00 /usr/lib/syste root 21 0.0 0.0 118476 1332 ? Ss 04:50 0:00 /usr/sbin/lvme root 37 0.0 0.0 101344 1228 ? Ssl 04:50 0:00 /usr/sbin/gssp rpc 44 0.1 0.0 64904 1052 ? Ss 04:50 0:00 /sbin/rpcbind root 209 0.1 0.1 364716 13444 ? Ssl 04:50 0:00 /usr/sbin/glus root 341 1.1 0.0 13368 1964 ? Ss 04:51 0:00 /bin/bash root 354 0.0 0.0 49020 1820 ? R+ 04:51 0:00 ps aux

[root@atomic-node1 /]# service glusterd status Redirecting to /bin/systemctl status glusterd.service ● glusterd.service – GlusterFS, a clustered file-system server Loaded: loaded (/usr/lib/systemd/system/glusterd.service; enabled; vendor preset: disabled) Active: active (running) since Tue 2016-05-17 04:50:41 UTC; 35s ago Process: 208 ExecStart=/usr/sbin/glusterd -p /var/run/glusterd.pid –log-level $LOG_LEVEL $GLUSTERD_OPTIONS (code=exited, status=0/SUCCESS) Main PID: 209 (glusterd) CGroup: /system.slice/docker-ff8f4af700d725dfe0e08939ec011c34ddf9dedc7204e0ced1cc355a56150742.scope/system.slice/glusterd.service └─209 /usr/sbin/glusterd -p /var/run/glusterd.pid –log-level INFO… ‣ 209 /usr/sbin/glusterd -p /var/run/glusterd.pid –log-level INFO… May 17 04:50:36 atomic-node1 systemd[1]: Starting Gluste… May 17 04:50:41 atomic-node1 systemd[1]: Started Gluster… Hint: Some lines were ellipsized, use -l to show in full. Let’s fetch some more details about GlusterFS in this container.

[root@atomic-node1 /]# gluster –version glusterfs 3.7.9 built on Mar 20 2016 03:19:49 Repository revision: git://git.gluster.com/glusterfs.git Copyright (c) 2006-2011 Gluster Inc. GlusterFS comes with ABSOLUTELY NO WARRANTY. You may redistribute copies of GlusterFS under the terms of the GNU General Public License. [root@atomic-node1 /]#

[root@atomic-node1 /]# mount |grep mnt /dev/mapper/atomic-node1-root on /mnt/brick1 type xfs (rw,relatime,seclabel,attr2,inode64,noquota) This container is built on top of CentOS base image as shown below.

[root@atomic-node1 /]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core)

[root@atomic-node1 /]#

In this article, we discussed, how to run GlusterFS as a pod in Kubernetes or Openshift setup.
[Part 2] covers how to use GlusterFS as a service, Persistent Volume for a Persistent Volume Claim.
[Part 3] covers how to use GlusterFS template to deploy GlusterFS pods in an Openshift/kubernetes setup.

[Coming Soon] Dynamic Provisioning of GlusterFS volumes in Kubernetes/Openshift!!

In this context I am talking about the dynamic provisioning capability of ‘glusterfs’ plugin in Kubernetes/Openshift. I have submitted a Pull Request to Kubernetes to add this functionality for GlusterFS. At present, there is no existing network storage provisioners in kubernetes eventhough there are cloud providers. The idea here is to make the glusterfs plugin capable of provisioning volumes on demand from kubernetes/openshift .. Cool, Isnt it ? Indeed this is a nice feature to have. That said, an OSE user request for a space for example : 20G and the glusterfs plugin takes this request and create 20G and bound that to the claim. The plugin can use any REST service, but the example patch is based on ‘heketi’. Here is the workflow: Start your kubernetes controller manager with highlighted options:
In this context I am talking about the dynamic provisioning capability of ‘glusterfs’ plugin in Kubernetes/Openshift. I have submitted a Pull Request to Kubernetes to add this functionality for GlusterFS. At present, there is no existing network storage provisioners in kubernetes eventhough there are cloud providers. The idea here is to make the glusterfs plugin capable of provisioning volumes on demand from kubernetes/openshift .. Cool, Isnt it ? Indeed this is a nice feature to have. That said, an OSE user request for a space for example : 20G and the glusterfs plugin takes this request and create 20G and bound that to the claim. The plugin can use any REST service, but the example patch is based on ‘heketi’. Here is the workflow: Start your kubernetes controller manager with highlighted options:

…kube controller-manager –v=3
–service-account-private-key-file=/tmp/kube-serviceaccount.key
–root-ca-file=/var/run/kubernetes/apiserver.crt –enable-hostpath-provisioner=false

–enable-network-storage-provisioner=true –storage-config=/tmp –net-provider=glusterfs
–pvclaimbinder-sync-period=15s –cloud-provider= –master=127.0.0.1:8080

Create a file called gluster.json in /tmp directory. The important fields in this config file are ‘endpoint’ and ‘resturl’. The endpoint has to be defined and match the setup. The resturl has been filled with the rest service which can take the input and create a gluster volume in the backend. As mentioned earlier I am using heketi for the same.

[hchiramm@dhcp35-111 tmp]$ cat gluster.json
{
“endpoint”: “glusterfs-cluster”,
“resturl”: “http://127.0.0.1:8081”,
“restauthenabled”:false,
“restuser”:””,
“restuserkey”:””
}
[hchiramm@dhcp35-111 tmp]$

We have to define an ENDPOINT and SERVICE. Below are the example configuration files.

ENDPOINT :
“ip” has to be filled with your gluster trusted pool IP.

[hchiramm@dhcp35-111 ]$ cat glusterfs-endpoint.json
{
“kind”: “Endpoints”,
“apiVersion”: “v1”,
“metadata”: {
“name”: “glusterfs-cluster”
},
“subsets”: [
{
“addresses”: [
{
“ip”: “10.36.4.112”
}
],
“ports”: [
{
“port”: 1
}
]
},
{
“addresses”: [
{
“ip”: “10.36.4.112”
}
],
“ports”: [
{
“port”: 1
}
]
}
]
}

SERVICE:
Please note that the Service Name is matching with ENDPOINT name

[hchiramm@dhcp35-111 ]$ cat gluster-service.json
{
“kind”: “Service”,
“apiVersion”: “v1”,
“metadata”: {
“name”: “glusterfs-cluster”
},
“spec”: {
“ports”: [
{“port”: 1}
]
}
}
[hchiramm@dhcp35-111 ]$

Finally we have a Persistent Volume Claim file as shown below:
NOTE: The size of the volume is mentioned as ’20G’:

[hchiramm@dhcp35-111 ]$ cat gluster-pvc.json
{
“kind”: “PersistentVolumeClaim”,
“apiVersion”: “v1”,
“metadata”: {
“name”: “glusterc”,
“annotations”: {
“volume.alpha.kubernetes.io/storage-class”: “glusterfs”
}
},
“spec”: {
“accessModes”: [
“ReadOnlyMany”
],
“resources”: {
“requests”: {
“storage”: “20Gi”
}
}
}
}
[hchiramm@dhcp35-111 ]$

Let’s start defining the endpoint, service and PVC.

[hchiramm@dhcp35-111 ]$ ./kubectl create -f glusterfs-endpoint.json
endpoints “glusterfs-cluster” created
[hchiramm@dhcp35-111 ]$ ./kubectl create -f gluster-service.json
service “glusterfs-cluster” created
[hchiramm@dhcp35-111 ]$ ./kubectl get ep,service
NAME ENDPOINTS AGE
ep/glusterfs-cluster 10.36.6.105:1 14s
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc/glusterfs-cluster 10.0.0.10 1/TCP 9s
svc/kubernetes 10.0.0.1 443/TCP 13m
[hchiramm@dhcp35-111 ]$ ./kubectl get pv,pvc
[hchiramm@dhcp35-111 ]$

Now, let’s request a claim!

[hchiramm@dhcp35-111 ]$ ./kubectl create -f glusterfs-pvc.json
persistentvolumeclaim “glusterc” created
[hchiramm@dhcp35-111 ]$ ./kubectl get pv,pvc
NAME CAPACITY ACCESSMODES STATUS CLAIM REASON AGE
pv/pvc-39ebcdc5-442b-11e6-8dfa-54ee7551fd0c 20Gi ROX Bound default/glusterc 2s
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
pvc/glusterc Bound pvc-39ebcdc5-442b-11e6-8dfa-54ee7551fd0c 0 3s
[hchiramm@dhcp35-111 ]$

Awesome! Based on the request it created a PV and BOUND to the PVClaim!!

[hchiramm@dhcp35-111 ]$ ./kubectl describe pv pvc-39ebcdc5-442b-11e6-8dfa-54ee7551fd0c
Name: pvc-39ebcdc5-442b-11e6-8dfa-54ee7551fd0c
Labels:
Status: Bound
Claim: default/glusterc
Reclaim Policy: Delete
Access Modes: ROX
Capacity: 20Gi
Message:
Source:
Type: Glusterfs (a Glusterfs mount on the host that shares a pod’s lifetime)
EndpointsName: glusterfs-cluster
Path: vol_038b56756f4e3ab4b07a87494097941c
ReadOnly: false
No events.
[hchiramm@dhcp35-111 ]$

Verify the volume exist in backend:

[root@ ~]# heketi-cli volume list |grep 038b56756f4e3ab4b07a87494097941c
038b56756f4e3ab4b07a87494097941c
[root@ ~]#

Let’s delete the PV claim —

[hchiramm@dhcp35-111 ]$ ./kubectl delete pvc glusterc
persistentvolumeclaim “glusterc” deleted
[hchiramm@dhcp35-111 ]$ ./kubectl get pv,pvc
[hchiramm@dhcp35-111 ]$

It got deleted!

Verify it from backend:

[root@ ~]# heketi-cli volume list |grep 038b56756f4e3ab4b07a87494097941c
[root@ ~]#

We can use the Volume for app pods by referring the claim name.
Hope this is a nice feature to have !

Please let me know if you have any comments/suggestions.

Also, the patch – https://github.com/kubernetes/kubernetes/pull/30888 is undergoing review in upstream as mentioned earlier and hopefully it will make it soon to the kubernetes release. I will provide an update here as soon as its available in upstream.