Bring persistent storage for your containers with KRBD on Kubernetes
Use RBD device to provide persistent storage to your containers. This work was initiated by a colleague of mine Huamin Chen. I would like to take the opportunity to thank him for the troubleshooting session we had. Having the ability to use persistent volume for your containers is critical, containers can be ephemeral since they are immutable. If they did on a machine they can be bootstrapped on another host without any problem. The only problem here is we need to ensure that somehow the data that come with this container will follow it no matter where it goes. This is exactly what we want to achieve with this implementation.
Pre requisite
This article assumes that your Kubernetes environment is up and running. First on your host install Ceph:
$ sudo yum install -y ceph-common |
W Important: the version of ceph-common must be >= 0.87.
Set up your Ceph environment:
$ sudo docker run -d \ |
Several actions are not assumed by Kubernetes such as:
- RBD volume creation
- Filesystem on this volume
So let’s do this first:
$ sudo rbd create foo -s 1024 |
Configure Kubernetes
First, we clone Kubernetes repository to get some handy file examples:
$ git clone https://github.com/GoogleCloudPlatform/kubernetes.git |
Get your ceph.admin
key and encode it in base64:
$ sudo ceph auth get-key client.admin |
R Note: it’s not mandatory to use the client.admin
key, you can use whatever key you want as soon as it has the approprieate permissions of the given pool.
Edit your ceph-secret.yml
with the base64 key:
apiVersion: v1
kind: Secret
metadata:
name: ceph-secret
data:
key: QVFCQU1vMVZxRTFPTWhBQVZwRVJQY3lRVTVwelU2SU9KMjJ4MXc9PQo=
Add your secret to Kubernetes:
$ kubectl create -f secret/ceph-secret.yaml |
Now, we edit our rbd-with-secret.json
pod file.
This file describes the content of your pod:
{
"apiVersion": "v1beta3",
"id": "rbdpd2",
"kind": "Pod",
"metadata": {
"name": "rbd2"
},
"spec": {
"containers": [
{
"name": "rbd-rw",
"image": "kubernetes/pause",
"volumeMounts": [
{
"mountPath": "/mnt/rbd",
"name": "rbdpd"
}
]
}
],
"volumes": [
{
"name": "rbdpd",
"rbd": {
"monitors": [
"192.168.0.1:6789"
],
"pool": "rbd",
"image": "foo",
"user": "admin",
"secretRef": {
"name": "ceph-secret"
},
"fsType": "ext4",
"readOnly": true
}
}
]
}
}
The relevant sections are:
mountPath
: where to mount the RBD image, this mountpoint must existmonitors
: address of the monitors (you can have asn many as you want)pool
: the pool used to store your imageimage
: name of the imagesecretRef
: name of the secretfsType
: filesystem type of the image
Now it’s time to fire it up your pod:
$ kubectl create -f rbd-with-secret.json |
Check the running containers:
$ docker ps |
Everything seems to be working well, let’s check the device status on the Kubernetes host:
$ sudo rbd showmapped |
The image got mapped, now we check where this image got mounted:
$ mount |grep kube |
Further work and known issue
The current implementation is here and it’s good to see that we merged such thing. It will be easier in the future to follow up on that original work. The “v2” will ease operators life, since they won’t need to pre-populate RBD images and filesystems.
There is a bug currently where the pod creation failed if the mount point doest not exist. This is fixed in Kubernetes 0.20.
I hope you will enjoy this as much as I do :)
Comments