Replace chp with traefik-proxy

This commit is contained in:
GeorgianaElena
2019-01-22 16:24:38 +02:00
parent 5d533735aa
commit eee29a0957
14 changed files with 119 additions and 97 deletions

View File

@@ -18,6 +18,7 @@ from copy import deepcopy
import os
import re
import sys
import asyncio
from .yaml import yaml
@@ -85,7 +86,7 @@ def add_item_to_config(config, property_path, value):
def remove_item_from_config(config, property_path, value):
"""
Add an item to a list in config.
Remove an item from a list in config.
"""
path_components = property_path.split('.')
@@ -183,11 +184,14 @@ def reload_component(component):
from tljh import systemd, traefik
if component == 'hub':
systemd.restart_service('jupyterhub')
# FIXME: Verify hub is back up?
# Ensure hub is back up
while not systemd.check_service_active('jupyterhub'):
asyncio.sleep(1)
while not systemd.check_hub_ready():
asyncio.sleep(1)
print('Hub reload with new configuration complete')
elif component == 'proxy':
traefik.ensure_traefik_config(STATE_DIR)
systemd.restart_service('configurable-http-proxy')
systemd.restart_service('traefik')
print('Proxy reload with new configuration complete')

View File

@@ -120,9 +120,6 @@ def ensure_jupyterhub_service(prefix):
with open(os.path.join(HERE, 'systemd-units', 'jupyterhub.service')) as f:
hub_unit_template = f.read()
with open(os.path.join(HERE, 'systemd-units', 'configurable-http-proxy.service')) as f:
proxy_unit_template = f.read()
with open(os.path.join(HERE, 'systemd-units', 'traefik.service')) as f:
traefik_unit_template = f.read()
@@ -133,28 +130,16 @@ def ensure_jupyterhub_service(prefix):
jupyterhub_config_path=os.path.join(HERE, 'jupyterhub_config.py'),
install_prefix=INSTALL_PREFIX,
)
systemd.install_unit('configurable-http-proxy.service', proxy_unit_template.format(**unit_params))
systemd.install_unit('jupyterhub.service', hub_unit_template.format(**unit_params))
systemd.install_unit('traefik.service', traefik_unit_template.format(**unit_params))
systemd.reload_daemon()
# Set up proxy / hub secret oken if it is not already setup
proxy_secret_path = os.path.join(STATE_DIR, 'configurable-http-proxy.secret')
if not os.path.exists(proxy_secret_path):
with open(proxy_secret_path, 'w') as f:
f.write('CONFIGPROXY_AUTH_TOKEN=' + secrets.token_hex(32))
# If we are changing CONFIGPROXY_AUTH_TOKEN, restart configurable-http-proxy!
systemd.restart_service('configurable-http-proxy')
# Start CHP if it has already not been started
systemd.start_service('configurable-http-proxy')
# If JupyterHub is running, we want to restart it.
systemd.restart_service('jupyterhub')
systemd.restart_service('traefik')
# Mark JupyterHub & CHP to start at boot time
systemd.enable_service('jupyterhub')
systemd.enable_service('configurable-http-proxy')
systemd.enable_service('traefik')
@@ -275,7 +260,7 @@ def ensure_admins(admins):
yaml.dump(config, f)
def ensure_jupyterhub_running(times=4):
def ensure_jupyterhub_running(times=20):
"""
Ensure that JupyterHub is up and running
@@ -432,7 +417,6 @@ def main():
logger.info("Setting up JupyterHub...")
ensure_node()
ensure_jupyterhub_package(HUB_ENV_PREFIX)
ensure_chp_package(HUB_ENV_PREFIX)
ensure_jupyterlab_extensions()
ensure_jupyterhub_service(HUB_ENV_PREFIX)
ensure_jupyterhub_running()

View File

@@ -10,7 +10,7 @@ from tljh import configurer, user
from tljh.config import INSTALL_PREFIX, USER_ENV_PREFIX, CONFIG_DIR
from tljh.normalize import generate_system_username
from tljh.yaml import yaml
from jupyterhub_traefik_proxy import TraefikTomlProxy
class UserCreatingSpawner(SystemdSpawner):
"""
@@ -43,8 +43,11 @@ c.JupyterHub.cleanup_servers = False
# Use a high port so users can try this on machines with a JupyterHub already present
c.JupyterHub.hub_port = 15001
c.ConfigurableHTTPProxy.should_start = False
c.ConfigurableHTTPProxy.api_url = 'http://127.0.0.1:15002'
c.TraefikTomlProxy.should_start = False
c.TraefikTomlProxy.traefik_api_password = "admin"
c.TraefikTomlProxy.traefik_api_username = "api_admin"
c.TraefikTomlProxy.toml_dynamic_config_file = "/opt/tljh/state/rules.toml"
c.JupyterHub.proxy_class = TraefikTomlProxy
c.SystemdSpawner.extra_paths = [os.path.join(USER_ENV_PREFIX, 'bin')]
c.SystemdSpawner.default_shell = '/bin/bash'

View File

@@ -1,27 +0,0 @@
# Template file for Configurable HTTP Proxy systemd service
# Uses simple string.format() for 'templating'
[Unit]
# Wait for network stack to be fully up before starting CHP
After=network.target
[Service]
User=nobody
Restart=always
# chp process should have no write access anywhere on disk
ProtectHome=tmpfs
ProtectSystem=strict
PrivateTmp=yes
PrivateDevices=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
EnvironmentFile={install_prefix}/state/configurable-http-proxy.secret
ExecStart={install_prefix}/hub/node_modules/.bin/configurable-http-proxy \
--ip 127.0.0.1 \
--port 15003 \
--api-ip 127.0.0.1 \
--api-port 15002 \
--error-target http://127.0.0.1:15001/hub/error
[Install]
# Start service when system boots
WantedBy=multi-user.target

View File

@@ -1,9 +1,9 @@
# Template file for JupyterHub systemd service
# Uses simple string.format() for 'templating'
[Unit]
# CHP must have successfully started *before* we launch JupyterHub
Requires=configurable-http-proxy.service
After=configurable-http-proxy.service
# Traefik must have successfully started *before* we launch JupyterHub
Requires=traefik.service
After=traefik.service
[Service]
User=root
@@ -17,7 +17,6 @@ PrivateDevices=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
# Source CONFIGPROXY_AUTH_TOKEN from here!
EnvironmentFile={install_prefix}/state/configurable-http-proxy.secret
Environment=TLJH_INSTALL_PREFIX={install_prefix}
ExecStart={python_interpreter_path} -m jupyterhub.app -f {jupyterhub_config_path}

View File

@@ -7,13 +7,13 @@ After=network.target
[Service]
User=root
Restart=always
# process only needs to write state/acme.json file, no other files
ProtectHome=tmpfs
ProtectSystem=strict
PrivateTmp=yes
PrivateDevices=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ReadWritePaths={install_prefix}/state/rules.toml
ReadWritePaths={install_prefix}/state/acme.json
WorkingDirectory={install_prefix}/state
ExecStart={install_prefix}/hub/bin/traefik \

View File

@@ -70,3 +70,48 @@ def enable_service(name):
'enable',
name
], check=True)
def check_service_active(name):
"""
Check if a service is currently active (running)
"""
try:
subprocess.run([
'systemctl',
'is-active',
name
], check=True)
return True
except subprocess.CalledProcessError:
return False
def check_hub_ready():
"""
Check if the hub is ready
"""
try:
last_restart = subprocess.check_output([
'systemctl',
'show',
'jupyterhub',
'-p',
'ActiveEnterTimestamp'
]).decode().strip()
last_restart = " ".join(last_restart.split(" ")[-3:-1])
out = subprocess.check_output([
'journalctl',
'-u',
'jupyterhub',
'--since',
last_restart
])
if "JupyterHub is now running at" in out.decode():
return True
except subprocess.CalledProcessError:
return False

View File

@@ -9,11 +9,11 @@ from tljh.configurer import load_config
# FIXME: support more than one platform here
plat = "linux-amd64"
traefik_version = "1.6.5"
traefik_version = "1.7.5"
# record sha256 hashes for supported platforms here
checksums = {
"linux-amd64": "9e77c7664e316953e3f5463c323dffeeecbb35d0b1db7fb49f52e1d9464ca193"
"linux-amd64": "4417a9d83753e1ad6bdd64bbbeaeb4b279bcc71542e779b7bcb3b027c6e3356e"
}
@@ -78,6 +78,9 @@ def ensure_traefik_config(state_dir):
os.fchmod(f.fileno(), 0o744)
f.write(new_toml)
with open(os.path.join(state_dir, "rules.toml"), "w") as f:
os.fchmod(f.fileno(), 0o744)
# ensure acme.json exists and is private
with open(os.path.join(state_dir, "acme.json"), "a") as f:
os.fchmod(f.fileno(), 0o600)

View File

@@ -33,7 +33,6 @@ idleTimeout = "10m0s"
{% if https['enabled'] %}
[entryPoints.https]
address = ":{{https['port']}}"
backend = "jupyterhub"
[entryPoints.https.tls]
{% if https['tls']['cert'] %}
[[entryPoints.https.tls.certificates]]
@@ -41,6 +40,17 @@ idleTimeout = "10m0s"
keyFile = "{{https['tls']['key']}}"
{% endif %}
{% endif %}
[entryPoints.auth_api]
address = ":8099"
[entryPoints.auth_api.auth.basic]
users = ["api_admin:$apr1$eS/j3kum$q/X2khsIEG/bBGsteP.x./"]
[wss]
protocol = "http"
[api]
dashboard = true
entrypoint = "auth_api"
{% if https['enabled'] and https['letsencrypt']['email'] %}
[acme]
@@ -57,13 +67,5 @@ entryPoint = "https"
{% endif %}
[file]
[frontends]
[frontends.jupyterhub]
backend = "jupyterhub"
passHostHeader = true
[backends]
[backends.jupyterhub]
[backends.jupyterhub.servers.chp]
url = "http://127.0.0.1:15003"
filename = "/opt/tljh/state/rules.toml"
watch = true