As a developer I wanted to experiment with Kubernetes environments which approximate production deployments. In order to do that I wanted a distributed storage solution and chose OpenEBS. Mainly because it was easy to get started and quick to get up and running. In this blog post I’ll describe how I did that.
Why OpenEBS?
I previously wrote a blog about using StorageOS as persistent storage solution for Charmed Kubernetes here. StorageOS is dependent on etcd. I was having difficulties getting etcd up again after a reboot. Since I wanted a storage solution without too much effort to get it running and not focus too much on external dependencies I decided to give OpenEBS a try. OpenEBS did not have the etcd dependency. I also considered using CephFS as described in the Charmed Kubernetes tutorials, but a deployment using charms would by default create a large number of additional hosts (for which my laptop didn’t have the resources) and storage would be external to the Kubernetes cluster making this setup more complex to deploy in other environments. The OpenEBS solution runs fully on Kubernetes.
In this blog I’ll describe a developer installation on Charmed Kubernetes (the environment described here). I used openebs-jiva-default as storage class. This is unsuitable for production scenario’s. OpenEBS provides cStor for that. Most of the OpenEBS development effort goes to cStor. cStor however requires a mounted block device. I have not tried this yet.
Installing OpenEBS
First I created my environment as described here. Note that this does not work on a Charmed Kubernetes install on LXC/LXD as-is! This was one of the reasons I decided to switch to MaaS+KVM.
For the creation of the environment I used the following yaml file as overlay. Note that I use 4 worker nodes. This setup requires at least 32Gb of RAM and 12 cores to run.
description: A highly-available, production-grade Kubernetes cluster.
series: bionic
applications:
etcd:
num_units: 2
kubernetes-master:
constraints: cores=1 mem=4G root-disk=16G
num_units: 2
kubernetes-worker:
constraints: cores=1 mem=3G root-disk=20G
num_units: 4
Next I enabled iscsi as per OpenEBS requirement in the worker nodes.
juju run "sudo systemctl enable iscsid && sudo systemctl start iscsid" --application kubernetes-worker
Allow creation of privileged containers. The containers need access to host devices to do their thing.
juju config kubernetes-master allow-privileged=true
Restart the environment
juju run "reboot" --application kubernetes-worker
juju run "reboot" --application kubernetes-master
Create a namespace
kubectl create namespace openebs
Add the OpenEBS Helm chart
helm repo add openebs https://openebs.github.io/charts
helm repo update
Add some configuration for OpenEBS. Parameters are described here.
cat << EOF > openebs-config.yaml
jiva:
replicas: 2
EOF
Install OpenEBS
helm install openebs stable/openebs --version 1.10.0 -f openebs-config.yaml --namespace openebs
Make sure the installation is completed before continuing. No pods in the openebs namespace should have state Pending. After the installation is completed, you can set the storageclass openebs-jiva-default as the default storageclass to use:
kubectl patch storageclass openebs-jiva-default -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
Also it helps to indicate in the storage class only one replica is needed. This way you can make due with only 2 worker nodes instead of 4:
kubectl apply -n openebs -f - <<END
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: openebs-jiva-default
annotations:
cas.openebs.io/config: |
- name: ReplicaCount
value: "1"
openebs.io/cas-type: jiva
storageclass.kubernetes.io/is-default-class: 'true'
provisioner: openebs.io/provisioner-iscsi
reclaimPolicy: Delete
volumeBindingMode: Immediate
END
Trying it out
Add the Jenkins repo
helm repo add stable https://kubernetes-charts.storage.googleapis.com/
helm repo update
Create a namespace
kubectl create namespace jenkins
Create a persistent volume claim
kubectl create -n jenkins -f - <<END
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jenkins-pv-claim
spec:
storageClassName: openebs-jiva-default
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
END
Create some Jenkins configuration to use the claim
cat << EOF > jenkins-config.yaml
persistence:
enabled: true
size: 5Gi
accessMode: ReadWriteOnce
existingClaim: jenkins-pv-claim
storageClass: "openebs-jiva-default"
EOF
Install Jenkins
helm install my-jenkins-release -f jenkins-config.yaml stable/jenkins --namespace jenkins
Get your ‘admin’ user password by running:
printf $(kubectl get secret --namespace jenkins my-jenkins-release -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo
Get the Jenkins URL to visit by running these commands in the same shell and login!
export POD_NAME=$(kubectl get pods --namespace jenkins -l "app.kubernetes.io/component=jenkins-master" -l "app.kubernetes.io/instance=my-jenkins-release" -o jsonpath="{.items[0].metadata.name}")
kubectl --namespace jenkins port-forward $POD_NAME 8080:8080