Installation¶
Traefik-proxy installation¶
Install JupyterHub:
$ python3 -m pip install jupyterhub
Install jupyterhub-traefik-proxy, which is available now as pre-release:
python3 -m pip install jupyterhub-traefik-proxy
In order to be able to launch JupyterHub with traefik-proxy or run the tests, traefik, etcd and consul must first be installed and added to your
PATH
.There are two ways you can install traefik, etcd and consul:
Through traefik-proxy’s install utility.
$ python3 -m jupyterhub_traefik_proxy.install --traefik --etcd --consul --output=/usr/local/bin
This will install the default versions of traefik, etcd and consul, namely
traefik-1.7.5
,etcd-3.3.10
andconsul_1.5.0
to/usr/local/bin
specified through the--output
option.It is also possible to install the binaries individually. For example to install traefik only:
$ python3 -m jupyterhub_traefik_proxy.install --traefik --output=/usr/local/bin
If no directory is passed to the installer, a dependencies directory will be created in the
traefik-proxy
directory. In this case, you must add this directory toPATH
, e.g.$ export PATH=$PATH:{$PWD}/dependencies
If you want to install other versions of traefik, etcd and consul in a directory of your choice, just specify it to the installer through the following arguments:
--traefik-version
--etcd-version
--consul-version
--output
Example:
$ python3 -m jupyterhub_traefik_proxy.install --traefik --etcd --consul --output=dep \ --traefik-version=1.6.6 --etcd-version=3.2.24 --consul-version=1.5.0
If the desired install directory doesn’t exist, it will be created by the installer.
To get a list of all the available options:
$ python3 -m jupyterhub_traefik_proxy.install --help
From traefik, etcd and consul release pages:
Enabling traefik-proxy in JupyterHub¶
TraefikTomlProxy, TraefikEtcdProxy and TraefikConsulProxy are custom proxy implementations that subclass Proxy and can register in JupyterHub config using c.JupyterHub.proxy_class
entrypoint.
On startup, JupyterHub will look by default for a configuration file, jupyterhub_config.py, in the current working directory. If the configuration file is not in the current working directory, you can load a specific config file and start JupyterHub using:
$ jupyterhub -f /path/to/jupyterhub_config.py
There is an example configuration file here that configures JupyterHub to run with TraefikEtcdProxy as the proxy and uses dummyauthenticator and simplespawner to enable testing without administrative privileges.
In jupyterhub_config.py:
c.JupyterHub.proxy_class = "traefik_toml"
# will configure JupyterHub to run with TraefikTomlProxy
c.JupyterHub.proxy_class = "traefik_etcd"
# will configure JupyterHub to run with TraefikEtcdProxy
c.JupyterHub.proxy_class = "traefik_consul"
# will configure JupyterHub to run with TraefikConsulProxy
Implementation details¶
Traefik Dashboard
Traefik provides a Web UI dashboard where you can see the frontends and backends registered, the routing rules, some metrics, but also other configuration elements. Find out more about traefik api’s, here.
Because of security concerns, in traefik-proxy implementation, traefik api endpoint isn’t exposed on the public http endpoint. Instead, it runs on a dedicated authenticated endpoint that’s on localhost by default.
The port on which traefik-proxy’s api will run, as well as the username and password used for authenticating, can be passed to the proxy through
jupyterhub_config.py
, e.g.:c.TraefikTomlProxy.traefik_api_url = "http://127.0.0.1:8099" c.TraefikTomlProxy.traefik_api_password = "admin" c.TraefikTomlProxy.traefik_api_username = "admin"
Check out TraefikProxy’s API Reference for more configuration options.
TKvProxy class
TKvProxy is a JupyterHub Proxy implementation that uses traefik and a key-value store. TraefikEtcdProxy and TraefikConsulProxy are proxy implementations that sublass
TKvProxy
. Other custom proxies that wish to implementat a JupyterHub Trafik KV store Proxy can sublassTKvProxy
. TKvProxy implements JupyterHub’s Proxy public API and there is no need to override these public methods. The methods that must be implemented by the proxies that sublassTKvProxy
are:_define_kv_specific_static_config()
- Define the traefik static configuration that configures traefik’s communication with the key-value store.
- Will be called during startup if should_start is True.
- Subclasses must define this method if the proxy is to be started by the Hub.
- In order to be picked up by the proxy, the static configuration
must be stored into
proxy.static_config
dict under thekv_name
key.
_kv_atomic_add_route_parts(jupyterhub_routespec, target, data, route_keys, rule)
Add the key-value pairs associated with a route within a key-value store transaction.
Will be called during add_route.
When retrieving or deleting a route, the parts of a route are expected to have the following structure:
[ key: jupyterhub_routespec , value: target ] [ key: target , value: data ] [ key: route_keys.backend_url_path , value: target ] [ key: route_keys.frontend_rule_path , value: rule ] [ key: route_keys.frontend_backend_path, value: route_keys.backend_alias] [ key: route_keys.backend_weight_path , value: w(int) ] # where w is the weight of the backend to be used during load balancing)
Returns:
- result (tuple):
- The transaction status (int, 0: failure, positive: success)
- The transaction response(str)
- result (tuple):
_kv_atomic_delete_route_parts(jupyterhub_routespec, route_keys)
- Delete the key-value pairs associated with a route, within a key-value store transaction (if the route exists).
- Will be called during delete_route.
- The keys associated with a route are:
- jupyterhub_routespec
- target
- route_keys.backend_url_path
- route_keys.frontend_rule_path
- route_keys.frontend_backend_path
- route_keys.backend_weight_path
- Returns:
- result (tuple):
- The transaction status (int, 0: failure, positive: success)
- The transaction response (str)
- result (tuple):
_kv_get_target(jupyterhub_routespec)
- Retrive the target from the key-value store.
- The target is the value associated with
jupyterhub_routespec
key. - Returns:
- The full URL associated with this route (str)
_kv_get_data(target)
- Retrive the data associated with the
target
from the key-value store. - Returns:
- A JSONable dict that holds extra info about the route (dict)
- Retrive the data associated with the
_kv_get_route_parts(kv_entry)
- Retrive all the parts that make up a route (i.e. routespec, target, data) from the key-value store given a
kv_entry
. - A
kv_entry
is a key-value store entry where the key starts withproxy.jupyterhub_prefix
. It is expected that only the routespecs will be prefixed withproxy.jupyterhub_prefix
when added to the kv store. - Returns:
- routespec: The normalized route specification passed in to add_route ([host]/path/)
- target: The target host for this route (proto://host)
- data: The arbitrary data dict that was passed in by JupyterHub when adding this route.
- Retrive all the parts that make up a route (i.e. routespec, target, data) from the key-value store given a
_kv_get_jupyterhub_prefixed_entries()
- Retrive from the kv store all the key-value pairs where the key starts with
proxy.jupyterhub_prefix
. - It is expected that only the routespecs will be prefixed with
proxy.jupyterhub_prefix
when added to the kv store. - Returns:
- routes: A list of key-value store entries where the keys start with
proxy.jupyterhub_prefix
.
- routes: A list of key-value store entries where the keys start with
- Retrive from the kv store all the key-value pairs where the key starts with
Testing jupyterhub-traefik-proxy¶
There are some tests that use etcdctl command line client for etcd. Make sure to set environment variable ETCDCTL_API=3 before running the tests, so that the v3 API to be used, e.g.:
$ export ETCDCTL_API=3
You can then run the all the test suite from the traefik-proxy directory with:
$ pytest -v ./tests
Or you can run a specific test with:
$ pytest -v ./tests/<test-file-name>