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

For reference: work towards adding JMTE hub (AWS, eksctl, cloudformation) #436

Closed
wants to merge 43 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
b25881e
deployer: accept provider=none for already setup k8s cluster access
consideRatio May 30, 2021
fbc0ddc
jmte: add 2i2c config for jmte deployment
consideRatio May 31, 2021
4e5051e
jmte: add aws infra (eksctl/cloudformation)
consideRatio May 31, 2021
5dca036
jmte: add volume hack to chown /shared folder
consideRatio Jun 1, 2021
9f912fb
jmte: add choldgraf
consideRatio Jun 2, 2021
f68460a
jmte: opt out of default tolerations
consideRatio Jun 2, 2021
10fee38
jmte: add @jonathan-taylor as allowed user
fperez Jun 2, 2021
51e3815
jmte: set default profile list option and add descriptions
consideRatio Jul 10, 2021
ea69e42
jmte: add jupyterhub-ssh
consideRatio Jul 18, 2021
291d12d
jmte: enable jupyterhub-sftp
consideRatio Aug 11, 2021
b19b6ac
jmte: add GPUs
consideRatio Sep 3, 2021
28f3006
jmte: increase start timeout to handle edge cases
consideRatio Oct 1, 2021
b388c04
jmte: increase user and worker node's disk volumes
consideRatio Oct 1, 2021
cd3e206
jmte: configure x1.16xlarge nodes
consideRatio Oct 14, 2021
8d7ac1f
jmte: tweak configuration related to GPU
consideRatio Oct 28, 2021
351adc5
jmte: disable JupyterLab collaborative mode, awaiting critical bugfixes
consideRatio Sep 3, 2021
f7f749b
jmte: adjust to basehub values refactoring
consideRatio Jan 26, 2022
314d146
jmte: github-app-auth-user: add related gitconfig and env vars
consideRatio Jan 26, 2022
b439dbf
jmte: enable possibility to show hidden files
consideRatio Feb 28, 2022
93d1acd
jmte: adjust to deployer script rework
consideRatio Mar 18, 2022
ce16522
jmte: add recent changes
consideRatio Apr 21, 2022
ec6046b
jmte: k8s 1.19 -> 1.22 upgrade and notes
consideRatio Apr 29, 2022
c7619ed
jmte: adjust dask-gateway config options
consideRatio Jun 8, 2022
93fd326
jmte: update to gh-scoped-creds
consideRatio Jun 16, 2022
1012216
jmte: configure 1 small node placeholder pod
consideRatio Jun 16, 2022
5b74730
jmte: Re-enable the continuous image puller
consideRatio Jun 16, 2022
2c93d9e
jmte: configure nodeSelector for userPlaceholder pod
consideRatio Jul 3, 2022
877419c
jmte: add env for the RDS db setup for jmte
consideRatio Jul 3, 2022
febbd09
jmte: ensure CUDA drivers propegate to containers
consideRatio Jul 16, 2022
18f0c82
jmte: add debugging pod manifest for node fs
consideRatio Jul 16, 2022
b7323f6
jmte: add k8s memory based emptyDir volume mount to /dev/shm
consideRatio Jul 18, 2022
3e04acc
jmte: increase spawn timeout as eks slowly pulls images
consideRatio Aug 1, 2022
072d093
jmte: add another availability zone for highmem instances
consideRatio Sep 5, 2022
2843ee5
jmte: add shared-public folder
consideRatio Sep 5, 2022
923475f
Slim down the debug-pod
consideRatio Sep 22, 2022
9d1f700
jmte: add test of latest image
consideRatio Sep 22, 2022
4291da1
jmte: add 256GB memory GPU node
consideRatio Dec 12, 2022
8927e31
jmte: update k8s from 1.22 to 1.24
consideRatio Dec 18, 2022
1217e0a
basehub: add nfs.homeSpaceReporter.enabled
consideRatio Dec 18, 2022
5e429dd
jmte: disable nfs.homeSpaceReporter.enabled
consideRatio Dec 18, 2022
275acbc
jmte: remove old dask-gateway workaround
consideRatio Dec 18, 2022
5b4be24
jmte: add proxy.htts.hosts explicitly as autohttps is used
consideRatio Dec 18, 2022
27a4592
jmte: fix GPU nodes labels/taints (16/64 CPU variants was failing)
consideRatio Jan 26, 2023
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
20 changes: 20 additions & 0 deletions config/clusters/jmte/cluster.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: jmte
provider: none
hubs:
- name: staging
domain: staging.hub.jupytearth.org
helm_chart: daskhub
auth0:
connection: github
helm_chart_values_files:
- common.values.yaml
- staging.values.yaml
- name: prod
display_name: "Jupyter Meets the Earth"
domain: hub.jupytearth.org
auth0:
connection: github
helm_chart: daskhub
helm_chart_values_files:
- common.values.yaml
- prod.values.yaml
429 changes: 429 additions & 0 deletions config/clusters/jmte/common.values.yaml

Large diffs are not rendered by default.

131 changes: 131 additions & 0 deletions config/clusters/jmte/prod.values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
basehub:
nfs:
enabled: true

jupyterhub:
# Reverts changes in basehub configuration to the z2jh defaults and ensures
# 1 pod is used as a placeholder pod, sized as the smallest node in the JMTE
# cluster. We also update singleuser.nodeSelector to ensure we default to
# have a placeholder for the smallest nodes only.
#
prePuller:
continuous:
enabled: true
scheduling:
userPlaceholder:
enabled: true
replicas: 1
resources:
requests:
cpu: 2.5
memory: 14G

singleuser:
# This default value will be relevant for the userPlaceholder
# configuration, but irrelevant for the defaults we override in our
# profileList configuration.
#
nodeSelector:
2i2c.org/node-cpu: "4"

# Eksctl: The service account was created by eksctl.
#
serviceAccountName: &user-sa s3-full-access

extraEnv:
# SCRATCH_BUCKET / PANGEO_SCRATCH are environment variables that
# help users write notebooks and such referencing this environment
# variable in a way that will work between users.
#
# $(ENV_VAR) will by evaluated by k8s automatically
#
# Cloudformation: The s3 bucket was created by cloudformation.
#
SCRATCH_BUCKET: s3://jmte-scratch/$(JUPYTERHUB_USER)
PANGEO_SCRATCH: s3://jmte-scratch/$(JUPYTERHUB_USER)
# An Amazon RDS postgresql 14 database server has been setup on a
# machine with 4 cores and 32 GB memory. See
# https://us-west-2.console.aws.amazon.com/rds/home?region=us-west-2#modify-instance:id=jmte-db.https://us-west-2.console.aws.amazon.com/rds/home?region=us-west-2#modify-instance:id=jmte-db
#
# I created a postgresql user and database for use by some like this:
#
# CREATE USER proj WITH ENCRYPTED PASSWORD '***';
# CREATE DATABASE proj;
# GRANT ALL PRIVILEGES ON DATABASE proj TO proj;
#
JMTE_DB_HOST: jmte-db.cqf1ngjal8bq.us-west-2.rds.amazonaws.com

initContainers:
# Need to explicitly fix ownership here, since EFS doesn't do anonuid
- name: volume-mount-ownership-fix
image: busybox
command:
[
"sh",
"-c",
"id && chown 1000:1000 /home/jovyan /home/jovyan/shared /home/jovyan/shared-public && ls -lhd /home/jovyan",
]
securityContext:
runAsUser: 0
volumeMounts:
- name: home
mountPath: /home/jovyan
subPath: "{username}"
- name: home
mountPath: /home/jovyan/shared
subPath: _shared
- name: home
mountPath: /home/jovyan/shared-public
subPath: _shared_public

proxy:
https:
hosts:
- hub.jupytearth.org
traefik:
# jupyterhub-ssh/sftp integration part 3/3:
#
# We must let traefik know it should listen for traffic (traefik entrypoint)
# and route it (traefik router) onwards to the jupyterhub-ssh k8s Service
# (traefik service).
#
extraStaticConfig:
entryPoints:
ssh-entrypoint:
address: :8022
sftp-entrypoint:
address: :2222
extraDynamicConfig:
tcp:
services:
ssh-service:
loadBalancer:
servers:
- address: jupyterhub-ssh:22
sftp-service:
loadBalancer:
servers:
- address: jupyterhub-sftp:22
routers:
ssh-router:
entrypoints: [ssh-entrypoint]
rule: HostSNI(`*`)
service: ssh-service
sftp-router:
entrypoints: [sftp-entrypoint]
rule: HostSNI(`*`)
service: sftp-service

dask-gateway:
gateway:
backend:
scheduler:
extraPodConfig:
serviceAccountName: *user-sa
worker:
extraPodConfig:
serviceAccountName: *user-sa

jupyterhub-ssh:
sftp:
enabled: true
34 changes: 34 additions & 0 deletions config/clusters/jmte/staging.values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
basehub:
nfs:
enabled: false

jupyterhub:
custom:
singleuserAdmin:
extraVolumeMounts: []

singleuser:
storage:
type: none
extraVolumeMounts: []

# cmd: Note the default in z2jh is jupyterhub-singleuser.
cmd:
- jupyterhub-singleuser
# WARNING: Collaborative mode is enabled in the staging hub specifically
# to debug a critical issue leading to a loss of data.
#
# ref: https://github.com/jupyterlab/jupyterlab/issues/12154#issuecomment-1069352840
# ref: https://discourse.jupyter.org/t/plans-on-bringing-rtc-to-jupyterhub/9813/13
# ref: https://github.com/jupyterlab/jupyterlab/pull/11599
#
- --LabApp.collaborative=True

proxy:
https:
hosts:
- staging.hub.jupytearth.org

jupyterhub-ssh:
sftp:
enabled: false
32 changes: 32 additions & 0 deletions debug-pod-node-fs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
apiVersion: v1
kind: Pod
metadata:
name: node-fs-inspection
spec:
containers:
- name: node-fs-inspection
image: ubuntu:22.04
command: ["sh", "-c", "sleep infinity"]
resources:
requests:
cpu: 225m
memory: "939524096"
volumeMounts:
- name: node-root-fs
mountPath: /node-root-fs
terminationGracePeriodSeconds: 1
nodeSelector:
2i2c.org/node-gpu: "1"
tolerations:
- effect: NoSchedule
key: hub.jupyter.org/dedicated
operator: Equal
value: user
- effect: NoSchedule
key: hub.jupyter.org_dedicated
operator: Equal
value: user
volumes:
- name: node-root-fs
hostPath:
path: /
63 changes: 63 additions & 0 deletions debug-pod.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
apiVersion: v1
kind: Pod
metadata:
name: jupyter-debugging
namespace: prod
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- preference:
matchExpressions:
- key: hub.jupyter.org/node-purpose
operator: In
values:
- user
weight: 100
containers:
- name: busybox
image: busybox
command: ["sh", "-c", "sleep infinity"]
securityContext:
runAsUser: 0
volumeMounts:
- mountPath: /nfs
name: home
- mountPath: /home/jovyan
name: home
subPath: fperez
- mountPath: /home/jovyan/shared
name: home
subPath: _shared
- mountPath: /home/jovyan/shared-public
name: home
subPath: _shared_public
resources:
requests:
cpu: 225m
memory: "939524096"
nodeSelector:
2i2c.org/node-cpu: "4"
schedulerName: prod-user-scheduler
serviceAccountName: s3-full-access
tolerations:
- effect: NoSchedule
key: hub.jupyter.org/dedicated
operator: Equal
value: user
- effect: NoSchedule
key: hub.jupyter.org_dedicated
operator: Equal
value: user
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- name: home
persistentVolumeClaim:
claimName: home-nfs
2 changes: 2 additions & 0 deletions deployer/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ def auth(self):
yield from self.auth_azure()
elif self.spec["provider"] == "kubeconfig":
yield from self.auth_kubeconfig()
elif self.spec["provider"] == "none":
yield
else:
raise ValueError(f'Provider {self.spec["provider"]} not supported')

Expand Down
1 change: 1 addition & 0 deletions deployer/cluster.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ properties:
authentication against the cluster. Currently supports gcp, aws, azure,
and raw kubeconfig files.
enum:
- none
- gcp
- kubeconfig
- aws
Expand Down
74 changes: 74 additions & 0 deletions eksctl/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
### Setup of k8s cluster via eksctl

TODO describe...

### Setup of extras via cloudformation

TODO describe...

### Setup of cluster-autoscaler in the k8s cluster

`eksctl` doesn't automatically install a cluster-autoscaler and it is not part
of a EKS based k8s cluster by itself, so it needs to be manually installed. The
cluster-autoscaler will need permissions to do its job though, and for that we
use some flags in our eksctl config file and then we install it with a Helm
chart.

#### eksctl configuration for cluster-autoscaler

We need our eksctl-cluster-config.yaml to:

1. Declare `nodeGroups.*.iam.withAddonPolicies.autoScaler=true`.

I believe doing so is what makes the following tags automatically be applied
on node groups, which is required by the cluster-autoscaler to detect them.

```
k8s.io/cluster-autoscaler/<cluster-name>
k8s.io/cluster-autoscaler/enabled
```

2. Declare additional tags for labels/taints.

```yaml
nodeGroups:
- name: worker-xlarge
labels:
k8s.dask.org/node-purpose: worker
taints:
k8s.dask.org_dedicated: worker:NoSchedule

# IMPORTANT: we also provide these tags alongside the labels/taints
# to help the cluster-autoscaler do its job.
#
tags:
k8s.io/cluster-autoscaler/node-template/label/k8s.dask.org/node-purpose: worker
k8s.io/cluster-autoscaler/node-template/taint/k8s.dask.org_dedicated: worker:NoSchedule
```


#### Installation of cluster-autoscaler

We rely on the [cluster-autoscaler Helm chart](https://github.com/kubernetes/autoscaler/tree/master/charts/cluster-autoscaler) to manage the k8s resources for the cluster-autoscaler we need to manually complement the k8s cluster with.

```
helm upgrade cluster-autocaler cluster-autoscaler \
--install \
--repo https://kubernetes.github.io/autoscaler \
--version 9.9.2 \
--namespace kube-system \
--set autoDiscovery.clusterName=jmte \
--set awsRegion=us-west-2
```

### Misc

- Create a auth0 application for github
- Update dns record ([jupytearth.org is managed on GCP by Erik](https://console.cloud.google.com/net-services/dns/zones/jupytearth-org/details?folder=&organizationId=&project=domains-sos))

### FIXME: Open questions

- How is cluster-autoscaler acquiring the permissions it needs? Is it by being
located on the node where we have
`nodeGroups.*.iam.withAddonPolicies.autoScaler=true`? Then we have ended up
granting permission to all pods on all nodes that are too high.
Loading