diff --git a/.github/workflows/deploy-grafana-dashboards.yaml b/.github/workflows/deploy-grafana-dashboards.yaml index de85e9ce99..f2112502ab 100644 --- a/.github/workflows/deploy-grafana-dashboards.yaml +++ b/.github/workflows/deploy-grafana-dashboards.yaml @@ -36,6 +36,7 @@ jobs: - cluster_name: ubc-eoas - cluster_name: utoronto - cluster_name: victor + - cluster_name: jupyter-health steps: - name: Checkout repo diff --git a/.github/workflows/deploy-hubs.yaml b/.github/workflows/deploy-hubs.yaml index 0e55c1ce00..f9ad90fbac 100644 --- a/.github/workflows/deploy-hubs.yaml +++ b/.github/workflows/deploy-hubs.yaml @@ -199,6 +199,7 @@ jobs: failure_nasa-ghg: "${{ env.failure_nasa-ghg }}" failure_qcl: "${{ env.failure_qcl }}" failure_jupyter-meets-the-earth: "${{ env.failure_jupyter-meets-the-earth }}" + failure_jupyter-health: "${{ env.failure_jupyter-health }}" failure_smithsonian: "${{ env.failure_smithsonian }}" failure_catalystproject-latam: "${{ env.failure_catalystproject-latam }}" failure_catalystproject-africa: "${{ env.failure_catalystproject-africa }}" diff --git a/config/clusters/jupyter-health/cluster.yaml b/config/clusters/jupyter-health/cluster.yaml new file mode 100644 index 0000000000..1332f85ef3 --- /dev/null +++ b/config/clusters/jupyter-health/cluster.yaml @@ -0,0 +1,28 @@ +name: jupyter-health +provider: aws +aws: + key: enc-deployer-credentials.secret.json + clusterType: eks + clusterName: jupyter-health + region: us-east-2 +support: + helm_chart_values_files: + - support.values.yaml + - enc-support.secret.values.yaml +hubs: + - name: staging + display_name: "Jupyter Health (staging)" + domain: staging.jupyter-health.2i2c.cloud + helm_chart: basehub + helm_chart_values_files: + - common.values.yaml + - staging.values.yaml + - enc-staging.secret.values.yaml + - name: prod + display_name: "Jupyter Health (prod)" + domain: jupyter-health.2i2c.cloud + helm_chart: basehub + helm_chart_values_files: + - common.values.yaml + - prod.values.yaml + - enc-prod.secret.values.yaml \ No newline at end of file diff --git a/config/clusters/jupyter-health/common.values.yaml b/config/clusters/jupyter-health/common.values.yaml new file mode 100644 index 0000000000..1719815dd4 --- /dev/null +++ b/config/clusters/jupyter-health/common.values.yaml @@ -0,0 +1,180 @@ +nfs: + enabled: true + pv: + enabled: true + # from https://docs.aws.amazon.com/efs/latest/ug/mounting-fs-nfs-mount-settings.html + mountOptions: + - rsize=1048576 + - wsize=1048576 + - timeo=600 + - soft # We pick soft over hard, so NFS lockups don't lead to hung processes + - retrans=2 + - noresvport + serverIP: fs-07b67adf6626672af.efs.us-east-2.amazonaws.com + baseShareName: / +jupyterhub: + custom: + 2i2c: + add_staff_user_ids_to_admin_users: true + add_staff_user_ids_of_type: "github" + jupyterhubConfigurator: + enabled: false + homepage: + templateVars: + org: + name: Jupyter Health + logo_url: https://jupyter.org/assets/homepage/main-logo.svg + url: https://github.com/jupyterhealth/ + designed_by: + name: "Jupyter Health" + url: https://github.com/jupyterhealth/ + operated_by: + name: "2i2c" + url: https://2i2c.org + funded_by: + name: "Jupyter Health" + url: https://www.earthdata.nasa.gov/esds/veda + hub: + allowNamedServers: true + config: + JupyterHub: + authenticator_class: github + GitHubOAuthenticator: + allowed_organizations: + - jupyterhealth + scope: + - read:org + Authenticator: + admin_users: + - minrk + - fperez + - colliand + - maryamv + singleuser: + defaultUrl: /lab + profileList: + - display_name: "Pangeo Notebook" + slug: pangeo + description: Pangeo based notebook with a Python environment + default: true + kubespawner_override: + image: quay.io/pangeo/pangeo-notebook:2024.03.22 + init_containers: + # Need to explicitly fix ownership here, as otherwise these directories will be owned + # by root on most NFS filesystems - neither EFS nor Google Filestore support anonuid + - name: volume-mount-ownership-fix + image: busybox:1.36.1 + command: + - sh + - -c + - id && chown 1000:1000 /home/jovyan /home/jovyan/shared && ls -lhd /home/jovyan + securityContext: + runAsUser: 0 + volumeMounts: + - name: home + mountPath: /home/jovyan + subPath: "{username}" + # mounted without readonly attribute here, + # so we can chown it appropriately + - name: home + mountPath: /home/jovyan/shared + subPath: _shared + profile_options: &profile_options + resource_allocation: &profile_options_resource_allocation + display_name: Resource Allocation + choices: + mem_1_9: + display_name: 1.9 GB RAM, upto 3.7 CPUs + kubespawner_override: + mem_guarantee: 1991341312 + mem_limit: 1991341312 + cpu_guarantee: 0.234375 + cpu_limit: 3.75 + node_selector: + node.kubernetes.io/instance-type: r5.xlarge + default: true + mem_3_7: + display_name: 3.7 GB RAM, upto 3.7 CPUs + kubespawner_override: + mem_guarantee: 3982682624 + mem_limit: 3982682624 + cpu_guarantee: 0.46875 + cpu_limit: 3.75 + node_selector: + node.kubernetes.io/instance-type: r5.xlarge + mem_7_4: + display_name: 7.4 GB RAM, upto 3.7 CPUs + kubespawner_override: + mem_guarantee: 7965365248 + mem_limit: 7965365248 + cpu_guarantee: 0.9375 + cpu_limit: 3.75 + node_selector: + node.kubernetes.io/instance-type: r5.xlarge + mem_14_8: + display_name: 14.8 GB RAM, upto 3.7 CPUs + kubespawner_override: + mem_guarantee: 15930730496 + mem_limit: 15930730496 + cpu_guarantee: 1.875 + cpu_limit: 3.75 + node_selector: + node.kubernetes.io/instance-type: r5.xlarge + mem_29_7: + display_name: 29.7 GB RAM, upto 3.7 CPUs + kubespawner_override: + mem_guarantee: 31861460992 + mem_limit: 31861460992 + cpu_guarantee: 3.75 + cpu_limit: 3.75 + node_selector: + node.kubernetes.io/instance-type: r5.xlarge + mem_60_6: + display_name: 60.6 GB RAM, upto 15.7 CPUs + kubespawner_override: + mem_guarantee: 65094813696 + mem_limit: 65094813696 + cpu_guarantee: 7.86 + cpu_limit: 15.72 + node_selector: + node.kubernetes.io/instance-type: r5.4xlarge + mem_121_2: + display_name: 121.2 GB RAM, upto 15.7 CPUs + kubespawner_override: + mem_guarantee: 130189627392 + mem_limit: 130189627392 + cpu_guarantee: 15.72 + cpu_limit: 15.72 + node_selector: + node.kubernetes.io/instance-type: r5.4xlarge + - display_name: "Rocker Geospatial with RStudio" + slug: rocker + description: R environment with many geospatial libraries pre-installed + kubespawner_override: + image: rocker/binder:4.3 + image_pull_policy: Always + # Launch RStudio after the user logs in + default_url: /rstudio + # Ensures container working dir is homedir + # https://github.com/2i2c-org/infrastructure/issues/2559 + working_dir: /home/rstudio + profile_options: *profile_options + - display_name: "Bring your own image" + description: Specify your own docker image (must have python and jupyterhub installed in it) + slug: custom + profile_options: + image: + display_name: Image + unlisted_choice: + enabled: True + display_name: "Custom image" + validation_regex: "^.+:.+$" + validation_message: "Must be a publicly available docker image, of form :" + kubespawner_override: + image: "{value}" + choices: {} + resource_allocation: *profile_options_resource_allocation + + scheduling: + userScheduler: + enabled: true diff --git a/config/clusters/jupyter-health/enc-deployer-credentials.secret.json b/config/clusters/jupyter-health/enc-deployer-credentials.secret.json new file mode 100644 index 0000000000..9b4b1c0204 --- /dev/null +++ b/config/clusters/jupyter-health/enc-deployer-credentials.secret.json @@ -0,0 +1,25 @@ +{ + "AccessKey": { + "AccessKeyId": "ENC[AES256_GCM,data:ZPnLxqCEDnm3k38kfkTBOxojO1U=,iv:+N1qti7SQAQ9ncTrkWmIhuo9BUrUDvM08LHsARfv84s=,tag:1xPNKQK7/vpJDSpXBG5H6A==,type:str]", + "SecretAccessKey": "ENC[AES256_GCM,data:gmoDHtJVBIPoNi0mozBr6ggzl/bZ8rnirpBeuzUYiejraE8k6sWw+A==,iv:DXGDhq9AekwSY+LAGG+vuDgVpDPHdaFZh4OIyfpraxA=,tag:TnnEEX0UFZjX8gSe78eROA==,type:str]", + "UserName": "ENC[AES256_GCM,data:l7xBnsJQh3wfSvrt91dxuqPUfFX9iKY=,iv:HNN1A/f70OCoY6YxS9VPwqFuusdSBhR7QWenu9eRg0M=,tag:MZRN9qU+xNrboAL99Cx1Tg==,type:str]" + }, + "sops": { + "kms": null, + "gcp_kms": [ + { + "resource_id": "projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs", + "created_at": "2024-03-27T03:12:17Z", + "enc": "CiUA4OM7eBALghHLDCATTTf2qSVQwFhR8G3uQdxd25yNBRNJfvfIEkkAXoW3Jmpb9Gxd2eYCUcE3E1WdVbkbAg/yf+Xxg0p3Aw1J73LcxTJTeifDx/s8qeuYZXyvxIsdy9DMW4xaMNOjZsdBSlqZMft8" + } + ], + "azure_kv": null, + "hc_vault": null, + "age": null, + "lastmodified": "2024-03-27T03:12:18Z", + "mac": "ENC[AES256_GCM,data:R4WEbpjhqioIvVWVhTZEY4D4+8HZanx+TU3RwrDazR/+1hbCV6a6nC4yaQG+3gRuoMGIQeRhiP8A5NifzcTeAtRZ9CYoFt/l4R39ow2z6BTGP1M2mNGGA0c6ZlqmJmrxyYIYcv4pWe3BfSBkCFjjqpj83C+AydNovUw2zJi+Gok=,iv:iR8sbRthqB+OpmvTJcrbTVAEXBHfyHqzRnAuk0vOQI0=,tag:t79XNiAlMiMgZK/sUBEp2g==,type:str]", + "pgp": null, + "unencrypted_suffix": "_unencrypted", + "version": "3.8.1" + } +} \ No newline at end of file diff --git a/config/clusters/jupyter-health/enc-grafana-token.secret.yaml b/config/clusters/jupyter-health/enc-grafana-token.secret.yaml new file mode 100644 index 0000000000..f5584666a1 --- /dev/null +++ b/config/clusters/jupyter-health/enc-grafana-token.secret.yaml @@ -0,0 +1,15 @@ +grafana_token: ENC[AES256_GCM,data:pFUEbEuI9Oos6YtuA/oXDKjP6HklrH8G6C8lLh87DDbjQ8Sz0BD9JotBBKoNzA==,iv:rA2kl2O0lcUDPDUcwxuF1F5nY9lydLl+0K2k3OKYkF8=,tag:FkFR4rGHV7xizsUL969Aug==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2024-03-27T03:32:37Z" + enc: CiUA4OM7eMIWtqEIQtysm+s5zxS/nKMoNkjDvRzgvAqs19hSfS03EkkAXoW3JssCZCIo6ovleKWINJnwDXgm/R5uTwhVZqRT0G4cficrTpplNQLvj5Lk7FcWeqqGaXK7pLeYaHeXmPBEDvj4YlRcYFrN + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2024-03-27T03:32:37Z" + mac: ENC[AES256_GCM,data:Hx2QfF6std3LBVVV4Bz4vXKFXmW6Pi220z3I4tXPUzuWX0mVyb5AUr8Je2diq+6ds2rWmhKFskL0CLA5/zP9U/9vfpnddkJy5K8krlDn08s6QQ8NN6fzBzaDksghoD7Z3aRW7Hn7GwbgALVpF6j20Ty4ilUPDPjuZXVi8iZDZSQ=,iv:/eMrdS7XKkaAN2OGs2RQn1Y6dIAdXbgTZR9K1BnH/tI=,tag:5JqsQHlzFf1ASNq/M20sjg==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.8.1 diff --git a/config/clusters/jupyter-health/enc-prod.secret.values.yaml b/config/clusters/jupyter-health/enc-prod.secret.values.yaml new file mode 100644 index 0000000000..a301f4b183 --- /dev/null +++ b/config/clusters/jupyter-health/enc-prod.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + GitHubOAuthenticator: + client_id: ENC[AES256_GCM,data:dK6sakIgpztIfiurNYY+8HtbynQ=,iv:yesxCvpGPK4QKLVNpI6LpWb8KX1brB/uhQIEg1tIbIg=,tag:35BASFn0mDkmBomDjAUNxQ==,type:str] + client_secret: ENC[AES256_GCM,data:nKIRhTK13eIaR1tIWWw/bfK4pclINcj1mr7k1xj7LnWc6FA+QJL+/g==,iv:6fKX5y8+3IogwOVuBrbNT8KoUAPebji58/9JX8cOTP0=,tag:Z6B0FtLLdrE1TunBAKJ68Q==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2024-03-27T03:26:11Z" + enc: CiUA4OM7eNaq2WnQcWV8UUsnnprPSIh0EJM+IyQbcq3ioRaxXOPIEkkAXoW3JilW+T15pzagOKIXjrqeJUpzLZzRZAWZXNJ9svGWZkhJpX6NtPJGNkXFx2dsjXG9pBm31G/7QJKdft93bmdvDu/0kQ53 + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2024-03-27T03:26:56Z" + mac: ENC[AES256_GCM,data:Zk8JTgNL+IM8S1kKe4ejbAUBWB+TzIFr9DhQ0RDRWV3c6r5XT3rBIqVCfHKhPh1RPeE8dFMdovxi/b62gkbUHHPQu+jemoQYofdd3BeuL8N2TZWL3L46uV/RBW0msqnALrZq0yD0hIcXNB4q/F1j0dUVd1wjrPxDaiFR1CYczK8=,iv:XkOBcJAnziqJi+vmP2SSP51x448aqilQ2gEA1a/Wkqg=,tag:SboAWeb1sD4hkYKf32mN2A==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.8.1 diff --git a/config/clusters/jupyter-health/enc-staging.secret.values.yaml b/config/clusters/jupyter-health/enc-staging.secret.values.yaml new file mode 100644 index 0000000000..62ffe8f0d5 --- /dev/null +++ b/config/clusters/jupyter-health/enc-staging.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + GitHubOAuthenticator: + client_id: ENC[AES256_GCM,data:dDQ5o50vtdrOeEAJSg1CYrzRjwY=,iv:zeb0Rh4NjNtfyGGzEVXAzSqdszDuTRrtC2F4tAp+D7Q=,tag:kLH86WnG3PmkpEEGoTau6w==,type:str] + client_secret: ENC[AES256_GCM,data:nqrPYv/i3NJ1TkAncgm+NF0r1U95HxV8pkQXYTMULqibiCwOhwq11g==,iv:5sk0Ac/JDFmArGFtfmsYJjwHNfIZW9Q45X2+hIB9x+o=,tag:4taAorVZrfs3FBMn7ala+w==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2024-03-27T03:20:32Z" + enc: CiUA4OM7ePrLrsqEqXlDkXkXRAWDaAdEbzVylzq8w6GKfCCJGgAvEkkAXoW3JiUlHtWirbwpxMHx9IojRvV71ZR67dw+MFn5ngfTuEWlU+fhhN0SDFd2a97Np9Bdw8RREy43KB++4GKUntGNNxppYhHh + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2024-03-27T03:21:41Z" + mac: ENC[AES256_GCM,data:YigsyrOdKkCTndXMaqS8Fbp54GPJ3xms4pQGxWyRxSf0xq8qf1CN82cM7laGIT/svGxtnelqSsj242uVdPOXLYSPyfibjrKhfNNEcjBakyzPJh0M5JE/7/fUqDSdlplP/8eihjKyQME7u0vBjOsNBKoYvO60131K+GwC7hy50Jw=,iv:k+UTWDJKPjdZHhaufhVGmuHip0BSH2qhFLl00bVv90Q=,tag:1dW5x+5w3AiC9nMYUvS9eQ==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.8.1 diff --git a/config/clusters/jupyter-health/enc-support.secret.values.yaml b/config/clusters/jupyter-health/enc-support.secret.values.yaml new file mode 100644 index 0000000000..19a28346a6 --- /dev/null +++ b/config/clusters/jupyter-health/enc-support.secret.values.yaml @@ -0,0 +1,17 @@ +prometheusIngressAuthSecret: + username: ENC[AES256_GCM,data:3KOczS+romK4eNELpyBv6Tf4w1mjlIUC7M3v/ni2UXI/KIm3aYzZtxdphrI4fyUBkOrbIUeFQ3uEn12usvoLXg==,iv:Nz+wm18W9ihBIQ3Q/D62RdP4ituhYkEBIMC8JUKnH8w=,tag:pOhYeh6JOBUzb6U07baQBg==,type:str] + password: ENC[AES256_GCM,data:1XQxK8KgONw8LSelTaQWyxnG0HK8YgxSJscw5ay33fLoLinFsO2c3Pi8K3FGV6rQ+7sQD3T0vZar+4dvpJuOxA==,iv:KXpm3d9g04CUFTQ/T8ZWukiK3lRoRd4NPFWeD3OCW7M=,tag:IfTNS6dtVTgcBGk0S2ztLQ==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2024-03-27T02:49:45Z" + enc: CiUA4OM7eNHuKWwS9mCMAvaC+jgrMgx4DNQl4IADj65qOGD+4GnGEkkAXoW3JqR++Cg3n3xLzB37L4koPU0VXt0eTmF8Si4ILpYMf89WP8MSiG3KA5kEzEmknHUC8Z27cJz7MYR6x6U4JvQXXfS4TiG2 + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2024-03-27T02:49:46Z" + mac: ENC[AES256_GCM,data:kExXzURzp2c3DVDNycX5nMDD6dfiJ2Ysp89AfNfIdcFEG7OJufK4xKykD+4WHNqipHqspP36zxjtWeljdwNM1ElK0jy3mDPfX2Da99t3D5ORFHuc8lQXSW1klMEf3efmkrZyYtba1kqjClvXMjy7hyG219VNqYHM5O5N3/fk0iA=,iv:eC7YfoGBRGFGlbbx5MVVqRsD0+YYld2uOzjYsUCqEwo=,tag:Q0ShSiBkXICRTH/XrHbGag==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.8.1 diff --git a/config/clusters/jupyter-health/prod.values.yaml b/config/clusters/jupyter-health/prod.values.yaml new file mode 100644 index 0000000000..b1072a659c --- /dev/null +++ b/config/clusters/jupyter-health/prod.values.yaml @@ -0,0 +1,13 @@ +userServiceAccount: + annotations: + eks.amazonaws.com/role-arn: arn:aws:iam::211125465508:role/jupyter-health-prod +jupyterhub: + ingress: + hosts: [jupyter-health.2i2c.cloud] + tls: + - hosts: [jupyter-health.2i2c.cloud] + secretName: https-auto-tls + hub: + config: + GitHubOAuthenticator: + oauth_callback_url: https://jupyter-health.2i2c.cloud/hub/oauth_callback diff --git a/config/clusters/jupyter-health/staging.values.yaml b/config/clusters/jupyter-health/staging.values.yaml new file mode 100644 index 0000000000..0548bc2591 --- /dev/null +++ b/config/clusters/jupyter-health/staging.values.yaml @@ -0,0 +1,13 @@ +userServiceAccount: + annotations: + eks.amazonaws.com/role-arn: arn:aws:iam::211125465508:role/jupyter-health-staging +jupyterhub: + ingress: + hosts: [staging.jupyter-health.2i2c.cloud] + tls: + - hosts: [staging.jupyter-health.2i2c.cloud] + secretName: https-auto-tls + hub: + config: + GitHubOAuthenticator: + oauth_callback_url: https://staging.jupyter-health.2i2c.cloud/hub/oauth_callback diff --git a/config/clusters/jupyter-health/support.values.yaml b/config/clusters/jupyter-health/support.values.yaml new file mode 100644 index 0000000000..5f04305a83 --- /dev/null +++ b/config/clusters/jupyter-health/support.values.yaml @@ -0,0 +1,34 @@ +prometheusIngressAuthSecret: + enabled: true + +prometheus: + server: + ingress: + enabled: true + hosts: + - prometheus.jupyter-health.2i2c.cloud + tls: + - secretName: prometheus-tls + hosts: + - prometheus.jupyter-health.2i2c.cloud + +grafana: + grafana.ini: + server: + root_url: https://grafana.jupyter-health.2i2c.cloud/ + auth.github: + enabled: true + allowed_organizations: 2i2c-org + ingress: + hosts: + - grafana.jupyter-health.2i2c.cloud + tls: + - secretName: grafana-tls + hosts: + - grafana.jupyter-health.2i2c.cloud + +cluster-autoscaler: + enabled: true + autoDiscovery: + clusterName: jupyter-health + awsRegion: us-east-2 \ No newline at end of file diff --git a/eksctl/jupyter-health.jsonnet b/eksctl/jupyter-health.jsonnet new file mode 100644 index 0000000000..15c92f2622 --- /dev/null +++ b/eksctl/jupyter-health.jsonnet @@ -0,0 +1,128 @@ +/* + This file is a jsonnet template of a eksctl's cluster configuration file, + that is used with the eksctl CLI to both update and initialize an AWS EKS + based cluster. + + This file has in turn been generated from eksctl/template.jsonnet which is + relevant to compare with for changes over time. + + To use jsonnet to generate an eksctl configuration file from this, do: + + jsonnet jupyter-health.jsonnet > jupyter-health.eksctl.yaml + + References: + - https://eksctl.io/usage/schema/ +*/ +local ng = import "./libsonnet/nodegroup.jsonnet"; + +// place all cluster nodes here +local clusterRegion = "us-east-2"; +local masterAzs = ["us-east-2a", "us-east-2b", "us-east-2c"]; +local nodeAz = "us-east-2a"; + +// Node definitions for notebook nodes. Config here is merged +// with our notebook node definition. +// A `node.kubernetes.io/instance-type label is added, so pods +// can request a particular kind of node with a nodeSelector +local notebookNodes = [ + { instanceType: "r5.xlarge" }, + { instanceType: "r5.4xlarge" }, + { instanceType: "r5.16xlarge" }, +]; +local daskNodes = []; + + +{ + apiVersion: 'eksctl.io/v1alpha5', + kind: 'ClusterConfig', + metadata+: { + name: "jupyter-health", + region: clusterRegion, + version: "1.29", + }, + availabilityZones: masterAzs, + iam: { + withOIDC: true, + }, + // If you add an addon to this config, run the create addon command. + // + // eksctl create addon --config-file=jupyter-health.eksctl.yaml + // + addons: [ + { + // aws-ebs-csi-driver ensures that our PVCs are bound to PVs that + // couple to AWS EBS based storage, without it expect to see pods + // mounting a PVC failing to schedule and PVC resources that are + // unbound. + // + // Related docs: https://docs.aws.amazon.com/eks/latest/userguide/managing-ebs-csi.html + // + name: 'aws-ebs-csi-driver', + version: "latest", + wellKnownPolicies: { + ebsCSIController: true, + }, + }, + ], + nodeGroups: [ + ng + { + namePrefix: 'core', + nameSuffix: 'a', + nameIncludeInstanceType: false, + availabilityZones: [nodeAz], + ssh: { + publicKeyPath: 'ssh-keys/jupyter-health.key.pub' + }, + instanceType: "r5.xlarge", + minSize: 1, + maxSize: 6, + labels+: { + "hub.jupyter.org/node-purpose": "core", + "k8s.dask.org/node-purpose": "core" + }, + }, + ] + [ + ng + { + namePrefix: 'nb', + availabilityZones: [nodeAz], + minSize: 0, + maxSize: 500, + instanceType: n.instanceType, + ssh: { + publicKeyPath: 'ssh-keys/jupyter-health.key.pub' + }, + labels+: { + "hub.jupyter.org/node-purpose": "user", + "k8s.dask.org/node-purpose": "scheduler" + }, + taints+: { + "hub.jupyter.org_dedicated": "user:NoSchedule", + "hub.jupyter.org/dedicated": "user:NoSchedule" + }, + } + n for n in notebookNodes + ] + ( if daskNodes != null then + [ + ng + { + namePrefix: 'dask', + availabilityZones: [nodeAz], + minSize: 0, + maxSize: 500, + ssh: { + publicKeyPath: 'ssh-keys/jupyter-health.key.pub' + }, + labels+: { + "k8s.dask.org/node-purpose": "worker" + }, + taints+: { + "k8s.dask.org_dedicated" : "worker:NoSchedule", + "k8s.dask.org/dedicated" : "worker:NoSchedule" + }, + instancesDistribution+: { + onDemandBaseCapacity: 0, + onDemandPercentageAboveBaseCapacity: 0, + spotAllocationStrategy: "capacity-optimized", + }, + } + n for n in daskNodes + ] else [] + ) +} \ No newline at end of file diff --git a/eksctl/ssh-keys/jupyter-health.key.pub b/eksctl/ssh-keys/jupyter-health.key.pub new file mode 100644 index 0000000000..fb770024d6 --- /dev/null +++ b/eksctl/ssh-keys/jupyter-health.key.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDMcnpH3hDz/1CfgIKIY9BGDXWDAh2ae3xXV5/XZ4shwt3M9e2wIeiHVEaBLOxLneb2Ff2l9AQ/7bSRYvZFFMyCn0X/uYufZw8Zcp48GSEXE4MuhgxNx16oDgB4TF+sTfZjF/8FQDJSa6LROX9ASOiftk3qE+2KMF1/dEN6uTsyXuIj8BvioYMNKnJFwmm/0JMgyWnfFNnj35oXV9U/hO4i+1oRmpls32YIDon16svKP9K/LxOX0PVvUt6fEbCzV/tQ0P6Ht9KK8bobUdgEQEYkt4CnhaHv28WdJoHTkpOW31jfQGg0TFhYNQQyeJN4Lwi6JGw6hkyuMuVMKgIe70GNGMyRD4tJ+8eME/CTeK5MeiuWDSGOPKBNo0TfGcaQn5CX+x+slRgzsH653qIIRQJkSHuGve/5m8g+J2WwwtRhAWP0xPK+ZKC7x3LohoOfv259bcNR98bE730FjzM6I0uCkttZ7cKBRuKwi5xFFlX01G4xGgHI5nKd9AegcP2tTis= yuvipanda@instantaneous-authenticity.local diff --git a/terraform/aws/projects/jupyter-health.tfvars b/terraform/aws/projects/jupyter-health.tfvars new file mode 100644 index 0000000000..b0a8c30d2f --- /dev/null +++ b/terraform/aws/projects/jupyter-health.tfvars @@ -0,0 +1,26 @@ +region = "us-east-2" + +cluster_name = "jupyter-health" + +cluster_nodes_location = "us-east-2a" + +user_buckets = { + "scratch-staging" : { + "delete_after" : 7 + }, + "scratch" : { + "delete_after" : 7 + }, +} + + +hub_cloud_permissions = { + "staging" : { + bucket_admin_access : ["scratch-staging"], + extra_iam_policy : "" + }, + "prod" : { + bucket_admin_access : ["scratch"], + extra_iam_policy : "" + }, +} \ No newline at end of file