From 5fb8e46e5c5eb13c47b96895bec557c13900a41d Mon Sep 17 00:00:00 2001 From: Simon Li Date: Mon, 25 Jul 2022 18:05:32 +0100 Subject: [PATCH 1/3] docker_build_host can be empty to disable docker.sock --- binderhub/app.py | 13 ++++++++----- binderhub/build.py | 29 +++++++++++++++++------------ 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/binderhub/app.py b/binderhub/app.py index 47198e60c..8c096505f 100644 --- a/binderhub/app.py +++ b/binderhub/app.py @@ -410,16 +410,19 @@ def _valid_badge_base_url(self, proposal): Currently, only paths are supported, and they are expected to be available on all the hosts. + + Set to empty to disable the docker socket mount. """, ) @validate("build_docker_host") def docker_build_host_validate(self, proposal): - parts = urlparse(proposal.value) - if parts.scheme != "unix" or parts.netloc != "": - raise TraitError( - "Only unix domain sockets on same node are supported for build_docker_host" - ) + if proposal.value: + parts = urlparse(proposal.value) + if parts.scheme != "unix" or parts.netloc != "": + raise TraitError( + "Only unix domain sockets on same node are supported for build_docker_host" + ) return proposal.value build_docker_config = Dict( diff --git a/binderhub/build.py b/binderhub/build.py index 6baa09d25..605662c5c 100644 --- a/binderhub/build.py +++ b/binderhub/build.py @@ -118,6 +118,7 @@ def __init__( The docker socket to use for building the image. Must be a unix domain socket on a filesystem path accessible on the node in which the build pod is running. + If empty no socket is mounted. image_name : str Full name of the image to build. Includes the tag. Passed through to repo2docker. @@ -350,20 +351,24 @@ def submit(self): Progress of the build can be monitored by listening for items in the Queue passed to the constructor as `q`. """ - volume_mounts = [ - client.V1VolumeMount( - mount_path="/var/run/docker.sock", name="docker-socket" + volume_mounts = [] + volumes = [] + + if self.docker_host: + volume_mounts.append( + client.V1VolumeMount( + mount_path="/var/run/docker.sock", name="docker-socket" + ) ) - ] - docker_socket_path = urlparse(self.docker_host).path - volumes = [ - client.V1Volume( - name="docker-socket", - host_path=client.V1HostPathVolumeSource( - path=docker_socket_path, type="Socket" - ), + docker_socket_path = urlparse(self.docker_host).path + volumes.append( + client.V1Volume( + name="docker-socket", + host_path=client.V1HostPathVolumeSource( + path=docker_socket_path, type="Socket" + ), + ) ) - ] if self.push_secret: volume_mounts.append( From 4e12189785af7e793f99837396045e5eca1ffa92 Mon Sep 17 00:00:00 2001 From: Simon Li Date: Mon, 25 Jul 2022 18:06:09 +0100 Subject: [PATCH 2/3] Add build_capabilities (container cap add) for build container --- binderhub/app.py | 13 +++++++++++++ binderhub/build.py | 11 +++++++++++ binderhub/build_local.py | 2 ++ binderhub/builder.py | 1 + 4 files changed, 27 insertions(+) diff --git a/binderhub/app.py b/binderhub/app.py index 8c096505f..614bda4b9 100644 --- a/binderhub/app.py +++ b/binderhub/app.py @@ -30,6 +30,7 @@ Bytes, Dict, Integer, + List, TraitError, Type, Unicode, @@ -502,6 +503,17 @@ def _default_build_namespace(self): config=True, ) + build_capabilities = List( + [], + help=""" + Additional Kubernetes capabilities to add to the build container + + If the special string "privileged" is found the container is run in + privileged mode and other capabilities are ignored. + """, + config=True, + ) + build_node_selector = Dict( {}, config=True, @@ -805,6 +817,7 @@ def initialize(self, *args, **kwargs): "ban_networks_min_prefix_len": self.ban_networks_min_prefix_len, "build_namespace": self.build_namespace, "build_image": self.build_image, + "build_capabilities": self.build_capabilities, "build_node_selector": self.build_node_selector, "build_pool": self.build_pool, "build_token_check_origin": self.build_token_check_origin, diff --git a/binderhub/build.py b/binderhub/build.py index 605662c5c..58b844f9b 100644 --- a/binderhub/build.py +++ b/binderhub/build.py @@ -83,6 +83,7 @@ def __init__( build_image, docker_host, image_name, + build_capabilities=None, git_credentials=None, push_secret=None, memory_limit=0, @@ -122,6 +123,10 @@ def __init__( image_name : str Full name of the image to build. Includes the tag. Passed through to repo2docker. + build_capabilities: [str] + Capabilities to add to the build pod. + If the special string "privileged" is found the container is run in + privileged mode and other capabilities are ignored. git_credentials : str Git credentials to use to clone private repositories. Passed through to repo2docker via the GIT_CREDENTIAL_ENV environment @@ -163,6 +168,7 @@ def __init__( self.image_name = image_name self.push_secret = push_secret self.build_image = build_image + self.build_capabilities = build_capabilities or [] self.main_loop = IOLoop.current() self.memory_limit = memory_limit self.memory_request = memory_request @@ -410,6 +416,11 @@ def submit(self): requests={"memory": self.memory_request}, ), env=env, + security_context=client.V1SecurityContext( + capabilities=client.V1Capabilities( + add=self.build_capabilities + ) + ), ) ], tolerations=[ diff --git a/binderhub/build_local.py b/binderhub/build_local.py index b356e4138..8cb0d6a77 100644 --- a/binderhub/build_local.py +++ b/binderhub/build_local.py @@ -124,6 +124,7 @@ def __init__( build_image, docker_host, image_name, + build_capabilities=None, git_credentials=None, push_secret=None, memory_limit=0, @@ -151,6 +152,7 @@ def __init__( Ref of repository to build Passed through to repo2docker. build_image : ignored + build_capabilities: ignored docker_host : ignored image_name : str Full name of the image to build. Includes the tag. diff --git a/binderhub/builder.py b/binderhub/builder.py index fdbc391c9..0e53cded2 100644 --- a/binderhub/builder.py +++ b/binderhub/builder.py @@ -436,6 +436,7 @@ async def get(self, provider_prefix, _unescaped_spec): image_name=image_name, push_secret=push_secret, build_image=self.settings["build_image"], + build_capabilities=self.settings["build_capabilities"], memory_limit=self.settings["build_memory_limit"], memory_request=self.settings["build_memory_request"], docker_host=self.settings["build_docker_host"], From 3affc7f37b2a2df843ec537845c16c0c403117b9 Mon Sep 17 00:00:00 2001 From: Simon Li Date: Mon, 25 Jul 2022 21:44:39 +0100 Subject: [PATCH 3/3] Add privileged build pod option --- binderhub/build.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/binderhub/build.py b/binderhub/build.py index 58b844f9b..52c4e717a 100644 --- a/binderhub/build.py +++ b/binderhub/build.py @@ -393,6 +393,13 @@ def submit(self): client.V1EnvVar(name="GIT_CREDENTIAL_ENV", value=self.git_credentials) ) + if "privileged" in self.build_capabilities: + security_context = client.V1SecurityContext(privileged=True) + else: + security_context = client.V1SecurityContext( + capabilities=client.V1Capabilities(add=self.build_capabilities) + ) + self.pod = client.V1Pod( metadata=client.V1ObjectMeta( name=self.name, @@ -416,11 +423,7 @@ def submit(self): requests={"memory": self.memory_request}, ), env=env, - security_context=client.V1SecurityContext( - capabilities=client.V1Capabilities( - add=self.build_capabilities - ) - ), + security_context=security_context, ) ], tolerations=[