Skip to content
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

Create EFS storage guide for AWS #715

Merged
merged 1 commit into from
Jun 11, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions doc/source/amazon/efs_storage.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
.. _amazon-aws:

Setting up EFS storage on AWS
-----------------------------

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add:

**Note: This section is experimental. Do not use in production unless you fully understand the drawbacks and limitations.**

ElasticFileSystem is distributed file system which speaks the NFS protocol. It is rumored to be a GlusterFS fork behind the scenes at AWS.

Drawbacks:

* Setting permissions on persistent volumes is not nailed down in the kubernetes spec yet. This adds some complications we will discuss later.

* A crafty user may be able to contact the EFS server directly and read other user's files depending on how the system is setup.

Procedure:

1. Setting up an EFS volume

Go through the EFS setup wizard in AWS (in the future this part may be scripted). The new EFS volume must be in
the same VPC as your cluster. This can be changed in the AWS settings after it has been created.

Next, create a new security group for NFS traffic (target other instances in that group). Add a rule for incoming NFS traffic to the node security group and to the master security group. Change the EFS volume to use that security group.


To verify that your EFS volume is working correctly, ssh into one of the master nodes and su to root. Next,
follow the steps on the EFS console page for mounting your NFS volume. The DNS entry may take a few minutes to show up.

Once the mount succeeds, unmount it and disconnect from the admin node.

2. Configuring Kubernetes to understand your EFS volume

Create test_efs.yaml::

apiVersion: v1
kind: PersistentVolume
metadata:
name: efs-persist
spec:
capacity:
storage: 123Gi
accessModes:
- ReadWriteMany
nfs:
server: fs-${EFS_ID}.efs.us-east-1.amazonaws.com
path: "/"

Create test_efs_claim.yaml::

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: efs-persist
spec:
storageClassName: ""
accessModes:
- ReadWriteMany
resources:
requests:
storage: 11Gi

The sizes in these files are misleading. There is no quota enforced with EFS. In the
future we want to set the efs PersistentVolume size to something ridiculously large
like 8EiB and the PersistentVolumeClaim to 10GB. As far as we know at the moment, these sizes don't matter.

A PersistentVolume defines a service which can perform a mount inside of a container. The
PersistentVolumeClaim is a way of reserving a portion of the PersistentVolume and potentially
locking access to it.

The storageClassName setting looks innocuous, but it is incredibly critical. The only non storage
class PV in the cluster is the one we defined above. In the future we should tag different PV's
and use tag filters in the PVC instead of relying on a default of "".

We are going to configure jupyterhub to use the same "static" claim among all of the containers. This
means that all of our users will be using the same EFS share which should be able to scale as high as we need.

This part is a little different than the standard guide. We need to create these PV's and PVC's in the
namespace that our app will live in. Choose a namespace (this will be the same as the namespace you will
use in the helm install step later on)

Run these commands to setup your namespace and storage::

kubectl create namespace <your namespace>
kubectl --namespace=<your namespace> apply -f test_efs.yaml
kubectl --namespace=<your namespace> apply -f test_efs_claim.yaml


I don't know if the PV needs to be in the namespace, but the arg does not seem to hurt anything. The PVC must be in the namespace or stuff will break in weird ways.

3. Configuring your application to use EFS as it's backing storage
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its


We now add the following to config.yaml::
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's put config.yaml in backticks.

`config.yaml`


singleuser:
image:
name: jupyter/base-notebook
tag: latest
storage:
type: "static"
static:
pvcName: "efs-persist"
subPath: 'home/{username}'
extraEnv:
CHOWN_HOME: 'yes'
uid: 0
fsGid: 0
cmd: "start-singleuser.sh"


The image setting overrides the default pinned jh base image since it has not yet been updated
to include the CHOWN_HOME setting. This will be fixed in Z2JH 0.7.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Zero to JupyterHub v0.7

Let's expand jh to JupyterHub in several places


type static tells jh not to use a storage class and instead use a PVC defined below.

pvcName matches the claim name we specified before

subPath tells where on the supplied storage the mount point should be. In this case it will
be "$EFS_ROOT/home/{username}"

It turns out there is a bug in jupyterhub where the default subPath does not work, and setting the
subPath to "{username}" breaks in the same way.

The extraEnv section set's environmental variables before trying to start jupyterhub inside of the user's
container. CHOWN_HOME is needed to force the ownership change of the home directory.

Kubernetes is still conflicted if a uid and a gid should be passed in to change how the directory is mounted
inside of the container. What we do for now is auto-chown the directory before jupyterhub has been started.

The UID/fsGID is necessary to force the container to run the start-singleuser.sh as root. Once
start-singleuser.sh has properly changed the ownership of the directory, it su's to the jupyterhub user.