jupyterhub on k8s 用户自定义资源大小:
1. 首先需要将前端的数据传到后端:
/usr/local/share/jupyterhub/templates/spawn.html
{% extends "page.html" %} {% if announcement_spawn %} {% set announcement = announcement_spawn %} {% endif %} {% block main %} <div class="container"> {% block heading %} <div class="row text-center"> <h1>Server Options</h1> </div> {% endblock %} <div class="row col-sm-offset-2 col-sm-8"> {% if for_user and user.name != for_user.name -%} <p>Spawning server for {{ for_user.name }}</p> {% endif -%} {% if error_message -%} <p class="spawn-error-msg text-danger"> Error: {{error_message}} </p> {% endif %} <form enctype="multipart/form-data" id="spawn_form" action="{{url}}" method="post" role="form" onsubmit="return dis()"> {{spawner_options_form | safe}} <label for="self-profile" class="form-control input-group"> <div class="col-md-1"> <input type="radio" name="profile" id="self-profile" value="self-profile"> </div> <div class="col-md-11"> <strong>Spark && Hail && GD environment. <i>Customize specified resources here: </i></strong> <p>Memory: <input type="number" name="memory" id="memory">G CPU: <input type="number" name="cpu" id="cpu">C</p> <div id="resource-error" style="display: none;color: red">资源申请不合法! Mem:[1:30]G CPU:[0:3.6]C</div> </div> </label> <br> <input type="submit" value="Start" class="btn btn-jupyter form-control"> </form> </div> <script type="text/javascript"> const txtMem = document.getElementById('memory'); const txtCPU = document.getElementById('cpu'); const txtErr = document.getElementById('resource-error'); txtErr.style.display = "none"; //校验 function dis() { //获取输入框内容 const tMem = txtMem.value; const tCPU = txtCPU.value; const profile_value = document.getElementById('self-profile').value; //判断 if (profile_value != 'self-profile') { return true; } if (!(tMem >= 1 && tMem <= 30)) { txtErr.style.display = 'inline-block'; return false;//校验不通过 } if (!(tCPU >= 0 && tCPU <= 3.6)) { txtErr.style.display = 'inline-block'; return false; } return true; } </script> </div> {% endblock %}
2. 解析传送到后端的数据
/usr/local/lib/python3.6/dist-packages/jupyterhub/handlers/pages.py
if 'self-profile' in form_options.get("profile") and "memory" in form_options and "cpu" in form_options: try: memory = form_options.get("memory", [])[0] cpu = form_options.get("cpu", [])[0] profile = f"mem:{memory}G, cpu:{cpu}" options = {"memory": memory, "cpu": cpu, "profile": profile} except Exception as e: options = await maybe_future(spawner.options_from_form(form_options)) else: options = await maybe_future(spawner.options_from_form(form_options)) await self.spawn_single_user(user, server_name=server_name, options=options)
3. 加载配置
@gen.coroutine def _load_profile(self, profile_name): """Load a profile by name Called by load_user_options """ # find the profile default_profile = self._profile_list[0] if 'mem:' in profile_name and 'cpu:' in profile_name: resource_info = dict([_.strip().split(":") for _ in profile_name.split(",")]) mem_value = resource_info.get("mem").strip() cpu_value = float(resource_info.get("cpu").strip()) kubespawner_override = { 'mem_guarantee': str(int(float(mem_value[:-1]) * 0.6)) + "G", 'mem_limit': mem_value, 'cpu_guarantee': cpu_value * 0.6, 'cpu_limit': cpu_value } else: for profile in self._profile_list: if profile.get('default', False): # explicit default, not the first default_profile = profile if profile['display_name'] == profile_name: break else: if profile_name: # name specified, but not found raise ValueError("No such profile: %s. Options include: %s" % ( profile_name, ', '.join(p['display_name'] for p in self._profile_list) )) else: # no name specified, use the default profile = default_profile self.log.debug("Applying KubeSpawner override for profile '%s'", profile['display_name']) kubespawner_override = profile.get('kubespawner_override', {}) for k, v in kubespawner_override.items(): if callable(v): v = v(self) self.log.debug(".. overriding KubeSpawner value %s=%s (callable result)", k, v) else: self.log.debug(".. overriding KubeSpawner value %s=%s", k, v) setattr(self, k, v)
Dockerfile
FROM jupyterhub/k8s-hub:0.9.0-beta.4 USER root COPY pages.py /usr/local/lib/python3.6/dist-packages/jupyterhub/handlers/pages.py COPY spawner.py /usr/local/lib/python3.6/dist-packages/kubespawner/spawner.py COPY spawn.html /usr/local/share/jupyterhub/templates/spawn.html RUN chmod 777 /usr/local/share/jupyterhub/templates/spawn.html USER jovyan