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 Local Development with Kubernetes with Docker Desktop #3158

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
53 changes: 53 additions & 0 deletions config/localhost.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# 127.0.0.1.nip.io will not work because when pods try to use it,
# the domain will resolve to the pod itself.
# The deploy.py overwrite the 127.0.0.1 to the user IP address.
binderhub:
config:
BinderHub:
# Use Kubernetes DNS
hub_url: http://jupyterhub.127.0.0.1.nip.io
use_registry: false

extraConfig:
# Disable send events to StackDriver on Google Cloud
01-eventlog:

registry:
username: "your-username"
# This is unsafe! Only se for local development
password: "your-password"

ingress:
https:
# This is unsafe! Only se for local development
enabled: false
hosts:
- 127.0.0.1.nip.io

jupyterhub:
ingress:
hosts:
- jupyterhub.127.0.0.1.nip.io

static:
ingress:
tls:
# This is unsafe! Only se for local development
enabled: false
hosts:
- static.127.0.0.1.nip.io

analyticsPublisher:
enabled: false

prometheus:
enabled: false

grafana:
enabled: false

cryptnono:
enabled: false

cluster-autoscaler:
enabled: false
31 changes: 29 additions & 2 deletions deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ def get_config_files(release, config_dir="config"):
return config_files


def deploy(release, name=None, dry_run=False, diff=False):
def deploy(release, name=None, dry_run=False, diff=False, ip_address=None):
"""Deploys a federation member to a k8s cluster.

Waits for deployments and daemonsets to become Ready
Expand Down Expand Up @@ -238,6 +238,20 @@ def deploy(release, name=None, dry_run=False, diff=False):
for config_file in config_files:
helm.extend(["-f", config_file])

if release == "localhost":
helm.extend(
[
"--set",
f"binderhub.config.BinderHub.hub_url=http://jupyterhub.{ip_address}.nip.io",
"--set",
f"binderhub.ingress.hosts={{{ip_address}.nip.io}}",
"--set",
f"binderhub.jupyterhub.ingress.hosts={{jupyterhub.{ip_address}.nip.io}}",
"--set",
f"static.ingress.hosts={{static.{ip_address}.nip.io}}",
]
)

check_call(helm, dry_run)
print(
BOLD + GREEN + f"SUCCESS: Helm {helm_commands[0]} for {release} completed" + NC,
Expand Down Expand Up @@ -437,6 +451,7 @@ def main():
"release",
help="Release to deploy",
choices=[
"localhost",
"staging",
"prod",
"ovh",
Expand All @@ -459,6 +474,10 @@ def main():
action="store_true",
help="If the script is running locally, skip auth step",
)
argparser.add_argument(
"--local-ip",
help="IP address of the local machine",
)
argparser.add_argument(
"--dry-run",
action="store_true",
Expand All @@ -479,6 +498,12 @@ def main():

args = argparser.parse_args()

if args.release == "localhost":
args.local = True

if args.local_ip is None:
raise ValueError("Cluster localhost requires IP address.")

# if one argument given make cluster == release
cluster = args.cluster or args.release

Expand Down Expand Up @@ -520,6 +545,8 @@ def main():
setup_auth_gcloud(args.release, cluster, args.dry_run)
elif cluster in AWS_DEPLOYMENTS:
setup_auth_aws(cluster, args.dry_run)
elif cluster == "localhost":
pass
else:
raise Exception("Cloud cluster not recognised!")

Expand All @@ -530,7 +557,7 @@ def main():
if args.stage in ("all", "certmanager"):
setup_certmanager(args.dry_run, args.diff)
if args.stage in ("all", "mybinder"):
deploy(args.release, args.name, args.dry_run, args.diff)
deploy(args.release, args.name, args.dry_run, args.diff, args.local_ip)


if __name__ == "__main__":
Expand Down
1 change: 1 addition & 0 deletions docs/source/getting_started/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ permissions, as well as contextual information about the mybinder.org deployment
.. toctree::
:maxdepth: 3

local_environment
getting_started
production_environment
terminology
73 changes: 73 additions & 0 deletions docs/source/getting_started/local_environment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Getting started with local development

This page contains a starting point for people who want to know more about the BinderHub deployment by playing around with a local development instance.

## Local Kubernetes

You will need a local Kubernetes cluster. A few options are

- [Kubernetes with Docker Desktop](https://docs.docker.com/desktop/features/kubernetes/) (recommended)
- [minikube](https://minikube.sigs.k8s.io/docs/)
- [k3d](https://k3d.io/stable/)
- [kind](https://kind.sigs.k8s.io/)

### Install Docker Desktop

Install Docker Desktop on [Mac](https://docs.docker.com/desktop/setup/install/mac-install/), [Windows](https://docs.docker.com/desktop/setup/install/windows-install/), or [Linux](https://docs.docker.com/desktop/setup/install/linux/). And [turn on Kubernetes](https://docs.docker.com/desktop/features/kubernetes/#install-and-turn-on-kubernetes).

## Set up `kubectl` to connect to Kubernetes

Once you have `kubectl` installed, you can connect it with your local Kubernetes.
To do so, run the following command:

```
kubectl config use-context k8s-context-name
```

If using Docker Desktop, `k8s-context-name` is `docker-desktop`.

You can test this out by running:

```
kubectl get -A pods
```

and a list of all running pods should be printed.

## Deploy Harbor to Kubernetes

Run the following command:

```
helm repo add harbor https://helm.goharbor.io
```

```
helm install harbor harbor/harbor
```

## Deploy mybinder.org to Kubernetes

Run the following command:

```
source cert-manager.env
```

```
for d in ./mybinder*/; do
helm dependency update "$d"
done
```

```
chartpress --skip-build
```

```
python deploy.py localhost
```

## Access your mybinder.org

Open http://localhost with your favourite web browser.
2 changes: 2 additions & 0 deletions mybinder/templates/static/ingress.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ spec:
port:
number: 80
{{- end }}
{{- if .Values.static.ingress.tls.enabled }}
tls:
- secretName: {{ .Values.static.ingress.tls.secretName }}
hosts:
{{- range $host := .Values.static.ingress.hosts }}
- {{ $host }}
{{- end }}
{{- end }}
1 change: 1 addition & 0 deletions mybinder/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,7 @@ static:
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
tls:
enabled: true
secretName: kubelego-tls-static

# values ref: https://github.com/grafana/helm-charts/blob/main/charts/grafana/values.yaml
Expand Down