{"id":37655666,"url":"https://github.com/graydenshand/eks_jupyterhub","last_synced_at":"2026-01-16T11:41:15.606Z","repository":{"id":190489499,"uuid":"682722677","full_name":"graydenshand/eks_jupyterhub","owner":"graydenshand","description":"Jupyterhub on EKS","archived":false,"fork":false,"pushed_at":"2024-11-01T18:23:55.000Z","size":43,"stargazers_count":2,"open_issues_count":2,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-11-01T19:23:47.295Z","etag":null,"topics":["aws","cdk","eks","jupyterhub","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/graydenshand.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-08-24T19:31:58.000Z","updated_at":"2024-02-08T02:26:47.000Z","dependencies_parsed_at":"2024-04-19T02:24:58.139Z","dependency_job_id":"5da8dffb-24d4-48dd-b728-e212ffb24163","html_url":"https://github.com/graydenshand/eks_jupyterhub","commit_stats":null,"previous_names":["graydenshand/eks_jupyterhub"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/graydenshand/eks_jupyterhub","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graydenshand%2Feks_jupyterhub","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graydenshand%2Feks_jupyterhub/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graydenshand%2Feks_jupyterhub/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graydenshand%2Feks_jupyterhub/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/graydenshand","download_url":"https://codeload.github.com/graydenshand/eks_jupyterhub/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graydenshand%2Feks_jupyterhub/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28478353,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T06:30:42.265Z","status":"ssl_error","status_checked_at":"2026-01-16T06:30:16.248Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","cdk","eks","jupyterhub","python"],"created_at":"2026-01-16T11:41:15.050Z","updated_at":"2026-01-16T11:41:15.597Z","avatar_url":"https://github.com/graydenshand.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# eks_jupyterhub\n\nAn example Jupyterhub deployment on EKS.\n\nFor full details on configuration options and security best practices, please refer to the [Jupyterhub on Kubernetes \ndocumentation](https://z2jh.jupyter.org/en/stable/index.html).\n\n`cdk.py` includes a [Cloud Development Kit (CDK)](https://docs.aws.amazon.com/cdk/v2/guide/home.html) app that will \ncreate the following resources in your AWS account:\n* A VPC\n* A few Docker images in ECR\n* An EFS file system\n* An RDS Database\n* A few IAM roles\n* An autoscaling EKS cluster running Jupyterhub on between 1-15 nodes.\n\nThe `templates` directory contains jinja2 templated files for this deployment:\n\n- `config.yaml.j2` contains [Jupyterhub helm chart configurations](https://z2jh.jupyter.org/en/latest/resources/reference.html).\nIn addition to setting up the EFS file system and RDS database integration, it defines two profiles with different cpu and memory settings\nand creates a \"shared\" directory which all users can access.\n- `config_secrets.py.j2` is a python script that is executed while the hub container is starting. This script allows us\nto securely pass secret values to the jupyterhub config that otherwise would be exposed in the cloudformation template.\nSpecifically, it is used here to build the postgres connection string from the credentials in secretsmanager.\n\nThe `images` directory defines Dockerfiles used in the deployment.\n\n- Extending Jupyter's [datascience](https://hub.docker.com/r/jupyter/datascience-notebook) base image, `user.Dockerfile`\ninstalls four common extensions: [`jupyterlab-git`](https://pypi.org/project/jupyterlab-git/),\n[`ipython-sql`](https://pypi.org/project/ipython-sql/), [`voila`](https://pypi.org/project/voila/),\n[`jupyter-scheduler`](https://pypi.org/project/jupyter-scheduler/).\n- `hub.Dockerfile` extends jupyterhubs \"Hub\" base image, adding boto3 to the python environment to enable looking up\nsecret from AWS secretsmanager while starting.\n- `traefik.Dockerfile`, while developing this, I was getting some rate limit errors from Dockerhub. We publish\nthis image to AWS ECR to avoid those.\n\n**Autoscaling**\n\nThis application uses two autoscaling node groups. One for system containers (e.g. the Hub service, idle-culler, etc) and\none for user containers (actual end user jupyter sessions).\n\nThis is implemented using kubernetes cluster-autoscaler, with taints to associate specific containers and node groups.\nWhen a  user signs on and starts a session, if there is not sufficient capacity on the cluster for the requested\nresources, a new node is started. This can take a few minutes, which can be a bit painful for end users. There is a way\nto pre-emptively autoscale before resources are actually needed (called 'user placeholders'). This feature is spelled out\nin the z2jh docs (linked below), however I wasn't able to get it working. If I can get it working I will update this\nimplementation.\n\nTo learn more about this, please refer to the [z2jh docs on autoscaling](https://z2jh.jupyter.org/en/stable/administrator/optimization.html),\nand the [kubernetes autoscaler](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md) docs.\n\n## Dependencies\n\n* NodeJS \u0026 [`aws-cdk`](https://www.npmjs.com/package/aws-cdk)\n* Python\u003e=3.11\n* [PDM](https://pypi.org/project/pdm/)\n* [kubectl](https://kubernetes.io/docs/tasks/tools/) (optional, but recommended)\n\n## Installation\n\n```\npdm sync -G dev\n```\n\n## Deploy\n\nTo deploy the stack to the account your currently authenticated against, run:\n\n```\ncdk deploy 'Jupyterhub/*' -O output.json\n```\n\nView `output.json` to find the command to add the deployed cluster to your kubeconfig. You're looking for the \noutput named something like `K8sClusterConfigCommand7A4D6E5F`. Its value is the command you need to run, something like:\n\n```\naws eks update-kubeconfig --name K8sClusterA30C4AE4-abcefabcdef1234567812345678 --region us-east-1 --role-arn arn:aws:iam::XXXXXXXXX:role/EksJupyterhub-MastersRole0257C11B-8P2R1A12Q234Q1\n```\n\nOnce you've added the cluster to your kubeconfig, you can view your pods.\n```\n$ kubectl -n jupyterhub get pods\nNAME                              READY   STATUS    RESTARTS   AGE\ncontinuous-image-puller-xjgw7     1/1     Running             0          8s\nhub-7c4ddbf7b4-dwvwf              0/1     ContainerCreating   0          8s\nproxy-77dfcb58df-qcst2            1/1     Running             0          8s\nuser-scheduler-7574d67cdb-f89m2   1/1     Running             0          8s\nuser-scheduler-7574d67cdb-fgv9n   1/1     Running             0          8s\n```\n\nOnce all pods are running, you can view your jupyterhub deployment by going to the address found in your output.json.\nSpecifically you're looking for the output named `JupyterhubEndpoint`, it will look something like\n`abcd12345678fedcba87654321-1044896179.us-east-1.elb.amazonaws.com`.\n\nGo to that address in your web browser.\nE.g. http://abcd12345678fedcba87654321-1044896179.us-east-1.elb.amazonaws.com.\n\nOnce there, type in any username and password and you can lauch a user server and start creating notebooks.\n\n## Next Steps\n\n1. [Setting up Authentication](https://jupyterhub.readthedocs.io/en/stable/reference/authenticators.html)\n2. [Enabling HTTPS](https://z2jh.jupyter.org/en/latest/administrator/security.html#https)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgraydenshand%2Feks_jupyterhub","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgraydenshand%2Feks_jupyterhub","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgraydenshand%2Feks_jupyterhub/lists"}