A common problem with containerized applications is that their local storage is ephemeral, meaning that when the container goes away, so does its local storage. If you’re a fan of the 12 Factor methodology, then this won’t be a big deal because you’re storing your data in a much more rugged backing store (RDS, S3, etc). But, what if you’re dealing with a legacy application that expects to read/write from an NFS mounted filesystem? What if you’re adventurous and you really want to run your MySQL databases inside of a container? This makes sense for development environments, where development speed is much more important than being production-ready. However, even in the case of development environments, you’d love for your data to stick around. Let me show you an easy way to use Amazon’s EFS with Rancher to give your containers persistent storage.
From here on out, I’m going to make the assumption that you have a Rancher server running and that you have at least one environment configured with at least one running host. If need help getting started, please refer to this previous blog post. In order to make life easier, Rancher has something called the Catalog. It’s a pretty large collection of pre-built services that you can spin up on your Rancher server with very little effort. It’s available on the menu bar in the Catalog item. It’s broken down into certified services, and community-supplied services.
The service that we need for this is the Rancher EFS service.
Click View Details. It only needs an AWS Access Key and an AWS Secret Key. If you create an IAM user specifically for this, make sure it has enough permissions to create EFS volumes and read/write to them. Do NOT use your root key for this!
Click the Launch button. In a few seconds the efs-driver container will be running on all hosts in the environment. In order for all of your containers in your environment to view the same filesystems, all associated EFS volumes will be mapped to each host.
Rancher manages EFS volumes with its storage manager under the Infrastructure menu item. Selecting the Storage item reveals a list of hosts and any associated volumes.
As of now, we have no storage volumes. Let’s create one to use as a backing store for our MySQL dev instance.
Click the Add Volume button. Set the name as mysql and click Create.
You now have a storage volume called mysql, but it’s currently inactive. There are no containers currently using it. This will be associated with an EFS volume in AWS, but it has not been created yet. The first time you spin up a container that uses it, it will also create the EFS volume.
Go back to the Stacks view by clicking the Stacks menu item and selecting User.
Click the Add Stack button and name it mysql. Click Create.
Click the Add Service button in the upper right of the stack view. Give your service the name mysql and set its image as mysql:latest
In the lower portion of the screen, you’ll see a set of tabs. The Command tab is already selected. Click the Add Environment Variable button.
Create an environment variable called MYSQL_ROOT_PASSWORD and set it to password.
Click the Volumes tab. Click Add Volume.
The MySQL docker image stores its data in /var/lib/mysql, so we will have to map our storage volume to that location. We specify this mapping by setting the volume field as mysql:/var/lib/mysql. This tells Rancher to use our storage volume named mysql and mount /var/lib/mysql to it. Click Create.
It will take a few minutes the first time we use the storage volume since Rancher has to go off and create the EFS volume for it. Once it’s up, click the Infrastructure menu item and select Storage. You should now see that the mysql volume is now active and the mounts column contains your running MySQL container.
In order to prove that our data really is persisted, let’s test it by creating a database and restarting the service. Without persistent disk, our data would vanish. Navigate back to your mysql service by using the Stacks menu item. Click on your mysql service within that stack to show the running containers. Click the ellipsis to the right of your running mysql container and select Execute Shell
You’re now in a shell session on your MySQL container. From here, you can connect to the running MySQL server by typing mysql -u root -ppassword Create a database, a table and a record
create database stackwire; use stackwire; create table test(col1 int); insert into test values(42);
Let’s make sure this valuable data won’t be lost when the container stops. Go ahead and restart the MySQL container using the Restart option in the ellipsis menu. Connect back into the container using Execute Shell. Start up the MySQL CLI with mysql -u root -ppassword stackwire. mysql> select * from test;
+------+ | col1 | +------+ | 42 | +------+ 1 row in set (0.00 sec) mysql>
Just like magic!