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

Support podman in k8s #1531

Merged
merged 37 commits into from
Dec 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
01d5260
chart: add an optional podman service pod
sgaist Sep 16, 2022
93f2f76
feat(build): add configurable environment variables
sgaist Sep 16, 2022
96f6d28
doc(setup-bindherhub): fix typos
sgaist Sep 21, 2022
375f75e
doc(setup-binderhub): Add pink setup documentation
sgaist Sep 21, 2022
b378c99
Merge branch 'jupyterhub:main' into podman_in_k8s
sgaist Oct 28, 2022
61cd2bc
fix(chart) Use DirectoryOrCreate
sgaist Oct 10, 2022
3b81882
refactor: unify dind and pink templates under container-builder
sgaist Oct 28, 2022
75b6a59
refactor: remove builders enabled property
sgaist Oct 28, 2022
b5aca72
refactor: deduplicate code in template helper
sgaist Oct 28, 2022
e15a922
refactor: move dedicated functions back to main template
sgaist Oct 28, 2022
8032a92
fix: remove enabled from values.yaml
sgaist Oct 28, 2022
5447e33
feat: implement proper pink support in image cleaner
sgaist Nov 10, 2022
b80ffbc
refactor: handle dind and pink in binderhub_config
sgaist Nov 10, 2022
3d89922
refactor: update documentation to use containerBuilderPod
sgaist Nov 10, 2022
6eff738
fix: fix linting input and new tests
sgaist Nov 10, 2022
aad07e8
fix: use containerBuilderPod in k8s API test values
sgaist Nov 10, 2022
6794005
Merge remote-tracking branch 'origin/main' into pr1531
manics Dec 4, 2022
6c49dab
docs: add image override suggestion when using pink
sgaist Dec 5, 2022
80596ea
fix: add missing fields to secret template
sgaist Dec 5, 2022
4c32186
refactor: create EnvBuild class from KubernetesBuildExecutor rather t…
sgaist Dec 5, 2022
8c2742d
refactor: use UID 0 and update storage volume mount for container bui…
sgaist Dec 5, 2022
6824b59
refactor: bring back dind enabled to be backward compatible
sgaist Dec 5, 2022
06ecf1b
chore: Fix indentation in template
sgaist Dec 6, 2022
de12448
refactor: Make notes error on use of dind.enabled
sgaist Dec 6, 2022
28d8df8
refactor: instantiate the builder daemonset only based on containerBu…
sgaist Dec 6, 2022
2de12f7
feat: make containerBuilderPod a required value
sgaist Dec 6, 2022
deaeffd
refactor: cleanup template test
sgaist Dec 6, 2022
c7a6e17
refactor: rename containerBuilderPod to imageBuilderType
sgaist Dec 6, 2022
381f0e9
refactor: use local in place of disabled for imageBuilderType
sgaist Dec 6, 2022
594273a
refactor: use hostSocketDir for pink as done with dind
sgaist Dec 8, 2022
8392e5b
refactor: unify volume names
sgaist Dec 8, 2022
5c475e9
refactor: use builder and daemonset variables to retrieve values
sgaist Dec 8, 2022
a3f3fcc
Formatting details for consistency
consideRatio Dec 11, 2022
0a49e62
feat: add podman image to dependencies watch
sgaist Dec 11, 2022
28d9702
refactor: use dedicated name for Docker and Podman socket
sgaist Dec 12, 2022
fa7a1af
feat(github/workflows): handle tag with and without v when checking f…
sgaist Dec 12, 2022
9558c28
chore: update podman image tag to v4.3.1
sgaist Dec 12, 2022
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
14 changes: 14 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,20 @@ jobs:
helm template --validate binderhub-test helm-chart/binderhub \
--values tools/templates/lint-and-validate-values.yaml

- name: "Helm template --validate for dind (with lint-and-validate-values.yaml)"
if: matrix.test == 'helm'
run: |
helm template --validate binderhub-test helm-chart/binderhub \
--values tools/templates/lint-and-validate-values.yaml \
--set imageBuilderType=dind

- name: "Helm template --validate for pink (with lint-and-validate-values.yaml)"
if: matrix.test == 'helm'
run: |
helm template --validate binderhub-test helm-chart/binderhub \
--values tools/templates/lint-and-validate-values.yaml \
--set imageBuilderType=pink

- name: Validate the chart against the k8s API
if: matrix.test == 'helm'
run: |
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/watch-dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ jobs:
registry: registry.hub.docker.com
repository: library/docker
values_path: dind.daemonset.image.tag
- name: podman
registry: quay.io
repository: podman/stable
values_path: pink.daemonset.image.tag

# FIXME: After docker-image-cleaner 1.0.0 is released, we can enable
# this. So far, there isn't any available stable release, and
Expand Down Expand Up @@ -59,7 +63,7 @@ jobs:
run: |
latest_tag=$(
docker run --rm quay.io/skopeo/stable list-tags docker://${{ matrix.registry }}/${{ matrix.repository }} \
| jq -r '[.Tags[] | select(. | match("^\\d+\\.\\d+\\.\\d+$") | .string)] | sort_by(split(".") | map(tonumber)) | last'
| jq -r '[.Tags[] | select(. | match("^v?\\d+\\.\\d+\\.\\d+$") | .string)] | sort_by(split(".") | map(ltrimstr("v") | tonumber)) | last'
)
echo "tag=$latest_tag" >> $GITHUB_OUTPUT

Expand Down
11 changes: 10 additions & 1 deletion binderhub/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,12 @@ def _default_namespace(self):
{}, help="Node selector for the kubernetes build pod.", config=True
)

extra_envs = Dict(
{},
help="Extra environment variables for the kubernetes build pod.",
config=True,
)

log_tail_lines = Integer(
100,
help=(
Expand Down Expand Up @@ -380,7 +386,10 @@ def submit(self):
)
)

env = []
env = [
client.V1EnvVar(name=key, value=value)
for key, value in self.extra_envs.items()
]
if self.git_credentials:
env.append(
client.V1EnvVar(name="GIT_CREDENTIAL_ENV", value=self.git_credentials)
Expand Down
43 changes: 42 additions & 1 deletion binderhub/tests/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from tornado.httputil import url_concat
from tornado.queues import Queue

from binderhub.build import Build, ProgressEvent
from binderhub.build import Build, KubernetesBuildExecutor, ProgressEvent
from binderhub.build_local import LocalRepo2dockerBuild, ProcessTerminated, _execute_cmd

from .utils import async_requests
Expand Down Expand Up @@ -241,6 +241,47 @@ def test_git_credentials_passed_to_podspec_upon_submit():
assert env["GIT_CREDENTIAL_ENV"] == git_credentials


def test_extra_environment_variables_passed_to_podspec_upon_submit():
extra_environments = {
"CONTAINER_HOST": "unix:///var/run/docker.sock",
"REGISTRY_AUTH_FILE": "/root/.docker/config.json",
}

mock_k8s_api = _list_image_builder_pods_mock()

class EnvBuild(KubernetesBuildExecutor):
q = mock.MagicMock()
api = mock_k8s_api
name = "test_build"
repo_url = "repo"
ref = "ref"
image_name = "name"
extra_envs = extra_environments
namespace = "build_namespace"
push_secret = ""
build_image = "image"
memory_limit = 0
docker_host = "http://mydockerregistry.local"
node_selector = {}

build = EnvBuild()

with mock.patch.object(build.stop_event, "is_set", return_value=True):
build.submit()

call_args_list = mock_k8s_api.create_namespaced_pod.call_args_list
assert len(call_args_list) == 1

args = call_args_list[0][0]
pod = args[1]

assert len(pod.spec.containers) == 1

env = {env_var.name: env_var.value for env_var in pod.spec.containers[0].env}

assert env == extra_environments


async def test_local_repo2docker_build():
q = Queue()
repo_url = "https://github.com/binderhub-ci-repos/cached-minimal-dockerfile"
Expand Down
38 changes: 33 additions & 5 deletions docs/source/zero-to-binderhub/setup-binderhub.rst
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ You now have a functioning BinderHub at the above IP address.
Customizing your Deployment
---------------------------

The Helm chart used to install your BinderHub deployemnt exposes a number of
The Helm chart used to install your BinderHub deployment exposes a number of
optional features. Below we describe a few of the most common customizations
and how you can configure them.

Expand Down Expand Up @@ -431,7 +431,7 @@ time at `the token administration page <https://github.com/settings/tokens>`_.
GitLab
^^^^^^

To access private GitLab repos, create an API token for your binderhub user
To access private GitLab repos, create an API token for your BinderHub user
under "User Settings" > "Access tokens". It at least needs the scopes "api" and
"read_repository".

Expand All @@ -452,20 +452,20 @@ clone a repo.
Use Docker-inside-Docker (DinD)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

By default, BinderHub will build pods with the host Docker installation.
By default, BinderHub will build images with the host Docker installation.
This often means you are stuck with whatever version of Docker provided by your
cloud provider. BinderHub supports an alternative that uses `Docker-in-Docker
(DinD) <https://hub.docker.com/_/docker>`_. To turn `dind` on, you'll need to set
the following configuration in your ``config.yaml`` file::

imageBuilderType: dind
dind:
enabled: true
daemonset:
image:
name: docker
tag: 18.09.2-dind

If you plan to host multiple BinderHub deployments on the same kubernetes
If you plan to host multiple BinderHub deployments on the same Kubernetes
cluster, you'll also need to isolate the host socket and library directory
for each DinD application::

Expand All @@ -474,4 +474,32 @@ for each DinD application::
hostSocketDir: /var/run/dind/"<name of deployment, e.g. staging>"


Use Podman-inside-Kubernetes (PinK)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In case Docker is not an option, Podman can be used as drop in replacement.
Note that the implications about using a host installation of Podman are the same
as with Docker. BinderHub supports an alternative that uses `Podman-in-Kubernetes
(PinK) <https://www.redhat.com/sysadmin/podman-inside-kubernetes>`_. To turn
`pink` on, you'll need to set the following configuration in your ``config.yaml`` file::

imageBuilderType: pink

You can optionally override the default podman image:

pink:
daemonset:
image:
name: quay.io/podman/stable
tag: v4.2.0
sgaist marked this conversation as resolved.
Show resolved Hide resolved

If you plan to host multiple BinderHub deployments on the same Kubernetes
cluster, you'll also need to isolate the host socket and library directory
for each DinD application::

pink:
hostStorageDir: /var/lib/pink/"<name of deployment, e.g. staging>"
hostSocketDir: /var/run/pink/"<name of deployment, e.g. staging>"


For next steps, see :doc:`../debug` and :doc:`turn-off`.
11 changes: 6 additions & 5 deletions helm-chart/binderhub/files/binderhub_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,12 @@ def get_value(key, default=None):
for section, sub_cfg in get_value("config", {}).items():
c[section].update(sub_cfg)

if get_value("dind.enabled", False) and get_value("dind.hostSocketDir"):
c.BinderHub.build_docker_host = "unix://{}/docker.sock".format(
get_value("dind.hostSocketDir")
)

imageBuilderType = get_value("imageBuilderType")
if imageBuilderType in ["dind", "pink"]:
hostSocketDir = get_value(f"{imageBuilderType}.hostSocketDir")
if hostSocketDir:
socketname = "docker" if imageBuilderType == "dind" else "podman"
c.BinderHub.build_docker_host = f"unix://{hostSocketDir}/{socketname}.sock"

if c.BinderHub.auth_enabled:
hub_url = urlparse(c.BinderHub.hub_url)
Expand Down
34 changes: 33 additions & 1 deletion helm-chart/binderhub/schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ required:
- jupyterhub
- deployment
- dind
- pink
- imageBuilderType
- imageCleaner
- ingress
- initContainers
Expand Down Expand Up @@ -349,14 +351,21 @@ properties:
See the [Kubernetes docs](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/)
to learn more about labels.

imageBuilderType:
type: string
enum: ["local", "dind", "pink"]
default: "local"
description: |
Selected image builder type

dind:
type: object
additionalProperties: false
properties:
enabled:
consideRatio marked this conversation as resolved.
Show resolved Hide resolved
type: boolean
description: |
TODO
DEPRECATED: Use `imageBuilderType: dind`
initContainers: &initContainers-spec
type: array
description: |
Expand Down Expand Up @@ -409,6 +418,29 @@ properties:
description: |
TODO

pink:
type: object
additionalProperties: false
properties:
initContainers: *initContainers-spec
daemonset:
type: object
additionalProperties: false
properties:
image: *image-spec
lifecycle: *lifecycle-spec
extraVolumes: *extraVolumes-spec
extraVolumeMounts: *extraVolumeMounts-spec
resources: *resources-spec
hostStorageDir:
type: string
description: |
Host path where the containers storage will be located
hostSocketDir:
type: string
description: |
Host path where the podman socket will be located

imageCleaner:
type: object
additionalProperties: false
Expand Down
8 changes: 8 additions & 0 deletions helm-chart/binderhub/templates/NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,14 @@ config:
{{- $breaking = print $breaking "\n\nRENAMED: jupyterhub.custom.cors.allowOrigin has been renamed to jupyterhub.hub.config.BinderSpawner.cors_allow_origin" }}
{{- end }}

{{- if hasKey .Values.dind "enabled" }}
{{- $breaking = print $breaking "\n\nCHANGED:" }}
{{- $breaking = print $breaking "\n\ndind:" }}
{{- $breaking = print $breaking "\n enabled: true" }}
{{- $breaking = print $breaking "\n\nmust as of version 0.3.0 be replace by" }}
{{- $breaking = print $breaking "\n\nimageBuilderType: dind" }}
{{- end }}

{{- if $breaking }}
{{- fail (print $breaking_title $breaking) }}
{{- end }}
Loading