diff --git a/.circleci/config.yml b/.circleci/config.yml index 0675240a9d..a664182417 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,7 +8,7 @@ jobs: # https://circleci.com/docs/2.0/arm-resources/#using-arm-resources test-arm: machine: - image: ubuntu-2004:202101-01 + image: ubuntu-2004:2022.04.1 resource_class: arm.medium steps: - checkout @@ -18,12 +18,22 @@ jobs: name: Check architecture - run: + # NOTE: we can't use k3s 1.24 and --docker unless we also install for + # example cri-dockerd as done in + # https://github.com/jupyterhub/action-k3s-helm. + # + # NOTE: we declare --egress-selector-mode=disabled to workaround + # intermittent issues in k3s introduced as a regression in k3s + # 1.22.10, 1.23.7, and 1.24.0. This is tracked in + # https://github.com/k3s-io/k3s/issues/5633. + # command: >- curl -sfL https://get.k3s.io | - INSTALL_K3S_CHANNEL=v1.20 sh -s - + INSTALL_K3S_CHANNEL=v1.23 sh -s - --disable metrics-server --disable traefik --docker + --egress-selector-mode=disabled name: Install K3S - run: @@ -40,20 +50,20 @@ jobs: pip3 install --no-cache-dir -r dev-requirements.txt name: Install dependencies - # TODO: test 'docker build' instead of buildx - # Ideally we'd use standard docker build since we're building for the native - # platform. Unfortunately the singleuser image can't be built on arm64, and the - # easiest way to skip this image is to use chartpress's --platform option, - # which is only supported with docker-buildx engine - run: command: | - chartpress --builder docker-buildx --platform linux/arm64 + export DOCKER_BUILDKIT=1 + chartpress name: Run chartpress - run: command: | export KUBECONFIG="$HOME/.kube/config" - helm upgrade --install jupyterhub ./jupyterhub --values dev-config.yaml --values dev-config-arm.yaml --wait + helm upgrade --install jupyterhub ./jupyterhub \ + --wait \ + --values dev-config.yaml \ + --values dev-config-arm.yaml \ + --values dev-config-local-chart-extra-config.yaml name: Install local chart - run: @@ -61,9 +71,29 @@ jobs: export KUBECONFIG="$HOME/.kube/config" export HUB_URL=http://localhost:30080 . ./ci/common - pytest --verbose --color=yes ./tests -m 'not netpol' + # Print out logs & definition info from all pods if the tests fail + pytest --verbose --color=yes ./tests -m 'not netpol' || \ + kubectl get pod -o name | \ + xargs -I {} /bin/bash -c \ + "echo Logs for {} && \ + kubectl get {} -o yaml && \ + kubectl describe {} && \ + kubectl logs --all-containers {} && \ + echo --------------------------------" name: Run tests + - run: + name: k8s namespace report + when: on_fail + command: | + export KUBECONFIG="$HOME/.kube/config" + wget https://raw.githubusercontent.com/jupyterhub/action-k8s-namespace-report/v1.1.0/k8s-namespace-report + bash k8s-namespace-report + environment: + NAMESPACE: "" + POD_SELECTOR: "" + IMPORTANT_WORKLOADS: "" + workflows: main: jobs: diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000000..08e2c862d1 --- /dev/null +++ b/.flake8 @@ -0,0 +1,7 @@ +[flake8] +# Ignore style and complexity +# E: style errors +# W: style warnings +# C: complexity +# D: docstring warnings (unused pydocstyle extension) +ignore = E, C, W, D diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index 81dbf0631a..40e0649746 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -1,47 +1,17 @@ -# dependabot.yml reference: https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/configuration-options-for-dependency-updates +# dependabot.yml reference: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file # # Notes: # - Status and logs from dependabot are provided at # https://github.com/jupyterhub/zero-to-jupyterhub-k8s/network/updates. # - YAML anchors are not supported here or in GitHub Workflows. -# - versioning-strategy: lockfile-only must not be used if you only have a plain -# requirements.txt like we do in images/singleuser-sample. -# - We explicitly set the "maintenance" label to help our changelog generator -# tool github-activity to categorize PRs. # - version: 2 updates: - # Maintain Python dependencies for the jupyterhub/k8s-hub image - - package-ecosystem: pip - directory: "/images/hub" - schedule: - interval: daily - time: "00:00" - timezone: "Etc/UTC" - versioning-strategy: lockfile-only - labels: - - maintenance - - dependencies - - # Maintain Python dependencies for the jupyterhub/k8s-singleuser-sample image - - package-ecosystem: pip - directory: "/images/singleuser-sample" - schedule: - interval: daily - time: "05:00" - timezone: "Etc/UTC" - labels: - - maintenance - - dependencies - # Maintain dependencies in our GitHub Workflows - - package-ecosystem: "github-actions" - directory: "/" # This should be / rather than .github/workflows + - package-ecosystem: github-actions + directory: / + labels: [ci] schedule: - interval: daily + interval: monthly time: "05:00" - timezone: "Etc/UTC" - labels: - - maintenance - - dependencies + timezone: Etc/UTC diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index bf56d31a34..2fb2b73f54 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,5 +1,5 @@ # This is a GitHub workflow defining a set of jobs with a set of steps. -# ref: https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions +# ref: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions # name: Publish @@ -7,18 +7,21 @@ name: Publish on: pull_request: paths-ignore: - - "doc/**" + - "docs/**" - "**.md" - ".github/workflows/*" - "!.github/workflows/publish.yaml" push: paths-ignore: - - "doc/**" + - "docs/**" - "**.md" - ".github/workflows/*" - "!.github/workflows/publish.yaml" branches-ignore: - "dependabot/**" + - "pre-commit-ci-update-config" + - "update-*" + - "vuln-scan-*" tags: - "**" @@ -28,53 +31,48 @@ jobs: # JupyterHub organization Helm chart repository. # # ref: https://github.com/jupyterhub/helm-chart - # ref: https://hub.docker.com/orgs/jupyterhub + # ref: https://quay.io/organization/jupyterhub publish: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: # chartpress requires git history to set chart version and image tags # correctly fetch-depth: 0 - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 with: - python-version: "3.8" + python-version: "3.11" - - name: store whether we are publishing the chart + - name: Decide to publish or not id: publishing shell: python - env: - REPO: ${{ github.repository }} - EVENT: ${{ github.event_name }} - REF: ${{ github.event.ref }} run: | import os - repo = os.environ["REPO"] - event = os.environ["EVENT"] - ref = os.environ["REF"] + repo = "${{ github.repository }}" + event = "${{ github.event_name }}" + ref = "${{ github.event.ref }}" publishing = "" if ( repo == "jupyterhub/zero-to-jupyterhub-k8s" and event == "push" and ( - # any tag ref.startswith("refs/tags/") - # or default branch or ref == "refs/heads/main" ) ): publishing = "true" print("Publishing chart") - print(f"::set-output name=publishing::{publishing}") + with open(os.environ["GITHUB_OUTPUT"], "a") as f: + f.write(f"publishing={publishing}\n") - name: Set up QEMU (for docker buildx) - uses: docker/setup-qemu-action@27d0a4f181a40b142cce983c5393082c365d1480 # dependabot updates to latest release + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx (for chartpress multi-arch builds) - uses: docker/setup-buildx-action@abe5d8f79a1606a2d3e218847032f3f2b1726ab0 # dependabot updates to latest release + uses: docker/setup-buildx-action@v3 - name: Install chart publishing dependencies (chartpress, helm) run: | @@ -110,7 +108,8 @@ jobs: # https://github.com/jupyterhub/zero-to-jupyterhub-k8s/settings/secrets/actions if: steps.publishing.outputs.publishing run: | - docker login -u "${{ secrets.DOCKER_USERNAME }}" -p "${{ secrets.DOCKER_PASSWORD }}" + docker login -u "${{ secrets.QUAY_USERNAME }}" -p "${{ secrets.QUAY_PASSWORD }}" quay.io + docker login -u "${{ secrets.DOCKER_USERNAME }}" -p "${{ secrets.DOCKER_PASSWORD }}" docker.io - name: Configure a git user # Having a user.email and user.name configured with git is required to @@ -123,7 +122,7 @@ jobs: - name: build chart with chartpress run: | - # Create values.schema.yaml from schema.yaml. + # Create values.schema.json from values.schema.yaml. ./tools/generate-json-schema.py # Append annotations to Chart.yaml with current images so that @@ -145,7 +144,7 @@ jobs: run: helm package jupyterhub # ref: https://github.com/actions/upload-artifact - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: steps.publishing.outputs.publishing == '' with: name: jupyterhub-${{ github.sha }} diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml new file mode 100644 index 0000000000..4327831409 --- /dev/null +++ b/.github/workflows/release-tag.yml @@ -0,0 +1,32 @@ +# Create a GitHub release whenever a tag is pushed. +# Tags that aren't in the form N.N.N are considered pre-releases. + +name: release-tag +on: + push: + tags: + - "**" + +jobs: + create-release: + runs-on: ubuntu-22.04 + permissions: + contents: write + steps: + # https://github.com/actions/github-script + # https://octokit.github.io/rest.js/v18#repos-create-release + - uses: actions/github-script@v6 + with: + script: | + if (!context.ref.startsWith('refs/tags/')) { + core.setFailed(`${context.ref} is not in the form refs/tags/$tag`) + } + const tag = context.ref.slice(10) + const prerelease = !tag.match(/\d+\.\d+\.\d+$/) + github.rest.repos.createRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + tag_name: tag, + prerelease: prerelease, + body: 'Please see the [changelog](https://zero-to-jupyterhub.readthedocs.io/en/latest/changelog.html) for details.' + }); diff --git a/.github/workflows/support-bot.yml b/.github/workflows/support-bot.yml new file mode 100644 index 0000000000..a65552ea36 --- /dev/null +++ b/.github/workflows/support-bot.yml @@ -0,0 +1,33 @@ +# https://github.com/dessant/support-requests +name: "Support Requests" + +on: + issues: + types: [labeled, unlabeled, reopened] + +permissions: + issues: write + +jobs: + action: + runs-on: ubuntu-22.04 + steps: + - uses: dessant/support-requests@v3 + with: + github-token: ${{ github.token }} + support-label: "support" + issue-comment: | + Hi there @{issue-author} :wave:! + + I closed this issue because it was labelled as a support question. + + Please help us organize discussion by posting this on the https://discourse.jupyter.org/ forum. If it's your first time posting + please read https://discourse.jupyter.org/t/getting-good-answers-to-your-questions/1825. + The more information you provide the more likely we can help you. + + Our goal is to sustain a positive experience for both users and developers. We use GitHub issues for specific discussions related to changing a repository's content, and let the forum be where we can more generally help and inspire each other. + + Thanks you for being an active member of our community! :heart: + close-issue: true + lock-issue: false + issue-lock-reason: "off-topic" diff --git a/.github/workflows/test-chart.yaml b/.github/workflows/test-chart.yaml index a5dc60130a..7655dbd2a2 100644 --- a/.github/workflows/test-chart.yaml +++ b/.github/workflows/test-chart.yaml @@ -1,5 +1,5 @@ # This is a GitHub workflow defining a set of jobs with a set of steps. -# ref: https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions +# ref: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions # name: Test chart @@ -9,35 +9,48 @@ name: Test chart on: pull_request: paths-ignore: - - "doc/**" + - "docs/**" - "**.md" - ".github/workflows/*" - "!.github/workflows/test-chart.yaml" push: paths-ignore: - - "doc/**" + - "docs/**" - "**.md" - ".github/workflows/*" - "!.github/workflows/test-chart.yaml" branches-ignore: - "dependabot/**" + - "pre-commit-ci-update-config" + - "update-*" + - "vuln-scan-*" workflow_dispatch: jobs: - lint_and_validate_rendered_templates: - runs-on: ubuntu-20.04 + lint_shell_scripts: + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 with: - python-version: "3.8" + python-version: "3.11" - name: Install dependencies - run: pip install chartpress yamllint + run: pip install pre-commit - - uses: pre-commit/action@v2.0.3 + - name: Run all stages including shellcheck (disabled by default) + run: pre-commit run --all --hook-stage manual + + lint_and_validate_rendered_templates: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 with: - extra_args: --config .pre-commit-config-shellcheck.yaml + python-version: "3.11" + + - name: Install dependencies + run: pip install chartpress yamllint - name: Lint and validate run: tools/templates/lint-and-validate.py @@ -47,7 +60,7 @@ jobs: continue-on-error: true lint_and_validate_templates_with_schema: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false @@ -64,10 +77,10 @@ jobs: - helm-version: v3.5.0 # minimal required version steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 with: - python-version: "3.8" + python-version: "3.11" - name: Install dependencies run: | @@ -101,7 +114,7 @@ jobs: continue-on-error: true test: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 timeout-minutes: 20 strategy: @@ -114,20 +127,17 @@ jobs: # # k3s-version: https://github.com/rancher/k3s/tags # k3s-channel: https://update.k3s.io/v1-release/channels + # include: - - k3s-channel: v1.21 - test: install - debuggable: debuggable - - k3s-channel: v1.20 + - k3s-channel: v1.29.0+k3s1 test: install - - k3s-channel: v1.19 - test: install - - k3s-channel: v1.18 # also test prePuller.hook + - k3s-channel: stable # also test hub-slim, and prePuller.hook test: install local-chart-extra-args: >- + --set hub.image.name=gcr.io/nii-ap-ops/k8s-hub --set prePuller.hook.enabled=true --set prePuller.hook.pullOnlyOnChanges=true - - k3s-channel: v1.17 # also test hub.existingSecret + - k3s-channel: v1.26 # also test hub.existingSecret test: install local-chart-extra-args: >- --set hub.existingSecret=test-hub-existing-secret @@ -135,34 +145,76 @@ jobs: --set hub.cookieSecret=bbbb2222 --set hub.config.CryptKeeper.keys[0]=cccc3333 create-k8s-test-resources: true - - # We run two upgrade tests where we first install an already released - # Helm chart version and then upgrades to the version we are now - # testing. We test upgrading from the latest stable version (like - # 1.2.3), and one from the latest dev version (like - # 1.2.3-n012.h1234abc). + # We run three upgrade tests where we first install an already released + # Helm chart version and then upgrade to the version we are now + # testing: + # - latest stable version (like 1.2.3) + # - latest dev version (like 1.2.3-0.dev.git.5810.hf475e7a4), + # - and an old version that requires a JupyterHub DB upgrade # # It can be very useful to see the "Helm diff" step's output from the # latest dev version. # - # The upgrade-from input should match the version information from - # https://jupyterhub.github.io/helm-chart/info.json - - k3s-channel: v1.19 + # The upgrade-from input should be a chart version, or match the version + # information from + # https://hub.jupyter.org/helm-chart/info.json + # + - k3s-channel: v1.25 test: upgrade upgrade-from: stable upgrade-from-extra-args: >- --set proxy.secretToken=aaaa1111 --set hub.cookieSecret=bbbb2222 --set hub.config.CryptKeeper.keys[0]=cccc3333 + --set hub.db.type=sqlite-pvc + --set singleuser.storage.type=dynamic + local-chart-extra-args: >- + --set hub.db.type=sqlite-pvc + --set singleuser.storage.type=dynamic create-k8s-test-resources: true -# - k3s-channel: v1.19 -# test: upgrade -# upgrade-from: dev -# upgrade-from-extra-args: >- -# --set proxy.secretToken=aaaa1111 + # v1.24はEOLとなっており、利用想定がないのでテストを除外する + # - k3s-channel: v1.24 + # test: upgrade + # upgrade-from: dev + # upgrade-from-extra-args: >- + # --set proxy.secretToken=aaaa1111 + # --set hub.db.type=sqlite-pvc + # --set singleuser.storage.type=dynamic + # local-chart-extra-args: >- + # --set hub.db.type=sqlite-pvc + # --set singleuser.storage.type=dynamic + # RCOSのリポジトリにjupyterhub chart version 2.0.0がないため、テストを除外する + # - k3s-channel: v1.23 + # test: upgrade + # # We're testing hub.db.upgrade with PostgreSQL so this version must be old + # # enough to require a DB upgrade + # upgrade-from: 2.0.0 + # upgrade-from-extra-args: >- + # --set proxy.secretToken=aaaa1111 + # --set hub.cookieSecret=bbbb2222 + # --set hub.config.CryptKeeper.keys[0]=cccc3333 + # --set hub.db.type=postgres + # --set hub.db.url=postgresql+psycopg2://postgres:postgres@postgresql:5432/jupyterhub + # --set singleuser.storage.type=dynamic + # local-chart-extra-args: >- + # --set hub.db.type=postgres + # --set hub.db.url=postgresql+psycopg2://postgres:postgres@postgresql:5432/jupyterhub + # --set singleuser.storage.type=dynamic + # --set hub.db.upgrade=true + # create-k8s-test-resources: true + # # https://artifacthub.io/packages/helm/bitnami/postgresql + # setup-postgresql-args: >- + # --version=11.6.13 + # --set auth.enablePostgresUser=true + # --set auth.postgresPassword=postgres + # --set auth.database=jupyterhub + # --set audit.logHostname=true + # --set audit.logConnections=true + # --set audit.logDisconnections=true + # --set audit.clientMinMessages=debug steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: # chartpress requires git history to set chart version and image tags # correctly @@ -172,28 +224,26 @@ jobs: # kubectl and helm # # ref: https://github.com/jupyterhub/action-k3s-helm/ - - uses: jupyterhub/action-k3s-helm@v1 + - uses: jupyterhub/action-k3s-helm@v3 with: k3s-channel: ${{ matrix.k3s-channel }} metrics-enabled: false traefik-enabled: false docker-enabled: true - # NOTE: actions/setup-python@v2 make use of a cache within the GitHub base - # environment and setup in a fraction of a second. - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 with: - python-version: "3.8" + python-version: "3.11" # Install a local ACME server to fill the role of Let's Encrypt (LE). We # do this as the HTTP challenge sent out by an ACME server must be able to # reach the ACME client in our autohttps pod. - name: Install local ACME server run: | - helm install pebble --repo https://jupyterhub.github.io/helm-chart/ pebble --values dev-config-pebble.yaml + helm install pebble --repo https://hub.jupyter.org/helm-chart/ pebble --values dev-config-pebble.yaml # Install CRD for Argo Rollouts - - name: Install Argo Aollouts + - name: Install Argo Rollouts run: | kubectl create namespace argo-rollouts kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml @@ -203,9 +253,10 @@ jobs: run: | pip3 install -r dev-requirements.txt chartpress + env: + DOCKER_BUILDKIT: "1" - # Generate values.schema.json from schema.yaml - - name: Generate values.schema.json from schema.yaml + - name: Generate values.schema.json from values.schema.yaml run: | tools/generate-json-schema.py @@ -213,47 +264,52 @@ jobs: # dedicated lint-and-validate-values.yaml config. - name: "Helm template --validate (with lint and validate config)" run: | - helm template --validate jupyterhub ./jupyterhub --values tools/templates/lint-and-validate-values.yaml + helm template --validate jupyterhub ./jupyterhub --values tools/templates/lint-and-validate-values.yaml ${{ matrix.helm-template-validate-extra-args }} # It is only needed at this point forward as this is when we install # jupyterhub and the autohttps pod is about to start, so for CI # performance we delayed this until now and did other things in between. - name: Await local ACME server - uses: jupyterhub/action-k8s-await-workloads@v1 + uses: jupyterhub/action-k8s-await-workloads@v2 with: timeout: 150 max-restarts: 1 + - name: "(Upgrade) Install PostgreSQL server chart" + if: matrix.setup-postgresql-args + run: | + . ./ci/common + helm install postgresql postgresql --repo=https://charts.bitnami.com/bitnami ${{ matrix.setup-postgresql-args }} + await_kubectl_rollout statefulset/postgresql + - name: "(Upgrade) Install ${{ matrix.upgrade-from }} chart" if: matrix.test == 'upgrade' run: | - . ./ci/common - UPGRADE_FROM_VERSION=$(curl -sS https://jupyterhub.github.io/helm-chart/info.json | jq -er '.jupyterhub.${{ matrix.upgrade-from }}') + # NOTE: We change the directory so jupyterhub the chart name won't be + # misunderstood as the local folder name. + # + # https://github.com/helm/helm/issues/9244 + cd ci + + if [ ${{ matrix.upgrade-from }} = stable ]; then + UPGRADE_FROM_VERSION=$(helm show chart --repo=https://rcosdp.github.io/CS-jhub-helm-chart/ jupyterhub | yq e '.version' -) + elif [ ${{ matrix.upgrade-from }} = dev ]; then + UPGRADE_FROM_VERSION=$(helm show chart --devel --repo=https://rcosdp.github.io/CS-jhub-helm-chart/ jupyterhub | yq e '.version' -) + else + UPGRADE_FROM_VERSION=${{ matrix.upgrade-from }} + fi echo "UPGRADE_FROM_VERSION=$UPGRADE_FROM_VERSION" >> $GITHUB_ENV echo "" echo "Installing already released jupyterhub version $UPGRADE_FROM_VERSION" - # FIXME: We change the directory so jupyterhub the chart name won't be - # misunderstood as the local folder name. - # - # https://github.com/helm/helm/issues/9244 - cd ci - helm install jupyterhub --repo https://jupyterhub.github.io/helm-chart/ jupyterhub --values ../dev-config-upstream.yaml --version=$UPGRADE_FROM_VERSION ${{ matrix.upgrade-from-extra-args }} + helm install jupyterhub --repo https://rcosdp.github.io/CS-jhub-helm-chart/ jupyterhub --values ../dev-config.yaml --version=$UPGRADE_FROM_VERSION ${{ matrix.upgrade-from-extra-args }} - name: "(Upgrade) Install helm diff" if: matrix.test == 'upgrade' run: | helm plugin install https://github.com/databus23/helm-diff - # ref: https://github.com/mikefarah/yq - - name: "(Upgrade) Install yq" - if: matrix.test == 'upgrade' - run: | - VERSION=v4.4.1 - wget https://github.com/mikefarah/yq/releases/download/$VERSION/yq_linux_amd64.tar.gz -qO - | tar xz - sudo mv yq_linux_amd64 /usr/bin/yq - - name: "(Upgrade) Helm diff ${{ matrix.upgrade-from }} chart with local chart" if: matrix.test == 'upgrade' run: | @@ -272,13 +328,15 @@ jobs: echo helm diff upgrade --install jupyterhub ./jupyterhub --values dev-config.yaml \ + --values dev-config-local-chart-extra-config.yaml \ + ${{ matrix.local-chart-extra-args }} \ --show-secrets \ --context=3 \ --post-renderer=ci/string-replacer.sh - name: "(Upgrade) Await ${{ matrix.upgrade-from }} chart" if: matrix.test == 'upgrade' - uses: jupyterhub/action-k8s-await-workloads@v1 + uses: jupyterhub/action-k8s-await-workloads@v2 with: timeout: 150 max-restarts: 1 @@ -297,14 +355,21 @@ jobs: - name: "Install local chart" run: | - helm upgrade --install jupyterhub ./jupyterhub --values dev-config.yaml ${{ matrix.local-chart-extra-args }} + helm upgrade --install jupyterhub ./jupyterhub \ + --values dev-config.yaml \ + --values dev-config-local-chart-extra-config.yaml \ + ${{ matrix.local-chart-extra-args }} - name: "Await local chart" - uses: jupyterhub/action-k8s-await-workloads@v1 + uses: jupyterhub/action-k8s-await-workloads@v2 with: timeout: 150 max-restarts: 1 + - name: "Sleep 60sec to await hub" + run: | + sleep 60 + - name: Await local chart cert acquisition run: | . ./ci/common @@ -315,7 +380,7 @@ jobs: run: | . ./ci/common # If you have problems with the tests add '--capture=no' to show stdout - pytest --verbose --maxfail=2 --color=yes ./tests + pytest --verbose --maxfail=2 --color=yes --capture=no ./tests # ref: https://github.com/jupyterhub/action-k8s-namespace-report - name: Kubernetes namespace report @@ -324,10 +389,7 @@ jobs: with: important-workloads: deploy/proxy - # WARNING: Only allow this for pull_request runs that doesn't contain - # sensitive information. - # - # action reference: https://github.com/mxschmitt/action-tmate@v3 - - name: To enter a SSH debugging session, read these logs - if: failure() && github.event_name == 'pull_request' && matrix.debuggable == 'debuggable' - uses: mxschmitt/action-tmate@v3 + - name: Debug PostgreSQL logs on failure + if: failure() && matrix.setup-postgresql-args + run: | + kubectl logs statefulset/postgresql diff --git a/.github/workflows/test-docker-build.yaml b/.github/workflows/test-docker-build.yaml index 74d6c6e708..366dfdfe19 100644 --- a/.github/workflows/test-docker-build.yaml +++ b/.github/workflows/test-docker-build.yaml @@ -1,5 +1,5 @@ # This is a GitHub workflow defining a set of jobs with a set of steps. -# ref: https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions +# ref: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions # name: Test docker multiarch build @@ -19,6 +19,9 @@ on: - ".github/workflows/test-docker-build.yaml" branches-ignore: - "dependabot/**" + - "pre-commit-ci-update-config" + - "update-*" + - "vuln-scan-*" workflow_dispatch: jobs: @@ -26,26 +29,26 @@ jobs: # - https://github.com/docker/build-push-action/blob/v2.3.0/docs/advanced/local-registry.md # - https://github.com/docker/build-push-action/blob/v2.3.0/docs/advanced/multi-platform.md build_images: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: # chartpress requires git history to set chart version and image tags # correctly fetch-depth: 0 - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 with: - python-version: "3.8" + python-version: "3.11" - name: Install chartpress run: pip install chartpress - name: Set up QEMU (for docker buildx) - uses: docker/setup-qemu-action@27d0a4f181a40b142cce983c5393082c365d1480 # dependabot updates to latest release + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx (for chartpress multi-arch builds) - uses: docker/setup-buildx-action@abe5d8f79a1606a2d3e218847032f3f2b1726ab0 # dependabot updates to latest release + uses: docker/setup-buildx-action@v3 - name: Build a multiple architecture Docker image run: >- diff --git a/.github/workflows/test-docs.yaml b/.github/workflows/test-docs.yaml index 91f0033150..4986b5d065 100644 --- a/.github/workflows/test-docs.yaml +++ b/.github/workflows/test-docs.yaml @@ -1,5 +1,5 @@ # This is a GitHub workflow defining a set of jobs with a set of steps. -# ref: https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions +# ref: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions # name: Test docs @@ -8,35 +8,43 @@ name: Test docs on: pull_request: paths: - - "doc/**" - - "**/schema.yaml" + - "docs/**" + - "**/values.schema.yaml" - "**/test-docs.yaml" push: paths: - - "doc/**" - - "**/schema.yaml" + - "docs/**" + - "**/values.schema.yaml" - "**/test-docs.yaml" branches-ignore: - "dependabot/**" + - "pre-commit-ci-update-config" + - "update-*" + - "vuln-scan-*" workflow_dispatch: jobs: linkcheck: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: - # chartpress, used by doc/conf.py, requires git history to set + # chartpress, used by docs/conf.py, requires git history to set # chart version and image tags correctly fetch-depth: 0 - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 with: - python-version: "3.8" + python-version: "3.11" - name: Install deps - run: pip install -r doc/requirements.txt + run: pip install -r docs/requirements.txt - name: make linkcheck run: | - cd doc + cd docs make linkcheck SPHINXOPTS='--color -W --keep-going' + + - name: summarise linkcheck issues + if: always() + run: | + ./ci/summarise-linkcheck-output ./docs/_build/linkcheck/output.json diff --git a/.github/workflows/vuln-scan.yaml b/.github/workflows/vuln-scan.yaml index 360645d5cf..c7acb67b33 100644 --- a/.github/workflows/vuln-scan.yaml +++ b/.github/workflows/vuln-scan.yaml @@ -1,28 +1,39 @@ # This is a GitHub workflow defining a set of jobs with a set of steps. -# ref: https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions +# ref: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions # # This workflow use aquasecurity/trivy to scan the images we have published for # known vulnerabilities. If there are such that can be patched, we let this # workflow fail to signal that unless we make an exception, which we do for the # singleuser-sample image only. # +# +# About environment: watch-dependencies +# +# To reduce the exposure of the secrets.jupyterhub_bot_pat token that was setup +# for the environment watch-dependencies, we have setup a dedicated environment +# according to steps in +# https://github.com/jupyterhub/team-compass/issues/516#issuecomment-1129961954. +# name: Vuln. scan on: + pull_request: + paths: + - ".github/workflows/vuln-scan.yaml" + push: + paths: + - ".github/workflows/vuln-scan.yaml" + branches: ["main"] schedule: - # At 00:00 - https://crontab.guru - - cron: "0 0 * * *" + # At 05:00 on Monday - https://crontab.guru + - cron: "0 5 * * 1" workflow_dispatch: jobs: trivy_image_scan: if: github.repository == 'jupyterhub/zero-to-jupyterhub-k8s' - runs-on: ubuntu-20.04 - # Write permissions granted for the peter-evans/create-pull-request action - # to push to a branch and create/update a PR - permissions: - contents: write - pull-requests: write + runs-on: ubuntu-22.04 + environment: watch-dependencies strategy: fail-fast: false @@ -37,25 +48,22 @@ jobs: - image_ref: image-awaiter accept_failure: false - image_ref: singleuser-sample - accept_failure: true + accept_failure: false steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: # chartpress requires git history to set chart version and image tags # correctly fetch-depth: 0 - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 with: - python-version: "3.8" + python-version: "3.11" - name: Install chartpress run: | - # FIXME: six is required by docker 5.0.0 but isn't explicitly required - # https://github.com/docker/docker-py/issues/2807 - # - pip install chartpress six + pip install chartpress # charpress --list-images output lines of name:tag format. We use it with # a search string in matrix.image_ref to find the specific image to scan @@ -69,9 +77,9 @@ jobs: ) echo "Identified image: $IMAGE_SPEC" - echo "::set-output name=spec::$IMAGE_SPEC" - echo "::set-output name=name::$(echo $IMAGE_SPEC | sed 's/\(.*\):.*/\1/')" - echo "::set-output name=tag::$(echo $IMAGE_SPEC | sed 's/.*:\(.*\)/\1/')" + echo "spec=$IMAGE_SPEC" >> $GITHUB_OUTPUT + echo "name=$(echo $IMAGE_SPEC | sed 's/\(.*\):.*/\1/')" >> $GITHUB_OUTPUT + echo "tag=$(echo $IMAGE_SPEC | sed 's/.*:\(.*\)/\1/')" >> $GITHUB_OUTPUT - name: Create ./tmp dir run: mkdir ./tmp @@ -79,7 +87,7 @@ jobs: # Action reference: https://github.com/aquasecurity/trivy-action - name: Scan latest published image id: scan_1 - uses: aquasecurity/trivy-action@8eccb5539730451af599c84f444c6d6cf0fc2bb0 + uses: aquasecurity/trivy-action@f78e9ecf42a1271402d4f484518b9313235990e1 with: image-ref: ${{ steps.image.outputs.spec }} format: json # ref: https://github.com/aquasecurity/trivy#save-the-results-as-json @@ -96,13 +104,15 @@ jobs: - name: Rebuild image id: rebuild if: steps.scan_1.outcome == 'failure' + env: + DOCKER_BUILDKIT: "1" run: | docker build -t rebuilt-image images/${{ matrix.image_ref }} - name: Scan rebuilt image id: scan_2 if: steps.rebuild.outcome == 'success' - uses: aquasecurity/trivy-action@8eccb5539730451af599c84f444c6d6cf0fc2bb0 + uses: aquasecurity/trivy-action@f78e9ecf42a1271402d4f484518b9313235990e1 with: image-ref: rebuilt-image format: json # ref: https://github.com/aquasecurity/trivy#save-the-results-as-json @@ -116,11 +126,11 @@ jobs: id: analyze if: steps.rebuild.outcome == 'success' run: | - echo "::set-output name=utc_time::$(date --utc +'%F_%T')" + echo "utc_time=$(date --utc +'%F_%T')" >> $GITHUB_OUTPUT json_to_misc() { # Count vulnerabilities - VULNERABILITY_COUNT="$(cat tmp/scan_$1.json | jq -r '[.[].Vulnerabilities | select(type != null)] | add | select(. != null) | length')" + VULNERABILITY_COUNT="$(cat tmp/scan_$1.json | jq -r '[.Results[].Vulnerabilities | select(type != null)] | add | select(. != null) | length')" echo "VULNERABILITY_COUNT_$1=$VULNERABILITY_COUNT" >> $GITHUB_ENV # Construct a markdown summary @@ -129,22 +139,22 @@ jobs: else echo "Target | Vuln. ID | Package Name | Installed v. | Fixed v." >> tmp/md_summary_$1.md echo "-|-|-|-|-" >> tmp/md_summary_$1.md - cat tmp/scan_$1.json | jq -r '.[] | select(.Vulnerabilities != null) | .Type + " | " + (.Vulnerabilities[] | .VulnerabilityID + " | " + .PkgName + " | " + .InstalledVersion + " | " + .FixedVersion)' | sort >> tmp/md_summary_$1.md + cat tmp/scan_$1.json | jq -r '.Results[] | select(.Vulnerabilities != null) | .Type + " | " + (.Vulnerabilities[] | .VulnerabilityID + " | " + .PkgName + " | " + .InstalledVersion + " | " + .FixedVersion)' | sort >> tmp/md_summary_$1.md fi - # Use hack to set a multiline string output - # ref: https://github.com/actions/toolkit/issues/403#issue-593398879 - TMP=$(cat tmp/md_summary_$1.md) - TMP="${TMP//'%'/'%25'}" - TMP="${TMP//$'\n'/'%0A'}" - TMP="${TMP//$'\r'/'%0D'}" - echo "::set-output name=md_summary_$1::$TMP" + # Set a multiline string output with the following technique: + # ref: https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings + # + eof_marker=EOF_$RANDOM + echo "md_summary_$1<<$eof_marker" >> $GITHUB_OUTPUT + cat tmp/md_summary_$1.md >> $GITHUB_OUTPUT + echo "$eof_marker" >> $GITHUB_OUTPUT # Calculate a hash of the markdown summary HASH=$(cat tmp/md_summary_$1.md | sha1sum) HASH=${HASH:0:10} export HASH_$1=$HASH - echo "::set-output name=hash_$1::$HASH" + echo "hash_$1=$HASH" >> $GITHUB_OUTPUT } json_to_misc 1 @@ -152,16 +162,16 @@ jobs: # Did rebuilding the image change anything? if [ "$HASH_1" == "$HASH_2" ]; then - echo "::set-output name=proceed::no" + echo "proceed=no" >> $GITHUB_OUTPUT echo "No vulnerabilities were patched by rebuilding the image - won't proceed!" else - echo "::set-output name=proceed::yes" + echo "proceed=yes" >> $GITHUB_OUTPUT echo "Vulnerabilities were patched by rebuilding the image - will proceed!" fi - name: Describe vulnerabilities if: steps.rebuild.outcome == 'success' - uses: aquasecurity/trivy-action@8eccb5539730451af599c84f444c6d6cf0fc2bb0 + uses: aquasecurity/trivy-action@f78e9ecf42a1271402d4f484518b9313235990e1 with: image-ref: rebuilt-image format: table @@ -186,17 +196,20 @@ jobs: file_to_update="images/${{ matrix.image_ref }}/Dockerfile" sed --in-place "s/\(#.*VULN_SCAN_TIME=\)\(.*\)/\1${value_to_set}/" "$file_to_update" + git --no-pager diff --color=always + # The create-pull-request action is smart enough to only create/update a # PR if there is a change to anything not .gitignored. A change will be # made only if the analyze steps outputted hash is changed. # # ref: https://github.com/peter-evans/create-pull-request - name: Create or update a PR - if: steps.analyze.outputs.proceed == 'yes' - uses: peter-evans/create-pull-request@7380612b49221684fefa025244f2ef4008ae50ad + if: steps.analyze.outputs.proceed == 'yes' && github.event_name != 'pull_request' + uses: peter-evans/create-pull-request@v5 with: - token: "${{ secrets.GITHUB_TOKEN }}" - author: jupyterhub vuln-scan bot + token: "${{ secrets.jupyterhub_bot_pat }}" + author: JupterHub Bot Account <105740858+jupyterhub-bot@users.noreply.github.com> + committer: JupterHub Bot Account <105740858+jupyterhub-bot@users.noreply.github.com> reviewers: consideratio branch: vuln-scan-${{ matrix.image_ref }} title: Vulnerability patch in ${{ matrix.image_ref }} diff --git a/.github/workflows/watch-dependencies.yaml b/.github/workflows/watch-dependencies.yaml new file mode 100644 index 0000000000..635acc360c --- /dev/null +++ b/.github/workflows/watch-dependencies.yaml @@ -0,0 +1,230 @@ +# This is a GitHub workflow defining a set of jobs with a set of steps. +# ref: https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions +# +# - Watch multiple images tags referenced in values.yaml to match the latest +# image tag. +# +# - Watch the jupyterhub pinning in images/*/requirements.in to match the +# latest jupyterhub version available on PyPI, and if doing this, also +# refreeze images/*/requirements.txt. +# +# About environment: watch-dependencies +# +# To reduce the exposure of the secrets.jupyterhub_bot_pat token that was setup +# for the environment watch-dependencies, we have setup a dedicated environment +# according to steps in +# https://github.com/jupyterhub/team-compass/issues/516#issuecomment-1129961954. +# +name: Watch dependencies + +on: + push: + paths: + - "images/*/requirements.in" + - ".github/workflows/watch-dependencies.yaml" + branches: ["main"] + schedule: + # Run at 05:00 every day, ref: https://crontab.guru/#0_5_*_*_* + - cron: "0 5 * * *" + workflow_dispatch: + +jobs: + update-image-dependencies: + # Don't run this job on forks + if: github.repository == 'jupyterhub/zero-to-jupyterhub-k8s' + runs-on: ubuntu-22.04 + environment: watch-dependencies + + strategy: + fail-fast: false + matrix: + include: + - name: chp + registry: registry.hub.docker.com + repository: jupyterhub/configurable-http-proxy + values_path: proxy.chp.image.tag + version_startswith: "" + version_patch_regexp_group_suffix: "" + + # traefik made us need to introduce version_patch_regexp_group_suffix + # to control if we accept omitting the patch version. The traefik + # image provides tags like 2.7 even though 2.7.0 hasn't been released, + # which makes bumping to it something we don't want to do. We still + # need to accept major.minor formatted tags though as the pause image + # has them. + # + - name: traefik + registry: registry.hub.docker.com + repository: library/traefik + values_path: proxy.traefik.image.tag + version_startswith: "" + version_patch_regexp_group_suffix: "" + + # kube-scheduler should be pinned to its minor version as bumping it + # will require manual interventions sometimes, see the notes in + # values.yaml about bumping its version. + # + - name: kube-scheduler + registry: registry.k8s.io + repository: kube-scheduler + values_path: scheduling.userScheduler.image.tag + version_startswith: "v1.26" + version_patch_regexp_group_suffix: "" + + - name: pause + registry: registry.k8s.io + repository: pause + values_path: scheduling.userPlaceholder.image.tag + version_startswith: "" + version_patch_regexp_group_suffix: "?" + + steps: + - uses: actions/checkout@v4 + + - name: Get values.yaml pinned tag of ${{ matrix.registry }}/${{ matrix.repository }} + id: local + run: | + local_tag=$(cat jupyterhub/values.yaml | yq e '.${{ matrix.values_path }}' -) + echo "tag=$local_tag" >> $GITHUB_OUTPUT + + - name: Get latest tag of ${{ matrix.registry }}/${{ matrix.repository }} + id: latest + # The skopeo image helps us list tags consistently from different docker + # registries. We use jq to filter out tags of the x.y or x.y.z format + # with the optional v prefix or version_startswith filter, and then sort + # based on the numerical x, y, and z values. Finally, we pick the last + # value in the list. + # + run: | + latest_tag=$( + docker run --rm quay.io/skopeo/stable list-tags docker://${{ matrix.registry }}/${{ matrix.repository }} \ + | jq -r '[.Tags[] | select(. | match("^v?\\d+\\.\\d+(\\.\\d+)${{ matrix.version_patch_regexp_group_suffix }}$") | .string | startswith("${{ matrix.version_startswith }}"))] | sort_by(split(".") | map(tonumber? // (.[1:] | tonumber))) | last' + ) + echo "tag=$latest_tag" >> $GITHUB_OUTPUT + + - name: Update values.yaml pinned tag + if: steps.local.outputs.tag != steps.latest.outputs.tag + run: | + sed --in-place 's/tag: "${{ steps.local.outputs.tag }}"/tag: "${{ steps.latest.outputs.tag }}"/g' jupyterhub/values.yaml + + - name: git diff + if: steps.local.outputs.tag != steps.latest.outputs.tag + run: git --no-pager diff --color=always + + # ref: https://github.com/peter-evans/create-pull-request + - name: Create a PR + if: steps.local.outputs.tag != steps.latest.outputs.tag + uses: peter-evans/create-pull-request@v5 + with: + token: "${{ secrets.jupyterhub_bot_pat }}" + author: JupterHub Bot Account <105740858+jupyterhub-bot@users.noreply.github.com> + committer: JupterHub Bot Account <105740858+jupyterhub-bot@users.noreply.github.com> + branch: update-image-${{ matrix.name }} + labels: maintenance,dependencies + commit-message: Update ${{ matrix.repository }} version from ${{ steps.local.outputs.tag }} to ${{ steps.latest.outputs.tag }} + title: Update ${{ matrix.repository }} version from ${{ steps.local.outputs.tag }} to ${{ steps.latest.outputs.tag }} + body: >- + A new ${{ matrix.repository }} image version has been detected, version + `${{ steps.latest.outputs.tag }}`. + + update-jupyterhub-dependencies: + # Don't run this job on forks + if: github.repository == 'jupyterhub/zero-to-jupyterhub-k8s' + runs-on: ubuntu-20.04 + environment: watch-dependencies + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + with: + python-version: "3.11" + + - name: Install Python dependencies + run: pip install packaging requests + + - name: Get images/hub/requirements.in pinned version of jupyterhub + id: local + run: | + local_version=$(cat images/hub/requirements.in | grep 'jupyterhub==' | sed 's/jupyterhub==//') + echo "version=$local_version" >> $GITHUB_OUTPUT + + - name: Get latest version of jupyterhub + id: latest + shell: python + run: | + import os + import packaging.version + import requests + + request = requests.get("https://pypi.org/pypi/jupyterhub/json") + data = request.json() + releases = data["releases"] + latest_version = sorted(releases.keys(), key=packaging.version.Version)[-1] + + with open(os.environ["GITHUB_OUTPUT"], "a") as f: + f.write(f"version={latest_version}\n") + + - name: Update pinned version of jupyterhub + if: steps.local.outputs.version != steps.latest.outputs.version + run: | + for img in hub singleuser-sample; do + sed --in-place 's/jupyterhub==${{ steps.local.outputs.version }}/jupyterhub==${{ steps.latest.outputs.version }}/g' images/$img/requirements.in + done + sed --in-place 's/appVersion: "${{ steps.local.outputs.version }}"/appVersion: "${{ steps.latest.outputs.version }}"/g' jupyterhub/Chart.yaml + + - name: Refreeze images/*/requirements.txt based on images/*/requirements.in + if: steps.local.outputs.version != steps.latest.outputs.version + run: ci/refreeze + + - name: git diff + if: steps.local.outputs.version != steps.latest.outputs.version + run: git --no-pager diff --color=always + + # ref: https://github.com/peter-evans/create-pull-request + - name: Create a PR + if: steps.local.outputs.version != steps.latest.outputs.version + uses: peter-evans/create-pull-request@v5 + with: + token: "${{ secrets.jupyterhub_bot_pat }}" + author: JupterHub Bot Account <105740858+jupyterhub-bot@users.noreply.github.com> + committer: JupterHub Bot Account <105740858+jupyterhub-bot@users.noreply.github.com> + branch: update-jupyterhub + labels: maintenance,dependencies + commit-message: Update jupyterhub from ${{ steps.local.outputs.version }} to ${{ steps.latest.outputs.version }} + title: Update jupyterhub from ${{ steps.local.outputs.version }} to ${{ steps.latest.outputs.version }} + body: >- + A new jupyterhub version has been detected, version + `${{ steps.latest.outputs.version }}`. + + refreeze-dockerfile-requirements-txt: + # Don't run this job on forks, but also not on the daily schedule to reduce + # noise. If we could run this weekly that would be reasonable, but updating + # these dependencies every day is too much noise. + # + if: github.repository == 'jupyterhub/zero-to-jupyterhub-k8s' && github.event_name != 'schedule' + runs-on: ubuntu-22.04 + environment: watch-dependencies + + steps: + - uses: actions/checkout@v4 + + - name: Refreeze images/*/requirements.txt based on images/*/requirements.in + run: ci/refreeze + + - name: git diff + run: git --no-pager diff --color=always + + # ref: https://github.com/peter-evans/create-pull-request + - name: Create a PR + uses: peter-evans/create-pull-request@v5 + with: + token: "${{ secrets.jupyterhub_bot_pat }}" + author: JupyterHub Bot Account <105740858+jupyterhub-bot@users.noreply.github.com> + committer: JupyterHub Bot Account <105740858+jupyterhub-bot@users.noreply.github.com> + branch: update-image-requirements + labels: dependencies + commit-message: "hub image: refreeze requirements.txt" + title: "hub image: refreeze requirements.txt" + body: >- + The hub image's requirements.txt has been refrozen based on + requirements.in. diff --git a/.gitignore b/.gitignore index bf073fb275..805555eee8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,17 @@ -### Zero to JupyterHub Kubernetes ### +### Repository specific files that are generated + jupyterhub/values.schema.json +docs/source/resources/reference.md tools/templates/rendered-templates/ -bin/ -.vagrant/ -tools/github.sqlite ci/ephemeral* tmp/ + +### Other misc things + .vscode -### macOS ### +### macOS *.DS_Store .AppleDouble .LSOverride @@ -33,23 +35,17 @@ Network Trash Folder Temporary Items .apdisk -### Vim ### +### Vim + # swap [._]*.s[a-w][a-z] [._]s[a-w][a-z] # session Session.vim -# temporary -.netrwhist -*~ -# auto-generated tag files -tags -# GCloud Credentials -data8-travis-creds.json -#### Python .gitignore from https://github.com/github/gitignore/blob/HEAD/Python.gitignore -#### +### Python .gitignore from https://github.com/github/gitignore/blob/HEAD/Python.gitignore + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] @@ -60,9 +56,6 @@ __pycache__/ # Distribution / packaging .Python -env/ -bin/kubectl -bin/minikube build/ develop-eggs/ dist/ @@ -75,9 +68,11 @@ parts/ sdist/ var/ wheels/ +share/python-wheels/ *.egg-info/ .installed.cfg *.egg +MANIFEST # PyInstaller # Usually these files are written by a python script from a template @@ -92,13 +87,17 @@ pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ +.nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml -*,cover +*.cover +*.py,cover .hypothesis/ +.pytest_cache/ +cover/ # Translations *.mo @@ -107,6 +106,8 @@ coverage.xml # Django stuff: *.log local_settings.py +db.sqlite3 +db.sqlite3-journal # Flask stuff: instance/ @@ -116,42 +117,84 @@ instance/ .scrapy # Sphinx documentation -doc/build/ -doc/source/reference/reference.md -doc/source/resources/reference.md +docs/_build/ # PyBuilder +.pybuilder/ target/ +# Jupyter Notebook .ipynb_checkpoints -# pyenv -.python-version +# IPython +profile_default/ +ipython_config.py -# celery beat schedule file +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff celerybeat-schedule +celerybeat.pid -# dotenv -.env +# SageMath parsed files +*.sage.py -# virtualenv +# Environments +.env .venv +env/ venv/ ENV/ -lib64 -pip-selfcheck.json -pyvenv.cfg +env.bak/ +venv.bak/ # Spyder project settings .spyderproject +.spyproject # Rope project settings .ropeproject -# Mac -.DS_STORE +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ -# Emacs -.#* +# Cython debug symbols +cython_debug/ -.idea +# PyCharm +# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ diff --git a/.pre-commit-config-shellcheck.yaml b/.pre-commit-config-shellcheck.yaml deleted file mode 100644 index 68a0c352f2..0000000000 --- a/.pre-commit-config-shellcheck.yaml +++ /dev/null @@ -1,6 +0,0 @@ -# See .pre-commit-config.yaml for more details. -repos: - - repo: https://github.com/gruntwork-io/pre-commit - rev: v0.1.12 - hooks: - - id: shellcheck diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3f295bdb8f..f4c3222be2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,30 +16,69 @@ # # https://github.com/koalaman/shellcheck#installing # -# pre-commit run --config .pre-commit-config-shellcheck.yaml --all-files +# pre-commit run --hook-stage=manual shellcheck --all-files # repos: + # Autoformat: Python code, syntax patterns are modernized + - repo: https://github.com/asottile/pyupgrade + rev: v3.15.0 + hooks: + - id: pyupgrade + args: + - --py38-plus + # Autoformat: Python code - repo: https://github.com/psf/black - rev: 21.8b0 + rev: 23.10.1 hooks: - id: black - args: [--target-version=py36] + args: + - --target-version=py38 + - --target-version=py39 + - --target-version=py310 + - --target-version=py311 + - --target-version=py312 + + # Autoformat: Python code + - repo: https://github.com/pycqa/isort + rev: 5.12.0 + hooks: + - id: isort + args: + - --profile=black # Autoformat: Bash scripts - repo: https://github.com/lovesegfault/beautysh - rev: v6.1.0 + rev: v6.2.1 hooks: - id: beautysh # Autoformat: markdown, yaml (but not helm templates) - repo: https://github.com/pre-commit/mirrors-prettier - rev: v2.3.2 + rev: v3.0.3 hooks: - id: prettier # Reset Chart.yaml version and values.yaml image tags - repo: https://github.com/jupyterhub/chartpress - rev: 1.3.0 + rev: 2.1.0 hooks: - id: chartpress + + # Linting: Python code (see the file .flake8) + - repo: https://github.com/PyCQA/flake8 + rev: "6.1.0" + hooks: + - id: flake8 + + - repo: https://github.com/gruntwork-io/pre-commit + rev: v0.1.22 + hooks: + # This requires shellcheck to be installed manually so is disabled by default + - id: shellcheck + stages: + - manual + +# pre-commit.ci config reference: https://pre-commit.ci/#configuration +ci: + autoupdate_schedule: monthly diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000000..66af176525 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,17 @@ +# Configuration on how ReadTheDocs (RTD) builds our documentation +# ref: https://readthedocs.org/projects/zero-to-jupyterhub/ +# ref: https://docs.readthedocs.io/en/stable/config-file/v2.html +# +version: 2 + +sphinx: + configuration: docs/source/conf.py + +build: + os: ubuntu-22.04 + tools: + python: "3.10" + +python: + install: + - requirements: docs/requirements.txt diff --git a/.readthedocs.yml b/.readthedocs.yml deleted file mode 100644 index 80d78e4d2d..0000000000 --- a/.readthedocs.yml +++ /dev/null @@ -1,25 +0,0 @@ -# Configuration on how ReadTheDocs (RTD) builds our documentation -# ref: https://readthedocs.org/projects/zero-to-jupyterhub/ -# ref: https://docs.readthedocs.io/en/stable/config-file/v2.html - -# Required (RTD configuration version) -version: 2 - -# Build documentation in the docs/ directory with Sphinx -sphinx: - configuration: doc/source/conf.py - -# Optionally build your docs in additional formats such as PDF and ePub -formats: [] - -# Optionally set the version of Python and requirements required to build your docs -python: - version: 3.7 - install: - # WARNING: This requirements file will be installed without the pip - # --upgrade flag in an existing environment. This means that if a - # package is specified without a lower boundary, we may end up - # accepting the existing version. - # - # ref: https://github.com/readthedocs/readthedocs.org/blob/0e3df509e7810e46603be47d268273c596e68455/readthedocs/doc_builder/python_environments.py#L335-L344 - - requirements: doc/requirements.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e48466997..00df2789af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3262 +1 @@ -# Changelog - -Here you can find upgrade changes in between releases and upgrade instructions. - -## UNRELEASED - -## [1.1] - -### [1.1.3] - 2021-08-25 - -## Maintenance and upkeep improvements - -- refactor: remove redundant trimSuffix of new lines after toYaml [#2358](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2358) ([@consideRatio](https://github.com/consideRatio)) -- build(deps): bump pycurl from 7.44.0 to 7.44.1 in /images/hub [#2352](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2352) ([@dependabot](https://github.com/dependabot)) -- build(deps): bump oauthenticator from 14.1.0 to 14.2.0 in /images/hub [#2350](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2350) ([@dependabot](https://github.com/dependabot)) -- build(deps): bump pycurl from 7.43.0.6 to 7.44.0 in /images/hub [#2347](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2347) ([@dependabot](https://github.com/dependabot)) - -## Documentation improvements - -- Add docs on GitHub team authentication [#2349](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2349) ([@j0nnyr0berts](https://github.com/j0nnyr0berts)) - -## Contributors to this release - -([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2021-08-05&to=2021-08-24&type=c)) - -[@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2021-08-05..2021-08-24&type=Issues) | [@j0nnyr0berts](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aj0nnyr0berts+updated%3A2021-08-05..2021-08-24&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2021-08-05..2021-08-24&type=Issues) - -### [1.1.2] - 2021-08-05 - -#### Bugs fixed - -- fix schema: hub.templateVars didn't accept configuration [#2343](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2343) ([@MridulS](https://github.com/MridulS)) - -#### Documentation improvements - -- docs: fix weird helm upgrade example [#2331](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2331) ([@hiroki-sawano](https://github.com/hiroki-sawano)) - -#### Contributors to this release - -([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2021-07-22&to=2021-08-05&type=c)) - -[@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2021-07-22..2021-08-05&type=Issues) | [@hiroki-sawano](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ahiroki-sawano+updated%3A2021-07-22..2021-08-05&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2021-07-22..2021-08-05&type=Issues) | [@MridulS](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AMridulS+updated%3A2021-07-22..2021-08-05&type=Issues) - -### [1.1.1] - 2021-07-22 - -#### Bugs fixed - -- fix hub.services schema regression from 1.1.0 [#2327](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2327) ([@consideRatio](https://github.com/consideRatio)) - -#### Continuous integration improvements - -- ci: misc fixes post 1.1.0 [#2326](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2326) ([@consideRatio](https://github.com/consideRatio)) - -### [1.1.0] - 2021-07-21 - -#### Highlights - -- **hub.services api tokens are now generated** - - The Helm chart now automatically seeds registered services under - `hub.services` with an api token. This is especially helpful for Helm charts - depending on this Helm chart such as `binderhub` or `daskhub`, for more - details see the - [`hub.services`](https://zero-to-jupyterhub.readthedocs.io/en/latest/resources/reference.html#hub-services) - entry in the configuration reference. - -- **Full arm64 compatebility** - - The Helm chart is fully arm64 compatible, even the `singleuser.image` that - previously wasn't. - -### Breaking changes - -This breaking change only concerns someone that has configured -`hub.services..name=` so that `` is different -from ``. In that case, the key in the k8s Secret exposing the -registered service's api token is now named `hub.services..apiToken` -instead of `hub.services..apiToken`. - -#### Notable dependencies updated - -| Dependency | Version in 1.0.0 | Version in 1.1.0 | Changelog link | Note | -| -------------------------------------------------------------------------------- | ---------------- | ---------------- | ----------------------------------------------------------------------------------------- | ---------------------------------- | -| [jupyterhub](https://github.com/jupyterhub/jupyterhub) | 1.4.1 | 1.4.2 | [Changelog](https://jupyterhub.readthedocs.io/en/stable/changelog.html) | Run in the `hub` pod | -| [kubespawner](https://github.com/jupyterhub/kubespawner) | 1.0.0 | 1.1.0 | [Changelog](https://jupyterhub-kubespawner.readthedocs.io/en/latest/changelog.html) | Run in the `hub` pod | -| [oauthenticator](https://github.com/jupyterhub/oauthenticator) | 14.0.0 | 14.1.0 | [Changelog](https://oauthenticator.readthedocs.io/en/latest/changelog.html) | Run in the `hub` pod | -| [ldapauthenticator](https://github.com/jupyterhub/ldapauthenticator) | 1.3.2 | 1.3.2 | [Changelog](https://github.com/jupyterhub/ldapauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | -| [ltiauthenticator](https://github.com/jupyterhub/ltiauthenticator) | 1.0.0 | 1.0.0 | [Changelog](https://github.com/jupyterhub/ltiauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | -| [nativeauthenticator](https://github.com/jupyterhub/nativeauthenticator) | 0.0.7 | 0.0.7 | [Changelog](https://github.com/jupyterhub/nativeauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | -| [jupyterhub-idle-culler](https://github.com/jupyterhub/jupyterhub-idle-culler) | 1.1 | 1.1 | - | Run in the `hub` pod | -| [configurable-http-proxy](https://github.com/jupyterhub/configurable-http-proxy) | 4.4.0 | 4.5.0 | [Changelog](https://github.com/jupyterhub/configurable-http-proxy/blob/HEAD/CHANGELOG.md) | Run in the `proxy` pod | -| [traefik](https://github.com/traefik/traefik) | v2.4.8 | v2.4.11 | [Changelog](https://github.com/traefik/traefik/blob/HEAD/CHANGELOG.md) | Run in the `autohttps` pod | -| [kube-scheduler](https://github.com/kubernetes/kube-scheduler) | v1.19.11 | v1.19.13 | - | Run in the `user-scheduler` pod(s) | - -For a detailed list of how Python dependencies have change in the `hub` Pod's Docker image, inspect the [images/hub/requirements.txt](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/images/hub/requirements.txt) file. - -#### New features added - -- Add configuration for arbitrary extra pod spec [#2306](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2306) ([@mallman](https://github.com/mallman)) - -#### Enhancements made - -- Add support for arm64 in singleuser-sample image [#2316](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2316) ([@consideRatio](https://github.com/consideRatio)) -- Seed hub.services' apiTokens [#2312](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2312) ([@consideRatio](https://github.com/consideRatio)) -- Add ingress.pathType config [#2305](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2305) ([@jtrouth](https://github.com/jtrouth)) - -#### Bugs fixed - -- Allow CHP to function in a IPv4 only and/or IPv6 only context [#2318](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2318) ([@consideRatio](https://github.com/consideRatio)) -- fix schema: accept proxy.traefik.extra[Static|Dynamic]Config [#2317](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2317) ([@consideRatio](https://github.com/consideRatio)) -- fix: bug if z2jh is used as a dependency with an alias [#2310](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2310) ([@consideRatio](https://github.com/consideRatio)) -- Fix failure to set imagePullSecrets for user-placeholder pods (scheduling.userPlaceholder.image config added) [#2293](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2293) ([@michaellzc](https://github.com/michaellzc)) - -#### Maintenance and upkeep improvements - -- build(deps): bump jupyterhub-kubespawner from 1.0.0 to 1.1.0 in /images/hub [#2324](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2324) ([@dependabot](https://github.com/dependabot)) -- Bump CHP version to 4.5.0 [#2321](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2321) ([@consideRatio](https://github.com/consideRatio)) -- build(deps): bump oauthenticator from 14.0.0 to 14.1.0 in /images/hub [#2320](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2320) ([@dependabot](https://github.com/dependabot)) -- Bump patch version of: traefik, kube-scheduler, pause [#2315](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2315) ([@consideRatio](https://github.com/consideRatio)) -- build(deps): bump jupyterhub from 1.4.1 to 1.4.2 in /images/hub [#2314](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2314) ([@dependabot](https://github.com/dependabot)) -- Remove deprecation logic for hub.extraConfig as a string [#2307](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2307) ([@consideRatio](https://github.com/consideRatio)) -- hub image: run apt-get upgrade by default to patch known vulns [#2304](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2304) ([@consideRatio](https://github.com/consideRatio)) - -#### Documentation improvements - -- Add changelog for 1.0.1 [#2287](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2287) ([@consideRatio](https://github.com/consideRatio)) -- Docs clarification culling behavior and configs [#2267](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2267) ([@cdibble](https://github.com/cdibble)) - -#### Continuous integration improvements - -- ci: improve lint-and-validate-values.yaml coverage [#2309](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2309) ([@consideRatio](https://github.com/consideRatio)) -- ci: Arm64 circleci test [#2302](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2302) ([@manics](https://github.com/manics)) - -#### Contributors to this release - -([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2021-06-25&to=2021-07-21&type=c)) - -[@cdibble](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acdibble+updated%3A2021-06-25..2021-07-21&type=Issues) | [@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2021-06-25..2021-07-21&type=Issues) | [@jtrouth](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajtrouth+updated%3A2021-06-25..2021-07-21&type=Issues) | [@mallman](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amallman+updated%3A2021-06-25..2021-07-21&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2021-06-25..2021-07-21&type=Issues) | [@michaellzc](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amichaellzc+updated%3A2021-06-25..2021-07-21&type=Issues) | [@minrk](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aminrk+updated%3A2021-06-25..2021-07-21&type=Issues) | [@yuvipanda](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ayuvipanda+updated%3A2021-06-25..2021-07-21&type=Issues) - -## [1.0] - -### [1.0.1] - 2021-06-25 - -#### Bugs fixed - -- Relax extraEnv schema to allow for array values [#2289](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2289) ([@consideRatio](https://github.com/consideRatio)) -- Relax hub.db.type schema to accept unknown database types [#2285](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2285) ([@consideRatio](https://github.com/consideRatio)) -- templates: quote namespace in case they are only contain numbers [#2284](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2284) ([@consideRatio](https://github.com/consideRatio)) -- Corrected scheduler rbac custom naming [#2276](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2276) ([@v1r7u](https://github.com/v1r7u)) -- Fix fullnameOverride for Ingress & PriorityClass resources [#2251](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2251) ([@v1r7u](https://github.com/v1r7u)) - -#### Maintenance and upkeep improvements - -- Bump traefik from 2.4.8 to 2.4.9 [#2288](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2288) ([@consideRatio](https://github.com/consideRatio)) -- singleuser-sample image: bump base image to reduce known vulns [#2286](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2286) ([@consideRatio](https://github.com/consideRatio)) -- schema: force labels and annotations to be strings [#2283](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2283) ([@consideRatio](https://github.com/consideRatio)) -- build(deps): bump nbgitpuller from 0.10.0 to 0.10.1 in /images/singleuser-sample [#2279](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2279) ([@dependabot](https://github.com/dependabot)) -- hub image: add sqlalchemy-cocroachdb dependency [#2262](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2262) ([@weisdd](https://github.com/weisdd)) -- build(deps): bump psycopg2-binary from 2.8.6 to 2.9.1 in /images/hub [#2259](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2259) ([@dependabot](https://github.com/dependabot)) -- build(deps): bump nbgitpuller from 0.9.0 to 0.10.0 in /images/singleuser-sample [#2247](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2247) ([@dependabot](https://github.com/dependabot)) - -#### Documentation improvements - -- docs: de-hardcode mentioned minimum helm version [#2272](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2272) ([@consideRatio](https://github.com/consideRatio)) -- added AWS EKS cluster scaling/auto-scaling documentation for z2jh [#2268](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2268) ([@cdibble](https://github.com/cdibble)) -- Update installation.md [#2249](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2249) ([@enolfc](https://github.com/enolfc)) -- Add participation in study notice to readme [#2248](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2248) ([@sgibson91](https://github.com/sgibson91)) -- Update 1.0.0-beta.1 changelog entry to 1.0.0 [#2245](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2245) ([@consideRatio](https://github.com/consideRatio)) - -#### Continuous integration improvements - -- Transition to use pre-commit hook in jupyterhub/chartpress [#2278](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2278) ([@consideRatio](https://github.com/consideRatio)) -- Remove pre-commit from GHA [#2273](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2273) ([@minrk](https://github.com/minrk)) - -#### Contributors to this release - -([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2021-06-09&to=2021-06-24&type=c)) - -[@cdibble](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acdibble+updated%3A2021-06-09..2021-06-24&type=Issues) | [@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2021-06-09..2021-06-24&type=Issues) | [@dependabot](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adependabot+updated%3A2021-06-09..2021-06-24&type=Issues) | [@enolfc](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aenolfc+updated%3A2021-06-09..2021-06-24&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2021-06-09..2021-06-24&type=Issues) | [@minrk](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aminrk+updated%3A2021-06-09..2021-06-24&type=Issues) | [@sgibson91](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asgibson91+updated%3A2021-06-09..2021-06-24&type=Issues) | [@v1r7u](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Av1r7u+updated%3A2021-06-09..2021-06-24&type=Issues) | [@weisdd](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aweisdd+updated%3A2021-06-09..2021-06-24&type=Issues) - -### [1.0.0] - 2021-06-09 - -This release includes a security announcement, breaking changes, several new -features, and more. Please read through this to be able to help yourself and -others upgrade successfully. - -As of the 1.0.0 version of this Helm chart, we aim to follow [SemVer 2 -versioning scheme](https://semver.org/) where breaking changes, new features, -and small bugfixes will increment the three version numbers. - -#### Highlights - -- **arm64 compatible images** - - All images except the user image (`singleuser.image`) now support the arm64 - architecture. This allows this Helm chart to be installable on a RaspberryPi - based k8s cluster. - -- **`hub.extraFiles` and `singleuser.extraFiles`** - - Have you wanted to mount various files to the hub pod or the user pods, such - as a configuration file or similar? While this could be done by creating a - dedicated ConfigMap that was mounted etc before, you don't need to go through - that trouble. - - Read more in [the configuration reference](https://zero-to-jupyterhub.readthedocs.io/en/latest/resources/reference.html#hub-extrafiles). - -- **Automatic secret generation** - - Are you explicitly passing `proxy.secretToken`, `hub.config.CryptKeeper.keys`, - `hub.config.JupyterHub.cookie_secret`? Do it one more time when upgrading to - 1.0.0! After that, they will be stored away in a k8s Secret and reused. - - If you install 1.0.0 from scratch, those will be automatically generated for - you if you don't specify them. - -- **Smoother helm upgrades** - - - `prePuller.hook.pullOnlyOnChanges` is now available and enabled by default, - which only intercepts a `helm upgrade` by pulling images if they have - changed since the last upgrade. - - - The `proxy` pod were sometimes restarted when it wasn't needed and that - could cause needless disruptions for users. This is now fixed. - -- **`fullnameOverride` and `nameOverride`** - - These options let you control the naming of the k8s resources created by the - Helm chart, but should _not be used_ unless you install from scratch. - - Read more in [the configuration - reference](https://zero-to-jupyterhub.readthedocs.io/en/latest/resources/reference.html#fullnameOverride). - -- **Referencing resources from a parent Helm chart's templates** - - Are you a developer of a Helm chart that depends on this Helm chart, and you - want to reference a k8s resource by name from one of your Helm templates? - - Learn how to do it the recommended way by reading [this - documentation](https://zero-to-jupyterhub.readthedocs.io/en/latest/administrator/advanced.html#referencing-resources-from-a-parent-helm-chart-s-templates). - -#### Security announcement - -The documentation for how to setup a Amazon EKS cluster included an insecure -step that would give anyone access to the Kubernetes cluster. If you have -followed these instructions between `0.7.0-beta.1` and `0.11.1`, please see the -[this post in the Jupyter forum](https://discourse.jupyter.org/t/-/9372). - -#### Breaking changes - -- **Kubernetes 1.17+ and Helm 3.5+ are now required** - - Helm 3 (3.5+) is now required. Helm 2 reached end of life last year and we - have started relying on Helm 3.5 specific features. - - Kubernetes 1.17+ is now required. It helped us avoid maintaining two separate - sets of implementations for the the user-scheduler. - -- **Schema validation of chart config** ([#2033](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2033), [#2200](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2200)) - - The Helm chart now bundles with a `values.schema.json` file that will validate - all use of the Helm chart during template rendering. If the Helm chart's - passed values doesn't comply with the schema, then `helm` will error before - the k8s api-server has become involved and anything has changed in the k8s - cluster. - - The most common validation errors are: - - - _Unrecognized config values_ - - For example if you have misspelled something. - - Note that if you want to pass your custom values for inspection by custom - logic in the hub pod, then you should pass these values via the `custom` - config section where anything will be accepted. - - - _Recognized config values with the wrong type_ - - For example if you have passed a numerical value to a configuration that - expected a string. - -- **Breaking changes to config** ([#2211](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2211)) - - As the Helm chart has evolved over time, configuration options have been - renamed and changed in various ways. With the release of 1.0.0, we enforce a - transition from various old configuration options to new that have previously - been ignored or accepted. - - If you are using outdated configuration options you will be informed about it - before any changes have been made to your deployment of the Helm chart. - -- **Default resource requests are no longer set** ([#2034](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2034), [#2226](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2226)) - - The helm chart now follows a common Helm chart practice by not setting default - resource requests or limits. - - To help in this transition, there is documentation with some guidance on - setting explicit resource requests available - [here](https://z2jh.jupyter.org/en/latest/administrator/optimization.html#explicit-memory-and-cpu-allocated-to-core-pods-containers). - - If you want to restore the previous behavior, you can explicitly set the - resource requests like below. - - ```yaml - hub: - resources: - requests: - cpu: 200m - memory: 512Mi - - proxy: - chp: - resources: - requests: - cpu: 200m - memory: 512Mi - - scheduling: - userScheduler: - resources: - requests: - cpu: 50m - memory: 256Mi - - prePuller: - resources: - requests: - cpu: 0 - memory: 0 - hook: - resources: - requests: - cpu: 0 - memory: 0 - ``` - -- **KubeSpawner and deletion of PVCs** ([jupyterhub#3337](https://github.com/jupyterhub/jupyterhub/pull/3337), [kubespawner#475](https://github.com/jupyterhub/kubespawner/pull/475)) - - Deleting a user in JupyterHub's admin interface (/hub/admin) or removing a - named server will now lead to the deletion of the user's or named server's - dynamically created PVC resource if there was one. - - To opt out of this behavior and retain the current behavior where dynamically - created PVC resources will remain, set `KubeSpawner.delete_pvc` to `false`. - - ```yaml - hub: - config: - KubeSpawner: - delete_pvc: false - ``` - - Note that this feature relies on both KubeSpawner 1.0.0+ and JupyterHub 1.4.1+ - which are included in this release. - -- **hub.existingSecret is reworked** ([#2042](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2042)) - - See [the - documentation](http://z2jh.jupyter.org/en/latest/resources/reference.html#hub-existingsecret) - and [pull request - #2042](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2042) for - more details. - -- **configurable-http-proxy statsd metrics removed** ([#2231](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2231)) - - [statsd metrics have been - removed](https://github.com/jupyterhub/configurable-http-proxy/pull/314) in - configurable-http-proxy. This will only affect administrators who have - overridden the CHP command line arguments as statsd is not supported in the - Helm chart. Support for Prometheus metrics will be added in a future release. - -#### Notable dependencies updated - -| Dependency | Version in 0.11.0 | Version in 1.0.0 | Changelog link | Note | -| -------------------------------------------------------------------------------- | ----------------- | ---------------- | ----------------------------------------------------------------------------------------- | ---------------------------------- | -| [jupyterhub](https://github.com/jupyterhub/jupyterhub) | 1.3.0 | 1.4.1 | [Changelog](https://jupyterhub.readthedocs.io/en/stable/changelog.html) | Run in the `hub` pod | -| [kubespawner](https://github.com/jupyterhub/kubespawner) | 0.15.0 | 1.0.0 | [Changelog](https://jupyterhub-kubespawner.readthedocs.io/en/latest/changelog.html) | Run in the `hub` pod | -| [oauthenticator](https://github.com/jupyterhub/oauthenticator) | 0.12.3 | 14.0.0 | [Changelog](https://oauthenticator.readthedocs.io/en/latest/changelog.html) | Run in the `hub` pod | -| [ldapauthenticator](https://github.com/jupyterhub/ldapauthenticator) | 1.3.2 | 1.3.2 | [Changelog](https://github.com/jupyterhub/ldapauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | -| [ltiauthenticator](https://github.com/jupyterhub/ltiauthenticator) | 1.0.0 | 1.0.0 | [Changelog](https://github.com/jupyterhub/ltiauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | -| [nativeauthenticator](https://github.com/jupyterhub/nativeauthenticator) | 0.0.6 | 0.0.7 | [Changelog](https://github.com/jupyterhub/nativeauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | -| [jupyterhub-idle-culler](https://github.com/jupyterhub/jupyterhub-idle-culler) | 1.0 | 1.1 | - | Run in the `hub` pod | -| [configurable-http-proxy](https://github.com/jupyterhub/configurable-http-proxy) | 4.2.2 | 4.4.0 | [Changelog](https://github.com/jupyterhub/configurable-http-proxy/blob/HEAD/CHANGELOG.md) | Run in the `proxy` pod | -| [traefik](https://github.com/traefik/traefik) | v2.3.7 | v2.4.8 | [Changelog](https://github.com/traefik/traefik/blob/HEAD/CHANGELOG.md) | Run in the `autohttps` pod | -| [kube-scheduler](https://github.com/kubernetes/kube-scheduler) | v1.19.7 | v1.19.11 | - | Run in the `user-scheduler` pod(s) | - -For a detailed list of how Python dependencies have change in the `hub` Pod's Docker image, inspect the [images/hub/requirements.txt](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/images/hub/requirements.txt) file. - -#### New features added - -- hub.service.extraPorts config option [#2148](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2148) ([@kafonek](https://github.com/kafonek)) -- Publish Arm64 compatible images [#2125](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2125) ([@manics](https://github.com/manics)) -- Enable opt-out of hub.jupyter.org/dedicated tolerations [#2101](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2101) ([@kafonek](https://github.com/kafonek)) -- Add prePuller.hook.pullOnlyOnChanges flag [#2066](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2066) ([@consideRatio](https://github.com/consideRatio)) -- values.schema.json ships with chart and configuration reference now covers all options [#2033](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2033) ([@consideRatio](https://github.com/consideRatio)) -- Allow extraFiles to be injected to hub / singleuser pods and automatically load config in /usr/local/etc/jupyterhub_config.d [#2006](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2006) ([@consideRatio](https://github.com/consideRatio)) -- Seed secrets (proxy.secretToken, etc) so they don't have to be manually generated [#1993](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1993) ([@consideRatio](https://github.com/consideRatio)) -- Support fullnameOverride / nameOverride and reference resources by named templates [#1923](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1923) ([@consideRatio](https://github.com/consideRatio)) - -#### Enhancements made - -- Add ...serviceAccount.annotations config for our k8s ServiceAccounts [#2236](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2236) ([@AndreaGiardini](https://github.com/AndreaGiardini)) -- upload chart as github artifact [#2086](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2086) ([@minrk](https://github.com/minrk)) -- allow override of CHP defaultTarget, errorTarget [#2079](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2079) ([@minrk](https://github.com/minrk)) -- Don't restart the proxy pod with each deploy [#2077](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2077) ([@yuvipanda](https://github.com/yuvipanda)) -- Add option to disable http port on LoadBalancer service [#2061](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2061) ([@tkislan](https://github.com/tkislan)) -- Add artificathub.io annotations to Chart.yaml before publishing [#2045](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2045) ([@consideRatio](https://github.com/consideRatio)) -- Make use of hub.existingSecret sustainable [#2042](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2042) ([@consideRatio](https://github.com/consideRatio)) -- Allow ingress.hosts to be omitted for a more generic rule [#2027](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2027) ([@consideRatio](https://github.com/consideRatio)) -- Also pull singleuser.initContainers with pre-puller [#1992](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1992) ([@consideRatio](https://github.com/consideRatio)) - -#### Bugs fixed - -- fix: prePuller.hook.pullOnlyOnChanges didn't work, now it does [#2174](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2174) ([@consideRatio](https://github.com/consideRatio)) -- Fix mixup of hook/continuous-image-puller following recent PR [#2100](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2100) ([@consideRatio](https://github.com/consideRatio)) -- Fix schema validation for Spawner.cpu/memory limits/guarantees [#2070](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2070) ([@consideRatio](https://github.com/consideRatio)) -- Support setting resources to null to omit them [#2055](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2055) ([@consideRatio](https://github.com/consideRatio)) -- pdb: default to maxUnavailable=1 instead of minAvailable=1 [#2039](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2039) ([@consideRatio](https://github.com/consideRatio)) -- fix: imagePullSecret.enabled to work alongside imagePullSecret.create [#2038](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2038) ([@consideRatio](https://github.com/consideRatio)) -- hub image build: fix use of PIP_OVERRIDES arg [#2036](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2036) ([@remche](https://github.com/remche)) -- fix: load only .py files in jupyterhub_config.d folder [#2023](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2023) ([@consideRatio](https://github.com/consideRatio)) -- Followup fixes to seed secrets PR (#1993) [#2016](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2016) ([@consideRatio](https://github.com/consideRatio)) -- fix: set tolerations to predefined labels on core pods [#2007](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2007) ([@consideRatio](https://github.com/consideRatio)) - -#### Maintenance and upkeep improvements - -- Test against k8s 1.21 and avoid deprecation warning for old k8s api policy/v1beta1 [#2243](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2243) ([@consideRatio](https://github.com/consideRatio)) -- Rename master branch to main [#2217](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2217) ([@manics](https://github.com/manics)) -- singleuser-sample: update base image [#2213](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2213) ([@consideRatio](https://github.com/consideRatio)) -- Remove deprecated logic and emit clear messages [#2211](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2211) ([@consideRatio](https://github.com/consideRatio)) -- refactor: stop manual hex-to-bytes conversion [#2209](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2209) ([@consideRatio](https://github.com/consideRatio)) -- schema: added details to hub|singleuser.extraFiles [#2198](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2198) ([@consideRatio](https://github.com/consideRatio)) -- Remove extraneous command from secret-sync image [#2182](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2182) ([@manics](https://github.com/manics)) -- maint: revert a workaround to make our priorityclass resources helm hooks [#2180](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2180) ([@consideRatio](https://github.com/consideRatio)) -- enable prePuller.hook.pullOnlyOnChanges by default [#2179](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2179) ([@consideRatio](https://github.com/consideRatio)) -- inline comment: info about the state used by prePuller.hook.pullOnlyOnChanges [#2173](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2173) ([@consideRatio](https://github.com/consideRatio)) -- images/hub - a regular run of script: hub/images/dependencies freeze --upgrade [#2168](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2168) ([@consideRatio](https://github.com/consideRatio)) -- build(deps): bump rsa from 4.6 to 4.7.2 in /images/hub [#2167](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2167) ([@dependabot](https://github.com/dependabot)) -- Update NOTES.txt, including removing "alpha" designation [#2165](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2165) ([@manics](https://github.com/manics)) -- docs: fix docs build for breaking change in sphinx redirection extension [#2156](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2156) ([@consideRatio](https://github.com/consideRatio)) -- Allow hub pod to manage k8s Secrets/Services for KubeSpawner.internal_ssl [#2065](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2065) ([@thomasv314](https://github.com/thomasv314)) -- Don't set default resource requests [#2034](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2034) ([@yuvipanda](https://github.com/yuvipanda)) -- cleanup: remove mistakenly added artifactshub.io config file [#2010](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2010) ([@consideRatio](https://github.com/consideRatio)) -- refactor: consistently use toYaml with annotations/labels [#2008](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2008) ([@consideRatio](https://github.com/consideRatio)) -- Require k8s 1.17+ to reduce complexity [#2005](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2005) ([@consideRatio](https://github.com/consideRatio)) -- refactor: systematically prefer use of with in templates [#2003](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2003) ([@consideRatio](https://github.com/consideRatio)) -- Specify prometheus.io/port for hub service [#2000](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2000) ([@yuvipanda](https://github.com/yuvipanda)) -- Autoformat bash scripts, yaml files, and markdown files with pre-commit [#1996](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1996) ([@manics](https://github.com/manics)) -- Remove deprecated user-scheduler config [#1995](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1995) ([@consideRatio](https://github.com/consideRatio)) -- Require Helm 3 to allow for enhancements [#1994](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1994) ([@consideRatio](https://github.com/consideRatio)) -- Remove unused nameField helper in \_helpers.tpl [#1991](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1991) ([@consideRatio](https://github.com/consideRatio)) - -#### Documentation improvements - -- docs: fix broken link [#2230](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2230) ([@consideRatio](https://github.com/consideRatio)) -- docs: add documentation about resource requests [#2226](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2226) ([@consideRatio](https://github.com/consideRatio)) -- docs: fix syntax error in markdown table [#2225](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2225) ([@consideRatio](https://github.com/consideRatio)) -- Remove setup-helm2.md [#2216](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2216) ([@manics](https://github.com/manics)) -- Add debug.enabled to admin debugging doc [#2215](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2215) ([@manics](https://github.com/manics)) -- Minor documentation fixes [#2206](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2206) ([@consideRatio](https://github.com/consideRatio)) -- Add changelog for 1.0.0-beta.1 [#2175](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2175) ([@consideRatio](https://github.com/consideRatio)) -- docs: we require helm3 not helm2 [#2159](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2159) ([@consideRatio](https://github.com/consideRatio)) -- fix cluster name for DO installation instructions [#2134](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2134) ([@RyanQuey](https://github.com/RyanQuey)) -- update k8 version for DO to currently available version [#2133](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2133) ([@RyanQuey](https://github.com/RyanQuey)) -- Include customisation under "Administrator Guide" [#2123](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2123) ([@manics](https://github.com/manics)) -- Update index.md [#2122](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2122) ([@rommeld](https://github.com/rommeld)) -- Correct the AKS GPU Link in documentation [#2109](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2109) ([@jabbera](https://github.com/jabbera)) -- Update postgres db url dialect in schema docs [#2105](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2105) ([@mriedem](https://github.com/mriedem)) -- Don't hard-code an old tag in customizing/user-environment.md [#2090](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2090) ([@manics](https://github.com/manics)) -- [DOC] Satisfy linkcheck [#2080](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2080) ([@minrk](https://github.com/minrk)) -- Fix spawner env injection example. [#2062](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2062) ([@danielballan](https://github.com/danielballan)) -- update a markdown syntax error [#2058](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2058) ([@yobome](https://github.com/yobome)) -- docs: helm3 compliance, avoid specification of chart versions [#2054](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2054) ([@consideRatio](https://github.com/consideRatio)) -- doc: Update installation docs to refer to current latest version [#2040](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2040) ([@spenczar](https://github.com/spenczar)) -- docs: package chart specific README.md with the chart [#2035](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2035) ([@consideRatio](https://github.com/consideRatio)) -- values.schema.json ships with chart and configuration reference now covers all options [#2033](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2033) ([@consideRatio](https://github.com/consideRatio)) -- Fix schema.yaml jsonschema syntax errors [#2031](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2031) ([@consideRatio](https://github.com/consideRatio)) - -#### Continuous integration improvements - -- ci: update publish/test-chart workflow triggers [#2212](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2212) ([@consideRatio](https://github.com/consideRatio)) -- ci: print pip packages versions for debugging [#2210](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2210) ([@consideRatio](https://github.com/consideRatio)) -- ci: vuln-scan update, less dedicated actions + warning instead of error [#2188](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2188) ([@consideRatio](https://github.com/consideRatio)) -- ci: fix permissions of PR creating action [#2186](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2186) ([@consideRatio](https://github.com/consideRatio)) -- docs/ci: run template tests against least known supported helm version and document that version [#2181](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2181) ([@consideRatio](https://github.com/consideRatio)) -- ci: accept 1 pod restart but not 2, test against k8s 1.21 [#2169](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2169) ([@consideRatio](https://github.com/consideRatio)) -- ci: precautions for security, update github_token permissions, pin actions [#2163](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2163) ([@consideRatio](https://github.com/consideRatio)) -- ci: update network tests as jupyter.org IPs changed [#2162](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2162) ([@consideRatio](https://github.com/consideRatio)) -- ci: Set author and pin SHA in vuln-scan workflow PR [#2153](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2153) ([@manics](https://github.com/manics)) -- publish workflow: build amd64 and arm64 prerequisites added [#2144](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2144) ([@consideRatio](https://github.com/consideRatio)) -- docs/ci: revert docutils pin, myst-parser fixed issue [#2141](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2141) ([@consideRatio](https://github.com/consideRatio)) -- docs: fix rtd build by pinning docutils [#2140](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2140) ([@consideRatio](https://github.com/consideRatio)) -- ci: increase test timeout for test reliability [#2083](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2083) ([@consideRatio](https://github.com/consideRatio)) -- ci: stop accepting test failures in k8s 1.20 [#2060](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2060) ([@consideRatio](https://github.com/consideRatio)) -- vuln-scan: fix all fixable vulns, and bugfix automation, and bump singleuser-sample [#2052](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2052) ([@consideRatio](https://github.com/consideRatio)) -- ci: fix Chart.yaml annotations for artifacthub.io image scanning [#2049](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2049) ([@consideRatio](https://github.com/consideRatio)) -- ci: install pyyaml before publishing to generate json schema [#2037](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2037) ([@consideRatio](https://github.com/consideRatio)) -- ci: use jupyterhub/action-k8s-await-workloads [#2021](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2021) ([@consideRatio](https://github.com/consideRatio)) -- ci: stop using --long as chartpress 1.0.0 makes it not needed [#2018](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2018) ([@consideRatio](https://github.com/consideRatio)) -- ci: use yq to parse version from Chart.yaml and save ~30 seconds [#2017](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2017) ([@consideRatio](https://github.com/consideRatio)) -- ci: accept k8s 1.20 failures until 1.20.3 is out [#2004](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2004) ([@consideRatio](https://github.com/consideRatio)) - -#### Contributors to this release - -([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2021-01-15&to=2021-05-28&type=c)) - -[@agnewp](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aagnewp+updated%3A2021-01-15..2021-05-28&type=Issues) | [@bbockelm](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abbockelm+updated%3A2021-01-15..2021-05-28&type=Issues) | [@betatim](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abetatim+updated%3A2021-01-15..2021-05-28&type=Issues) | [@choldgraf](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acholdgraf+updated%3A2021-01-15..2021-05-28&type=Issues) | [@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2021-01-15..2021-05-28&type=Issues) | [@damianavila](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adamianavila+updated%3A2021-01-15..2021-05-28&type=Issues) | [@danielballan](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adanielballan+updated%3A2021-01-15..2021-05-28&type=Issues) | [@dependabot](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adependabot+updated%3A2021-01-15..2021-05-28&type=Issues) | [@dhirschfeld](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adhirschfeld+updated%3A2021-01-15..2021-05-28&type=Issues) | [@github-actions](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Agithub-actions+updated%3A2021-01-15..2021-05-28&type=Issues) | [@jabbera](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajabbera+updated%3A2021-01-15..2021-05-28&type=Issues) | [@jgwerner](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajgwerner+updated%3A2021-01-15..2021-05-28&type=Issues) | [@kafonek](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Akafonek+updated%3A2021-01-15..2021-05-28&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2021-01-15..2021-05-28&type=Issues) | [@meeseeksmachine](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ameeseeksmachine+updated%3A2021-01-15..2021-05-28&type=Issues) | [@mhwasil](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amhwasil+updated%3A2021-01-15..2021-05-28&type=Issues) | [@michzimny](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amichzimny+updated%3A2021-01-15..2021-05-28&type=Issues) | [@MickeyShnaiderman-RecoLabs](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AMickeyShnaiderman-RecoLabs+updated%3A2021-01-15..2021-05-28&type=Issues) | [@minrk](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aminrk+updated%3A2021-01-15..2021-05-28&type=Issues) | [@mriedem](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amriedem+updated%3A2021-01-15..2021-05-28&type=Issues) | [@NerdSec](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ANerdSec+updated%3A2021-01-15..2021-05-28&type=Issues) | [@pcfens](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Apcfens+updated%3A2021-01-15..2021-05-28&type=Issues) | [@pvanliefland](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Apvanliefland+updated%3A2021-01-15..2021-05-28&type=Issues) | [@remche](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aremche+updated%3A2021-01-15..2021-05-28&type=Issues) | [@roelbaz](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aroelbaz+updated%3A2021-01-15..2021-05-28&type=Issues) | [@rommeld](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Arommeld+updated%3A2021-01-15..2021-05-28&type=Issues) | [@RyanQuey](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ARyanQuey+updated%3A2021-01-15..2021-05-28&type=Issues) | [@spenczar](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aspenczar+updated%3A2021-01-15..2021-05-28&type=Issues) | [@support](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asupport+updated%3A2021-01-15..2021-05-28&type=Issues) | [@thomasv314](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Athomasv314+updated%3A2021-01-15..2021-05-28&type=Issues) | [@tkislan](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Atkislan+updated%3A2021-01-15..2021-05-28&type=Issues) | [@willingc](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Awillingc+updated%3A2021-01-15..2021-05-28&type=Issues) | [@yobome](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ayobome+updated%3A2021-01-15..2021-05-28&type=Issues) | [@yuvipanda](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ayuvipanda+updated%3A2021-01-15..2021-05-28&type=Issues) - -## [0.11] - -### [0.11.1] - 2021-01-15 - -This release fixes a regression in the Ingress resource and a bump of -jupyterhub-nativeauthenticator from 0.0.6 to 0.0.7. - -#### Bugs fixed - -- fix: fix of ingress regression and improved testing ([@consideRatio](https://github.com/consideRatio)) - -#### Maintenance and upkeep improvements - -- build(deps): bump jupyterhub-nativeauthenticator from 0.0.6 to 0.0.7 in /images/hub [#1988](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1988) ([@dependabot](https://github.com/dependabot)) - -### [0.11.0] - 2021-01-14 - -Please read the _security announcement_ and the _breaking changes_ below, and -also note that this is the last release supporting Helm 2 and k8s versions lower -than 1.16. - -#### Security announcement - -This release contains the patched version of jupyterhub/oauthenticator which -contained a security issue that influenced version 0.10.0 - 0.10.5 (but not -0.10.6) of this Helm chart. - -Please don't use versions 0.10.0 - 0.10.5 and upgrade to 0.10.6 or later. If you -are using OAuthenticator, please check your list of users and [delete any -unauthorized users who may have logged in during usage of version 0.10.0 - -10.10.5](https://jupyterhub.readthedocs.io/en/1.2.2/getting-started/authenticators-users-basics.html#add-or-remove-users-from-the-hub). - -See [the published security -advisory](https://github.com/jupyterhub/oauthenticator/security/advisories/GHSA-384w-5v3f-q499) -for more information, and refer to [this forum -post](https://discourse.jupyter.org/t/collaboration-to-mitigate-issues-of-security-advisory-in-oauthenticator/7520) -to share insights that can be useful to others. - -#### Breaking changes - -- **`auth` configuration moves to `hub.config` - [#1943](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1943)** - - Helm chart configuration under `auth` is now no longer supported. If you make - a `helm upgrade` using `auth` configuration, the upgrade will abort before any - changes are made to the k8s cluster and you will be provided with the - equivalent configuration using the new system under `hub.config`. - - By default, the printed equivalent configuration is censored as it can contain - secrets that shouldn't be exposed. By passing `--global.safeToShowValues=true` - you can get an uncensored version. - -- **Pod Disruption Budget's now disabled by default - [#1938](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1938)** - - A Pod Disruption Budget (PDB) for the hub and proxy pods were created by - default before, but will by default not be created from now on. The - consequence of this is that the pods now can get _evicted_. - - Eviction will happen as part of `kubectl drain` on a node, or by a cluster - autoscaler removing a underused node. - -#### Notable dependencies updated - -| Dependency | Version in 0.10.6 | Version in 0.11.0 | Changelog link | Note | -| -------------------------------------------------------------------------------- | ----------------- | ----------------- | ----------------------------------------------------------------------------------------- | ---------------------------------- | -| [jupyterhub](https://github.com/jupyterhub/jupyterhub) | 1.2.2 | 1.3.0 | [Changelog](https://jupyterhub.readthedocs.io/en/stable/changelog.html) | Run in the `hub` pod | -| [kubespawner](https://github.com/jupyterhub/kubespawner) | 0.14.1 | 0.15.0 | [Changelog](https://jupyterhub-kubespawner.readthedocs.io/en/latest/changelog.html) | Run in the `hub` pod | -| [oauthenticator](https://github.com/jupyterhub/oauthenticator) | 0.12.1 | 0.12.3 | [Changelog](https://oauthenticator.readthedocs.io/en/latest/changelog.html) | Run in the `hub` pod | -| [ldapauthenticator](https://github.com/jupyterhub/ldapauthenticator) | 1.3.2 | 1.3.2 | [Changelog](https://github.com/jupyterhub/ldapauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | -| [ltiauthenticator](https://github.com/jupyterhub/ltiauthenticator) | 0.4.0 | 1.0.0 | [Changelog](https://github.com/jupyterhub/ltiauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | -| [nativeauthenticator](https://github.com/jupyterhub/nativeauthenticator) | 0.0.6 | 0.0.6 | [Changelog](https://github.com/jupyterhub/nativeauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | -| [jupyterhub-idle-culler](https://github.com/jupyterhub/jupyterhub-idle-culler) | 1.0 | 1.0 | - | Run in the `hub` pod | -| [configurable-http-proxy](https://github.com/jupyterhub/configurable-http-proxy) | 4.2.2 | 4.2.2 | [Changelog](https://github.com/jupyterhub/configurable-http-proxy/blob/HEAD/CHANGELOG.md) | Run in the `proxy` pod | -| [traefik](https://github.com/traefik/traefik) | v2.3.2 | v2.3.7 | [Changelog](https://github.com/traefik/traefik/blob/HEAD/CHANGELOG.md) | Run in the `autohttps` pod | -| [kube-scheduler](https://github.com/kubernetes/kube-scheduler) | v1.19.2 | v1.19.7 | - | Run in the `user-scheduler` pod(s) | - -For a detailed list of how Python dependencies have change in the `hub` Pod's Docker image, inspect the [images/hub/requirements.txt](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/images/hub/requirements.txt) file. - -#### Enhancements made - -- ci: automatically scan and patch our images for known vulnerabilities [#1942](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1942) ([@consideRatio](https://github.com/consideRatio)) - -#### Bugs fixed - -- Fix failure to block insecure metadata server IP [#1950](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1950) ([@consideRatio](https://github.com/consideRatio)) -- Enable hub livenessProbe by default and relax hub/proxy probes [#1941](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1941) ([@consideRatio](https://github.com/consideRatio)) -- Disable PDBs for hub/proxy, add PDB for autohttps, and relocate config proxy.pdb to proxy.chp.pdb [#1938](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1938) ([@consideRatio](https://github.com/consideRatio)) - -#### Maintenance and upkeep improvements - -- dep: bump traefik (autohttps pod) from v2.3.2 to v2.3.7 [#1986](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1986) ([@consideRatio](https://github.com/consideRatio)) -- k8s: update Ingress / PriorityClass apiVersions [#1983](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1983) ([@consideRatio](https://github.com/consideRatio)) -- dep: bump kube-scheduler from 1.19.2 to 1.19.7 [#1981](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1981) ([@consideRatio](https://github.com/consideRatio)) -- singleuser-sample image: bump jupyerhub to 1.3.0 [#1961](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1961) ([@consideRatio](https://github.com/consideRatio)) -- build(deps): bump jupyterhub from 1.2.2 to 1.3.0 in /images/hub [#1959](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1959) ([@dependabot](https://github.com/dependabot)) -- Vulnerability patch in network-tools [#1947](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1947) ([@github-actions](https://github.com/github-actions)) -- hub image: bump jupyterhub-kubespawner from 0.14.1 to 0.15.0 in /images/hub [#1946](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1946) ([@dependabot](https://github.com/dependabot)) -- Helm template linting - remove extra space [#1945](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1945) ([@DArtagan](https://github.com/DArtagan)) -- hub image: bump jupyterhub-hmacauthenticator from 0.1 to 1.0 in /images/hub [#1944](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1944) ([@dependabot](https://github.com/dependabot)) -- add hub.config passthrough and use it for all auth config [#1943](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1943) ([@consideRatio](https://github.com/consideRatio)) -- hub image: bump ltiauthenticator to 1.0.0 and oauthenticator to 0.12.3 [#1932](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1932) ([@consideRatio](https://github.com/consideRatio)) -- bump oauthenticator to 0.12.2 [#1925](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1925) ([@minrk](https://github.com/minrk)) - -#### Documentation improvements - -- docs: 100% MyST Markdown [#1974](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1974) ([@consideRatio](https://github.com/consideRatio)) -- docs: remove unused config of esoteric sphinx builders [#1969](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1969) ([@consideRatio](https://github.com/consideRatio)) -- docs: fix the dynamically set version of chart/jupyterhub [#1968](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1968) ([@consideRatio](https://github.com/consideRatio)) -- Adds a linebreak [#1957](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1957) ([@arokem](https://github.com/arokem)) -- Fixes link to authentication guide from user-management.md [#1955](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1955) ([@arokem](https://github.com/arokem)) -- Adds cli command for finding the k8s version on Azure. [#1954](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1954) ([@arokem](https://github.com/arokem)) - -#### Continuous integration improvements - -- ci: accept helm lint --strict failure, but ensure GitHub UI warns [#1985](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1985) ([@consideRatio](https://github.com/consideRatio)) -- ci: replace kubeval with helm template --validate [#1984](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1984) ([@consideRatio](https://github.com/consideRatio)) -- ci: use extracted github action for namespace report [#1980](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1980) ([@consideRatio](https://github.com/consideRatio)) -- ci: add another upgrade test and provide a template rendering diff [#1978](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1978) ([@consideRatio](https://github.com/consideRatio)) -- ci: linkcheck rework: avoid duplicated build, add colors, make it fail loud [#1976](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1976) ([@consideRatio](https://github.com/consideRatio)) -- ci: run tests conditionally on changed paths [#1975](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1975) ([@consideRatio](https://github.com/consideRatio)) -- ci: use k3s-channel instead of k3s-version [#1973](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1973) ([@consideRatio](https://github.com/consideRatio)) -- ci: full_namespace_report improvements for restartCount > 0 [#1971](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1971) ([@consideRatio](https://github.com/consideRatio)) -- pre-commit: chartpress --reset on Chart.yaml/values.yaml changes [#1970](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1970) ([@consideRatio](https://github.com/consideRatio)) -- ci: full_namespace_report function improved [#1967](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1967) ([@consideRatio](https://github.com/consideRatio)) -- ci: dependabot, add notes to config, fix singleuser-sample config [#1966](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1966) ([@consideRatio](https://github.com/consideRatio)) -- ci: let pytest keep running even if one test has failed [#1965](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1965) ([@consideRatio](https://github.com/consideRatio)) -- ci: help dependabot only trigger one set of tests [#1964](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1964) ([@consideRatio](https://github.com/consideRatio)) -- ci: remove yaml anchors from dependabot config [#1963](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1963) ([@consideRatio](https://github.com/consideRatio)) -- ci: Test against k8s 1.20 [#1956](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1956) ([@consideRatio](https://github.com/consideRatio)) -- ci: vuln scan fix [#1953](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1953) ([@consideRatio](https://github.com/consideRatio)) -- ci: let dependabot update used GitHub action's versions [#1949](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1949) ([@consideRatio](https://github.com/consideRatio)) -- ci: let dependabot update jupyterhub, replace JUPYTERHUB_VERSION with PIP_OVERRIDES [#1948](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1948) ([@consideRatio](https://github.com/consideRatio)) -- ci: automatically scan and patch our images for known vulnerabilities [#1942](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1942) ([@consideRatio](https://github.com/consideRatio)) -- ci: action-k3s-helm was moved to jupyterhub [#1939](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1939) ([@manics](https://github.com/manics)) -- ci: fix of intermittent netpol test failure [#1933](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1933) ([@consideRatio](https://github.com/consideRatio)) - -#### Contributors to this release - -([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2020-11-27&to=2021-01-13&type=c)) - -[@arokem](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aarokem+updated%3A2020-11-27..2021-01-13&type=Issues) | [@betatim](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abetatim+updated%3A2020-11-27..2021-01-13&type=Issues) | [@chicocvenancio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Achicocvenancio+updated%3A2020-11-27..2021-01-13&type=Issues) | [@choldgraf](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acholdgraf+updated%3A2020-11-27..2021-01-13&type=Issues) | [@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2020-11-27..2021-01-13&type=Issues) | [@DArtagan](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ADArtagan+updated%3A2020-11-27..2021-01-13&type=Issues) | [@dependabot](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adependabot+updated%3A2020-11-27..2021-01-13&type=Issues) | [@github-actions](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Agithub-actions+updated%3A2020-11-27..2021-01-13&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2020-11-27..2021-01-13&type=Issues) | [@minrk](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aminrk+updated%3A2020-11-27..2021-01-13&type=Issues) | [@naterush](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Anaterush+updated%3A2020-11-27..2021-01-13&type=Issues) | [@rokroskar](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Arokroskar+updated%3A2020-11-27..2021-01-13&type=Issues) | [@yuvipanda](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ayuvipanda+updated%3A2020-11-27..2021-01-13&type=Issues) - -## [0.10] - -### [0.10.6] - 2020-11-27 - -This release is a security workaround for jupyterhub/oauthenticator described in https://github.com/jupyterhub/oauthenticator/security/advisories/GHSA-384w-5v3f-q499. - -Please don't use versions 0.10.0 - 0.10.5 and upgrade to 0.10.6 or later. If any users have been authorized during usage of 0.10.0 - 0.10.5 who should not have been, they must be deleted via the API or admin interface, [per the documentation](https://jupyterhub.readthedocs.io/en/1.2.2/getting-started/authenticators-users-basics.html#add-or-remove-users-from-the-hub). - -### [0.10.5] - 2020-11-27 - -This release bumps the JupyterHub version from 1.2.1 to 1.2.2. See [JupyterHub's -changelog](https://jupyterhub.readthedocs.io/en/stable/changelog.html?highlight=changelog) -for more information. - -## Bugs fixed - -- image: bump JupyterHub to 1.2.2 from 1.2.1 for bugfixes [#1924](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1924) ([@consideRatio](https://github.com/consideRatio)) - -#### Maintenance and upkeep improvements - -- pre-commit autoformat: black and beautysh [#1920](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1920) ([@manics](https://github.com/manics)) - -#### Contributors to this release - -([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2020-11-21&to=2020-11-27&type=c)) - -[@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2020-11-21..2020-11-27&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2020-11-21..2020-11-27&type=Issues) - -### [0.10.4] - 2020-11-21 - -A patch release to patch a bug in the dependency oauthenticator that made users -have their servers spawn before they had the chance to choose a server -configuration if c.KubeSpawner.profile_list was configured. - -#### Bugs fixed - -- hub image: bump oauthenticator and prometheus-client [#1918](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1918) ([@consideRatio](https://github.com/consideRatio)) - -#### Contributors to this release - -([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2020-11-16&to=2020-11-21&type=c)) - -[@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2020-11-16..2020-11-21&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2020-11-16..2020-11-21&type=Issues) - -### [0.10.3] - 2020-11-16 - -This release contain minor enhancements and bugfix in a dependency that could -have resulted in unwanted hub pod restarts. Helm 2.16+ has been explicitly -required, which it should had been already in 0.10.0. - -Please be aware that Helm 2 has reached its end of life and won't get any -security patches any more. We aim to drop support of Helm 2 soon to be able to -rely on Helm 3 features. - -#### Enhancements made - -- Configurable resource requests for hook-image-awaiter [#1906](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1906) ([@consideRatio](https://github.com/consideRatio)) -- Add use_lookup_dn_username parameter for LDAP [#1903](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1903) ([@JarnoRFB](https://github.com/JarnoRFB)) -- Allow exposing extra ports in autohttps/traefik deployment [#1901](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1901) ([@yuvipanda](https://github.com/yuvipanda)) -- prePuller.extraTolerations added for the image-puller daemonsets [#1883](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1883) ([@jerkern](https://github.com/jerkern)) - -## Bugs fixed - -- hub image: kubernetes 12.0.1, nativeauth 0.0.6, tornado 6.1 [#1912](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1912) ([@consideRatio](https://github.com/consideRatio)) - -#### Maintenance and upkeep improvements - -- hub image: kubernetes 12.0.1, nativeauth 0.0.6, tornado 6.1 [#1912](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1912) ([@consideRatio](https://github.com/consideRatio)) -- Require helm v2.16.0 explicitly and minor CI updates [#1911](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1911) ([@consideRatio](https://github.com/consideRatio)) -- CI: make upgrades more robust and skip 1m precautionary sleep [#1904](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1904) ([@consideRatio](https://github.com/consideRatio)) -- CI: publish with helpful commit message [#1898](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1898) ([@consideRatio](https://github.com/consideRatio)) -- Replace Travis with GitHub workflow [#1896](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1896) ([@manics](https://github.com/manics)) -- Avoid harmless error in user-scheduler [#1895](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1895) ([@consideRatio](https://github.com/consideRatio)) -- removal: contributors script [#1669](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1669) ([@consideRatio](https://github.com/consideRatio)) - -#### Documentation improvements - -- Update jupyterhub extension documentation to specify namespace [#1909](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1909) ([@plant99](https://github.com/plant99)) -- DOCS: Adding note on limit to guarantee ratio [#1897](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1897) ([@choldgraf](https://github.com/choldgraf)) -- Changelog for 0.10.2 [#1893](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1893) ([@consideRatio](https://github.com/consideRatio)) - -#### Contributors to this release - -([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2020-10-30&to=2020-11-15&type=c)) - -[@betatim](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abetatim+updated%3A2020-10-30..2020-11-15&type=Issues) | [@choldgraf](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acholdgraf+updated%3A2020-10-30..2020-11-15&type=Issues) | [@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2020-10-30..2020-11-15&type=Issues) | [@JarnoRFB](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AJarnoRFB+updated%3A2020-10-30..2020-11-15&type=Issues) | [@jerkern](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajerkern+updated%3A2020-10-30..2020-11-15&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2020-10-30..2020-11-15&type=Issues) | [@minrk](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aminrk+updated%3A2020-10-30..2020-11-15&type=Issues) | [@plant99](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aplant99+updated%3A2020-10-30..2020-11-15&type=Issues) | [@tirumerla](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Atirumerla+updated%3A2020-10-30..2020-11-15&type=Issues) | [@yuvipanda](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ayuvipanda+updated%3A2020-10-30..2020-11-15&type=Issues) - -### [0.10.2] - 2020-10-30 - -A bugfix release to add securityContext configuration on _all_ the containers in the image-puller pods, which can be needed when a k8s PodSecurityPolicy is forcing pods to startup as non-root users. - -Note that whoever need to comply with a strict PodSecurityPolicy will also need to `--set singleuser.cloudMetadata.blockWithIptables=false`, but should read [this documentation](https://zero-to-jupyterhub.readthedocs.io/en/latest/administrator/security.html#audit-cloud-metadata-server-access) before doing so. - -#### Bugs fixed - -- Add securityContext to all image-puller pods' containers [#1892](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1892) ([@consideRatio](https://github.com/consideRatio)) - -#### Documentation improvements - -- Changelog for 0.10.1 [#1890](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1890) ([@consideRatio](https://github.com/consideRatio)) - -#### Contributors to this release - -([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2020-10-30&to=2020-10-30&type=c)) - -[@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2020-10-30..2020-10-30&type=Issues) | [@jatinder91](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajatinder91+updated%3A2020-10-30..2020-10-30&type=Issues) - -### [0.10.1] - 2020-10-30 - -A bugfix release simply updating JupyterHub to 1.2.1. JupyterHub 1.2.1 fixes a regression related to registered JupyterHub services using the `oauth_no_confirm` configuration. - -#### Bugs fixed - -- Use JupyterHub 1.2.1 - fixes regression for external JH services' oauth_no_confirm config [#1889](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1889) ([@minrk](https://github.com/minrk)) - -#### Maintenance and upkeep improvements - -- Fix CI that broke as assumptions changed about latest published version [#1887](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1887) ([@consideRatio](https://github.com/consideRatio)) - -#### Documentation improvements - -- Update changelog for 0.10.0 release [#1886](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1886) ([@consideRatio](https://github.com/consideRatio)) - -#### Contributors to this release - -([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2020-10-29&to=2020-10-30&type=c)) - -[@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2020-10-29..2020-10-30&type=Issues) | [@minrk](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aminrk+updated%3A2020-10-29..2020-10-30&type=Issues) - -### [0.10.0] - 2020-10-29 - -This release makes the deployment more robust, and enhances users ability to -configure the Helm chart in general. Some defaults have been changed allowing -the Helm chart to easier comply with PodSecurityPolicies by default. - -#### Breaking changes: - -- Anyone relying on configuration in the `proxy.https` section are now - explicitly required to set `proxy.https.enabled` to `true`. - -- Anyone using `hub.imagePullSecret` or `singleuser.imagePullSecret` should now - instead use the chart wide `imagePullSecret` with the same syntax which will - be helping all the JupyterHub pod's get images from a private image registry. - For more information, see [the configuration - reference](https://zero-to-jupyterhub.readthedocs.io/en/latest/resources/reference.html#imagepullsecret). - -- Predefined Kubernetes - [NetworkPolicies](https://kubernetes.io/docs/concepts/services-networking/network-policies/) - are now created by default, explicitly describing allowed incoming (_ingress_) - and outgoing (_egress_) network communication for the hub, proxy, and user - pods. These `NetworkPolicy` resources are very permissive on the outgoing - traffic (egress), but is limiting the incoming traffic to what is known to be - needed. - - Note that these NetworkPolicies only influence network communication in a - Kubernetes cluster if a NetworkPolicy controller enforce them, such as Calico. - - Also note that if network policies are enforced, you can safely stop actively - blocking access to so called cloud metadata servers for the user pods by - setting `singleuser.cloudMetadata.blockWithIptables=false`. - - See the [security - documentation](https://zero-to-jupyterhub.readthedocs.io/en/latest/administrator/security.html#kubernetes-network-policies) - and the [configuration - reference](https://zero-to-jupyterhub.readthedocs.io/en/latest/resources/reference.html#proxy-chp-networkpolicy) - for more details. - -- The Helm chart configuration `proxy.networkPolicy` has been removed, - `proxy.chp.networkPolicy` (proxy pod) and `proxy.traefik.networkPolicy` - (autohttps pod) must be used instead. - -- The Helm chart configuration `proxy.containerSecurityContext` is renamed to - `proxy.chp.containerSecurityContext`. - -- The k8s ConfigMap `hub-config` k8s Secret `hub-secret` are now merged into - `hub-secret`, which will affect anyone who use the `hub.existingSecret` - option. - -#### Release highlights - -- **Environment variables in pods with K8S config**. An ability to configure environment variables in pods with a k8s native syntax - has been added. This allows you to reference and mount a field in a k8s Secret - as an environment variable for example. For more information, read [about - extraEnv](https://zero-to-jupyterhub.readthedocs.io/en/latest/resources/reference.html#singleuser-extraenv) - in the configuration reference. -- **Configure secrets for all pods via the helm chart**. imagePullSecrets for all the pods in the Helm chart can now be configured - chart wide. See the configuration reference about - [imagePullSecret](https://zero-to-jupyterhub.readthedocs.io/en/latest/resources/reference.html#imagepullsecret) - and - [imagePullSecrets](https://zero-to-jupyterhub.readthedocs.io/en/latest/resources/reference.html#imagepullsecrets) - for more details. -- **Pod security is easier to use and configure**. Deploying the Helm chart in a cluster with a PodSecurityPolicy active is now - easier, because the pods' containers now have `securityContext` set on them to - run with relatively low permissions which are also configurable if needed. -- **More reliable TLS certificates**. The `autohttps` pod that is running to acquire TLS certificates if - `proxy.https.type=letsencrypt` is now more reliably acquiring certificates. If - you currently have such issue, do `kubectl delete deploy/autohttps` and - `kubectl delete secret proxy-public-tls-acme` and then deploy the Helm chart - again with `helm upgrade`. - -#### Notable dependencies updated - -| Dependency | Version in previous release | Version in this release | Changelog link | Note | -| -------------------------------------------------------------------------------- | --------------------------- | ----------------------- | ----------------------------------------------------------------------------------------- | ---------------------------------- | -| [jupyterhub](https://github.com/jupyterhub/jupyterhub) | 1.1.0 | 1.2.0 | [Changelog](https://jupyterhub.readthedocs.io/en/stable/changelog.html) | Run in the `hub` pod | -| [kubespawner](https://github.com/jupyterhub/kubespawner) | 0.11.1 | 0.14.1 | [Changelog](https://jupyterhub-kubespawner.readthedocs.io/en/latest/changelog.html) | Run in the `hub` pod | -| [oauthenticator](https://github.com/jupyterhub/oauthenticator) | 0.11.0 | 0.12.0 | [Changelog](https://oauthenticator.readthedocs.io/en/latest/changelog.html) | Run in the `hub` pod | -| [ldapauthenticator](https://github.com/jupyterhub/ldapauthenticator) | 1.3.0 | 1.3.2 | [Changelog](https://github.com/jupyterhub/ldapauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | -| [ltiauthenticator](https://github.com/jupyterhub/ltiauthenticator) | 0.4.0 | 0.4.0 | [Changelog](https://github.com/jupyterhub/ltiauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | -| [nativeauthenticator](https://github.com/jupyterhub/nativeauthenticator) | 0.0.5 | 0.0.5 | [Changelog](https://github.com/jupyterhub/nativeauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | -| [jupyterhub-idle-culler](https://github.com/jupyterhub/jupyterhub-idle-culler) | - | v1.0 | - | Run in the `hub` pod | -| [configurable-http-proxy](https://github.com/jupyterhub/configurable-http-proxy) | 4.2.1 | 4.2.2 | [Changelog](https://github.com/jupyterhub/configurable-http-proxy/blob/HEAD/CHANGELOG.md) | Run in the `proxy` pod | -| [traefik](https://github.com/traefik/traefik) | v2.1 | v2.3.2 | [Changelog](https://github.com/traefik/traefik/blob/HEAD/CHANGELOG.md) | Run in the `autohttps` pod | -| [kube-scheduler](https://github.com/kubernetes/kube-scheduler) | v1.13.12 | v1.19.2 | - | Run in the `user-scheduler` pod(s) | - -For a detailed list of how Python dependencies have change in the `hub` Pod's -Docker image, inspect the [images/hub/requirements.txt](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/images/hub/requirements.txt) file. - -#### Enhancements made - -- Allow adding extra labels to the traefik pod [#1862](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1862) ([@yuvipanda](https://github.com/yuvipanda)) -- Add proxy.service.extraPorts to add ports to the k8s Service proxy-public [#1852](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1852) ([@yuvipanda](https://github.com/yuvipanda)) -- netpol: allowedIngressPorts and interNamespaceAccessLabels config added with defaults retaining 0.9.1 current behavior [#1842](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1842) ([@consideRatio](https://github.com/consideRatio)) -- hub.command and hub.args configuration added [#1840](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1840) ([@cbanek](https://github.com/cbanek)) -- Add nodeSelector and tolerations config for all pods of Helm chart [#1827](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1827) ([@stevenstetzler](https://github.com/stevenstetzler)) -- Added config prePuller.pullProfileListImages [#1818](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1818) ([@consideRatio](https://github.com/consideRatio)) -- Added config option: proxy.chp.extraCommandLineFlags [#1813](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1813) ([@consideRatio](https://github.com/consideRatio)) -- Set container securityContext by default [#1798](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1798) ([@consideRatio](https://github.com/consideRatio)) -- Support chart wide and pod specific config of imagePullSecrets [#1794](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1794) ([@consideRatio](https://github.com/consideRatio)) -- Added proxy.chp.extraEnv and proxy.traefik.extraEnv configuration [#1784](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1784) ([@agrahamlincoln](https://github.com/agrahamlincoln)) -- Remove memory / cpu limits for pre-puller [#1780](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1780) ([@yuvipanda](https://github.com/yuvipanda)) -- Add additional liveness and readiness probe properties [#1767](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1767) ([@rmoe](https://github.com/rmoe)) -- Minimal and explicit resource requests for image-puller pods [#1764](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1764) ([@consideRatio](https://github.com/consideRatio)) -- hook-image-puller: -pod-scheduling-wait-duration flag added for reliability during helm upgrades [#1763](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1763) ([@consideRatio](https://github.com/consideRatio)) -- Make continuous image puller pods evictable [#1762](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1762) ([@consideRatio](https://github.com/consideRatio)) -- hub.extraEnv / singleuser.extraEnv in dict format to support k8s EnvVar spec [#1757](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1757) ([@consideRatio](https://github.com/consideRatio)) -- Add config for hub/proxy/autohttps container's securityContext [#1708](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1708) ([@mriedem](https://github.com/mriedem)) -- Add annotations to image puller pods [#1702](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1702) ([@duongnt](https://github.com/duongnt)) -- fix: intentionally error on missing Let's Encrypt contact email configuration [#1701](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1701) ([@consideRatio](https://github.com/consideRatio)) -- Add services API tokens in hub-secret [#1689](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1689) ([@betatim](https://github.com/betatim)) -- Tweaking readiness/liveness probe: faster startup [#1671](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1671) ([@consideRatio](https://github.com/consideRatio)) -- Tighten and flesh out networkpolicies [#1670](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1670) ([@consideRatio](https://github.com/consideRatio)) -- DX: k3s/k3d instead of kind & CI: autohttps testing [#1664](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1664) ([@consideRatio](https://github.com/consideRatio)) -- autohttps: instant secret-sync shutdown [#1659](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1659) ([@consideRatio](https://github.com/consideRatio)) -- Use DNS names instead of IPv4 addresses to be IPv6 friendly [#1643](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1643) ([@stv0g](https://github.com/stv0g)) -- autohttps: traefik's config now configurable and in YAML [#1636](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1636) ([@consideRatio](https://github.com/consideRatio)) -- Feat: autohttps readinessProbe for quicker validated startup and shutdown [#1633](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1633) ([@consideRatio](https://github.com/consideRatio)) -- switching to myst markdown in docs [#1628](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1628) ([@choldgraf](https://github.com/choldgraf)) -- Bind proxy on IPv4 and IPv6 for dual stack support [#1624](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1624) ([@stv0g](https://github.com/stv0g)) -- Do not hardcode IPv4 localhost address for IPv6 compatibility [#1623](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1623) ([@stv0g](https://github.com/stv0g)) -- enable network policy by default [#1271](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1271) ([@minrk](https://github.com/minrk)) -- Allow configuration of Kuberspawner's pod_name_template [#1144](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1144) ([@tmshn](https://github.com/tmshn)) - -#### Bugs fixed - -- Bump KubeSpawner to 0.14.1 to fix a bug in 0.14.0 about image_pull_secrets [#1868](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1868) ([@consideRatio](https://github.com/consideRatio)) -- netpol: allowedIngressPorts and interNamespaceAccessLabels config added with defaults retaining 0.9.1 current behavior [#1842](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1842) ([@consideRatio](https://github.com/consideRatio)) -- user-scheduler: let image locality etc matter again [#1837](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1837) ([@consideRatio](https://github.com/consideRatio)) -- Add retryable HTTP client to image-awaiter [#1830](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1830) ([@bleggett](https://github.com/bleggett)) -- prePuller: fix recently introduced regression [#1817](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1817) ([@consideRatio](https://github.com/consideRatio)) -- userScheduler: only render associated PDB resource if userScheduler itself is enabled [#1812](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1812) ([@consideRatio](https://github.com/consideRatio)) -- Fix same functionality for proxy.traefik.extraEnv as other extraEnv [#1808](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1808) ([@consideRatio](https://github.com/consideRatio)) -- Set container securityContext by default [#1798](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1798) ([@consideRatio](https://github.com/consideRatio)) -- Relax hook-image-puller to make upgrades more reliable [#1787](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1787) ([@consideRatio](https://github.com/consideRatio)) -- Updates to user-scheduler's coupling to the kube-scheduler binary [#1778](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1778) ([@consideRatio](https://github.com/consideRatio)) -- https: Only expose port 443 if we really have HTTPS on [#1758](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1758) ([@yuvipanda](https://github.com/yuvipanda)) -- jupyterhub existing image pull secret configuration load bug fixed [#1727](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1727) ([@mpolatcan](https://github.com/mpolatcan)) -- fix: jupyterhub services without apiToken was ignored [#1721](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1721) ([@consideRatio](https://github.com/consideRatio)) -- fix: autohttps cert acquisition stability fixed [#1719](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1719) ([@consideRatio](https://github.com/consideRatio)) -- Enable the user scheduler to pay attention to CSI volume count [#1699](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1699) ([@rschroll](https://github.com/rschroll)) -- secret-sync: selective write to secret / functional logs [#1678](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1678) ([@consideRatio](https://github.com/consideRatio)) -- Tighten and flesh out networkpolicies [#1670](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1670) ([@consideRatio](https://github.com/consideRatio)) - -#### Maintenance and upkeep improvements - -- use jupyterhub 1.2.0 [#1884](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1884) ([@minrk](https://github.com/minrk)) -- Update Travis CI badge following .org -> com migration [#1882](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1882) ([@consideRatio](https://github.com/consideRatio)) -- Remove globus_sdk and update various Docker images [#1881](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1881) ([@consideRatio](https://github.com/consideRatio)) -- Complementary fix to recent aesthetics PR [#1878](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1878) ([@consideRatio](https://github.com/consideRatio)) -- Helm template aesthetics fixes [#1877](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1877) ([@consideRatio](https://github.com/consideRatio)) -- Added rediraffe redirecgtion [#1876](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1876) ([@NerdSec](https://github.com/NerdSec)) -- Bump OAuthenticator to 0.12.0 from 0.11.0 [#1874](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1874) ([@consideRatio](https://github.com/consideRatio)) -- Dependency: bump proxy pods image of CHP to 4.2.2 for bugfixes and docker image dependency updates [#1873](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1873) ([@consideRatio](https://github.com/consideRatio)) -- Pin Traefik to v2.3.2 for cert acquisition stability [#1859](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1859) ([@consideRatio](https://github.com/consideRatio)) -- CI: Add logs for autohttps pod on failure to debug intermittent issue [#1855](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1855) ([@consideRatio](https://github.com/consideRatio)) -- CI: Try to improve test stability and autohttps cert aquisition reliability [#1854](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1854) ([@consideRatio](https://github.com/consideRatio)) -- CI: bump k3s and helm versions [#1848](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1848) ([@consideRatio](https://github.com/consideRatio)) -- Add dependabot config to update dependencies automatically [#1844](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1844) ([@jgwerner](https://github.com/jgwerner)) -- try out jupyterhub 1.2.0b1 [#1841](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1841) ([@minrk](https://github.com/minrk)) -- Remove unnecessary Dockerfile build step [#1833](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1833) ([@bleggett](https://github.com/bleggett)) -- Add schema.yaml and validate.py to .helmignore [#1832](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1832) ([@consideRatio](https://github.com/consideRatio)) -- CI: reorder ci jobs to provide relevant feedback quickly [#1828](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1828) ([@consideRatio](https://github.com/consideRatio)) -- Revert recent removal of image-pulling related to cloudMetadata blocker [#1826](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1826) ([@consideRatio](https://github.com/consideRatio)) -- Add maintainers / owners to register with Artifact Hub [#1820](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1820) ([@consideRatio](https://github.com/consideRatio)) -- CI: fix RTD builds on push to master [#1816](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1816) ([@consideRatio](https://github.com/consideRatio)) -- deprecation: warn when proxy.https is modified and proxy.https.enabled=true [#1807](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1807) ([@consideRatio](https://github.com/consideRatio)) -- Soft deprecate singleuser.cloudMetadata.enabled in favor of blockWithIptables [#1805](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1805) ([@consideRatio](https://github.com/consideRatio)) -- hub livenessProbe: bump from 1m to 3m delay before probes are sent [#1804](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1804) ([@consideRatio](https://github.com/consideRatio)) -- hub image: bump kubespawner to 0.14.0 [#1802](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1802) ([@consideRatio](https://github.com/consideRatio)) -- ci: bump helm to 3.3.2 and test with k8s 1.19 also [#1783](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1783) ([@consideRatio](https://github.com/consideRatio)) -- user-scheduler: tweak modern configuration [#1782](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1782) ([@consideRatio](https://github.com/consideRatio)) -- Update to newer version of 'pause' container [#1781](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1781) ([@yuvipanda](https://github.com/yuvipanda)) -- Remove memory / cpu limits for pre-puller [#1780](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1780) ([@yuvipanda](https://github.com/yuvipanda)) -- Updates to user-scheduler's coupling to the kube-scheduler binary [#1778](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1778) ([@consideRatio](https://github.com/consideRatio)) -- hub: Switch base image to latest LTS [#1772](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1772) ([@yuvipanda](https://github.com/yuvipanda)) -- CI: Add test for singleuser.extraEnv [#1769](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1769) ([@consideRatio](https://github.com/consideRatio)) -- Bump KubeSpawner to 0.13.0 [#1768](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1768) ([@consideRatio](https://github.com/consideRatio)) -- CI: always publish helm chart on push to master [#1765](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1765) ([@consideRatio](https://github.com/consideRatio)) -- Bump traefik (autohttps pod) to v2.3 [#1756](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1756) ([@consideRatio](https://github.com/consideRatio)) -- Update JupyterHub's python package dependencies [#1752](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1752) ([@jgwerner](https://github.com/jgwerner)) -- Fix travis by pinning docker python package version [#1743](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1743) ([@chancez](https://github.com/chancez)) -- update kubespawner to 0.12 [#1722](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1722) ([@minrk](https://github.com/minrk)) -- k8s api compatibility: add conditional to ingress apiVersion [#1718](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1718) ([@davidsmf](https://github.com/davidsmf)) -- Upgrade libc to patch vulnerability in hub img [#1715](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1715) ([@meneal](https://github.com/meneal)) -- Autohttps reliability fix: bump traefik version [#1714](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1714) ([@consideRatio](https://github.com/consideRatio)) -- k8s-hub img rebuild -> dependencies refrozen [#1713](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1713) ([@consideRatio](https://github.com/consideRatio)) -- removing circleci [#1711](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1711) ([@choldgraf](https://github.com/choldgraf)) -- Complexity reduction - combine passthrough values.yaml data in hub-config (k8s configmap) to hub-secret (k8s secret) [#1682](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1682) ([@consideRatio](https://github.com/consideRatio)) -- secret-sync: selective write to secret / functional logs [#1678](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1678) ([@consideRatio](https://github.com/consideRatio)) -- DX: k3s/k3d instead of kind & CI: autohttps testing [#1664](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1664) ([@consideRatio](https://github.com/consideRatio)) -- cleanup: remove old deploy secret [#1661](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1661) ([@consideRatio](https://github.com/consideRatio)) -- RTD build fix: get correct version of sphinx [#1658](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1658) ([@consideRatio](https://github.com/consideRatio)) -- Force sphinx>=2,<3 for myst_parser [#1657](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1657) ([@consideRatio](https://github.com/consideRatio)) -- Use idle culler from jupyterhub-idle-culler package [#1648](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1648) ([@yuvipanda](https://github.com/yuvipanda)) -- Refactor: reference ports by name instead of repeating the number [#1645](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1645) ([@consideRatio](https://github.com/consideRatio)) -- DX: refactor helm template [#1635](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1635) ([@consideRatio](https://github.com/consideRatio)) -- CI: fix sphinx warnings turned into errors [#1634](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1634) ([@consideRatio](https://github.com/consideRatio)) -- Dep: Bump deploy/autohttps's traefik to v2.2 [#1632](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1632) ([@consideRatio](https://github.com/consideRatio)) -- DX: more recognizable port numbers [#1631](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1631) ([@consideRatio](https://github.com/consideRatio)) - -#### Documentation improvements - -- Add back Helm chart badge for latest pre-release (alpha, beta) [#1879](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1879) ([@consideRatio](https://github.com/consideRatio)) -- Added rediraffe redirecgtion [#1876](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1876) ([@NerdSec](https://github.com/NerdSec)) -- docs: fix edit button, so it doesn't go to a 404 page [#1864](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1864) ([@consideRatio](https://github.com/consideRatio)) -- Fix link to Hub23 docs [#1860](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1860) ([@sgibson91](https://github.com/sgibson91)) -- Provide links to Hub23 deployment guide [#1850](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1850) ([@sgibson91](https://github.com/sgibson91)) -- docs: clarify user-placeholder resource requests [#1835](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1835) ([@consideRatio](https://github.com/consideRatio)) -- Change doc structure [#1825](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1825) ([@NerdSec](https://github.com/NerdSec)) -- Remove mistakenly introduced artifact [#1824](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1824) ([@consideRatio](https://github.com/consideRatio)) -- fixing broken links [#1823](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1823) ([@choldgraf](https://github.com/choldgraf)) -- README.md: badges for the helm chart repo to go directly to the relevant view [#1815](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1815) ([@consideRatio](https://github.com/consideRatio)) -- Docs: fix some sphinx warnings [#1796](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1796) ([@consideRatio](https://github.com/consideRatio)) -- Fix legacy version in DigitalOcean Kubernetes setup doc [#1788](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1788) ([@subwaymatch](https://github.com/subwaymatch)) -- Add terraform resources to the community resources section [#1776](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1776) ([@salvis2](https://github.com/salvis2)) -- Docs: fixes to outdated links found by the linkchecker [#1770](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1770) ([@consideRatio](https://github.com/consideRatio)) -- Leave a comment about where HUB*SERVICE*\* values come from [#1766](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1766) ([@mriedem](https://github.com/mriedem)) -- Unindent lines to fix the bug in "Specify certificate through Secret resource" [#1755](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1755) ([@salvis2](https://github.com/salvis2)) -- [Documentation] Authenticating with Auth0 [#1736](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1736) ([@asubb](https://github.com/asubb)) -- Docs/schema.yaml patches [#1735](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1735) ([@rubdos](https://github.com/rubdos)) -- Fix broken link to Jupyter contributor guide [#1729](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1729) ([@sgibson91](https://github.com/sgibson91)) -- Fix link [#1728](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1728) ([@JarnoRFB](https://github.com/JarnoRFB)) -- docs: myst-parser deprecation adjustment [#1723](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1723) ([@consideRatio](https://github.com/consideRatio)) -- docs: fix linkcheck warning [#1720](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1720) ([@consideRatio](https://github.com/consideRatio)) -- Docs: fix squeezed logo, broken links, and strip unused CSS and templates [#1710](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1710) ([@consideRatio](https://github.com/consideRatio)) -- Add documentation to create a Kubernetes cluster on OVH [#1704](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1704) ([@jtpio](https://github.com/jtpio)) -- DX: final touches on CONTRIBUTING.md [#1696](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1696) ([@consideRatio](https://github.com/consideRatio)) -- Update Google auth to use a list for hosted_domain [#1695](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1695) ([@petebachant](https://github.com/petebachant)) -- Simplify setting up JupyterLab as default [#1690](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1690) ([@yuvipanda](https://github.com/yuvipanda)) -- Use --num-nodes instead of --size to resize gcloud cluster [#1688](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1688) ([@aculich](https://github.com/aculich)) -- docs: fix broken links [#1687](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1687) ([@consideRatio](https://github.com/consideRatio)) -- Change helm chart version in setup documentation [#1685](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1685) ([@ivanpokupec](https://github.com/ivanpokupec)) -- Docs: assume usage of helm3 over deprecated helm2 [#1684](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1684) ([@GeorgianaElena](https://github.com/GeorgianaElena)) -- removal: Vagrant for local dev [#1668](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1668) ([@consideRatio](https://github.com/consideRatio)) -- docs: fixed links [#1666](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1666) ([@consideRatio](https://github.com/consideRatio)) -- DX: k3s/k3d instead of kind & CI: autohttps testing [#1664](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1664) ([@consideRatio](https://github.com/consideRatio)) -- Reference static ip docs [#1663](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1663) ([@GeorgianaElena](https://github.com/GeorgianaElena)) -- Docs: remove too outdated cost-calculator [#1660](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1660) ([@consideRatio](https://github.com/consideRatio)) -- Update create service principle command. [#1654](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1654) ([@superyaniv](https://github.com/superyaniv)) -- proxy.service.type: Default is different from hub.service.type [#1647](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1647) ([@manics](https://github.com/manics)) -- Fix user storage customization variable [#1640](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1640) ([@bibz](https://github.com/bibz)) -- Fix broken links in the Reference documentation [#1639](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1639) ([@bibz](https://github.com/bibz)) -- Update index.rst [#1629](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1629) ([@deinal](https://github.com/deinal)) -- AWS documentation fixes [#1564](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1564) ([@metonymic-smokey](https://github.com/metonymic-smokey)) -- add Auth0 configuration documentation [#1436](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1436) ([@philvarner](https://github.com/philvarner)) - -#### Contributors to this release - -A huge warm thank you for the collaborative effort in this release! Below we -celebrate this specific GitHub repositories contributors, but we have reason to -be thankful to soo many other contributors in the projects we depend on! Thank -you everyone! - -([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2020-04-15&to=2020-10-29&type=c)) - -[@01100010011001010110010101110000](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3A01100010011001010110010101110000+updated%3A2020-04-15..2020-10-29&type=Issues) | [@ablekh](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aablekh+updated%3A2020-04-15..2020-10-29&type=Issues) | [@aculich](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aaculich+updated%3A2020-04-15..2020-10-29&type=Issues) | [@adi413](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aadi413+updated%3A2020-04-15..2020-10-29&type=Issues) | [@agrahamlincoln](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aagrahamlincoln+updated%3A2020-04-15..2020-10-29&type=Issues) | [@aguinaldoabbj](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aaguinaldoabbj+updated%3A2020-04-15..2020-10-29&type=Issues) | [@Aisuko](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AAisuko+updated%3A2020-04-15..2020-10-29&type=Issues) | [@akaszynski](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aakaszynski+updated%3A2020-04-15..2020-10-29&type=Issues) | [@albertmichaelj](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aalbertmichaelj+updated%3A2020-04-15..2020-10-29&type=Issues) | [@alexmorley](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aalexmorley+updated%3A2020-04-15..2020-10-29&type=Issues) | [@amanda-tan](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aamanda-tan+updated%3A2020-04-15..2020-10-29&type=Issues) | [@arpitsri3](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aarpitsri3+updated%3A2020-04-15..2020-10-29&type=Issues) | [@asubb](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aasubb+updated%3A2020-04-15..2020-10-29&type=Issues) | [@aydintd](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aaydintd+updated%3A2020-04-15..2020-10-29&type=Issues) | [@bebosudo](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abebosudo+updated%3A2020-04-15..2020-10-29&type=Issues) | [@BertR](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ABertR+updated%3A2020-04-15..2020-10-29&type=Issues) | [@betatim](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abetatim+updated%3A2020-04-15..2020-10-29&type=Issues) | [@betolink](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abetolink+updated%3A2020-04-15..2020-10-29&type=Issues) | [@bibz](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abibz+updated%3A2020-04-15..2020-10-29&type=Issues) | [@bleggett](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ableggett+updated%3A2020-04-15..2020-10-29&type=Issues) | [@cam72cam](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acam72cam+updated%3A2020-04-15..2020-10-29&type=Issues) | [@carat64](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acarat64+updated%3A2020-04-15..2020-10-29&type=Issues) | [@cbanek](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acbanek+updated%3A2020-04-15..2020-10-29&type=Issues) | [@cboettig](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acboettig+updated%3A2020-04-15..2020-10-29&type=Issues) | [@chancez](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Achancez+updated%3A2020-04-15..2020-10-29&type=Issues) | [@chicocvenancio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Achicocvenancio+updated%3A2020-04-15..2020-10-29&type=Issues) | [@choldgraf](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acholdgraf+updated%3A2020-04-15..2020-10-29&type=Issues) | [@chrisroat](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Achrisroat+updated%3A2020-04-15..2020-10-29&type=Issues) | [@clkao](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aclkao+updated%3A2020-04-15..2020-10-29&type=Issues) | [@conet](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aconet+updated%3A2020-04-15..2020-10-29&type=Issues) | [@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2020-04-15..2020-10-29&type=Issues) | [@craig-willis](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acraig-willis+updated%3A2020-04-15..2020-10-29&type=Issues) | [@cslovell](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acslovell+updated%3A2020-04-15..2020-10-29&type=Issues) | [@dalonlobo](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adalonlobo+updated%3A2020-04-15..2020-10-29&type=Issues) | [@dalssaso](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adalssaso+updated%3A2020-04-15..2020-10-29&type=Issues) | [@danroliver](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adanroliver+updated%3A2020-04-15..2020-10-29&type=Issues) | [@DarkBlaez](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ADarkBlaez+updated%3A2020-04-15..2020-10-29&type=Issues) | [@davidsmf](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adavidsmf+updated%3A2020-04-15..2020-10-29&type=Issues) | [@deinal](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adeinal+updated%3A2020-04-15..2020-10-29&type=Issues) | [@dimm0](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adimm0+updated%3A2020-04-15..2020-10-29&type=Issues) | [@dkipping](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adkipping+updated%3A2020-04-15..2020-10-29&type=Issues) | [@dmpe](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Admpe+updated%3A2020-04-15..2020-10-29&type=Issues) | [@donotpush](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adonotpush+updated%3A2020-04-15..2020-10-29&type=Issues) | [@duongnt](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aduongnt+updated%3A2020-04-15..2020-10-29&type=Issues) | [@easel](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aeasel+updated%3A2020-04-15..2020-10-29&type=Issues) | [@echarles](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aecharles+updated%3A2020-04-15..2020-10-29&type=Issues) | [@Edward-liang](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AEdward-liang+updated%3A2020-04-15..2020-10-29&type=Issues) | [@eric-leblouch](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aeric-leblouch+updated%3A2020-04-15..2020-10-29&type=Issues) | [@erinfry6](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aerinfry6+updated%3A2020-04-15..2020-10-29&type=Issues) | [@etheleon](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aetheleon+updated%3A2020-04-15..2020-10-29&type=Issues) | [@farzadz](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Afarzadz+updated%3A2020-04-15..2020-10-29&type=Issues) | [@filippo82](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Afilippo82+updated%3A2020-04-15..2020-10-29&type=Issues) | [@frankgu968](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Afrankgu968+updated%3A2020-04-15..2020-10-29&type=Issues) | [@frouzbeh](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Afrouzbeh+updated%3A2020-04-15..2020-10-29&type=Issues) | [@GeorgianaElena](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AGeorgianaElena+updated%3A2020-04-15..2020-10-29&type=Issues) | [@GergelyKalmar](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AGergelyKalmar+updated%3A2020-04-15..2020-10-29&type=Issues) | [@gsemet](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Agsemet+updated%3A2020-04-15..2020-10-29&type=Issues) | [@Guanzhou-Ke](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AGuanzhou-Ke+updated%3A2020-04-15..2020-10-29&type=Issues) | [@Gungo](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AGungo+updated%3A2020-04-15..2020-10-29&type=Issues) | [@h4gen](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ah4gen+updated%3A2020-04-15..2020-10-29&type=Issues) | [@harsimranmaan](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aharsimranmaan+updated%3A2020-04-15..2020-10-29&type=Issues) | [@hdimitriou](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ahdimitriou+updated%3A2020-04-15..2020-10-29&type=Issues) | [@hickst](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ahickst+updated%3A2020-04-15..2020-10-29&type=Issues) | [@hnykda](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ahnykda+updated%3A2020-04-15..2020-10-29&type=Issues) | [@hqwl159](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ahqwl159+updated%3A2020-04-15..2020-10-29&type=Issues) | [@IamViditAgarwal](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AIamViditAgarwal+updated%3A2020-04-15..2020-10-29&type=Issues) | [@ilhaan](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ailhaan+updated%3A2020-04-15..2020-10-29&type=Issues) | [@ivanpokupec](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aivanpokupec+updated%3A2020-04-15..2020-10-29&type=Issues) | [@jacobtomlinson](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajacobtomlinson+updated%3A2020-04-15..2020-10-29&type=Issues) | [@jahstreet](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajahstreet+updated%3A2020-04-15..2020-10-29&type=Issues) | [@JarnoRFB](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AJarnoRFB+updated%3A2020-04-15..2020-10-29&type=Issues) | [@jeremievallee](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajeremievallee+updated%3A2020-04-15..2020-10-29&type=Issues) | [@jgerardsimcock](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajgerardsimcock+updated%3A2020-04-15..2020-10-29&type=Issues) | [@jgwerner](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajgwerner+updated%3A2020-04-15..2020-10-29&type=Issues) | [@josibake](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajosibake+updated%3A2020-04-15..2020-10-29&type=Issues) | [@JPMoresmau](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AJPMoresmau+updated%3A2020-04-15..2020-10-29&type=Issues) | [@jreadey](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajreadey+updated%3A2020-04-15..2020-10-29&type=Issues) | [@jtlz2](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajtlz2+updated%3A2020-04-15..2020-10-29&type=Issues) | [@jtpio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajtpio+updated%3A2020-04-15..2020-10-29&type=Issues) | [@julienchastang](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajulienchastang+updated%3A2020-04-15..2020-10-29&type=Issues) | [@jzf2101](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajzf2101+updated%3A2020-04-15..2020-10-29&type=Issues) | [@kinow](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Akinow+updated%3A2020-04-15..2020-10-29&type=Issues) | [@kristofmartens](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Akristofmartens+updated%3A2020-04-15..2020-10-29&type=Issues) | [@kyprifog](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Akyprifog+updated%3A2020-04-15..2020-10-29&type=Issues) | [@leolb-aphp](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aleolb-aphp+updated%3A2020-04-15..2020-10-29&type=Issues) | [@loki1978](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aloki1978+updated%3A2020-04-15..2020-10-29&type=Issues) | [@ltupin](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Altupin+updated%3A2020-04-15..2020-10-29&type=Issues) | [@lxylxy123456](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Alxylxy123456+updated%3A2020-04-15..2020-10-29&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2020-04-15..2020-10-29&type=Issues) | [@mathematicalmichael](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amathematicalmichael+updated%3A2020-04-15..2020-10-29&type=Issues) | [@meeseeksmachine](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ameeseeksmachine+updated%3A2020-04-15..2020-10-29&type=Issues) | [@meneal](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ameneal+updated%3A2020-04-15..2020-10-29&type=Issues) | [@metonymic-smokey](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ametonymic-smokey+updated%3A2020-04-15..2020-10-29&type=Issues) | [@mhwasil](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amhwasil+updated%3A2020-04-15..2020-10-29&type=Issues) | [@minrk](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aminrk+updated%3A2020-04-15..2020-10-29&type=Issues) | [@mjuric](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amjuric+updated%3A2020-04-15..2020-10-29&type=Issues) | [@moorepants](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amoorepants+updated%3A2020-04-15..2020-10-29&type=Issues) | [@mpolatcan](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ampolatcan+updated%3A2020-04-15..2020-10-29&type=Issues) | [@mriedem](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amriedem+updated%3A2020-04-15..2020-10-29&type=Issues) | [@mrocklin](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amrocklin+updated%3A2020-04-15..2020-10-29&type=Issues) | [@NerdSec](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ANerdSec+updated%3A2020-04-15..2020-10-29&type=Issues) | [@nscozzaro](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Anscozzaro+updated%3A2020-04-15..2020-10-29&type=Issues) | [@openthings](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aopenthings+updated%3A2020-04-15..2020-10-29&type=Issues) | [@pcfens](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Apcfens+updated%3A2020-04-15..2020-10-29&type=Issues) | [@perllaghu](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aperllaghu+updated%3A2020-04-15..2020-10-29&type=Issues) | [@petebachant](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Apetebachant+updated%3A2020-04-15..2020-10-29&type=Issues) | [@peterrmah](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Apeterrmah+updated%3A2020-04-15..2020-10-29&type=Issues) | [@philvarner](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aphilvarner+updated%3A2020-04-15..2020-10-29&type=Issues) | [@prateekkhera](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aprateekkhera+updated%3A2020-04-15..2020-10-29&type=Issues) | [@rabernat](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Arabernat+updated%3A2020-04-15..2020-10-29&type=Issues) | [@RAbraham](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ARAbraham+updated%3A2020-04-15..2020-10-29&type=Issues) | [@remche](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aremche+updated%3A2020-04-15..2020-10-29&type=Issues) | [@rkdarst](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Arkdarst+updated%3A2020-04-15..2020-10-29&type=Issues) | [@rkevin-arch](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Arkevin-arch+updated%3A2020-04-15..2020-10-29&type=Issues) | [@rmoe](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Armoe+updated%3A2020-04-15..2020-10-29&type=Issues) | [@rnestler](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Arnestler+updated%3A2020-04-15..2020-10-29&type=Issues) | [@rschroll](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Arschroll+updated%3A2020-04-15..2020-10-29&type=Issues) | [@rubdos](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Arubdos+updated%3A2020-04-15..2020-10-29&type=Issues) | [@ryanlovett](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aryanlovett+updated%3A2020-04-15..2020-10-29&type=Issues) | [@salvis2](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asalvis2+updated%3A2020-04-15..2020-10-29&type=Issues) | [@sampathkethineedi](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asampathkethineedi+updated%3A2020-04-15..2020-10-29&type=Issues) | [@scivm](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ascivm+updated%3A2020-04-15..2020-10-29&type=Issues) | [@Sefriol](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ASefriol+updated%3A2020-04-15..2020-10-29&type=Issues) | [@sgibson91](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asgibson91+updated%3A2020-04-15..2020-10-29&type=Issues) | [@sgloutnikov](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asgloutnikov+updated%3A2020-04-15..2020-10-29&type=Issues) | [@shenghu](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ashenghu+updated%3A2020-04-15..2020-10-29&type=Issues) | [@snickell](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asnickell+updated%3A2020-04-15..2020-10-29&type=Issues) | [@sstarcher](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asstarcher+updated%3A2020-04-15..2020-10-29&type=Issues) | [@stefansedich](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Astefansedich+updated%3A2020-04-15..2020-10-29&type=Issues) | [@stevenstetzler](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Astevenstetzler+updated%3A2020-04-15..2020-10-29&type=Issues) | [@stv0g](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Astv0g+updated%3A2020-04-15..2020-10-29&type=Issues) | [@subwaymatch](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asubwaymatch+updated%3A2020-04-15..2020-10-29&type=Issues) | [@summerswallow-whi](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asummerswallow-whi+updated%3A2020-04-15..2020-10-29&type=Issues) | [@superyaniv](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asuperyaniv+updated%3A2020-04-15..2020-10-29&type=Issues) | [@support](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asupport+updated%3A2020-04-15..2020-10-29&type=Issues) | [@suryag10](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asuryag10+updated%3A2020-04-15..2020-10-29&type=Issues) | [@TiemenSch](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ATiemenSch+updated%3A2020-04-15..2020-10-29&type=Issues) | [@tirumerla](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Atirumerla+updated%3A2020-04-15..2020-10-29&type=Issues) | [@tjcrone](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Atjcrone+updated%3A2020-04-15..2020-10-29&type=Issues) | [@tmshn](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Atmshn+updated%3A2020-04-15..2020-10-29&type=Issues) | [@TomasBeuzen](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ATomasBeuzen+updated%3A2020-04-15..2020-10-29&type=Issues) | [@tracek](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Atracek+updated%3A2020-04-15..2020-10-29&type=Issues) | [@verdurin](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Averdurin+updated%3A2020-04-15..2020-10-29&type=Issues) | [@vindvaki](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Avindvaki+updated%3A2020-04-15..2020-10-29&type=Issues) | [@vishwesh5](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Avishwesh5+updated%3A2020-04-15..2020-10-29&type=Issues) | [@welcome](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Awelcome+updated%3A2020-04-15..2020-10-29&type=Issues) | [@willingc](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Awillingc+updated%3A2020-04-15..2020-10-29&type=Issues) | [@yuvipanda](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ayuvipanda+updated%3A2020-04-15..2020-10-29&type=Issues) | [@zxcGrace](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AzxcGrace+updated%3A2020-04-15..2020-10-29&type=Issues) - -## [0.9] - -### [0.9.0] - 2020-04-15 - -#### Release summary - -This Helm chart release is mainly a maintenance release featuring the latest -JupyterHub (1.1.0) and authenticators along with bug fixes and some additional -helpful configuration options. - -Noteworthy: - -- An issue with automatic acquisition of HTTPS certificates has been resolved - since 0.9.0-beta.3. -- Fixed a compatibility issue with Kubernetes 1.16+ -- The `images/hub/requirements.txt` file in this repo can now be used to track - what specific version has been used at any point in time. -- [jupyterhub-nativeauthenticator](https://native-authenticator.readthedocs.io/en/latest/) added to the JupyterHub Docker image. - -Bumped dependencies: - -- jupyterhub version 1.1.0 -- jupyterhub-ldapauthenticator version 1.3.0 -- jupyterhub-kubespawner version 0.11.1 -- oauthenticator version 0.11.0 -- kubernetes version 10.0.1 - -#### Upgrade instructions (IMPORTANT) - -1. If you are using Helm 2, upgrade to the latest Helm 2 version. And if you are - using Helm 3, upgrade to the latest Helm 3 version. - - Upgrading to Helm 3 from Helm 2 requires additional steps not covered here, - so for now please stay with your current major version of helm (2 or 3). - - ``` - # Figure out what version you currently have locally, you should use - # release of the same major version you have used before. - helm version - ``` - - Install either the latest [Helm - 2](https://v2.helm.sh/docs/using_helm/#installing-helm) or [Helm - 3](https://helm.sh/docs/intro/install/) depending on what major version you - currently had worked with. - - ``` - # verify you successfully upgraded helm - helm version - - # if you just upgraded helm 2, also upgrade tiller - helm init --upgrade --service-account=tiller - ``` - -2. Use `--cleanup-on-fail` when using `helm upgrade`. - - Helm can enter a problematic state by a `helm` install or upgrade process - which started creating Kubernetes resources, but then didn't finish at all or - didn't finish successfully. It can cause resources created that helm will - later come in conflict with. - - To mitigate this, we suggest always using `--cleanup-on-fail` with this Helm - chart, it is a solid behavior that reduce a lot of head ache. - -3. If you use `--wait`, or `--atomic` which implies `--wait`: do not manually - cancel the upgrade! - - If you would abort the upgrade when using `--wait` and Kubernetes resources - has been created, resources will have been created that can cause conflict - with future upgrades and require you to manually clean them up. - -4. Delete resources that could cause issues before upgrading. - - ```shell - # replace below with where jupyterhub is installed - kubectl delete -n clusterrole,clusterrolebinding,role,rolebinding,serviceaccount,deployment,configmap,service -l component=autohttps - ``` - -#### Troubleshooting upgrade - -If you get an error similar to the one below, it is a symptom of having -attempted a `helm upgrade` that failed where helm lost track of some newly -created resources. A good solution is to delete all of these resources and try -again. - -```shell -# replace below with where jupyterhub is installed -kubectl delete -n clusterrole,clusterrolebinding,role,rolebinding,serviceaccount,deployment,configmap,service -l component=autohttps -``` - -To avoid this in the future, use `--cleanup-on-fail` with the `helm upgrade` -command. It is not a fool proof way to avoid it, but . And note that even if that flag is used, an interupption for example during `--wait` or `--atomic` which implies `--wait`, be -aware of an interruption while waiting can very likely cause this to arise on -the following upgrade attempt. - -> ``` -> error: kind ConfigMap with the name "traefik-proxy-config" already exists in -> the cluster and wasn't defined in the previous release. Before upgrading, -> please either delete the resource from the cluster or remove it from the chart -> ``` - -#### Dependency updates - -- Bump configurable-http-proxy image [#1598](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1598) ([@consideRatio](https://github.com/consideRatio)) -- fix: Bump to base-notebook with JH 1.1.0 etc [#1588](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1588) ([@bitnik](https://github.com/bitnik)) - -#### Maintenance - -- Docs: refactor/docs for local development of docs [#1617](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1617) ([@consideRatio](https://github.com/consideRatio)) -- [MRG] sphinx: linkcheck in travis (allowed to fail) [#1611](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1611) ([@manics](https://github.com/manics)) -- [MRG] Sphinx: warnings are errors [#1610](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1610) ([@manics](https://github.com/manics)) -- pydata theme [#1608](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1608) ([@choldgraf](https://github.com/choldgraf)) -- Small typo fix in doc [#1591](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1591) ([@sebastianpfischer](https://github.com/sebastianpfischer)) -- [MRG] Pin sphinx theme [#1589](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1589) ([@manics](https://github.com/manics)) -- init helm and tiller with history-max settings [#1587](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1587) ([@bitnik](https://github.com/bitnik)) -- Changelog for 0.9.0-beta.4 [#1585](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1585) ([@manics](https://github.com/manics)) -- freeze environment in hub image [#1562](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1562) ([@minrk](https://github.com/minrk)) - -### [0.9.0-beta.4] - 2020-02-26 - -#### Added - -- Add nativeauthenticator to hub image [#1583](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1583) ([@consideRatio](https://github.com/consideRatio)) -- Add option to remove named server when culling [#1558](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1558) ([@betatim](https://github.com/betatim)) - -#### Dependency updates - -- jupyterhub-ldapauthenticator==1.3 [#1576](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1576) ([@manics](https://github.com/manics)) -- First-class azuread support, oauth 0.11 [#1563](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1563) ([@minrk](https://github.com/minrk)) -- simplify hub-requirements [#1560](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1560) ([@minrk](https://github.com/minrk)) -- Bump to base-notebook with JH 1.1.0 etc [#1549](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1549) ([@consideRatio](https://github.com/consideRatio)) - -#### Fixed - -- Fix removing of named servers when culled [#1567](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1567) ([@consideRatio](https://github.com/consideRatio)) - -#### Maintenance - -- Added gitlab URL [#1577](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1577) ([@metonymic-smokey](https://github.com/metonymic-smokey)) -- Fix reference doc link [#1570](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1570) ([@clkao](https://github.com/clkao)) -- Add contributor badge [#1559](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1559) ([@GeorgianaElena](https://github.com/GeorgianaElena)) -- Trying to clean up formatting [#1555](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1555) ([@jeremycadams](https://github.com/jeremycadams)) -- Remove unneeded directive in traefik config [#1554](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1554) ([@yuvipanda](https://github.com/yuvipanda)) -- Added documentation of secret https mode [#1553](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1553) ([@RossRKK](https://github.com/RossRKK)) -- Helm 3 preview [#1543](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1543) ([@manics](https://github.com/manics)) - -### [0.9.0-beta.3] - 2020-01-17 - -#### Dependency updates - -- Deploy jupyterhub 1.1.0 stable [#1548](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1548) ([@minrk](https://github.com/minrk)) -- Bump chartpress for Helm 3 compatible dev releases [#1542](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1542) ([@consideRatio](https://github.com/consideRatio)) - -#### Fixed - -- Replace kube-lego + nginx ingress with traefik [#1539](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1539) ([@yuvipanda](https://github.com/yuvipanda)) - -#### Maintenance - -- Update step zero for Azure docs with commands to setup an VNet and network policy [#1527](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1527) ([@sgibson91](https://github.com/sgibson91)) -- Fix duplicate docs label [#1544](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1544) ([@manics](https://github.com/manics)) -- Made GCP docs of compute zone names generic [#1431](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1431) ([@metonymic-smokey](https://github.com/metonymic-smokey)) - -### [0.9.0-beta.2] - 2019-12-26 - -#### Fixed - -- Fix major breaking change if all HTTPS options was disabled introduced just before beta.1 [#1534](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1534) ([@dirkcgrunwald](https://github.com/dirkcgrunwald)) - -### [0.9.0-beta.1] - 2019-12-26 - -Some highlights of relevance for this release are: - -- The default configuration is now catering to autoscaling clusters where nodes - can be added and removed, as compared to fixed clusters where there is only a - fixed amount of nodes. Set `scheduling.userScheduler.enabled` to false if you - are on a fixed size cluster. -- Kubernetes 1.16 compatibility achieved -- Updated dependencies - - jupyterhub==1.1.0b1 - - kubernetes==0.10.1 - - kubespawner==0.11.1 - - oauthenticator==0.10.0 - -#### Added - -- Added ability to configure liveness/readiness probes on the hub/proxy [#1480](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1480) ([@mrow4a](https://github.com/mrow4a)) -- Added ability to use an existing/shared image pull secret for hub and image pullers [#1426](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1426) ([@LaurentGoderre](https://github.com/LaurentGoderre)) -- Added ability to configure the proxy's load balancer service's access restrictions (`loadBalancerSourceRanges`) [#1418](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1418) ([@GergelyKalmar](https://github.com/GergelyKalmar)) -- Added `user-scheduler` pod->node scheduling policy configuration [#1409](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1409) ([@yuvipanda](https://github.com/yuvipanda)) -- Added ability to add additional ingress rules to k8s NetworkPolicy resources [#1380](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1380) ([@yuvipanda](https://github.com/yuvipanda)) -- Enabled the continuous image puller by default [#1276](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1276) ([@consideRatio](https://github.com/consideRatio)) -- Added ability to configure initContainers of the hub pod [#1274](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1274) ([@scottyhq](https://github.com/scottyhq)) -- Enabled the user-scheduler by default [#1272](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1272) ([@minrk](https://github.com/minrk)) -- Added ability to use an existing jupyterhub configuration k8s secret for hub (not recommended) [#1142](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1142) ([@koen92](https://github.com/koen92)) -- Added use of liveness/readinessProbe by default [#1004](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1004) ([@tmshn](https://github.com/tmshn)) - -#### Dependency updates - -- Bump JupyterHub to 1.1.0b1 [#1533](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1533) ([@consideRatio](https://github.com/consideRatio)) -- Update JupyterHub version [#1524](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1524) ([@bitnik](https://github.com/bitnik)) -- Re-add ltiauthenticator 0.4.0 to hub image [#1519](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1519) ([@consideRatio](https://github.com/consideRatio)) -- Fix hub image dependency versions, disable ltiauthenticator, use chartpress==0.5.0 [#1518](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1518) ([@consideRatio](https://github.com/consideRatio)) -- Update hub image dependencies and RELEASE.md regarding dependencies [#1484](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1484) ([@consideRatio](https://github.com/consideRatio)) -- Bump kubespawner to 0.11.1 for spawner progress bugfix [#1502](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1502) ([@consideRatio](https://github.com/consideRatio)) -- Updated hub image dependencies [#1484](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1484) ([@consideRatio](https://github.com/consideRatio)) -- Updated kube-scheduler binary used by user-scheduler, kubespawner, kubernetes python client, and oauthenticator [#1483](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1483) ([@consideRatio](https://github.com/consideRatio)) -- Bump CHP to 4.2.0 - we get quicker chart upgrades now [#1481](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1481) ([@consideRatio](https://github.com/consideRatio)) -- Bump singleuser-sample [#1473](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1473) ([@consideRatio](https://github.com/consideRatio)) -- Bump python-kubernetes to 9.0._ (later also to 10.0._) [#1454](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1454) ([@clkao](https://github.com/clkao)) -- Bump tmpauthenticator to 0.6 (needed for jupyterhub 1.0) [#1299](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1299) ([@manics](https://github.com/manics)) -- Include jupyter-firstuseauthenticator. [#1288](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1288) ([@danielballan](https://github.com/danielballan)) -- Bump jupyterhub to 1.0.0 (later also to a post 1.0.0 commit) [#1263](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1263) ([@minrk](https://github.com/minrk)) -- Bump CHP image to 4.1.0 from 3.0.0 (later to 4.2.0) [#1246](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1246) ([@consideRatio](https://github.com/consideRatio)) -- Bump oauthenticator 0.8.2 (later to 0.10.0) [#1239](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1239) ([@minrk](https://github.com/minrk)) -- Bump jupyterhub to 1.0b2 (later to an post 1.0.0 commit) [#1224](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1224) ([@minrk](https://github.com/minrk)) - -#### Fixed - -- Workaround upstream kubernetes issue regarding https health check [#1531](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1531) ([@sstarcher](https://github.com/sstarcher)) -- User-scheduler RBAC permissions for local-path-provisioner + increase robustness of hub.baseUrl interaction with the hub deployments health endpoint [#1530](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1530) ([@cutiechi](https://github.com/cutiechi)) -- Fixing #1300 User-scheduler doesn't work with rancher/local-path-provisioner [#1516](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1516) ([@cgiraldo](https://github.com/cgiraldo)) -- Move z2jh.py to a python and linux distribution agnostic path [#1478](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1478) ([@mrow4a](https://github.com/mrow4a)) -- Bugfix for proxy upgrade strategy in PR #1401 [#1404](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1404) ([@consideRatio](https://github.com/consideRatio)) -- Use recreate CHP proxy pod's deployment strategy [#1401](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1401) ([@consideRatio](https://github.com/consideRatio)) -- Proxy deployment: Change probes to https port [#1378](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1378) ([@chicocvenancio](https://github.com/chicocvenancio)) -- Readiness and liveness probes re-added [#1361](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1361) ([@consideRatio](https://github.com/consideRatio)) -- Use 443 as https port or redirection. FIX #806 [#1341](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1341) ([@chicocvenancio](https://github.com/chicocvenancio)) -- Revert "Configure liveness/readinessProbe" [#1356](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1356) ([@consideRatio](https://github.com/consideRatio)) -- Ensure helm chart configuration is passed to JupyterHub where needed [#1338](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1338) ([@bitnik](https://github.com/bitnik)) -- Make proxy redirect to the service port 443 instead of the container port 8443 [#1337](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1337) ([@LucidNeko](https://github.com/LucidNeko)) -- Disable becoming root inside hub and proxy containers [#1280](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1280) ([@yuvipanda](https://github.com/yuvipanda)) -- Configure KubeSpawner with the `singleuser.image.pullPolicy` properly [#1248](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1248) ([@vmarkovtsev](https://github.com/vmarkovtsev)) -- Supply `hub.runAsUser` for the hub at the container level instead of the pod level [#1240](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1240) ([@tmc](https://github.com/tmc)) -- Relax HSTS requirement on subdomains [#1219](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1219) ([@yuvipanda](https://github.com/yuvipanda)) - -#### Maintenance - -- typo [#1529](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1529) ([@raybellwaves](https://github.com/raybellwaves)) -- fix link to Helm chart best practices [#1523](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1523) ([@rpwagner](https://github.com/rpwagner)) -- Adding Globus to the list of users [#1522](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1522) ([@rpwagner](https://github.com/rpwagner)) -- Missing page link for our RBAC documentation #1508 [#1514](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1514) ([@n3o-Bhushan](https://github.com/n3o-Bhushan)) -- Correction of warnings from: make html [#1513](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1513) ([@consideRatio](https://github.com/consideRatio)) -- Fixing URL for user-management documentation #1511 [#1512](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1512) ([@n3o-Bhushan](https://github.com/n3o-Bhushan)) -- DOC: fixing authentication link in user customization guide [#1510](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1510) ([@n3o-Bhushan](https://github.com/n3o-Bhushan)) -- DOC: fix kubernetes setup link [#1505](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1505) ([@raybellwaves](https://github.com/raybellwaves)) -- Update changelog for 0.9.0-beta.1 [#1503](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1503) ([@consideRatio](https://github.com/consideRatio)) -- Fix broken link in architecture.rst [#1488](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1488) ([@amcnicho](https://github.com/amcnicho)) -- Bump kind to 0.6.0 and kindest/node versions [#1487](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1487) ([@clkao](https://github.com/clkao)) -- Avoid rate limiting for k8s resource validation [#1485](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1485) ([@consideRatio](https://github.com/consideRatio)) -- Switching to the Pandas Sphinx theme [#1472](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1472) ([@choldgraf](https://github.com/choldgraf)) -- Add vi / less to hub image [#1471](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1471) ([@yuvipanda](https://github.com/yuvipanda)) -- Added existing pull secrets changes from PR #1426 to schema [#1461](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1461) ([@sgloutnikov](https://github.com/sgloutnikov)) -- Chart upgrade tests [#1459](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1459) ([@consideRatio](https://github.com/consideRatio)) -- Replaced broken links in authentication document #1449 [#1457](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1457) ([@n3o-Bhushan](https://github.com/n3o-Bhushan)) -- Fix typo in home page of docs [#1456](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1456) ([@celine168](https://github.com/celine168)) -- Use helm 2.15.1 [#1453](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1453) ([@consideRatio](https://github.com/consideRatio)) -- Support CD with git tags [#1450](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1450) ([@consideRatio](https://github.com/consideRatio)) -- Added Laurent Goderre as contributor [#1443](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1443) ([@LaurentGoderre](https://github.com/LaurentGoderre)) -- Note about future hard deprecation [#1441](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1441) ([@consideRatio](https://github.com/consideRatio)) -- Fix link formatting for ingress.enabled [#1438](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1438) ([@jtpio](https://github.com/jtpio)) -- CI rework - use kind, validate->test->publish, contrib and release rework [#1422](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1422) ([@consideRatio](https://github.com/consideRatio)) -- Mounting jupyterhub_config.py etc. [#1407](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1407) ([@consideRatio](https://github.com/consideRatio)) -- Ignore venv files [#1388](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1388) ([@GeorgianaElena](https://github.com/GeorgianaElena)) -- Added example for populating notebook user home directory [#1382](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1382) ([@gareth-j](https://github.com/gareth-j)) -- Fix typo in jupyterhub_config.py comment [#1376](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1376) ([@loganlinn](https://github.com/loganlinn)) -- Fixed formatting error in links [#1363](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1363) ([@tlkh](https://github.com/tlkh)) -- Instructions for adding GPUs and increasing shared memory [#1358](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1358) ([@tlkh](https://github.com/tlkh)) -- delete redundant prepuller documentation [#1348](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1348) ([@bitnik](https://github.com/bitnik)) -- Add py-spy to hub image [#1327](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1327) ([@yuvipanda](https://github.com/yuvipanda)) -- Changing Azure Container Service to Azure Kubernetes Service [#1322](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1322) ([@seanmck](https://github.com/seanmck)) -- add explanation for lifecycle_hooks in kubespawner_override [#1309](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1309) ([@clancychilds](https://github.com/clancychilds)) -- Update chart version to 0.8.2 in the docs [#1304](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1304) ([@jtpio](https://github.com/jtpio)) -- Fix azure cli VMSSPreview feature register command [#1298](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1298) ([@dazzag24](https://github.com/dazzag24)) -- Unbreak git build [#1294](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1294) ([@joshbode](https://github.com/joshbode)) -- Update Dockerfile to JH 1.0 [#1291](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1291) ([@vilhelmen](https://github.com/vilhelmen)) -- Fix a couple of mistakes in Google Kubernetes instructions [#1290](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1290) ([@astrofrog](https://github.com/astrofrog)) -- Suggest quotes around tag. [#1289](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1289) ([@danielballan](https://github.com/danielballan)) -- hub: Add useful debugging tools to hub image [#1279](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1279) ([@yuvipanda](https://github.com/yuvipanda)) -- Clean up a line in the CI logs [#1278](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1278) ([@consideRatio](https://github.com/consideRatio)) -- Fix prePuller.extraImages linting etc [#1275](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1275) ([@consideRatio](https://github.com/consideRatio)) -- Fixed minor bug in google pricing calculator [#1264](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1264) ([@noahbjohnson](https://github.com/noahbjohnson)) -- [MRG] Update to Docs: Deploying an Autoscaling Kubernetes cluster on Azure [#1258](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1258) ([@sgibson91](https://github.com/sgibson91)) -- Update to Docs: Add Azure scale command to Expanding/Contracting Cluster section [#1256](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1256) ([@sgibson91](https://github.com/sgibson91)) -- removing extra buttons [#1254](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1254) ([@choldgraf](https://github.com/choldgraf)) -- test appVersion in Chart.yaml [#1238](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1238) ([@minrk](https://github.com/minrk)) -- Adjusts whitespace for a code block in AWS instructions. [#1237](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1237) ([@arokem](https://github.com/arokem)) -- Change heading of multiple-profiles section [#1236](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1236) ([@moschlar](https://github.com/moschlar)) -- Suggest Discourse in issue template [#1234](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1234) ([@manics](https://github.com/manics)) -- Added OAuth callback URL to keycloak OIDC example [#1232](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1232) ([@sgloutnikov](https://github.com/sgloutnikov)) -- Updated notes, pod status to Running [#1231](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1231) ([@sgloutnikov](https://github.com/sgloutnikov)) -- Updated AWS EKS region-availability statement. [#1223](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1223) ([@javabrett](https://github.com/javabrett)) -- Fix the default value of lifecycleHooks [#1218](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1218) ([@consideRatio](https://github.com/consideRatio)) -- Update user-environment.rst [#1217](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1217) ([@manycoding](https://github.com/manycoding)) -- Add Digital Ocean Cloud Instructions for Kubernetes [#1192](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1192) ([@alexmorley](https://github.com/alexmorley)) - -## [0.8] - -### [0.8.2] - 2019-04-01 - -Bumped the underlying JupyterHub to 0.9.6. - -### [0.8.1] - 2019-03-28 - -Bumped the underlying JupyterHub to 0.9.5. - -### [0.8.0] - [Richie Benaud](https://en.wikipedia.org/wiki/Richie_Benaud) - 2019-01-24 - -This release contains JupyterHub version 0.9.4. It requires Kubernetes >= 1.11 and Helm >= 2.11.0. -See [the Helm Chart repository](https://github.com/jupyterhub/helm-chart#release-notes) for -a list of relevant dependencies for all Helm Chart versions. - -It contains new features, additional configuration options, and bug fixes. - -#### Upgrading from 0.7 - -To upgrade your cluster: - -1. backup your hub-db-dir persistent volume and previous configuration files, to be safe -2. read changes here and make any needed updates to your configuration -3. upgrade the chart: - - helm repo update - helm upgrade $RELEASE --force --version 0.8.0 --values config.yaml - -The `--force` flag allows deletion and recreation of objects -that have certain changes, such as different labels, -which are forbidden otherwise. - -#### Breaking changes - -- Github organisation OAuth: `auth.github.org_whitelist` has been renamed to `auth.github.orgWhitelist` to be consistent with helm's camelCase style - -#### Troubleshooting - -If you encounter issues with upgrades, check for changed configuration in this document, and make sure your config is up to date. - -If you aren't able to get the upgrade to work, -you can [rollback](https://docs.helm.sh/helm/#helm-rollback) -to a previous version with: - - helm rollback $RELEASE - -Feel free to [ping us on gitter](https://gitter.im/jupyterhub/jupyterhub) -if you have problems or questions. - -#### New Features - -##### Easier user-selectable profiles upon login - -Profile information is now passed through to KubeSpawner. This means you can -[specify multiple user profiles that users can select from](https://zero-to-jupyterhub.readthedocs.io/en/latest/user-environment.html?highlight=profile#allow-users-to-create-their-own-conda-environments) -when they log in. ([#402](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/issues/402)) - -##### Configurable image pull secrets - -Improvements to the Helm Chart to let users specify private information that lets -the Hub pull from private Docker registries. New information includes -Kubernetes Secrets, an email field, large JSON blobs in the password field (required -in order to pull from a private gcr.io registry from an external cluster). - -It also ensures that the image puller DaemonSets have the same credentials to pull the images. - -(thanks to @AlexMorreale) #851 - -##### Improved user scheduling and resource management - -#891 - -Want to make your autoscheduler work efficiently? Then you should schedule pods to pack tight instead of spread out. The user scheduler accomplishes this. - -- **Pod priority and User placeholders** - #929 - -Want to scale up before users arrive so they don't end up waiting for the node to pull an image of several gigabytes in size? By adding a configurable fixed amount of user placeholder pods with a lower [pod priority](https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/) than real user pods, we can accomplish this. It requires k8s v1.11 though. - -- **preferScheduleNextToRealUsers - improves autoscaling** - #930 - This setting slightly improves the ability for a cluster autoscaler to scale down by increasing the likelihood of user placeholders being left alone on a node rather than real users. Real users can't be moved around while user placeholder pods can - -#### Minor upgrades and development improvements - -- **Update jupyterhub to 0.9.4** -- **Update kubespawner to 0.10.1** -- **Allow setting of storage labels** - #924 -- **Tolerations for node taints** - #925 -- **Making the core and user pods affinity have configurable presets** - #927 -- **Improved linting and validation + CI integration** - #844 -- **Improved CI tests** - #846 -- **Cleanup of orphaned files** - #842 - Two files were left unused in the repo. -- **cull.maxAge bugfix** - #853 - `cull.maxAge` previously didn't influence the culler service, as the value was never consumed. This is fixed by a single one line commit in a PR. -- **No more duplicates of puller pods** - #854 - Nobody wants pods running that does nothing. By using the new `before-hook-creation` value for the `deletion-policy` Helm hook together with a single name for our Helm hook resources, we can ensure never having orphaned image pullers. -- **Remove pod-culler image** - #890 #919 - Before JupyterHub 0.9 the pod-culler was a standalone pod with a custom image. But now it is a internal service of the JupyterHub pod, so in this PR we slim the remnant code. -- **Upgrade to k8s 1.9 APIs** - #920 - Migrate to more stable K8s resource APIs from `beta`. -- **Update of the singleuser-sample image** - #888 - `git` and `nbgitpuller` are now available by default -- **Switch to using a StatefulSet for the Hub** **\*** - The Hub should perhaps be a StatefulSet rather than a Deployment as it tends to be tied to a PV that can only be mounted by one single Hub. See this issue: https://github.com/helm/charts/issues/1863 -- Show users deprecation and error messages when they use certain deprecated - configuration (e.g. `hub.extraConfig` as a single string) - or incompatible combinations. -- **Updates to the guide** - #850 -- **Updates to inline documentation** - #939 - -#### [Richie Benaud](https://www.cricket.com.au/players/richie-benaud/gvp5xSjUp0q6Qd7IM5TbCg) - -_(excerpt from https://www.cricket.com.au/players/richie-benaud/gvp5xSjUp0q6Qd7IM5TbCg)_ - -Possibly the most iconic man in Australian cricket, Richie Benaud enjoyed a career spanning nearly -70 years in the game. On the field, he scored 767 runs at 19.66 in his 27 matches against England, -while he also picked up 83 wickets. Off the field, -he has been just as important. His commentary has been second to none since making his radio debut in 1960. - -While playing for Australia, fans flocked to the cricket to watch Benaud led sides -dominate whoever they played. The late 1950’s to early 1960’s was a golden period in -Australian cricket, with players such as Simpson, Lawry and Harvey -scoring runs, while Benaud and Davidson did the damage with the ball. - -Richie Benaud was responsible for resurrecting cricket in this country. The world was -changing at that time, and so was cricket. It was being shown on television for the -first time, while radio coverage was becoming more advanced. Benaud -felt he had a duty to the Australian public to make the game more entertaining. Sure, -you could argue that the 1961 series was dull, but at least Australia -retained the Ashes. Nobody will forget the tied Test against the West Indies, or Benaud’s -audacious move to bowl around the wicket in Manchester. - -Benaud is credited with popularising the tactics we see today. Huddles after a wicket -were born in the Benaud era. Declaring just before stumps in a bid to steal a late wicket -was something he thrived upon. Bowling into the rough is now seen -as common practice. - -Benaud was also prepared to try new things with the ball. He worked very hard on -perfecting his wrong’un, the flipper and the top-spinner. His leg-spinner even had variety -to it, making him one of the most complete tweakers at the time. - -His leadership earned him respect immediately. Players loved being guided the -likeable larrikin from Penrith. He looked after everyone both as a team, but also on an -individual basis. His teammates trusted his innovative ideas, while -he trusted them to execute them to the fullest. - -For most Australians, summer means cricket. And cricket means hearing the dulcet -tones of their favourite commentator, Richie Benaud. From the cream coloured suit, to the -witty repartee with his colleagues, Benaud is the complete package - -#### Contributors - -This release wouldn't have been possible without the wonderful contributors -to the [zero-to-jupyterhub](https://github.com/jupyterhub/zero-to-jupyterhub-k8s), -and [KubeSpawner](https://github.com/jupyterhub/kubespawner) repos. -We'd like to thank everyone who contributed in any form - Issues, commenting -on issues, PRs and reviews since the last Zero to JupyterHub release. - -[(Frank) Yu Cheng Gu](https://github.com/frankgu968) -[1160300422-RenQJ](https://github.com/1160300422) -[1kastner](https://github.com/1kastner) -[2efper](https://github.com/2efPer) -[A. Tan ](https://github.com/amanda-tan) -[Aadi Deshpande](https://github.com/cilquirm) -[abremirata28](https://github.com/abremirata28) -[AcademicAdmin](https://github.com/AcademicAdmin) -[Adam Huffman](https://github.com/verdurin) -[Adrian Wilke](https://github.com/adibaba) -[Akanksha Bhardwaj](https://github.com/sashafierce) -[Akhil Lawrence](https://github.com/akhilputhiry) -[Al Johri](https://github.com/AlJohri) -[AlbanWende](https://github.com/AlbanWende) -[Alejandro del Castillo](https://github.com/adelcast) -[Aleksandr Blekh](https://github.com/ablekh) -[Alex Morreale](https://github.com/AlexMorreale) -[Alex Newman](https://github.com/posix4e) -[Alexander Comerford](https://github.com/cmrfrd) -[Alexander Sadleir](https://github.com/maxious) -[amangarg96](https://github.com/amangarg96) -[Amirahmad Khordadi](https://github.com/khordadi) -[Andreas Hilboll](https://github.com/andreas-h) -[andregouveiasantana](https://github.com/andregouveiasantana) -[Andrew](https://github.com/feriat) -[Andrew Catellier](https://github.com/whlteXbread) -[angelikamukhina](https://github.com/angelikamukhina) -[Anton Khodak](https://github.com/anton-khodak) -[arcady-genkin](https://github.com/arcady-genkin) -[Ariel Rokem](https://github.com/arokem) -[Arne Küderle](https://github.com/AKuederle) -[atne2008](https://github.com/atne2008) -[awalther](https://github.com/awalther) -[Ben Zipperer](https://github.com/benzipperer) -[Beneath](https://github.com/beneathcrypto) -[Benjamin Egelund-Müller](https://github.com/bem7) -[BertR](https://github.com/BertR) -[bharathwgl](https://github.com/bharathwgl) -[bing-he](https://github.com/bing-he) -[bjyxmas](https://github.com/bjyxmas) -[bpoettinger](https://github.com/bpoettinger) -[Brad Skaggs](https://github.com/bskaggs) -[Braden](https://github.com/brasie) -[Brian E. Granger](https://github.com/ellisonbg) -[Bruno P. Kinoshita](https://github.com/kinow) -[brynjsmith](https://github.com/brynjsmith) -[Calvin Canh Tran](https://github.com/canhtran) -[camer314](https://github.com/camer314) -[Carol Willing](https://github.com/willingc) -[Caspian](https://github.com/Cas-pian) -[cfoisy-osisoft](https://github.com/cfoisy-osisoft) -[ChanakyaBandara](https://github.com/ChanakyaBandara) -[chang-zhijie](https://github.com/chang-zhijie) -[Chao Wang](https://github.com/wangxiaoxiao88) -[Chen Zhiwei](https://github.com/chenzhiwei) -[Chester Li](https://github.com/chaoleili) -[Chia-liang Kao](https://github.com/clkao) -[Chris Holdgraf](https://github.com/choldgraf) -[Chris Seal](https://github.com/cmseal) -[Christian Alis](https://github.com/ianalis) -[Christian Mesh](https://github.com/cam72cam) -[chrlunden](https://github.com/chrlunden) -[Clancy Childs](https://github.com/clancychilds) -[Clemens Tolboom](https://github.com/clemens-tolboom) -[cmw2196](https://github.com/cmw2196) -[Cody Scott](https://github.com/Siecje) -[Craig Willis](https://github.com/craig-willis) -[cristofercri](https://github.com/cristofercri) -[Curtis Maves](https://github.com/cmaves) -[cybertony](https://github.com/cybertony) -[Daisuke Taniwaki](https://github.com/dtaniwaki) -[Dalon Lobo](https://github.com/dalonlobo) -[danamer](https://github.com/danamer) -[Daniel Bachler](https://github.com/danyx23) -[Daniel Chalef](https://github.com/danielchalef) -[Daniel Hnyk](https://github.com/hnykda) -[danielpcs](https://github.com/danielpcs) -[Danny H](https://github.com/toblender) -[DataVictorEngineer](https://github.com/DataVictorEngineer) -[Dave Hirschfeld](https://github.com/dhirschfeld) -[Dave Porter](https://github.com/porterde) -[David Andersen](https://github.com/dtandersen) -[David John Gagne](https://github.com/djgagne) -[Davide](https://github.com/davidedelvento) -[Deleted user](https://github.com/ghost) -[Denis Shestakov](https://github.com/denshe) -[Dennis Kipping](https://github.com/dkipping) -[Derek Ludwig](https://github.com/dsludwig) -[DerekHeldtWerle](https://github.com/DerekHeldtWerle) -[DewinGoh](https://github.com/DewinGoh) -[Diogo](https://github.com/dmvieira) -[djknight1](https://github.com/djknight1) -[DmitrII Gerasimenko](https://github.com/kidig) -[Doug Blank](https://github.com/dsblank) -[Dr. Di Prodi](https://github.com/robomotic) -[Dr. Zoltán Katona](https://github.com/zkatona) -[Dylan Nelson](https://github.com/dnelson86) -[ebebpl](https://github.com/ebebpl) -[Eliran Bivas](https://github.com/bivas) -[eode](https://github.com/eode) -[Eran Pinhas](https://github.com/eran-pinhas) -[eric-leblouch](https://github.com/eric-leblouch) -[ericblau](https://github.com/ericblau) -[Erik LaBianca](https://github.com/easel) -[Erik Sundell](https://github.com/consideRatio) -[Ermakov Petr](https://github.com/ermakovpetr) -[erolosty](https://github.com/erolosty) -[Evan Savage](https://github.com/candu) -[Evert Rol](https://github.com/evertrol) -[Ezequiel Gioia](https://github.com/eze1981) -[fahadabbas91](https://github.com/fahadabbas91) -[farzadz](https://github.com/farzadz) -[foxlisimulation](https://github.com/foxlisimulation) -[frouzbeh](https://github.com/frouzbeh) -[Félix-Antoine Fortin](https://github.com/cmd-ntrf) -[Gabriel Abdalla Cavalcante](https://github.com/gcavalcante8808) -[Gabriel Fair](https://github.com/gabefair) -[Gaetan Semet](https://github.com/gsemet) -[Gang Chen](https://github.com/ssword) -[Gary Lucas](https://github.com/luck02) -[Georgiana Elena](https://github.com/GeorgianaElena) -[gerroon](https://github.com/gerroon) -[Giuseppe Attardi](https://github.com/attardi) -[Glen A Knight](https://github.com/glenak1911) -[Gonzalo Fernandez ordas](https://github.com/rainmanh) -[Guilherme Oenning](https://github.com/goenning) -[Guo Zhang](https://github.com/Guo-Zhang) -[gweis](https://github.com/gweis) -[Gábor Lipták](https://github.com/gliptak) -[Hagen Hoferichter](https://github.com/h4gen) -[hani1814](https://github.com/hani1814) -[Hans Permana](https://github.com/hans-permana) -[hhuuggoo](https://github.com/hhuuggoo) -[hichemken](https://github.com/hichemken) -[HT-Moh](https://github.com/HT-Moh) -[HuangHenghua](https://github.com/HuangHenghua) -[HuiWang](https://github.com/scially) -[Ian Carroll](https://github.com/itcarroll) -[Ian Stuart](https://github.com/perllaghu) -[Ivan Brezina](https://github.com/ibre5041) -[J Forde](https://github.com/jzf2101) -[J Gerard](https://github.com/jgerardsimcock) -[j08rebelo](https://github.com/j08rebelo) -[Jacob Matuskey](https://github.com/jmatuskey) -[Jacob Tomlinson](https://github.com/jacobtomlinson) -[Jaime Ferrando Huertas](https://github.com/jiwidi) -[James Swineson](https://github.com/Jamesits) -[jameshgrn](https://github.com/jameshgrn) -[Jan Niederau](https://github.com/Japhiolite) -[Jason Belsky](https://github.com/jbelsky) -[Jason Hu](https://github.com/Jameshzc) -[Jason Rigby](https://github.com/jasonrig) -[jason4zhu](https://github.com/jason4zhu) -[Jeff Whitworth](https://github.com/jwhitwo) -[Jeffrey Bush](https://github.com/coderforlife) -[jeffwji](https://github.com/jeffwji) -[Jessica B. Hamrick](https://github.com/jhamrick) -[jfleury-eidos](https://github.com/jfleury-eidos) -[Ji Ma](https://github.com/ma-ji) -[Jiren Jin](https://github.com/jinjiren) -[jiyer2016](https://github.com/jiyer2016) -[jlc175](https://github.com/jlc175) -[jmabry](https://github.com/jmabry) -[jmchandonia](https://github.com/jmchandonia) -[jmf](https://github.com/jmfcodes) -[Joe Hamman](https://github.com/jhamman) -[Joerg Klein](https://github.com/joergklein) -[John Chase](https://github.com/johnchase) -[John Readey](https://github.com/jreadey) -[John Shojaei](https://github.com/titan550) -[Jonathan Terhorst](https://github.com/terhorst) -[Jordan Miller](https://github.com/LegitStack) -[Josh Bode](https://github.com/joshbode) -[Joshua Milas](https://github.com/DeepHorizons) -[JP Moresmau](https://github.com/JPMoresmau) -[jpays](https://github.com/jpays) -[Juan Cruz-Benito](https://github.com/cbjuan) -[Julian Rüth](https://github.com/saraedum) -[Julien Chastang](https://github.com/julienchastang) -[Justin Ray Vrooman](https://github.com/vroomanj) -[Jürgen Hermann](https://github.com/jhermann) -[Kah Mun](https://github.com/kavemun) -[kangzebin](https://github.com/kangzebin) -[Kelly L. Rowland](https://github.com/kellyrowland) -[Kenan Erdogan](https://github.com/bitnik) -[Kerwin Sun](https://github.com/00Kai0) -[kevbutler](https://github.com/kevbutler) -[Kevin Bates](https://github.com/kevin-bates) -[khawarhere](https://github.com/khawarhere) -[kide007](https://github.com/kide007) -[Kim-Seonghyeon](https://github.com/Kim-Seonghyeon) -[kishitaku0630](https://github.com/kishitaku0630) -[Koshmaar](https://github.com/Koshmaar) -[Koustuv Sinha](https://github.com/koustuvsinha) -[krinsman](https://github.com/krinsman) -[Kristian Gregorius Hustad](https://github.com/KGHustad) -[Kristiyan](https://github.com/katsar0v) -[KSHITIJA SAHARAN](https://github.com/kshitija08) -[Kuriakin Zeng](https://github.com/kuriakinzeng) -[Kyla Harper](https://github.com/kyla-harper) -[Lachlan Musicman](https://github.com/datakid) -[Laurent Abbal](https://github.com/laurentabbal) -[Leo Gallucci](https://github.com/elgalu) -[Leopold Talirz](https://github.com/ltalirz) -[Li-Xian Chen](https://github.com/twbrandon7) -[Lisa Stillwell](https://github.com/lstillwe) -[ljb445300387](https://github.com/ljb445300387) -[Loïc Antoine Gombeaud](https://github.com/LoicAG) -[Loïc Estève](https://github.com/lesteve) -[Lucas Durand](https://github.com/lucasdurand) -[Lukasz Tracewski](https://github.com/tracek) -[m.fab](https://github.com/go-bears) -[Ma](https://github.com/ma010) -[mangecoeur](https://github.com/mangecoeur) -[Manish Kushwaha](https://github.com/manish0749) -[Marc Illien](https://github.com/jackblackCH) -[marinalopez2110](https://github.com/marinalopez2110) -[Mark Mirmelstein](https://github.com/markm42) -[Marlene Silva Marchena](https://github.com/msmarchena) -[Martin Gergov](https://github.com/marto1) -[Martin Zugnoni](https://github.com/martinzugnoni) -[Marvin Solano](https://github.com/marvin-solano) -[Marwan Baghdad](https://github.com/MrwanBaghdad) -[Matthias Bussonnier](https://github.com/Carreau) -[Matthias Klan](https://github.com/mklan) -[Matthias Lee](https://github.com/matthiaslee) -[Matthieu Boileau](https://github.com/boileaum) -[Max Mensing](https://github.com/madmax2012) -[mdivk](https://github.com/mdivk) -[Meesam Shah](https://github.com/meesam15) -[Michael Carroll](https://github.com/neffo) -[Michael Huttner](https://github.com/mhuttner) -[Michael Lovci](https://github.com/mlovci) -[Michael McCarthy](https://github.com/RonanMcCarthy) -[Michael Milligan](https://github.com/mbmilligan) -[Michael Pilosov](https://github.com/mathematicalmichael) -[michec81](https://github.com/michec81) -[Mike Croucher](https://github.com/mikecroucher) -[MikeSpark](https://github.com/MikeSpark) -[Min RK](https://github.com/minrk) -[MisterZ](https://github.com/Misteur-Z) -[Moritz Kirschner](https://github.com/cellador) -[Moritz Schlarb](https://github.com/moschlar) -[moskiGithub](https://github.com/moskiGithub) -[mpolidori](https://github.com/mpolidori) -[mrclttnz](https://github.com/mrclttnz) -[MubashirullahD](https://github.com/MubashirullahD) -[Muhammad-Imtiaz](https://github.com/Muhammad-Imtiaz) -[mxcheng2011](https://github.com/mxcheng2011) -[myidealab](https://github.com/myidealab) -[Naineel Shah](https://github.com/naineel) -[narala558](https://github.com/narala558) -[newturok](https://github.com/newturok) -[Ney Torres](https://github.com/Neyt) -[Nic Wayand](https://github.com/NicWayand) -[Nico Bellack](https://github.com/bellackn) -[nifuki](https://github.com/nifuki) -[Nils Werner](https://github.com/nils-werner) -[not4everybody](https://github.com/not4everybody) -[NotSharath](https://github.com/NotSharath) -[nschiraldi](https://github.com/nschiraldi) -[Nujjy](https://github.com/Nujjy) -[oscar6echo](https://github.com/oscar6echo) -[Paperone80](https://github.com/Paperone80) -[Patafix](https://github.com/Patafix) -[Paul Mazzuca](https://github.com/PaulMazzuca) -[Paul Shealy](https://github.com/paulshealy1) -[Paulo Roberto de Oliveira Castro](https://github.com/prcastro) -[Pav K](https://github.com/kalaytan) -[payalbhatia](https://github.com/payalbhatia) -[Peter Parente](https://github.com/parente) -[Peter Reid](https://github.com/ReidWeb) -[Phil Elson](https://github.com/pelson) -[Phil Fenstermacher](https://github.com/pcfens) -[Philipp Kats](https://github.com/Casyfill) -[phpdistiller](https://github.com/phpdistiller) -[phxedmond](https://github.com/phxedmond) -[Piotr](https://github.com/karpikpl) -[Pouria Hadjibagheri](https://github.com/xenatisch) -[powerLeePlus](https://github.com/powerLeePlus) -[Pratik Lal](https://github.com/pratik-lal) -[pydeepak](https://github.com/Deepakdubey90) -[Qcy](https://github.com/chaoyue729) -[R. C. Thomas](https://github.com/rcthomas) -[raghav130593](https://github.com/raghav130593) -[Rahul Sharma](https://github.com/rahulswimmer) -[Rama Krishna Jinka](https://github.com/rjinka) -[RBALAJI5](https://github.com/RBALAJI5) -[rbq](https://github.com/rbq) -[Richard C Gerkin](https://github.com/rgerkin) -[Richard Darst](https://github.com/rkdarst) -[Richard Huntrods](https://github.com/huntrods) -[richyanicky](https://github.com/richyanicky) -[Rob Nagler](https://github.com/robnagler) -[robin](https://github.com/rollbackchen) -[robotsp](https://github.com/robotsp) -[rothwewi](https://github.com/rothwewi) -[rushikeshraut777](https://github.com/rushikeshraut777) -[Ryan](https://github.com/ev1lm0nk3y) -[Ryan Abernathey](https://github.com/rabernat) -[Ryan Lovett](https://github.com/ryanlovett) -[Ryan McGuire](https://github.com/EnigmaCurry) -[rzuidhof](https://github.com/rzuidhof) -[Saiprasad Balasubramanian](https://github.com/backtrackbaba) -[Sam Manzer](https://github.com/samuelmanzer) -[samRddhimat](https://github.com/samRddhimat) -[Santosh](https://github.com/sdandey) -[Saranya411](https://github.com/Saranya411) -[Scott Crooks](https://github.com/sc250024) -[sdementen](https://github.com/sdementen) -[SeaDude](https://github.com/SeaDude) -[SergeyK1](https://github.com/SergeyK1) -[Shannon](https://github.com/jingsong-liu) -[Shi Pengcheng](https://github.com/shipengcheng1230) -[shibbas](https://github.com/shibbas) -[Shinichi TAMURA](https://github.com/tmshn) -[Shiva1789](https://github.com/Shiva1789) -[sidebo](https://github.com/sidebo) -[Sigurður Baldursson](https://github.com/sigurdurb) -[Simon Li](https://github.com/manics) -[Sindre Gulseth](https://github.com/sgulseth) -[SivaMaplelabs](https://github.com/SivaMaplelabs) -[sjillidimudi](https://github.com/sjillidimudi) -[skruse](https://github.com/skruse) -[smoulderme](https://github.com/smoulderme) -[Solaris](https://github.com/SolarisYan) -[Spencer Ogden](https://github.com/spencerogden) -[sreekanthmg](https://github.com/sreekanthmg) -[Steven B](https://github.com/sblack4) -[Steven Silvester](https://github.com/blink1073) -[StudyQuant](https://github.com/studyquant) -[Subhash](https://github.com/signinred) -[Suchit](https://github.com/asuchit) -[summerswallow](https://github.com/summerswallow) -[summerswallow-whi](https://github.com/summerswallow-whi) -[Søren Fuglede Jørgensen](https://github.com/fuglede) -[Taewon](https://github.com/tkang007) -[Tania Allard](https://github.com/trallard) -[Taposh Dutta Roy](https://github.com/taposh) -[techie879](https://github.com/techie879) -[ThibTrip](https://github.com/ThibTrip) -[Thomas Mendoza](https://github.com/tgmachina) -[thomas-rabiller-azimut](https://github.com/thomas-rabiller-azimut) -[Thong Kuah](https://github.com/kuahyeow) -[thongnnguyen](https://github.com/thongnnguyen) -[Tim Crone](https://github.com/tjcrone) -[Tim Head](https://github.com/betatim) -[Timothy Griffiths](https://github.com/timgriffiths) -[Timothy Liu](https://github.com/tlkh) -[Todd Gamblin](https://github.com/tgamblin) -[Tom](https://github.com/T0mWz) -[Tomer Leibovich](https://github.com/tomerleib) -[tregin](https://github.com/tregin) -[Tren Huang](https://github.com/spiketren) -[Tuhina Chatterjee](https://github.com/tuhina2020) -[Tyler Gregory](https://github.com/01100010011001010110010101110000) -[Uday](https://github.com/udaynaik) -[Udit Arora](https://github.com/uditarora) -[Vasu Gaur](https://github.com/gaurcs) -[Victor Lopez](https://github.com/victorcete) -[Vidit Agarwal](https://github.com/IamViditAgarwal) -[VidJa](https://github.com/VidJa) -[Vincent Feng](https://github.com/iVincentFeng) -[vishal49naik49](https://github.com/vishal49naik49) -[Vivek](https://github.com/II-VSB-II) -[Vivek Rai](https://github.com/raivivek) -[vivekbiet](https://github.com/vivekbiet) -[Vlad-Mihai Sima](https://github.com/vladmihaisima) -[Volker Braun](https://github.com/vbraun) -[wangcong](https://github.com/congfairy) -[Wangsoo Kim](https://github.com/wangsookim) -[whositwhatnow](https://github.com/whositwhatnow) -[Will](https://github.com/xuwaters) -[Will Starms](https://github.com/vilhelmen) -[Willem Pienaar](https://github.com/woop) -[Xavier Lange](https://github.com/xrl) -[YborBorn](https://github.com/YborBorn) -[YizTian](https://github.com/tony-tian) -[Yoav Tzelnick](https://github.com/yoavtzelnick) -[YoongHM](https://github.com/yoonghm) -[yugushihuang](https://github.com/yugushihuang) -[Yuvi Panda](https://github.com/yuvipanda) -[Yuze Ma](https://github.com/bobmayuze) -[Zac Flamig](https://github.com/zflamig) -[Zach Day](https://github.com/zacharied) -[Zachary Sailer](https://github.com/Zsailer) -[Zafer Cesur](https://github.com/zcesur) -[zmkhazi](https://github.com/zmkhazi) -[zneudl](https://github.com/zneudl) -[田进](https://github.com/EndlessTJ) -[邱雨波](https://github.com/CraftHeart) -[高彦涛](https://github.com/gytlinux) - -## [0.7.0](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/compare/v0.6...0.7.0) - [Alex Blackwell](https://en.wikipedia.org/wiki/Alex_Blackwell) - 2018-09-03 - -This release contains JupyterHub version 0.9.2, additional configuration options -and various bug fixes. - -**IMPORTANT:** This upgrade will require your users to stop their work at some -point and have their pod restarted. You may want to give them a heads up ahead -of time or do it during nighttime if none are active then. - -### Upgrading from v0.6 - -If you are running `v0.5` of the chart, you should upgrade to `v0.6` first -before upgrading to `0.7.0`. You can find out what version you are using by -running `helm list`. - -Follow the steps below to upgrade from `v0.6` to `0.7.0`. - -#### 1. (Optional) Ensure the hub's and users' data isn't lost - -This step is optional, but a recommended safeguard when the hub's and users' -data is considered important. The changes makes the PersistentVolumes (PVs), -which represent storage (user data and hub database) remain even if the -PersistentVolumeClaims (PVCs) are deleted. The downside of this is that it -requires you to perform manual cleanup of PVs when you want to stop spending -money for the storage. - -```sh -# The script is a saftey measure and patches your PersistentVolumes (PV) to -# not be garbage collected if the PersistentVolumeClaim (PVC) are deleted. -NAMESPACE= - -# Ensure the hub's and users' data isn't lost -hub_and_user_pvs=($(kubectl get persistentvolumeclaim --no-headers --namespace $NAMESPACE | awk '{print $3}')) -for pv in ${hub_and_user_pvs[@]}; -do - kubectl patch persistentvolume $pv --patch '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}' -done -``` - -#### 2. Update Helm (v2.9.1+ required) - -```sh -# Update helm -curl https://raw.githubusercontent.com/kubernetes/helm/HEAD/scripts/get | bash - -# Update tiller (on the cluster) -helm init --upgrade --service-account=tiller - -# Verify the update -# NOTE: you may need to cancel and re-run the command, it should work within 30 -# seconds. -helm version -# VERIFY: Did it return both the client and server version? -# Client: &version.Version{SemVer:"v2.10.0", GitCommit:"9ad53aac42165a5fadc6c87be0dea6b115f93090", GitTreeState:"clean"} -# Server: &version.Version{SemVer:"v2.10.0", GitCommit:"9ad53aac42165a5fadc6c87be0dea6b115f93090", GitTreeState:"clean"} -``` - -#### 3. (Optional) Clean up pre-puller resources - -The pre-puller component of v0.6 could leave leftover resources after it finished, -instead of cleaning up after itself. -This script removes the pre-puller resources created by v0.6. - -```sh -# This script will delete resources that were meant to be temporary -# The bug that caused this is fixed in version 0.7.0 of the Helm chart -NAMESPACE= - -resource_types="daemonset,serviceaccount,clusterrole,clusterrolebinding,job" -for bad_resource in $(kubectl get $resource_types --namespace $NAMESPACE | grep '/pre-pull' | awk '{print $1}'); -do - kubectl delete $bad_resource --namespace $NAMESPACE --now -done - -kubectl delete $resource_types --selector hub.jupyter.org/deletable=true --namespace $NAMESPACE --now -``` - -#### 4. (Recommended) Clean up problematic revisions in your Helm release - -This step is recommended due to bugs in Helm that could cause your JupyterHub -Helm chart installation (release) to get stuck in an invalid state. -The symptoms are often that `helm upgrade` commands fail with the reason that some resource does or doesn't exist. - -```sh -# Look up the name of your Helm release (installation of a Helm chart) -helm list - -# Store the name of the Helm release -RELEASE_NAME= - -# Give yourself an overview of this release's revisions -helm history $RELEASE_NAME - -# Check if you have multiple revisions in a DEPLOYED status (a bug), or if you -# have old PENDING_UPGRADES or FAILED revisions (may be problematic). -helm history $RELEASE_NAME | grep --extended-regexp "DEPLOYED|FAILED|PENDING_UPGRADE" - -# If you have multiple revisions in DEPLOYED status, this script will clean up -# all configmaps except the latest with DEPLOYED status. -deployed_revisions=($(helm history $RELEASE_NAME | grep DEPLOYED | awk '{print $1}')) -for revision in ${deployed_revisions[@]::${#deployed_revisions[@]}-1}; -do - kubectl delete configmap $RELEASE_NAME.v$revision --namespace kube-system -done - -# It seems plausible that upgrade failures could have to do with revisions -# having a PENDING_UPGRADE or FAILED status in the revision history. To delete -# them run the following command. -kubectl delete configmap --selector "NAME=$RELEASE_NAME,STATUS in (FAILED,PENDING_UPGRADE)" --namespace kube-system -``` - -#### 5. Perform the upgrade - -**IMPORTANT:** Do not miss out on the `--force` flag! -`--force` is required due to changes in labelling of jupyterhub resources -in 0.7. -Helm cannot upgrade from the labelling scheme in 0.6 to that in 0.7 without `--force`, which deletes and recreates the deployments. - -```sh -RELEASE_NAME= -NAMESPACE= - -helm repo add jupyterhub https://jupyterhub.github.io/helm-chart/ -helm repo update - -# NOTE: We need the --force flag to allow recreation of resources that can't be -# upgraded to the new state by a patch. -helm upgrade $RELEASE_NAME jupyterhub/jupyterhub --install \ - --force \ - --version=0.7.0 \ - --namespace=$NAMESPACE \ - --values config.yaml \ - --timeout 1800 -``` - -#### 6. Manage active users - -Active users with running pods must restart their pods. If they don't the next -time they attempt to access their server they may end up with `{“error”: “invalid_redirect_uri”, “error_description”: “Invalid redirect URI”}`. - -You have the power to force this to happen, but it will abort what they are -doing right now. If you want them to be able to do it in their own pace, you -could use the `/hub/admin` path and shut them down manually when they are done. - -``` -NAMESPACE= - -# Inspect what users are currently running -kubectl get pod --selector component=singleuser-server --namespace $NAMESPACE - -# Force all of them to shutdown their servers, and ensure the hub gets to -# realize that happened through a restart. -kubectl delete pod --selector component=singleuser-server --namespace $NAMESPACE -kubectl delete pod --selector component=hub --namespace $NAMESPACE -``` - -#### Troubleshooting - Cleanup of cluster - -If things fail, you can try the following before installing the chart. If you -decide to take these steps, we recommend step 1 is taken first in order to not -loose data and that you ensure the old data is made available by the -troubleshooting step below. - -```sh -RELEASE_NAME= - -# WARNING: Deletes everything installed by the Helm chart! -# WARNING: If you have not changed the reclaim policy of the hub in step 1, the -# hub never be able to remember anything about past users. Also note -# that even if you have taken step 1, you must also make the PVs become -# `Available` again before the hub starts up again. -# NOTE: This does not include user pods or user storage PVCs as they have been -# indirectly created by KubeSpawner -helm delete $RELEASE_NAME --purge - -# WARNING: Deletes everything within the namespace! -# WARNING: If you have not changed the reclaim policy of the hub and users in -# step 1, the hub's stored information about the users and the user's -# storage will be lost forever. Also note that even if you have taken -# step 1, you must also make the hub and users PVs become `Available` -# before the hub and users startup again. -kubectl delete namespace -``` - -If you took these steps and step 1, you should probably right now continue with -the next troubleshooting section about making `Released` PVs `Available` for -reuse. - -#### Troubleshooting - Make `Released` PVs `Available` for reuse - -If you followed step 1 and 2, you can after cleanup of a cluster reuse the old -hub's and users' storage if you do this step before you installs the Helm chart -again. - -In more technical words: if you have deleted PVCs such as `hub-db-dir` or -`claim-anyusername`, their PVs will end in a `Released` state assuming they had -a `reclaimPolicy` set to `Retain`. To make use of these PVs again, we must make -them `Available` for the to future PVCs that needs a PV to bind to. - -```sh -NAMESPACE= - -# Ensure the hub's and users' PVs are made `Available` again -hub_and_user_pvs=($(kubectl get persistentvolume | grep -E "Released.+$NAMESPACE/(hub-db-dir|claim-)" | awk '{print $1}')) -for pv in ${hub_and_user_pvs[@]}; -do - kubectl patch persistentvolume $pv --patch '{"spec":{"claimRef":{"uid":null}}}}' -done - -# Ensure you don't have any PVCs in the lost state -lost_pvcs=($(kubectl get persistentvolumeclaim --namespace $NAMESPACE | grep -E "(hub-db-dir|claim-).+Lost" | awk '{print $1}')) -for pvc in ${lost_pvcs[@]}; -do - echo kubectl delete persistentvolumeclaim $pvc --namespace $NAMESPACE -done -``` - -### Contributors - -[A. Tan ](https://github.com/amanda-tan) -[Aaron Culich](https://github.com/aculich) -[abhismvit](https://github.com/abhismvit) -[AC](https://github.com/miramar-labs) -[AcademicAdmin](https://github.com/AcademicAdmin) -[Adam Grant](https://github.com/harmon) -[Adam Huffman](https://github.com/verdurin) -[Adam Thornton](https://github.com/athornton) -[Adam Tilghman](https://github.com/agt-ucsd) -[Adam-Origamiiris](https://github.com/Adam-Origamiiris) -[Afreen Rahman](https://github.com/Afreen04) -[agustaf](https://github.com/agustaf) -[agustiin](https://github.com/agustiin) -[aisensiy](https://github.com/aisensiy) -[Ajay Changulani](https://github.com/Ajay-Changulani) -[Akhil Lawrence](https://github.com/akhilputhiry) -[akkibatra](https://github.com/akkibatra) -[Alan King](https://github.com/kingaj12) -[Albert J. de Vera](https://github.com/ajdevera) -[Alejandro del Castillo](https://github.com/adelcast) -[Alejandro Gastón Alvarez](https://github.com/alealv) -[Aleksandr Blekh](https://github.com/ablekh) -[Alex Leith](https://github.com/alexgleith) -[Alex Marandon](https://github.com/amarandon) -[Alex Mellnik](https://github.com/amellnik) -[Alex Moore](https://github.com/Akmoore7) -[Alex Morreale](https://github.com/AlexMorreale) -[Alex Tasioulis](https://github.com/alex1x) -[Alexander](https://github.com/bzz) -[Alexander Hendorf](https://github.com/alanderex) -[Alexander Kruzhkov](https://github.com/YOxan) -[Alexander Morley](https://github.com/alexmorley) -[Alexander Schwartzberg](https://github.com/aeksco) -[Allen Downey](https://github.com/AllenDowney) -[AlphaSRE](https://github.com/AlphaSRE) -[Alramzey](https://github.com/Alramzey) -[amangarg96](https://github.com/amangarg96) -[Amirahmad Khordadi](https://github.com/khordadi) -[Amit Rathi](https://github.com/amit1rrr) -[Analect](https://github.com/Analect) -[anasos](https://github.com/anasos) -[Andre Celere](https://github.com/acelere) -[Andrea Abelli](https://github.com/abelliae) -[Andrea Turrini](https://github.com/andreat) -[Andrea Zonca](https://github.com/zonca) -[Andreas Heider](https://github.com/ah-) -[Andrew Berger](https://github.com/rueberger) -[Andrew Melo](https://github.com/PerilousApricot) -[andrewcheny](https://github.com/andrewcheny) -[András Tóth](https://github.com/tothandras) -[André Luiz Diniz](https://github.com/andrelu) -[Andy Berner](https://github.com/andybrnr) -[Andy Doddington](https://github.com/Andy-Doddington) -[angus evans](https://github.com/joingithubkor) -[Anirudh Vyas](https://github.com/AnirudhVyas) -[Ankit ](https://github.com/ankitml) -[Ankit Sharma](https://github.com/ankitksharma) -[ankit2894](https://github.com/ankit2894) -[Anthony Suen](https://github.com/anthonysuen) -[Anton Akhmerov](https://github.com/akhmerov) -[Antonino Ingargiola](https://github.com/tritemio) -[Antonio Serrano](https://github.com/AntonioSerrano) -[AranVinkItility](https://github.com/AranVinkItility) -[Arda Aytekin](https://github.com/aytekinar) -[Ariel Balter](https://github.com/abalter) -[Ariel Rokem](https://github.com/arokem) -[arkroop](https://github.com/arkroop) -[Arthur](https://github.com/konfiot) -[arthur](https://github.com/ppLorins) -[Arthur Koziel](https://github.com/arthurk) -[ArvinSiChuan](https://github.com/ArvinSiChuan) -[aseishas](https://github.com/aseishas) -[at-cchaloux](https://github.com/at-cchaloux) -[atullo2](https://github.com/atullo2) -[Bastian Greshake Tzovaras](https://github.com/gedankenstuecke) -[bbarney213](https://github.com/bbarney213) -[bbrauns](https://github.com/bbrauns) -[Ben Chuanlong Du](https://github.com/dclong) -[Benjamin Paz](https://github.com/bendavidpaz) -[Benoit Rospars](https://github.com/brospars) -[BerserkerTroll](https://github.com/BerserkerTroll) -[BhagyasriYella](https://github.com/BhagyasriYella) -[bhavybarca](https://github.com/bhavybarca) -[Birgetit](https://github.com/Birgetit) -[bitnik](https://github.com/bitnik) -[Borislav Aymaliev](https://github.com/aymaliev) -[Botty Dimanov](https://github.com/bottydim) -[Brad Skaggs](https://github.com/bskaggs) -[Brandon Sharitt](https://github.com/bsharitt) -[Brent](https://github.com/xuande) -[Brian E. Granger](https://github.com/ellisonbg) -[Brian Ray](https://github.com/brianray) -[Bruce Beauchamp](https://github.com/Prettyfield) -[Bruce Chiarelli](https://github.com/bccomm) -[Byă](https://github.com/hungbya) -[Camilla](https://github.com/Winterflower) -[Camilo Núñez Fernández](https://github.com/camilo-nunez) -[Cara](https://github.com/cara-a-k) -[carluri](https://github.com/carluri) -[Carol Willing](https://github.com/willingc) -[Caspian](https://github.com/Cas-pian) -[chack05](https://github.com/chack05) -[chang-zhijie](https://github.com/chang-zhijie) -[chaomaer](https://github.com/chaomaer) -[chaoyue729](https://github.com/chaoyue729) -[Charles Forelle](https://github.com/cforelle) -[chenyg0911](https://github.com/chenyg0911) -[Chester Li](https://github.com/chaoleili) -[Chia-liang Kao](https://github.com/clkao) -[Chico Venancio](https://github.com/chicocvenancio) -[Chris Fournier](https://github.com/cfournie) -[Chris Holdgraf](https://github.com/choldgraf) -[Chris Seal](https://github.com/cmseal) -[Chris Van Pelt](https://github.com/vanpelt) -[Christiaan Swanepoel](https://github.com/christiaanjs) -[Christian Alis](https://github.com/ianalis) -[Christian Hotz-Behofsits](https://github.com/inkrement) -[Christian Mesh](https://github.com/cam72cam) -[Christian Moscardi](https://github.com/cmoscardi) -[Christine Banek](https://github.com/cbanek) -[Christopher Hench](https://github.com/henchc) -[ckbhatt](https://github.com/ckbhatt) -[Claudius Mbemba](https://github.com/User1m) -[cloud-science](https://github.com/cloud-science) -[Cody Scott](https://github.com/Siecje) -[Cord](https://github.com/CordThomas) -[Cory Johns](https://github.com/johnsca) -[cqzlxl](https://github.com/cqzlxl) -[Craig Willis](https://github.com/craig-willis) -[Curtis Maves](https://github.com/cmaves) -[cyberquasar](https://github.com/cyberquasar) -[cybertony](https://github.com/cybertony) -[cyberyor](https://github.com/cyberyor) -[Daisuke Taniwaki](https://github.com/dtaniwaki) -[daleshsd](https://github.com/daleshsd) -[Dan Allan](https://github.com/danielballan) -[Dan Hoerst](https://github.com/DanHoerst) -[Dan Lidral-Porter](https://github.com/aperiodic) -[Daniel](https://github.com/daniel-ciocirlan) -[Daniel Morrison](https://github.com/draker42) -[danielmaitre](https://github.com/danielmaitre) -[danielrychel](https://github.com/danielrychel) -[Dario Romero](https://github.com/darioromero) -[darky2004](https://github.com/darky2004) -[DataVictorEngineer](https://github.com/DataVictorEngineer) -[Dave Aitken](https://github.com/actionshrimp) -[Dave Hirschfeld](https://github.com/dhirschfeld) -[David Bath](https://github.com/davidbath) -[David Doherty](https://github.com/dado0583) -[David Kügler](https://github.com/dkuegler) -[David Maxson](https://github.com/scnerd) -[David Napier](https://github.com/dnapier) -[David Pérez Comendador](https://github.com/perez1987) -[David Pérez-Suárez](https://github.com/dpshelio) -[David Sanftenberg](https://github.com/dbsanfte) -[Davide](https://github.com/davidedelvento) -[deep-42-thought](https://github.com/deep-42-thought) -[Deleted user](https://github.com/ghost) -[DerekHeldtWerle](https://github.com/DerekHeldtWerle) -[Dhawal Patel](https://github.com/dhawal55) -[disimone](https://github.com/disimone) -[DmitrII Gerasimenko](https://github.com/kidig) -[Dmitry Mishin](https://github.com/dimm0) -[Dominic Suciu](https://github.com/domsooch) -[Don Kelly](https://github.com/karfai) -[Doug Holt](https://github.com/dholt) -[Dragos Cojocari](https://github.com/dragos-cojocari) -[dturaev](https://github.com/dturaev) -[Dwight Townsend](https://github.com/townsenddw) -[Dylan Lentini](https://github.com/dyltini) -[Eamon Keane](https://github.com/EamonKeane) -[Eddy Elbrink](https://github.com/elbrinke) -[Emmanuel Gomez](https://github.com/emmanuel) -[Enol Fernández](https://github.com/enolfc) -[epoch1970](https://github.com/epoch1970) -[Eric Charles](https://github.com/echarles) -[Erik Sundell](https://github.com/consideRatio) -[Ermakov Petr](https://github.com/ermakovpetr) -[ernestmartinez](https://github.com/ernestmartinez) -[EtienneDesticourt](https://github.com/EtienneDesticourt) -[Evan](https://github.com/eexe1) -[Evan Van Dam](https://github.com/evandam) -[Evert Rol](https://github.com/evertrol) -[eylenth](https://github.com/eylenth) -[Ezequiel Gioia](https://github.com/eze1981) -[fahadabbas91](https://github.com/fahadabbas91) -[Faras Sadek](https://github.com/farassadek) -[forbxy](https://github.com/forbxy) -[Francisco Zamora-Martinez](https://github.com/pakozm) -[FU Zhipeng](https://github.com/gavin971) -[Fyodor](https://github.com/lgg) -[Félix-Antoine Fortin](https://github.com/cmd-ntrf) -[G YASHASVI](https://github.com/iamyashasvi) -[Gaetan Semet](https://github.com/gsemet) -[Gaëtan Lehmann](https://github.com/glehmann) -[gbrahmi](https://github.com/gbrahmi) -[George Jose](https://github.com/G2Jose) -[Gerben Welter](https://github.com/GerbenWelter) -[Gerhard Burger](https://github.com/burgerga) -[GladysNalvarte](https://github.com/GladysNalvarte) -[Glen A Knight](https://github.com/glenak1911) -[Graham Dumpleton](https://github.com/GrahamDumpleton) -[grant-guo](https://github.com/grant-guo) -[GRC](https://github.com/gaorongchao) -[Guillaume EB](https://github.com/guillaumeeb) -[guimou](https://github.com/guimou) -[Guo Zhang](https://github.com/Guo-Zhang) -[gweis](https://github.com/gweis) -[Hagen Hoferichter](https://github.com/h4gen) -[hanbeibei](https://github.com/hanbeibei) -[hani1814](https://github.com/hani1814) -[Hans Petter Bieker](https://github.com/hpbieker) -[happytest143](https://github.com/happytest143) -[Hassan Mudassir](https://github.com/hassanmudassir-rzt) -[Helder Rodrigues](https://github.com/HelderGualberto) -[hemantasingh](https://github.com/hemantasingh) -[Henddher Pedroza](https://github.com/wjehenddher) -[hjclub123](https://github.com/hjclub123) -[huhuhang](https://github.com/huhuhang) -[Hunter Jackson](https://github.com/hunterjackson) -[Ian](https://github.com/yfc845) -[Indrajeet Singh](https://github.com/itsindra) -[ironv](https://github.com/ironv) -[IssacPan](https://github.com/IssacPan) -[Ivan Grbavac](https://github.com/grbinho) -[J Forde](https://github.com/jzf2101) -[J Gerard](https://github.com/jgerardsimcock) -[Jacob Tomlinson](https://github.com/jacobtomlinson) -[James Curtin](https://github.com/jamescurtin) -[James Davidheiser](https://github.com/jdavidheiser) -[James Londal](https://github.com/jlondal) -[James Veitch](https://github.com/darth-veitcher) -[Jan Kalo](https://github.com/JanKalo) -[Jason Kuruzovich](https://github.com/jkuruzovich) -[Jason Williams](https://github.com/JasonJWilliamsNY) -[jason4zhu](https://github.com/jason4zhu) -[javin-gn](https://github.com/javin-gn) -[Jeremie Vallee](https://github.com/jeremievallee) -[Jeremy Lewi](https://github.com/jlewi) -[Jeremy Tuloup](https://github.com/jtpio) -[Jerry Schuman](https://github.com/pingthings) -[Jesse Cai](https://github.com/jcaip) -[Jesse Kinkead](https://github.com/jkinkead) -[Jesse Zhang](https://github.com/EmptyCrown) -[Jessica Wong](https://github.com/jessawong) -[Jim Basney](https://github.com/jbasney) -[Jim Hendricks](https://github.com/jhendric98) -[Jiri Kuncar](https://github.com/jirikuncar) -[jlsimms](https://github.com/jlsimms) -[jm2004](https://github.com/jm2004) -[Joakim](https://github.com/Sefriol) -[JocelynDelalande](https://github.com/JocelynDelalande) -[Joe Hamman](https://github.com/jhamman) -[Joel Pfaff](https://github.com/joelpfaff) -[John Kaltenbach](https://github.com/jkbach) -[John Readey](https://github.com/jreadey) -[johnbotsis](https://github.com/johnbotsis) -[johnkpark](https://github.com/johnkpark) -[johnpaulantony](https://github.com/johnpaulantony) -[Jonas Adler](https://github.com/adler-j) -[Jonathan](https://github.com/yocode) -[Jonathan Brant](https://github.com/jbrant) -[Jonathan Wheeler](https://github.com/jondoesntgit) -[jonny86](https://github.com/jonny86) -[Joost W. Döbken](https://github.com/JWDobken) -[Jose Manuel Monsalve Diaz](https://github.com/josemonsalve2) -[Josh Barnes](https://github.com/jcb91) -[Josh Temple](https://github.com/joshtemple) -[João Barreto](https://github.com/JoaoBarreto) -[jpolchlo](https://github.com/jpolchlo) -[JPUnD](https://github.com/JPUnD) -[Juan Cabanela](https://github.com/JuanCab) -[Julien Chastang](https://github.com/julienchastang) -[Jurian Kuyvenhoven](https://github.com/JurianK) -[Justin Holmes](https://github.com/sherl0cks) -[Justin Moen](https://github.com/superquest) -[justkar4u](https://github.com/justkar4u) -[JYang25](https://github.com/JYang25) -[Jürgen Hermann](https://github.com/jhermann) -[kakzhetak](https://github.com/kakzhetak) -[kaliko](https://github.com/mxjeff) -[Kam Kasravi](https://github.com/kkasravi) -[Kannan Kumar](https://github.com/kannankumar) -[karthikpitchaimani](https://github.com/karthikpitchaimani) -[Kenneth Lyons](https://github.com/ixjlyons) -[Kevin P. Fleming](https://github.com/kpfleming) -[kevkid](https://github.com/kevkid) -[Kirill Dubovikov](https://github.com/kdubovikov) -[Knarfux](https://github.com/fbessou) -[Ko Ohashi](https://github.com/kouohhashi) -[krinsman](https://github.com/krinsman) -[KrisL](https://github.com/gixita) -[Kristiyan](https://github.com/katsar0v) -[lambertjosh](https://github.com/lambertjosh) -[Lars Biemans](https://github.com/lbiemans) -[Leo Gallucci](https://github.com/elgalu) -[leolurunhe](https://github.com/leolurunhe) -[Leopold Talirz](https://github.com/ltalirz) -[LeoPsidom](https://github.com/leopsidom) -[lfzyx](https://github.com/lfzyx) -[lgc019](https://github.com/lgc019) -[Lifubang](https://github.com/lifubang) -[liusztc09](https://github.com/liusztc09) -[liuzhliang](https://github.com/liuzhliang) -[llancellotti](https://github.com/llancellotti) -[lmerli84](https://github.com/lmerli84) -[loginoff](https://github.com/loginoff) -[Louis Garman](https://github.com/leg100) -[Luca De Feo](https://github.com/defeo) -[Luca Grazioli](https://github.com/Luke035) -[Lucas Durand](https://github.com/lucasdurand) -[Lucas Kushner](https://github.com/lphk92) -[Lukasz Lempart](https://github.com/wookasz) -[Lukasz Tracewski](https://github.com/tracek) -[Lutz Behnke](https://github.com/cypherfox) -[M Pacer](https://github.com/mpacer) -[Maciej Sawicki](https://github.com/viroos) -[madsi1m](https://github.com/madsi1m) -[mak-aravind](https://github.com/mak-aravind) -[Malin Aandahl](https://github.com/MalinAan) -[Manjukb](https://github.com/Manjukb) -[Marc BUFFAT](https://github.com/mbuffat) -[marciocourense](https://github.com/marciocourense) -[Marco Pleines](https://github.com/MarcoMeter) -[Marcus Hunger](https://github.com/fnordian) -[Marcus Levine](https://github.com/marcusianlevine) -[Mario Campos](https://github.com/mario-campos) -[Marius van Niekerk](https://github.com/mariusvniekerk) -[Mark Mirmelstein](https://github.com/markm42) -[marmaduke woodman](https://github.com/maedoc) -[Martin Forde](https://github.com/mforde84) -[Martín Anzorena](https://github.com/martjanz) -[maryamdev](https://github.com/maryamdev) -[Mas](https://github.com/airtime166) -[mascarom](https://github.com/mascarom) -[Mathew Blonc](https://github.com/blonc) -[Matt Hansen](https://github.com/hansen-m) -[Matteo Ipri](https://github.com/matteoipri) -[matthdan](https://github.com/matthdan) -[Matthew Bray](https://github.com/mattjbray) -[Matthew Rocklin](https://github.com/mrocklin) -[Matthias Bussonnier](https://github.com/Carreau) -[Matthias Klan](https://github.com/mklan) -[mattvw](https://github.com/mattvw) -[Max Joseph](https://github.com/mbjoseph) -[Maxim Moinat](https://github.com/MaximMoinat) -[mdivk](https://github.com/mdivk) -[Mereep](https://github.com/Mereep) -[merlin1608](https://github.com/merlin1608) -[Micah](https://github.com/micahscopes) -[Micah Smith](https://github.com/micahjsmith) -[Michael Huttner](https://github.com/mhuttner) -[Michael Milligan](https://github.com/mbmilligan) -[Michael Ransley](https://github.com/mransley) -[michec81](https://github.com/michec81) -[Michele Bertasi](https://github.com/mbrt) -[Miguel Caballer](https://github.com/micafer) -[Mike Hamer](https://github.com/mikehamer) -[Min RK](https://github.com/minrk) -[MincingWords](https://github.com/MincingWords) -[MisterZ](https://github.com/david-dumas) -[mohanamurali7](https://github.com/mohanamurali7) -[Mohit](https://github.com/Mohitsharma44) -[Monica Dessole](https://github.com/mdessole) -[moskiGithub](https://github.com/moskiGithub) -[mrkjones1979](https://github.com/mrkjones1979) -[mzilinski](https://github.com/mzilinski) -[n3f](https://github.com/n3f) -[Naeem Rashid](https://github.com/naeemkhan12) -[Naineel Shah](https://github.com/naineel) -[NaizEra](https://github.com/NaizEra) -[nauhpc](https://github.com/nauhpc) -[ndiy](https://github.com/ndiy) -[Neelanshu92](https://github.com/Neelanshu92) -[Nehemiah I. Dacres](https://github.com/dacresni) -[Neth Six](https://github.com/nethsix) -[ngokhoa96](https://github.com/ngokhoa96) -[Nick Brown](https://github.com/uptownnickbrown) -[Nickolaus D. Saint](https://github.com/NickolausDS) -[nickray](https://github.com/nickray) -[Nico Bellack](https://github.com/bellackn) -[Nicolas M. Thiéry](https://github.com/nthiery) -[Nikolay Dandanov](https://github.com/ndandanov) -[Nikolay Voronchikhin](https://github.com/nikolayvoronchikhin) -[niveau0](https://github.com/niveau0) -[Norman Gray](https://github.com/nxg) -[ogre0403](https://github.com/ogre0403) -[Ola Tarkowska](https://github.com/ola-t) -[oneklc](https://github.com/oneklc) -[OpenThings](https://github.com/openthings) -[ormskirk77](https://github.com/ormskirk77) -[P.J. Little](https://github.com/pjlittle) -[Pat W](https://github.com/patwoowong) -[Patafix](https://github.com/Patafix) -[Paul Adams](https://github.com/p5a0u9l) -[Paul Laskowski](https://github.com/paul-laskowski) -[Paul Mazzuca](https://github.com/PaulMazzuca) -[Paulo Roberto de Oliveira Castro](https://github.com/prcastro) -[Pav K](https://github.com/kalaytan) -[pedrovgp](https://github.com/pedrovgp) -[pekosro](https://github.com/pekosro) -[Peter Majchrak](https://github.com/petoknm) -[pgarapon](https://github.com/pgarapon) -[Phil Fenstermacher](https://github.com/pcfens) -[philippschw](https://github.com/philippschw) -[Phuong Cao](https://github.com/pmcao) -[picca](https://github.com/picca) -[Pierre Accorsi](https://github.com/paccorsi) -[Pinakibiswasdevops](https://github.com/Pinakibiswasdevops) -[Pius Nyakoojo](https://github.com/PiusNyakoojo) -[pjamason](https://github.com/pjamason) -[Pouria Hadjibagheri](https://github.com/xenatisch) -[Prabhu Kasinathan](https://github.com/prabhu1984) -[Pramod Rizal](https://github.com/prkriz) -[Pranay Hasan Yerra](https://github.com/pranayhasan) -[Prateek](https://github.com/prateekpg2455) -[prateek2408](https://github.com/prateek2408) -[Prerak Mody](https://github.com/prerakmody) -[Przybyszo](https://github.com/Przybyszo) -[psnx](https://github.com/psnx) -[pydo](https://github.com/yonghuming) -[pyjones1](https://github.com/pyjones1) -[R. C. Thomas](https://github.com/rcthomas) -[Rachidramadan1990](https://github.com/Rachidramadan1990) -[radudragusin](https://github.com/radudragusin) -[Rafael Ladislau](https://github.com/rafael-ladislau) -[Rafael Mejia](https://github.com/rafmesal) -[raghu20ram](https://github.com/raghu20ram) -[raja](https://github.com/raksja) -[Ramin](https://github.com/transfluxus) -[Ranjit](https://github.com/ranjitiyer) -[Raphael Nestler](https://github.com/rnestler) -[RaRam](https://github.com/RaRam) -[Raviraju Vysyaraju](https://github.com/ravirajuv) -[reddyvenu](https://github.com/reddyvenu) -[Ricardo Rocha](https://github.com/rochaporto) -[Rich Signell](https://github.com/rsignell-usgs) -[Richard Caunt](https://github.com/psyvision) -[Richard Darst](https://github.com/rkdarst) -[Richard England](https://github.com/renglandatsmu) -[Richard Ting](https://github.com/richardtin) -[Rizwan Saeed](https://github.com/rizwansaeed) -[Rob](https://github.com/rtruxal) -[Robert Casey](https://github.com/rcasey-iris) -[Robert Drysdale](https://github.com/robdrysdale) -[Robert Jiang ](https://github.com/robert-juang) -[Robert Schroll](https://github.com/rschroll) -[robin](https://github.com/rollbackchen) -[Robin](https://github.com/robmarkcole) -[Robin Scheibler](https://github.com/fakufaku) -[roemer2201](https://github.com/roemer2201) -[Rok Roškar](https://github.com/rokroskar) -[Roman Gorodeckij](https://github.com/holms) -[roversne](https://github.com/roversne) -[Roy Wedge](https://github.com/rwedge) -[Royi](https://github.com/RoyiAvital) -[Rui Zhang](https://github.com/zhangruiskyline) -[Ruslan Usifov](https://github.com/tantra35) -[Ryan Abernathey](https://github.com/rabernat) -[Ryan Lovett](https://github.com/ryanlovett) -[rydeng](https://github.com/rydeng) -[sabarnwa](https://github.com/sabarnwa) -[sabyasm](https://github.com/sabyasm) -[sadanand25](https://github.com/sadanand25) -[Sam Manzer](https://github.com/samuelmanzer) -[Sambaiah Kilaru](https://github.com/ksambaiah) -[samy](https://github.com/goforthanddie) -[Sangram Gaikwad](https://github.com/sangramga) -[sanjaydatasciencedojo](https://github.com/sanjaydatasciencedojo) -[Sanmati Jain](https://github.com/jainsanmati) -[saransha](https://github.com/saransha) -[Saranya411](https://github.com/Saranya411) -[sarath145p](https://github.com/sarath145p) -[Satendra Kumar](https://github.com/satendrakumar) -[saurav maharjan](https://github.com/saurssauravjs) -[saurs saurav](https://github.com/isaurssaurav) -[SB](https://github.com/SofianeB) -[sbailey-auro](https://github.com/sbailey-auro) -[Scott Crooks](https://github.com/sc250024) -[Scott Sanderson](https://github.com/ssanderson) -[SeaDude](https://github.com/SeaDude) -[semanticyongjia](https://github.com/semanticyongjia) -[serlina](https://github.com/serlina) -[Seshadri Ramaswami](https://github.com/sesh1989) -[shalan7](https://github.com/shalan7) -[Shana Matthews](https://github.com/shanamatthews) -[Shannon](https://github.com/jingsong-liu) -[Shantanu Singh](https://github.com/shantanusingh16) -[Shengxin Huang](https://github.com/FukoH) -[shilpam11](https://github.com/shilpam11) -[Shiva Prasanth](https://github.com/cedric05) -[shreddd](https://github.com/shreddd) -[Shuo YU](https://github.com/collinwo) -[Sigurður Baldursson](https://github.com/sigurdurb) -[Simon Li](https://github.com/manics) -[Sirawit Pongnakintr](https://github.com/s6007589) -[SivaMaplelabs](https://github.com/SivaMaplelabs) -[smiller5678](https://github.com/smiller5678) -[srican](https://github.com/srican) -[srini_b](https://github.com/Srinivasb0) -[Stanislav Nazmutdinov](https://github.com/PrintScr) -[stczwd](https://github.com/stczwd) -[Stefano Nicotri](https://github.com/stefanonicotri) -[Stefano Taschini](https://github.com/taschini) -[Stephanie Gott](https://github.com/gottsme) -[Stephen Lecrenski](https://github.com/slecrenski) -[Stephen Pascoe](https://github.com/stephenpascoe) -[Stephen Sackett](https://github.com/ssackett) -[Steven Silvester](https://github.com/blink1073) -[Stéphane Pouyllau](https://github.com/spouyllau) -[sudheer0553](https://github.com/sudheer0553) -[Sugu Sougoumarane](https://github.com/sougou) -[Suman Addanki](https://github.com/suman724) -[summerswallow](https://github.com/summerswallow) -[summerswallow-whi](https://github.com/summerswallow-whi) -[sundeepChandhoke](https://github.com/sundeepChandhoke) -[Sunip Mukherjee](https://github.com/sunipkmukherjee) -[svzdvdoptum](https://github.com/svzdvdoptum) -[swgong](https://github.com/sw-gong) -[Sylvain Desroziers](https://github.com/sdesrozis) -[syutbai](https://github.com/syutbai) -[T. George](https://github.com/tgeorgeux) -[tankeryang](https://github.com/tankeryang) -[TapasSpark](https://github.com/TapasSpark) -[Tassos Sarbanes](https://github.com/sarbanes) -[teddy Kossoko](https://github.com/KOSSOKO) -[tgamal](https://github.com/tgamal) -[Thomas Ashish Cherian](https://github.com/PandaWhoCodes) -[Thomas Kluyver](https://github.com/takluyver) -[Thomas Mendoza](https://github.com/tgmachina) -[thongnnguyen](https://github.com/thongnnguyen) -[Thoralf Gutierrez](https://github.com/thoralf-gutierrez) -[Tim Crone](https://github.com/tjcrone) -[Tim Freund](https://github.com/timfreund) -[Tim Head](https://github.com/betatim) -[Tim Kennell Jr.](https://github.com/tikenn) -[Tim Klever](https://github.com/tklever) -[Tim Shi](https://github.com/strin) -[TimKreuzer](https://github.com/TimKreuzer) -[Tirthankar Chakravarty](https://github.com/tchakravarty) -[titansmc](https://github.com/titansmc) -[Tobias Morville](https://github.com/TMorville) -[tobiaskaestner](https://github.com/tobiaskaestner) -[Tom Davidson](https://github.com/tjd2002) -[Tom Kwong](https://github.com/tk3369) -[Tom O'Connor](https://github.com/ichasepucks) -[Tomas Barton](https://github.com/deric) -[Tommaso Fabbri](https://github.com/tfabbri) -[Tyler Erickson](https://github.com/tylere) -[tzujan](https://github.com/tzujan) -[uday2002](https://github.com/uday2002) -[Umar Sikander](https://github.com/umar-sik) -[UsDAnDreS](https://github.com/UsDAnDreS) -[Vaclav Pavlin](https://github.com/vpavlin) -[Varun M S](https://github.com/meranamvarun) -[Victor Paraschiv](https://github.com/vicpara) -[vishwesh5](https://github.com/vishwesh5) -[Vladimir Kozhukalov](https://github.com/kozhukalov) -[vpvijay87](https://github.com/vpvijay87) -[W.](https://github.com/ManifoldFR) -[wangaiwudi](https://github.com/wangaiwudi) -[Wei Hao](https://github.com/whao) -[weih1121](https://github.com/weih1121) -[weimindong2016](https://github.com/weimindong2016) -[whitebluecloud](https://github.com/whitebluecloud) -[whositwhatnow](https://github.com/whositwhatnow) -[will](https://github.com/zsluedem) -[Will Starms](https://github.com/vilhelmen) -[William H](https://github.com/sylus) -[William Hosford](https://github.com/whosford) -[wtsyang](https://github.com/wtsyang) -[XIAHUALOU](https://github.com/XIAHUALOU) -[xuhuijun](https://github.com/xuhuijun) -[Y-L-18](https://github.com/Y-L-18) -[yee379](https://github.com/yee379) -[yeisonseverinopucv](https://github.com/yeisonseverinopucv) -[Yiding](https://github.com/wydwww) -[Yifan Li](https://github.com/Eagles2F) -[yougha54](https://github.com/yougha54) -[Youri Noel Nelson](https://github.com/ynnelson) -[yuandongfang](https://github.com/yuandongfang) -[Yueqi Wang](https://github.com/yueqiw) -[yugushihuang](https://github.com/yugushihuang) -[Yuhi Ishikura](https://github.com/uphy) -[Yuval Kalugny](https://github.com/kalugny) -[Yuvi Panda](https://github.com/yuvipanda) -[Zac Flamig](https://github.com/zflamig) -[Zachary Sailer](https://github.com/Zsailer) -[Zachary Zhao](https://github.com/zacharyzhao) -[ZachGlassman](https://github.com/ZachGlassman) -[zaf](https://github.com/zafeirakopoulos) -[Zafer Cesur](https://github.com/zcesur) -[zearaujo07](https://github.com/zearaujo07) -[Zeb Nicholls](https://github.com/znicholls) -[Zelphir Kaltstahl](https://github.com/ZelphirKaltstahl) -[ZenRay](https://github.com/ZenRay) -[zero](https://github.com/zero-88) -[zeusal](https://github.com/zeusal) -[Zhongyi](https://github.com/zhongyiio) -[Zhou (Joe) Yuan](https://github.com/yuanzhou) -[ziedbouf](https://github.com/ziedbouf) -[zlshi](https://github.com/zlshi) -[zmkhazi](https://github.com/zmkhazi) -[Zoltan Fedor](https://github.com/zoltan-fedor) -[zyc](https://github.com/499244188) -[Øystein Efterdal](https://github.com/oefterdal) -[孙永乐](https://github.com/cattei) -[张旭](https://github.com/zhangxu999) -[武晨光](https://github.com/mission-young) -[陈镇秋](https://github.com/ChenZhenQiu) - -## [0.6] - [Ellyse Perry](https://en.wikipedia.org/wiki/Ellyse_Perry) - 2017-01-29 - -This release is primarily focused on better support -for Autoscaling, Microsoft Azure support & better -default security. There are also a number of bug fixes -and configurability improvements! - -### Breaking changes - -#### Pre-puller configuration - -In prior versions (v0.5), if you wanted to disable the pre-puller, -you would use: - -```yaml -prePuller: - enabled: false -``` - -Now, to disable the pre-puller, you need to use: - -```yaml -prePuller: - hook: - enabled: false -``` - -See the [pre-puller docs](http://zero-to-jupyterhub.readthedocs.io/en/latest/advanced.html#pre-pulling-images-for-faster-startup) for more info! - -### Upgrading from 0.5 - -This release does not require any special steps to upgrade from v0.5. See the [upgrade documentation](https://zero-to-jupyterhub.readthedocs.io/en/latest/upgrading.html) -for general upgrading steps. - -If you are running v0.4 of the chart, you should upgrade to v0.5 first -before upgrading to v0.6. You can find out what version you are using -by running `helm list`. - -#### Troubleshooting - -If your helm upgrade fails due to the error `no Ingress with the name "jupyterhub-internal" found`, -you may be experiencing a [helm bug](https://github.com/kubernetes/helm/issues/3275). To work -around this, run `kubectl --namespace= delete ingress jupyterhub-internal` and -re-run the `helm upgrade` command. Note that this will cause a short unavailability of your hub -over HTTPS, which will resume normal availability once the deployment upgrade completes. - -### New Features - -#### More secure by default - -z2jh is more secure by default with 0.6. We now -block access to cloud security metadata endpoints by -default. - -See the [security documentation](http://zero-to-jupyterhub.readthedocs.io/en/latest/security.html) for more details. It has seen a number of improvements, and we recommend -you read through it! - -#### Autoscaling improvements - -Some cloud providers support the [kubernetes node autoscaler](https://github.com/kubernetes/autoscaler/tree/HEAD/cluster-autoscaler), -which can add / remove nodes depending on how much your -cluster is being used. In this release, we made a few -changes to let z2jh interact better with the autoscaler! - -- Configure z2jh to ['pack' your users](http://zero-to-jupyterhub.readthedocs.io/en/latest/advanced.html#picking-a-scheduler-strategy) - onto nodes, rather than 'spread' them across nodes. -- A ['continuous' pre-puller](http://zero-to-jupyterhub.readthedocs.io/en/latest/advanced.html?highlight=prepull#pre-pulling-images-for-faster-startup) - that allows user images to - be pulled on new nodes easily, leading to faster startup - times for users on new nodes. ([link]) -- Hub and Proxy pod will not be disrupted by autoscaler, - by using [PodDisruptionBudget](https://kubernetes.io/docs/tasks/run-application/configure-pdb/)s. The Hub & Proxy will also stick - together if possible, thus minimizing the number of nodes - that can not be downsized by the autoscaler. - -There is more work to be done for good autoscaling support, -but this is a good start! - -#### Better Azure support - -Azure's new managed Kubernetes service ([AKS](https://docs.microsoft.com/en-us/azure/aks/)) is much -better supported by this version! - -- We have much better documentation on using z2jh with Azure! -- We rewrote our pre-puller so it works on Azure (previously it did not) - -Azure AKS is still in preview mode, so be aware of that -before using it in any production workloads! - -See the [setting up Kubernetes on Microsoft AKS](http://zero-to-jupyterhub.readthedocs.io/en/latest/create-k8s-cluster.html#setting-up-kubernetes-on-microsoft-azure-container-service-aks) section for more information. - -#### Better configurability - -We now have better documentation and bug fixes for configurability! - -- `extraConfig` can be a dictionary instead of just a - string. This helps when you have to split your `config.yaml` - into multiple files for complex deployments -- How user storage works by default is [better documented](http://zero-to-jupyterhub.readthedocs.io/en/latest/user-storage.html) -- Reading config in `extraConfig` from `extraConfigMap` now actually works! -- You can configure the URL that users are directed to after they log in. - This allows [defaulting users to JupyterLab](http://zero-to-jupyterhub.readthedocs.io/en/latest/user-environment.html#use-jupyterlab-by-default) -- You can pre-pull multiple images now, for custom configuration that needs multiple images -- [Better instructions](http://zero-to-jupyterhub.readthedocs.io/en/latest/user-environment.html#pre-populating-user-s-home-directory-with-files) - on pre-populating your user's filesystem using [nbgitpuller](https://github.com/data-8/nbgitpuller) - -### [Ellyse Perry](https://en.wikipedia.org/wiki/Ellyse_Perry) - -_(excerpt from https://www.cricket.com.au/players/ellyse-perry/1aMxKNyEOUiJqhq7N5Tlwg)_ - -Arguably the best athlete in Australia, Ellyse Perry’s profile continues to rise -with the dual cricket and soccer international having played World Cups for both sports. - -Perry became the youngest Australian ever to play senior international cricket when -she made her debut in the second ODI of the Rose Bowl Series in Darwin in July 2007 -before her 17th birthday. - -She went on to make her domestic debut in the 2007-08 Women’s National Cricket League -season, taking 2-29 from 10 overs in her first match. - -Since her national debut, Perry has become a regular fixture for the Southern Stars, -playing in the 2009 ICC Women’s World Cup and the ICC Women’s World Twenty20 in the same year. - -Leading Australia’s bowling attack, Perry played a crucial role in the ICC Women’s -World Twenty20 Final in the West Indies in 2010. - -The match came down to the wire, with New Zealand requiring five runs off the last -ball to claim the title. Under immense pressure, Perry bowled the final ball of the -tournament, which New Zealand’s Sophie Devine struck straight off the bat. - -The talented footballer stuck out her boot to deflect the ball to Lisa Sthalekar at -mid-on, securing the trophy for Australia. Perry’s figures of 3-18 in the final saw -her take home the Player of the Match award. - -Perry featured prominently in Australia's three-peat of World T20 victories, -selected for the Team of the Tournament in 2012 and 2014. - -She was named [ICC Female Cricketer of the Year](http://www.abc.net.au/news/2017-12-22/ellyse-perry-named-iccs-womens-cricketer-of-the-year/9280538) in 2017. - -### Contributors - -This release wouldn't have been possible without the wonderful contributors -to the [zero-to-jupyterhub](https://github.com/jupyterhub/zero-to-jupyterhub-k8s), -and [KubeSpawner](https://github.com/jupyterhub/kubespawner) repos. -We'd like to thank everyone who contributed in any form - Issues, commenting -on issues, PRs and reviews since the last Zero to JupyterHub release. - -In alphabetical order, - -- [Aaron Culich](https://github.com/aculich) -- [Anirudh Ramanathan](https://github.com/foxish) -- [Antoine Dao](https://github.com/twanito) -- [BerserkerTroll](https://github.com/BerserkerTroll) -- [Carol Willing](https://github.com/willingc) -- [Chris Holdgraf](https://github.com/choldgraf) -- [Christian Mesh](https://github.com/cam72cam) -- [Erik Sundell](https://github.com/consideRatio) -- [forbxy](https://github.com/forbxy) -- [Graham Dumpleton](https://github.com/GrahamDumpleton) -- [gweis](https://github.com/gweis) -- [Ian Allison](https://github.com/ianabc) -- [Jason Kuruzovich](https://github.com/jkuruzovich) -- [Jesse Kinkead](https://github.com/jkinkead) -- [madanam1](https://github.com/madanam1) -- [Matthew Rocklin](https://github.com/mrocklin) -- [Matthias Bussonnier](https://github.com/Carreau) -- [Min RK](https://github.com/minrk) -- [Ryan Lovett](https://github.com/ryanlovett) -- [Simon Li](https://github.com/manics) -- [Steve Buckingham](https://github.com/stevebuckingham) -- [Steven Normore](https://github.com/snormore) -- [Tim Head](https://github.com/betatim) -- [Yuvi Panda](https://github.com/yuvipanda) -- [ZachGlassman](https://github.com/ZachGlassman) - -## [0.5] - [Hamid Hassan](http://www.espncricinfo.com/afghanistan/content/player/311427.html) - 2017-12-05 - -JupyterHub 0.8, HTTPS & scalability. - -### Upgrading from 0.4 - -See the [upgrade documentation](https://zero-to-jupyterhub.readthedocs.io/en/latest/upgrading.html) for upgrade steps. - -### New Features - -#### JupyterHub 0.8 - -JupyterHub 0.8 is full of new features - see [CHANGELOG](https://jupyterhub.readthedocs.io/en/0.8.1/changelog.html#id1) -for more details. Specific features made to benefit this chart are: - -1. No more 'too many redirects' errors at scale. -2. Lots of performance improvements, we now know we can handle up to 4k active users -3. Concurrent spawn limits (set via `hub.concurrentSpawnLimit`) can be used to limit the concurrent - number of users who can try to launch on the hub at any given time. This can be - tuned to avoid crashes when hundreds of users try to launch at the same time. It gives - them a friendly error message + asks them to try later, rather than spinning forever. -4. Active Server limit (set via `hub.activeServerLimit`) can be used to limit the - total number of active users that can be using the hub at any given time. This allows - admins to control the size of their clusters. -5. Memory limits & guarantees (set via `singleuser.memory`) can now contain fractional - units. So you can say `0.5G` instead of having to use `512M`. - -And lots more! - -#### Much easier HTTPS - -It is our responsibility as software authors to make it very easy for admins to set up -HTTPS for their users. v0.5 makes this much easier than v0.4. You can find the new -instructions [here](http://zero-to-jupyterhub.readthedocs.io/en/latest/extending-jupyterhub.html#setting-up-https) and -they are much simpler! - -You can also now use your own HTTPS certificates & keys rather than using Let's Encrypt. - -#### More authenticators supported - -The following new authentication providers have been added: - -1. GitLab -2. CILogon -3. Globus - -You can also set up a whitelist of users by adding to the list in `auth.whitelist.users`. - -#### Easier customization of `jupyterhub_config.py` - -You can always put extra snippets of `jupyterhub_config.py` configuration in -`hub.extraConfig`. Now you can also add extra environment variables to the hub -in `hub.extraEnv` and extra configmap items via `hub.extraConfigMap`. ConfigMap -items can be arbitrary YAML, and you can read them via the `get_config` function in -your `hub.extraConfig`. This makes it cleaner to customize the hub's config in -ways that's not yet possible with config.yaml. - -#### Hub Services support - -You can also add [external JupyterHub Services](http://jupyterhub.readthedocs.io/en/latest/reference/services.html) -by adding them to `hub.services`. Note that you are still responsible for actually -running the service somewhere (perhaps as a deployment object). - -#### More customization options for user server environments - -More options have been added under `singleuser` to help you customize the environment -that the user is spawned in. You can change the uid / gid of the user with `singleuser.uid` -and `singleuser.fsGid`, mount extra volumes with `singleuser.storage.extraVolumes` & -`singleuser.storage.extraVolumeMounts` and provide extra environment variables with -`singleuser.extraEnv`. - -### Hamid Hassan - -Hamid Hassan is a fast bowler who currently plays for the Afghanistan National -Cricket Team. With nicknames ranging from -["Afghanistan's David Beckham"](https://www.rferl.org/a/interview-afghan-cricketer-living-the-dream/24752618.html) to -["Rambo"](http://www.nzherald.co.nz/nz/news/article.cfm?c_id=1&objectid=11413633), -he is considered by many to be Afghanistan's first Cricket Superhero. Currently -known for fast (145km/h+) deliveries, cartwheeling celebrations, war painted -face and having had to flee Afghanistan as a child to escape from war. He [says](http://www.nzherald.co.nz/nz/news/article.cfm?c_id=1&objectid=11413633) -he plays because "We are ambassadors for our country and we want to show the -world that Afghanistan is not like people recognise it by terrorists and these -things. We want them to know that we have a lot of talent as well" - -### Contributors - -This release wouldn't have been possible without the wonderful contributors -to the [zero-to-jupyterhub](https://github.com/jupyterhub/zero-to-jupyterhub-k8s), -[JupyterHub](https://github.com/jupyterhub/jupyterhub), [KubeSpawner](https://github.com/jupyterhub/kubespawner) -and [OAuthenticator](http://github.com/jupyterhub/oauthenticator) repos. -We'd like to thank everyone who contributed in any form - Issues, commenting -on issues, PRs and reviews since the last Zero to JupyterHub release. - -In alphabetical order, - -- [Aaron Culich](https://github.com/aculich) -- [abeche](https://github.com/alexxxxx) -- [Abhinandan Dubey](https://github.com/alivcor) -- [Adam Thornton](https://github.com/athornton) -- [Adrin Jalali](https://github.com/adrinjalali) -- [Aidis Stukas](https://github.com/aidiss) -- [Aleksandr Blekh](https://github.com/ablekh) -- [Alessandro Vozza](https://github.com/ams0) -- [Alex Hilson](https://github.com/alexhilson) -- [Analect](https://github.com/Analect) -- [Andrea Zonca](https://github.com/zonca) -- [Andreas](https://github.com/Jibbow) -- [Andrew Berger](https://github.com/rueberger) -- [András Tóth](https://github.com/tothandras) -- [angrylandmammal](https://github.com/angrylandmammal) -- [Anirudh Ramanathan](https://github.com/foxish) -- [Antonino Ingargiola](https://github.com/tritemio) -- [apachipa](https://github.com/apachipa) -- [Ariel Rokem](https://github.com/arokem) -- [astrodb](https://github.com/astrodb) -- [Ayushi Agarwal](https://github.com/ayushiagarwal) -- [batchku](https://github.com/batchku) -- [bbhopesh](https://github.com/bbhopesh) -- [Bill Major](https://github.com/rwmajor2) -- [Brad Svee](https://github.com/sveesible) -- [Brian E. Granger](https://github.com/ellisonbg) -- [BrianVanEtten](https://github.com/BrianVanEtten) -- [calz1](https://github.com/calz1) -- [Camilo Núñez Fernández](https://github.com/camilo-nunez) -- [Carol Willing](https://github.com/willingc) -- [Chris Holdgraf](https://github.com/choldgraf) -- [Christian Barra](https://github.com/barrachri) -- [Christian Moscardi](https://github.com/cmoscardi) -- [Christophe Lecointe](https://github.com/christophelec) -- [Christopher Hench](https://github.com/henchc) -- [Christopher Ostrouchov](https://github.com/costrouc) -- [ckbhatt](https://github.com/ckbhatt) -- [Cody Scott](https://github.com/Siecje) -- [Colin Goldberg](https://github.com/colingoldberg) -- [daleshsd](https://github.com/daleshsd) -- [danroliver](https://github.com/danroliver) -- [Dave Hirschfeld](https://github.com/dhirschfeld) -- [David](https://github.com/davidXire) -- [Davide](https://github.com/davidedelvento) -- [deisi](https://github.com/deisi) -- [Dennis Pfisterer](https://github.com/pfisterer) -- [Dennis Verspuij](https://github.com/dennisverspuij) -- [Diogo](https://github.com/dmvieira) -- [dmceballosg](https://github.com/dmceballosg) -- [Dominic Follett-Smith](https://github.com/dominicfollett) -- [Doug Blank](https://github.com/dsblank) -- [Enol Fernández](https://github.com/enolfc) -- [Erik Sundell](https://github.com/consideRatio) -- [erolosty](https://github.com/erolosty) -- [FalseProtagonist](https://github.com/FalseProtagonist) -- [fmilano1975](https://github.com/fmilano1975) -- [Forrest Collman](https://github.com/fcollman) -- [Fred Mitchell](https://github.com/fm75) -- [Gil Forsyth](https://github.com/gforsyth) -- [Goutham Balaraman](https://github.com/gouthambs) -- [gryslik](https://github.com/gryslik) -- [gweis](https://github.com/gweis) -- [haasad](https://github.com/haasad) -- [hani1814](https://github.com/hani1814) -- [Hanno Rein](https://github.com/hannorein) -- [harschware](https://github.com/harschware) -- [Ian Allison](https://github.com/ianabc) -- [Isaiah Leonard](https://github.com/ihleonard-c3) -- [J Forde](https://github.com/jzf2101) -- [Jacob Tomlinson](https://github.com/jacobtomlinson) -- [jai11](https://github.com/jai11) -- [jbmarcille](https://github.com/jbmarcille) -- [Jeet Shah](https://github.com/iamjeet) -- [Jeroen Vuurens](https://github.com/jeroenvuurens) -- [Jessica B. Hamrick](https://github.com/jhamrick) -- [jiamicu](https://github.com/jiamicu) -- [jiancai1992](https://github.com/jiancai1992) -- [jm2004](https://github.com/jm2004) -- [joefromct](https://github.com/joefromct) -- [John Haley](https://github.com/johnhaley81) -- [jonny86](https://github.com/jonny86) -- [Joshua Milas](https://github.com/DeepHorizons) -- [JoshuaC3](https://github.com/JoshuaC3) -- [João Vítor Amaro](https://github.com/joaoamaro70) -- [Justin Ray Vrooman](https://github.com/vroomanj) -- [Keith Callenberg](https://github.com/keithcallenberg) -- [KenB](https://github.com/y2kbowen) -- [Kenneth Lyons](https://github.com/ixjlyons) -- [krak3nnn](https://github.com/krak3nnn) -- [Kristiyan](https://github.com/katsar0v) -- [Kuisong Tong](https://github.com/ktong) -- [kuldeepyadav](https://github.com/kuldeepyadav) -- [Kyle Kelley](https://github.com/rgbkrk) -- [lcfcefyn](https://github.com/lcfcefyn) -- [Leo Gallucci](https://github.com/elgalu) -- [lesiano](https://github.com/lesiano) -- [Lorena A. Barba](https://github.com/labarba) -- [lrob](https://github.com/lrob) -- [Lukasz Tracewski](https://github.com/tracek) -- [Mahesh Vangala](https://github.com/vangalamaheshh) -- [Marco Sirabella](https://github.com/mjsir911) -- [marcostrullato](https://github.com/marcostrullato) -- [Marius van Niekerk](https://github.com/mariusvniekerk) -- [MarkusTeufelberger](https://github.com/MarkusTeufelberger) -- [Matt Koken](https://github.com/patback66) -- [Matteo Cerutti](https://github.com/m4ce) -- [Matthias Bussonnier](https://github.com/Carreau) -- [Michael Li](https://github.com/tianhuil) -- [Mike](https://github.com/s-t-e-a-l-t-h) -- [MikeM](https://github.com/mmacny) -- [Min RK](https://github.com/minrk) -- [misolietavec](https://github.com/misolietavec) -- [Moiz Sajid](https://github.com/moizsajid) -- [Morgan Jones](https://github.com/mogthesprog) -- [mraky](https://github.com/mraky) -- [mrinmoyprasad](https://github.com/mrinmoyprasad) -- [nabriis](https://github.com/nabriis) -- [Nickolaus D. Saint](https://github.com/NickolausDS) -- [Nocturnal316](https://github.com/Nocturnal316) -- [Olivier Cloarec](https://github.com/ocloarec) -- [Pedro Henriques dos Santos Teixeira](https://github.com/pedroteixeira) -- [Pranay Hasan Yerra](https://github.com/pranayhasan) -- [prof-schacht](https://github.com/prof-schacht) -- [Puneet Jindal](https://github.com/puneetjindal) -- [R. C. Thomas](https://github.com/rcthomas) -- [ramonberger](https://github.com/ramonberger) -- [Randy Guthrie](https://github.com/randguth) -- [Richard Caunt](https://github.com/psyvision) -- [richmoore1962](https://github.com/richmoore1962) -- [Rishika Sinha](https://github.com/rsinha25) -- [Robert Wlodarczyk](https://github.com/SimplicityGuy) -- [Ruben Orduz](https://github.com/rdodev) -- [Ryan Lovett](https://github.com/ryanlovett) -- [Ryan Wang](https://github.com/rwangr) -- [rydeng](https://github.com/rydeng) -- [SarunasG](https://github.com/SarunasG) -- [Saul Shanabrook](https://github.com/saulshanabrook) -- [Scott Calabrese Barton](https://github.com/scbarton) -- [Scott Sanderson](https://github.com/ssanderson) -- [Simon Li](https://github.com/manics) -- [Stefano Nicotri](https://github.com/stefanonicotri) -- [surma-lodur](https://github.com/surma-lodur) -- [Sven Mayer](https://github.com/SamyStyle) -- [swigicat](https://github.com/swigicat) -- [SY_Wang](https://github.com/kiwi0217) -- [Thomas Kluyver](https://github.com/takluyver) -- [Thomas Mendoza](https://github.com/tgmachina) -- [Tim Head](https://github.com/betatim) -- [toddpfaff](https://github.com/toddpfaff) -- [Tom O'Connor](https://github.com/ichasepucks) -- [toncek87](https://github.com/toncek87) -- [Tony ](https://github.com/Montereytony) -- [Travis Sturzl](https://github.com/tsturzl) -- [Tyler Cloutier](https://github.com/cloutiertyler) -- [uday2002](https://github.com/uday2002) -- [Udita Bose](https://github.com/uditabose) -- [uttamkumar123](https://github.com/uttamkumar123) -- [will](https://github.com/zsluedem) -- [Wilmer Ramirez](https://github.com/will17cr) -- [xgdgsc](https://github.com/xgdgsc) -- [Yan Zhao](https://github.com/yan130) -- [Yinan Li](https://github.com/liyinan926) -- [yoryicopo](https://github.com/yoryicopo) -- [Yu-Hang "Maxin" Tang](https://github.com/yhtang) -- [Yuvi Panda](https://github.com/yuvipanda) -- [Zachary Ogren](https://github.com/zogren) -- [Zhenwen Zhang](https://github.com/zhangzhenwen) -- [Zoltan Fedor](https://github.com/zoltan-fedor) - -## [0.4] - [Akram](#akram) - 2017-06-23 - -Stability, HTTPS & breaking changes. - -### Installation and upgrades - -We **recommend** that you delete prior versions of the package and install the -latest version. If you are very familiar with Kubernetes, you can upgrade from -an older version, but we still suggest deleting and recreating your -installation. - -### Breaking changes - -- The **name of a user pod** and a **dynamically created home directory [PVC (PersistentVolumeClaim)](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims)** no longer include - the `userid` in them by default. If you are using dynamic PVCs for `home` - directories (which is the default), you will need to _manually rename_ these - directories before upgrading. - Otherwise, new PVCs will be created, and users might freak out when viewing the newly created directory and think that their home directory appears empty. - - See [PR #56](https://github.com/jupyterhub/kubespawner/pull/56) on - what needs to change. - -- A **[StorageClass](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#storageclasses)** - is no longer created by default. This shouldn't affect most new installs, - since most cloud provider installations have a default (as of Kubernetes 1.6). - If you are using an older version of Kubernetes, the easiest thing to do is to - upgrade to a newer version. If not, you can create a StorageClass manually - and everything should continue to work. - -- `token.proxy` is removed. Use **`proxy.secretToken`** instead. - If your `config.yaml` contains something that looks like the following: - - ```yaml - token: - proxy: - ``` - - you should change that to: - - ```yaml - proxy: - secretToken: - ``` - -### Added - -- Added **GitHub Authentication support**, thanks to [Jason Kuruzovich](https://github.com/jkuruzovich). -- Added **[Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) support**! - If your cluster already has Ingress support (with automatic Let's Encrypt support, perhaps), - you can easily use that now. -- We now add a **label** to user pods / PVCs with their usernames. -- Support using a **static PVC** for user `home` directories or for the hub database. This makes this release usable - with clusters where you only have one NFS share that must be used for the whole hub. -- **PostgreSQL** is now a supported hub database backend provider. -- You can set annotations & labels on the **proxy-public service** now. - -### Changed - -- We now use the official [configurable http proxy](http://github.com/jupyterhub/configurable-http-proxy) - (CHP) as the proxy, rather than the unofficial - [nchp](https://github.com/yuvipanda/jupyterhub-nginx-chp). This should be a - no-op (or require no changes) for the most part. JupyterHub errors might - display a nicer error page. -- The version of KubeSpawner uses the official Kubernetes - [python client](https://github.com/kubernetes-incubator/client-python/) rather - than [pycurl](http://pycurl.io/). This helps with scalability a little. - -### Removed - -- The deprecated `createNamespace` parameter no longer works, alongside the - deprecated `name` parameter. You probably weren't using these anyway - they - were kept only for backwards compatibility with very early versions. - -### Contributors - -This release made possible by the awesome work of the following contributors -(in alphabetical order): - -- [Analect](https://github.com/analect) -- [Carol Willing](https://github.com/willingc) -- [Jason Kuruzovich](https://github.com/jkuruzovich) -- [Min RK](https://github.com/minrk/) -- [Yuvi Panda](https://github.com/yuvipanda/) - -<3 - -### Akram - -[Wasim Akram](https://en.wikipedia.org/wiki/Wasim_Akram) (وسیم اکرم) is considered by many to be -the greatest pace bowler of all time and a founder of the fine art of -[reverse swing bowling](https://en.wikipedia.org/wiki/Swing_bowling#Reverse_swing). - -## 0.3 - -### [0.3.1] - 2017-05-19 - -KubeSpawner updates. [Release note](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/releases/tag/v0.3.1) - -### [0.3] - 2017-05-15 - -Deployer UX fixes. [Release note](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/releases/tag/v0.3) - -## [0.2] - 2017-05-01 - -Minor cleanups and features. [Release note](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/releases/tag/v0.2) - -## [0.1] - 2017-04-10 - -Initial Public Release. [Release note](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/releases/tag/v0.1) +The changelog is now available at https://z2jh.jupyter.org/en/latest/changelog.html. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c76ddb29c6..eee8ebd800 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ git clone https://github.com/jupyterhub/zero-to-jupyterhub-k8s # Setting up for documentation development -See [doc/README.md](doc/README.md). +See [docs/README.md](docs/README.md). # Setting up for Helm chart development @@ -30,7 +30,7 @@ This needs to be installed: - Python 3.6+ (install at [Anaconda.com](https://www.anaconda.com/distribution/) or [Python.org](https://www.python.org/downloads/)) and dependencies: ```shell pip install -r dev-requirements.txt - pip install -r doc/requirements.txt + pip install -r docs/requirements.txt ``` You can check if you have it all like this: @@ -174,7 +174,7 @@ For more information, see **Install Pebble** ```shell -helm repo add jupyterhub https://jupyterhub.github.io/helm-chart/ +helm repo add jupyterhub https://hub.jupyter.org/helm-chart/ helm repo update helm upgrade --install pebble jupyterhub/pebble --cleanup-on-fail --values dev-config-pebble.yaml ``` @@ -331,7 +331,7 @@ Did you get an error like one of these below? # while running apt-get install while building a docker image with chartpress E: Failed to fetch http://archive.ubuntu.com/ubuntu/pool/main/r/rtmpdump/librtmp1_2.4+20151223.gitfa8646d.1-1_amd64.deb Could not connect to archive.ubuntu.com:80 (91.189.88.174). - connect (113: No route to host) Could not connect to archive.ubuntu.com:80 (91.189.88.31). - connect (113: No route to host) [IP: 91.189.88.174 80] # [...] -subprocess.CalledProcessError: Command '['docker', 'build', '-t', 'jupyterhub/k8s-hub:0.9-217f798', 'images/hub', '--build-arg', 'JUPYTERHUB_VERSION=git+https://github.com/jupyterhub/jupyterhub@master']' returned non-zero exit status 100. +subprocess.CalledProcessError: Command '['docker', 'build', '-t', 'quay.io/jupyterhub/k8s-hub:0.9-217f798', 'images/hub', '--build-arg', 'JUPYTERHUB_VERSION=git+https://github.com/jupyterhub/jupyterhub@master']' returned non-zero exit status 100. # while installing a dependency for our k8s cluster Unable to connect to the server: dial tcp: lookup docs.projectcalico.org on 127.0.0.53:53: read udp 127.0.0.1:56409->127.0.0.53:53: i/o timeout diff --git a/README.md b/README.md index 94a57e4540..4a646cd285 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # Zero to JupyterHub with Kubernetes [![Documentation build status](https://img.shields.io/readthedocs/zero-to-jupyterhub?logo=read-the-docs)](https://zero-to-jupyterhub.readthedocs.io/en/latest/?badge=latest) -[![GitHub Workflow Status - Test](https://img.shields.io/github/workflow/status/jupyterhub/zero-to-jupyterhub-k8s/Test%20chart?logo=github&label=tests)](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/actions) -[![GitHub Workflow Status - Vuln. scan](https://img.shields.io/github/workflow/status/jupyterhub/zero-to-jupyterhub-k8s/Vuln.%20scan?logo=github&label=Vuln.%20scan)](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/actions) -[![Latest stable release of the Helm chart](https://img.shields.io/badge/dynamic/json.svg?label=stable&url=https://jupyterhub.github.io/helm-chart/info.json&query=$.jupyterhub.stable&colorB=orange&logo=helm)](https://jupyterhub.github.io/helm-chart#jupyterhub) -[![Latest pre-release of the Helm chart](https://img.shields.io/badge/dynamic/json.svg?label=pre&url=https://jupyterhub.github.io/helm-chart/info.json&query=$.jupyterhub.pre&colorB=orange&logo=helm)](https://jupyterhub.github.io/helm-chart#development-releases-jupyterhub) -[![Latest development release of the Helm chart](https://img.shields.io/badge/dynamic/json.svg?label=dev&url=https://jupyterhub.github.io/helm-chart/info.json&query=$.jupyterhub.latest&colorB=orange&logo=helm)](https://jupyterhub.github.io/helm-chart#development-releases-jupyterhub) +[![GitHub Workflow Status - Test](https://img.shields.io/github/actions/workflow/status/jupyterhub/zero-to-jupyterhub-k8s/test-chart.yaml?logo=github&label=tests)](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/actions) +[![GitHub Workflow Status - Vuln. scan](https://img.shields.io/github/actions/workflow/status/jupyterhub/zero-to-jupyterhub-k8s/vuln-scan.yaml?logo=github&label=Vuln.%20scan)](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/actions) +[![Latest stable release of the Helm chart](https://img.shields.io/badge/dynamic/json.svg?label=stable&url=https://hub.jupyter.org/helm-chart/info.json&query=$.jupyterhub.stable&colorB=orange&logo=helm)](https://jupyterhub.github.io/helm-chart#jupyterhub) +[![Latest pre-release of the Helm chart](https://img.shields.io/badge/dynamic/json.svg?label=pre&url=https://hub.jupyter.org/helm-chart/info.json&query=$.jupyterhub.pre&colorB=orange&logo=helm)](https://jupyterhub.github.io/helm-chart#development-releases-jupyterhub) +[![Latest development release of the Helm chart](https://img.shields.io/badge/dynamic/json.svg?label=dev&url=https://hub.jupyter.org/helm-chart/info.json&query=$.jupyterhub.latest&colorB=orange&logo=helm)](https://jupyterhub.github.io/helm-chart#development-releases-jupyterhub)
[![GitHub](https://img.shields.io/badge/issue_tracking-github-blue?logo=github)](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/issues) [![Discourse](https://img.shields.io/badge/help_forum-discourse-blue?logo=discourse)](https://discourse.jupyter.org/c/jupyterhub/z2jh-k8s) @@ -50,7 +50,7 @@ Much of the initial groundwork for this documentation is information learned from the successful use of JupyterHub and Kubernetes at UC Berkeley in their [Data 8](http://data8.org/) program. -![](doc/source/_static/images/data8_massive_audience.jpg) +![](docs/source/_static/images/data8_massive_audience.jpg) ## Acknowledgements diff --git a/RELEASE.md b/RELEASE.md index c321f02e12..fb6053979f 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -14,7 +14,8 @@ The JupyterHub Helm chart relies on many dependent projects, and when we make a ### Dependent Python packages -Update JupyterHub's Python dependencies in `images/hub/requirements.txt` by going to the folder and running `./dependencies freeze --upgrade`. +Update JupyterHub's Python dependencies in `images/hub/requirements.txt` by +following the instructions in `images/hub/README.md`. Also consider nudging dependent projects in the JupyterHub GitHub organization for a release. @@ -27,7 +28,7 @@ Also consider nudging dependent projects in the JupyterHub GitHub organization f These images version/tags are set in [values.yaml](jupyterhub/values.yaml), consider bumping the version of these as well. - [ ] [configurable-http-proxy](https://github.com/jupyterhub/configurable-http-proxy) - - [Available image tags](https://hub.docker.com/r/jupyterhub/configurable-http-proxy/tags) + - [Available image tags](https://quay.io/repository/jupyterhub/configurable-http-proxy?tab=tags) - values.yaml entry: `proxy.chp.image` - [ ] [traefik/traefik](https://github.com/traefik/traefik) - [Available image tags](https://hub.docker.com/_/traefik?tab=tags) @@ -47,7 +48,7 @@ Also the images we build are based on some image specified in the `FROM` stateme ## Pre-release iteration -- Update `CHANGELOG.md` +- Update `docs/source/changelog.md` - [ ] Generate a list of PRs using [executablebooks/github-activity](https://github.com/executablebooks/github-activity) ```bash @@ -64,16 +65,16 @@ Also the images we build are based on some image specified in the `FROM` stateme ```bash git checkout main git reset --hard /main - git tag -a x.y.z-beta.1 -m x.y.z-beta.1 - git push --follow-tags main + tbump x.y.z-beta.1 ``` + This will automatically create a [GitHub prerelease](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/releases). - Announce the x.y.z-beta.1 release - [ ] Write a discourse post ## Final release -- Update `CHANGELOG.md` +- Update `docs/source/changelog.md` - [ ] Generate a list of merged PRs and a list of contributors and update the changelog. ```bash @@ -88,12 +89,16 @@ Also the images we build are based on some image specified in the `FROM` stateme ```bash git checkout main git reset --hard /main - git tag -a x.y.z -m x.y.z HEAD - git push --follow-tags main + tbump x.y.z ``` - - [ ] Create a GitHub release. - Visit the [release page](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/releases) and create a new release referencing the recent tag. Add a brief text like the one below. + This will automatically create a [GitHub release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/releases). + + - [ ] Set the next prerelease version (don't create a tag). + + ```bash + tbump --no-tag x.y.z+1-0.dev + ``` - Communicate - [ ] Update the beta release's discourse post. diff --git a/chartpress.yaml b/chartpress.yaml index fa4c8bde1b..2b5f0599b7 100644 --- a/chartpress.yaml +++ b/chartpress.yaml @@ -13,6 +13,14 @@ charts: # Dev: imagePrefix can be useful to override if you want to trial something # locally developed in a remote k8s cluster. imagePrefix: gcr.io/nii-ap-ops/k8s- + # baseVersion should be a -0.dev suffixed version, where the version should + # be the next major, minor, or patch version depending on what we have + # merged so far into the main branch. If for example we have merged a + # breaking change it should be the next major version, like 3.0.0-0.dev. + # + # baseVersion should be managed via tbump, see RELEASE.md for details + # + baseVersion: "3.2.2" repo: git: RCOSDP/CS-jhub-helm-chart published: https://rcosdp.github.io/CS-jhub-helm-chart/ @@ -22,10 +30,12 @@ charts: # Authenticator are running. hub: valuesPath: hub.image - # Dev: buildArgs can help you try the Helm chart against unreleased - # versions of JupyterHub or KubeSpawner. - # buildArgs: - # PIP_OVERRIDES: "jupyterhub==1.3.0 git+https://github.com/your-username-here/kubespawner.git" + # hub-slim, an alternative hub image that doesn't include some + # basic utilities for k8s admins + hub-slim: + contextPath: images/hub + extraBuildCommandOptions: + - --target=slim-stage # secret-sync, a sidecar container running in the autohttps pod to next to # Traefik meant to sync a TLS certificate with a k8s Secret. @@ -48,4 +58,3 @@ charts: # singleuser-sample, a primitive user container to start with. singleuser-sample: valuesPath: singleuser.image - PIP_OVERRIDES: jupyterhub==1.4.2 diff --git a/ci/common b/ci/common index c28d82afc7..71c6d34aa8 100755 --- a/ci/common +++ b/ci/common @@ -13,22 +13,26 @@ setup_helm () { curl -sf https://raw.githubusercontent.com/helm/helm/HEAD/scripts/get-helm-3 | DESIRED_VERSION=${HELM_VERSION} bash } +await_kubectl_rollout() { + kubectl rollout status --watch --timeout 300s "$1" +} + await_pebble() { - kubectl rollout status --watch --timeout 300s deployment/pebble \ - && kubectl rollout status --watch --timeout 300s deployment/pebble-coredns + await_kubectl_rollout deployment/pebble \ + && await_kubectl_rollout deployment/pebble-coredns } await_jupyterhub() { - kubectl rollout status --watch --timeout 300s deployment/proxy \ - && kubectl rollout status --watch --timeout 300s deployment/hub \ + await_kubectl_rollout deployment/proxy \ + && await_kubectl_rollout deployment/hub \ && ( if kubectl get deploy/autohttps &> /dev/null; then - kubectl rollout status --watch --timeout 300s deployment/autohttps + await_kubectl_rollout deployment/autohttps fi ) \ && ( if kubectl get deploy/user-scheduler &> /dev/null; then - kubectl rollout status --watch --timeout 300s deployment/user-scheduler + await_kubectl_rollout deployment/user-scheduler fi ) } diff --git a/ci/publish b/ci/publish index a2b7482090..63fa73b6e2 100755 --- a/ci/publish +++ b/ci/publish @@ -6,10 +6,10 @@ # Exit on errors, assert env vars, log commands set -eux -PUBLISH_ARGS="--push --publish-chart \ +PUBLISH_ARGS="--push \ --builder docker-buildx \ --platform linux/amd64 --platform linux/arm64 \ - " +" # chartpress use git to push to our Helm chart repository, which is the gh-pages # branch of jupyterhub/helm-chart. We have installed a private SSH key within @@ -31,11 +31,19 @@ if [[ $GITHUB_REF != refs/tags/* ]]; then PR_OR_HASH=$(git log -1 --pretty=%h-%B | head -n1 | sed 's/^.*\(#[0-9]*\).*/\1/' | sed 's/^\([0-9a-f]*\)-.*/@\1/') LATEST_COMMIT_TITLE=$(git log -1 --pretty=%B | head -n1) EXTRA_MESSAGE="${GITHUB_REPOSITORY}${PR_OR_HASH} ${LATEST_COMMIT_TITLE}" - chartpress $PUBLISH_ARGS --extra-message "${EXTRA_MESSAGE}" + + # shellcheck disable=SC2086 + chartpress $PUBLISH_ARGS --extra-message "${EXTRA_MESSAGE}" --publish-chart + # shellcheck disable=SC2086 + chartpress $PUBLISH_ARGS --extra-message "${EXTRA_MESSAGE}" --image-prefix=jupyterhub/k8s- else # Setting a tag explicitly enforces a rebuild if this tag had already been # built and we wanted to override it. - chartpress $PUBLISH_ARGS --tag "${GITHUB_REF:10}" + + # shellcheck disable=SC2086 + chartpress $PUBLISH_ARGS --tag "${GITHUB_REF:10}" --publish-chart + # shellcheck disable=SC2086 + chartpress $PUBLISH_ARGS --tag "${GITHUB_REF:10}" --image-prefix=jupyterhub/k8s- fi # Let us log the changes chartpress did, it should include replacements for diff --git a/ci/refreeze b/ci/refreeze new file mode 100755 index 0000000000..97abf6a1e1 --- /dev/null +++ b/ci/refreeze @@ -0,0 +1,19 @@ +#!/bin/bash +set -xeuo pipefail +IMAGES=${1:-images/hub images/singleuser-sample} + +# Because `pip-compile` resolves `requirements.txt` with the current +# Python for the current platform, it should be run on the same Python +# version and platform as our Dockerfile. + +for img in ${IMAGES}; do + pushd "$img" + docker run --rm \ + --env=CUSTOM_COMPILE_COMMAND='Use the "Run workflow" button at https://github.com/jupyterhub/zero-to-jupyterhub-k8s/actions/workflows/watch-dependencies.yaml' \ + --volume="$PWD:/io" \ + --workdir=/io \ + --user=root \ + python:3.11-bullseye \ + sh -c 'pip install pip-tools==6.* && pip-compile --resolver=backtracking --upgrade' + popd +done diff --git a/ci/summarise-linkcheck-output b/ci/summarise-linkcheck-output new file mode 100755 index 0000000000..864479337d --- /dev/null +++ b/ci/summarise-linkcheck-output @@ -0,0 +1,23 @@ +#!/bin/bash +# Parse the output.json created by the Sphinx linkchecker +# and summarise broken and redirected links + +set -eu +LINKCHECK="$1" + +N_BROKEN=$(jq -r 'select(.status=="broken")' "$LINKCHECK" | jq -s length) +N_PERMANENT_REDIRECT=$(jq -r 'select(.status=="redirected")' "$LINKCHECK" | jq -s length) + +# shellcheck disable=SC2086 +if [[ $N_BROKEN -gt 0 ]]; then + printf "\n\033[31;1m%s\033[0m\n" "Broken links" + jq -r 'select(.status=="broken") | "\(.filename):\(.lineno) \(.uri)\n \(.info)"' "$LINKCHECK" +fi + +# shellcheck disable=SC2086 +if [[ $N_PERMANENT_REDIRECT -gt 0 ]]; then + printf "\n\033[35;1m%s\033[0m\n" "Permanently redirected links" + jq -r 'select(.status=="redirected" and .code==301) | "\(.filename):\(.lineno) \(.uri)\n \(.info)"' "$LINKCHECK" +fi + +exit "$N_BROKEN" diff --git a/dev-config-arm.yaml b/dev-config-arm.yaml index 09140439b3..68629665a9 100644 --- a/dev-config-arm.yaml +++ b/dev-config-arm.yaml @@ -2,8 +2,3 @@ proxy: https: enabled: false - -singleuser: - image: - name: sakuraiyuta/base-notebook - tag: latest diff --git a/dev-config-local-chart-extra-config.yaml b/dev-config-local-chart-extra-config.yaml new file mode 100644 index 0000000000..ba5b301188 --- /dev/null +++ b/dev-config-local-chart-extra-config.yaml @@ -0,0 +1,10 @@ +# This config file is useful in the upgrade tests, where we upgrade from +# either the latest stable chart or the latest dev release of the chart. This +# config is only applied to the chart we upgrade to. It helps us handle +# situations when we add new configuration options that would fail with a schema +# validation error in the previous chart versions. +# +# Note that one could think that it would be possible to have dev-config.yaml +# include this config and then pass --set hub.some-option=null to null it out +# when it must not be passed, but that still triggers schema validation errors. +# diff --git a/dev-config-upstream.yaml b/dev-config-upstream.yaml deleted file mode 100644 index 237ca4d683..0000000000 --- a/dev-config-upstream.yaml +++ /dev/null @@ -1,181 +0,0 @@ -proxy: - service: - type: NodePort - nodePorts: - http: 30080 - https: 30443 - https: - enabled: true - type: letsencrypt - hosts: - - local.jovyan.org - letsencrypt: - contactEmail: "jovyan@jupyter.test" - acmeServer: https://pebble/dir - traefik: - extraVolumes: - - name: pebble-root-cert - configMap: - name: pebble - extraVolumeMounts: - - name: pebble-root-cert - subPath: root-cert.pem - mountPath: /etc/pebble/root-cert.pem - extraEnv: - LEGO_CA_CERTIFICATES: /etc/pebble/root-cert.pem - chp: - resources: - requests: - memory: 0 - cpu: 0 - networkPolicy: - egress: [] # overrides allowance of 0.0.0.0/0 - -hub: - db: - type: sqlite-memory - services: - # The test service and its apiToken is used to make requests in our pytest - # suite of tests. Note that it can be overridden by the hub.existingSecret, - # which can cause tests to fail with 403. - test: - admin: true - apiToken: give-pytest-control - test-hub-existing-secret: - apiToken: dddd4444 - test-explicit-name: - name: some-explicitly-set-name - apiToken: eeee5555 - test-generation-of-apiToken: {} - networkPolicy: - egress: # overrides allowance of 0.0.0.0/0 - # In kind/k3s clusters the Kubernetes API server is exposing this port - - ports: - - protocol: TCP - port: 6443 - resources: - requests: - memory: 0 - cpu: 0 - extraConfig: - # emit logs associated with our pytest tests - test_hub_existing_secret: | - try: - from z2jh import get_secret_value - - print() - print("TEST LOGS: test_hub_existing_secret") - print(f"hub.existingSecret={get_config('hub.existingSecret')}") - print() - print(f"hub.db.type={get_config('hub.db.type')}") - print(f"MYSQL_PWD={os.environ.get('MYSQL_PWD', None)}") - print(f"PGPASSWORD={os.environ.get('PGPASSWORD', None)}") - print() - print(f"hub.services.test-hub-existing-secret.apiToken={get_secret_value('hub.services.test-hub-existing-secret.apiToken', None)}") - print() - print(f"CONFIGPROXY_AUTH_TOKEN={os.environ.get('CONFIGPROXY_AUTH_TOKEN', None)}") - print(f"hub.config.ConfigurableHTTPProxy.auth_token={get_secret_value('hub.config.ConfigurableHTTPProxy.auth_token', None)}") - print(f"hub.config.JupyterHub.cookie_secret={get_secret_value('hub.config.JupyterHub.cookie_secret', None)}") - print(f"hub.config.CryptKeeper.keys={get_secret_value('hub.config.CryptKeeper.keys', None)}") - print() - print(f"singleuser.extraLabels.test-chart-managed-secret={get_config('singleuser.extraLabels.test-chart-managed-secret')}") - print(f"singleuser.extraLabels.test-self-managed-secret={get_config('singleuser.extraLabels.test-self-managed-secret')}") - print("---") - print() - except ImportError: - print("WARNING: z2jh.py didn't contain get_secret_value") - - extraFiles: - my_config: - mountPath: /usr/local/etc/jupyterhub/jupyterhub_config.d/my_config.py - stringData: | - with open("/tmp/created-by-extra-files-config.txt", "w") as f: - f.write("hello world!") - binaryData1: &binaryData1 - mountPath: /tmp/binaryData.txt - mode: 0666 - binaryData: | - aGVsbG8gd - 29ybGQhCg== - binaryData2: &binaryData2 - mountPath: /tmp/dir1/binaryData.txt - mode: 0666 - binaryData: aGVsbG8gd29ybGQhCg== - stringData1: &stringData1 - mountPath: /tmp/stringData.txt - mode: 0666 - stringData: hello world! - stringData2: &stringData2 - mountPath: /tmp/dir1/stringData.txt - mode: 0666 - stringData: hello world! - data-yaml: &data-yaml - mountPath: /etc/test/data.yaml - mode: 0444 - data: - config: - map: - number: 123 - string: "hi" - list: [1, 2] - data-yml: &data-yml - <<: *data-yaml - mountPath: /etc/test/data.yml - data-json: &data-json - <<: *data-yaml - mountPath: /etc/test/data.json - data-toml: &data-toml - <<: *data-yaml - mountPath: /etc/test/data.toml - -singleuser: - extraLabels: - test-chart-managed-secret: "ok" - extraFiles: - binaryData1: *binaryData1 - binaryData2: *binaryData2 - stringData1: *stringData1 - stringData2: *stringData2 - data-yaml: *data-yaml - data-yml: *data-yml - data-json: *data-json - data-toml: *data-toml - storage: - type: none - memory: - guarantee: null - networkPolicy: - # For testing purposes in test_singleuser_netpol - egress: - - to: - # jupyter.org has multiple IPs associated with it, among them are these - # two. We explicitly allow access to one, but leave out the the other. - - ipBlock: - cidr: 104.21.25.233/32 - # - ipBlock: - # cidr: 172.67.134.225/32 - extraEnv: - TEST_ENV_FIELDREF_TO_NAMESPACE: - valueFrom: - fieldRef: - fieldPath: metadata.namespace - -prePuller: - hook: - enabled: false - -scheduling: - userScheduler: - enabled: true - replicas: 2 - # Can be set too low too not show scoring of scheduled pods, but also too - # high to show hex dumps of all network traffic. - # - # FIXME: Tweak this to include scoring, but exclude hex dumps. 10 includes - # hex dumps. 4 does not include scoring. Trying with 6... - logLevel: 6 - podPriority: - enabled: true - -debug: - enabled: true diff --git a/dev-config.yaml b/dev-config.yaml index 9285c9c6cc..1cf5f04e4f 100644 --- a/dev-config.yaml +++ b/dev-config.yaml @@ -34,6 +34,18 @@ proxy: hub: db: type: sqlite-memory + loadRoles: + test-scoped-access: + description: Used to JupyterHub 2.0.0+ RBAC scoped access, currently to the /hub/api/info endpoint via read:hub. + scopes: [read:hub] + services: [test-with-scoped-access] + test-role-with-explicit-name: + name: test-role-2 + description: Access to users' information and group membership + scopes: [users, groups] + users: [cyclops, gandalf] + services: [test] + groups: [] services: # The test service and its apiToken is used to make requests in our pytest # suite of tests. Note that it can be overridden by the hub.existingSecret, @@ -41,6 +53,8 @@ hub: test: admin: true apiToken: give-pytest-control + test-with-scoped-access: + apiToken: give-pytest-scoped-control test-hub-existing-secret: apiToken: dddd4444 test-explicit-name: @@ -49,10 +63,13 @@ hub: test-generation-of-apiToken: {} networkPolicy: egress: # overrides allowance of 0.0.0.0/0 - # In kind/k3s clusters the Kubernetes API server is exposing this port - ports: + # In kind/k3s clusters the Kubernetes API server is exposing this port - protocol: TCP port: 6443 + # For testing postgres + - protocol: TCP + port: 5432 resources: requests: memory: 0 @@ -128,7 +145,6 @@ hub: <<: *data-yaml mountPath: /etc/test/data.toml - schedulableNotebook: enabled: false secretToken: daad2e18301c37a14d0f6818b17283bbccc6c9637b652983dc5cfd538aba3326 # dummy @@ -154,7 +170,10 @@ singleuser: memory: guarantee: null networkPolicy: - # For testing purposes in test_singleuser_netpol + # For testing purposes in the test_spawn_netpol test, we override egress and + # egressAllowRules.nonPrivateIPs to slim the egress rules to a minimum. + egressAllowRules: + nonPrivateIPs: false egress: - to: # jupyter.org has multiple IPs associated with it, among them are these @@ -163,6 +182,12 @@ singleuser: cidr: 104.21.25.233/32 # - ipBlock: # cidr: 172.67.134.225/32 + networkTools: + resources: + requests: + memory: 0 + cpu: 0 + extraEnv: TEST_ENV_FIELDREF_TO_NAMESPACE: valueFrom: diff --git a/dev-requirements.txt b/dev-requirements.txt index a999cc71cd..adf4067751 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -5,7 +5,7 @@ # # ref: https://github.com/jupyterhub/chartpress # -chartpress>=1.1.0 +chartpress>=2.1,<3 # pytest run tests that require requests and pyyaml pytest>=3.7.1 @@ -17,3 +17,6 @@ click # used to formatting and linting pre-commit>=2.0.0 + +# used for tagging releases +tbump diff --git a/doc/requirements.txt b/doc/requirements.txt deleted file mode 100644 index 713cf3685c..0000000000 --- a/doc/requirements.txt +++ /dev/null @@ -1,17 +0,0 @@ -# Order matters: -# - myst-parser depends on "sphinx>=2,<4" -# - pydata-sphinx-theme depends on "sphinx" -# - sphinx-copybutton depends on "sphinx>=1.8" -# -# Listing either pydata-sphinx-theme or sphinx-copybutton first will make the -# myst-parser constraints on sphinx be ignored, so myst-parser should go -# first. This is only relevant if sphinx==1.* is already installed in the -# environment, which it is on ReadTheDocs. -# -chartpress -myst-parser -pydata-sphinx-theme -pyyaml -sphinx-autobuild -sphinx-copybutton -sphinxext-rediraffe diff --git a/doc/source/_static/images/azure/scale_condition.png b/doc/source/_static/images/azure/scale_condition.png deleted file mode 100644 index e5225baa79..0000000000 Binary files a/doc/source/_static/images/azure/scale_condition.png and /dev/null differ diff --git a/doc/source/_static/images/azure/scale_in.png b/doc/source/_static/images/azure/scale_in.png deleted file mode 100644 index a1aa0388fe..0000000000 Binary files a/doc/source/_static/images/azure/scale_in.png and /dev/null differ diff --git a/doc/source/_static/images/azure/scale_out.png b/doc/source/_static/images/azure/scale_out.png deleted file mode 100644 index 0d789b1ce0..0000000000 Binary files a/doc/source/_static/images/azure/scale_out.png and /dev/null differ diff --git a/doc/source/kubernetes/microsoft/step-zero-azure-autoscale.md b/doc/source/kubernetes/microsoft/step-zero-azure-autoscale.md deleted file mode 100644 index f578679a31..0000000000 --- a/doc/source/kubernetes/microsoft/step-zero-azure-autoscale.md +++ /dev/null @@ -1,375 +0,0 @@ -(microsoft-azure-autoscale)= - -# Kubernetes on Microsoft Azure Kubernetes Service (AKS) with Autoscaling - -```{warning} -These instructions involve parts of the Azure command line that are in preview, hence the following documentation is subject to change. -``` - -You can create a Kubernetes cluster [either through the Azure portal website, or using the Azure command line tools](https://docs.microsoft.com/en-us/azure/aks/). - -This page describes the commands required to setup a Kubernetes cluster using the command line. -If you prefer to use the Azure portal see the [Azure Kubernetes Service quickstart](https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough-portal). - -1. Prepare your Azure shell environment. You have two options, one is to use - the Azure interactive shell, the other is to install the Azure command-line - tools locally. Instructions for each are below. - - - **Using the Azure interactive shell**. The [Azure Portal](https://portal.azure.com) - contains an interactive shell that you can use to communicate with your - Kubernetes cluster. To access this shell, go to [portal.azure.com](https://portal.azure.com) - and click on the button below. - - ```{image} ../../_static/images/azure/cli_start.png - :align: center - ``` - - ```{note} - * If you get errors like `could not retrieve token from local cache`, - try refreshing your browser window. - * The first time you do this, you'll be asked to create a storage - account where your shell filesystem will live. - ``` - - - **Install command-line tools locally**. You can access the Azure CLI via - a package that you can install locally. - - To do so, first follow the [installation instructions](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest) in the - Azure documentation. Then run the following command to connect your local - CLI with your account: - - ``` - az login - ``` - - You'll need to open a browser and follow the instructions in your terminal - to log in. - -2. Activate the correct subscription. Azure uses the concept - of **subscriptions** to manage spending. You can - get a list of subscriptions your account has access to by running: - - ``` - az account list --refresh --output table - ``` - - Pick the subscription you want to use for creating the cluster, and set that - as your default. - If you only have one subscription you can ignore this step. - - ``` - az account set --subscription - ``` - -3. Setup the CLI for Autoscaling features. - First install the [aks-preview](https://github.com/Azure/azure-cli-extensions/tree/HEAD/src/aks-preview) CLI extension. - This will grant access to new commands. - - ``` - az extension add --name aks-preview - ``` - - We then need to register the scale set feature. - - ``` - az feature register --name VMSSPreview --namespace Microsoft.ContainerService - ``` - - A VMSS is a [Virtual Machine Scale Set](https://docs.microsoft.com/en-us/azure/virtual-machine-scale-sets/overview), that is to say an autoscalable set of virtual machines. - - The previous command will take a while to register. - Use the following command to check it's status. - - ``` - az feature list \ - --output table \ - --query "[?contains(name, 'Microsoft.ContainerService/VMSSPreview')].{Name:name,State:properties.state}" - ``` - - Once the VMSSPreview feature has been registered, refresh the registration with the following command. - - ``` - az provider register --namespace Microsoft.ContainerService - ``` - -4. Create a resource group. Azure uses the concept of - **resource groups** to group related resources together. - We need to create a resource group in a given data center location. We will create - computational resources _within_ this resource group. - - ``` - az group create \ - --name= \ - --location= \ - --output table - ``` - - where: - - - `--name` specifies the name of your resource group. We recommend using something - that uniquely identifies this hub. For example, if you are creating a resource group - for UC Berkeley's 2018 Spring Data100 Course, you may give it a - `` of `ucb_2018sp_data100_hub`. - - `--location` specifies the location of the data center you want your resource to be in. - For options, see the - [Azure list of locations that support AKS](https://docs.microsoft.com/en-us/azure/aks/quotas-skus-regions#region-availability). - - `--output table` specifies that the output should be in human readable - format, rather than the default JSON output. We shall use this with most - commands when executing them by hand. - - Consider [setting a cloud budget](https://docs.microsoft.com/en-us/partner-center/set-an-azure-spending-budget-for-your-customers) - for your Azure account in order to make sure you don't accidentally - spend more than you wish to. - -5. Choose a cluster name. - - In the following steps we'll run commands that ask you to input a cluster - name. We recommend using something descriptive and short. We'll refer to - this as `` for the remainder of this section. - - The next step will create a few files on your filesystem, so first create - a folder in which these files will go. We recommend giving it the same - name as your cluster: - - ``` - mkdir - cd - ``` - -6. Create an ssh key to secure your cluster. - - ``` - ssh-keygen -f ssh-key- - ``` - - It will prompt you to add a password, which you can leave empty if you wish. - This will create a public key named `ssh-key-.pub` and a private key named - `ssh-key-`. Make sure both go into the folder we created earlier, - and keep both of them safe! - - This command will also print out something to your terminal screen. You - don't need to do anything with this text. - -7. Create a virtual network and sub-network. - - Kubernetes does not by default come with a controller that enforces `networkpolicy` resources. - `networkpolicy` resources are important as they define how Kubernetes pods can securely communicate with one another and the outside sources, for example, the internet. - - To enable this in Azure, we must first create a [Virtual Network](https://docs.microsoft.com/en-gb/azure/virtual-network/virtual-networks-overview) with Azure's own network policies enabled. - - This section of the documentation is following the Microsoft Azure tutorial on [creating an AKS cluster and enabling network policy](https://docs.microsoft.com/en-us/azure/aks/use-network-policies#create-an-aks-cluster-and-enable-network-policy), which includes information on using [Calico](https://docs.projectcalico.org) network policies. - - ``` - az network vnet create \ - --resource-group \ - --name \ - --address-prefixes 10.0.0.0/8 \ - --subnet-name \ - --subnet-prefix 10.240.0.0/16 - ``` - - where: - - - `--resource-group` is the ResourceGroup you created - - `--name` is the name you want to assign to your virtual network, for example, `hub-vnet` - - `--address-prefixes` are the IP address prefixes for your virtual network - - `--subnet-name` is your desired name for your subnet, for example, `hub-subnet` - - `--subnet-prefixes` are the IP address prefixes in [CIDR format](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) for the subnet - - We will now retrieve the application IDs of the VNet and subnet we just created and save them to bash variables. - - ``` - VNET_ID=$(az network vnet show \ - --resource-group \ - --name \ - --query id \ - --output tsv) - SUBNET_ID=$(az network vnet subnet show \ - --resource-group \ - --vnet-name \ - --name \ - --query id \ - --output tsv) - ``` - - We will create an Azure Active Directory (Azure AD) [service principal](https://docs.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals) for use with the cluster, and assign the [Contributor role](https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#contributor) for use with the VNet. - Make sure `SERVICE-PRINCIPAL-NAME` is something recognisable, for example, `binderhub-sp`. - - ``` - SP_PASSWD=$(az ad sp create-for-rbac \ - --name \ - --role Contributor \ - --scope $VNET_ID \ - --query password \ - --output tsv) - SP_ID=$(az ad sp show \ - --id http:// \ - --query appId \ - --output tsv) - ``` - - You will need Owner role on your subscription for this step to succeed. - -8. Create an AKS cluster. - - The following command will request a Kubernetes cluster within the resource - group that we created earlier. - - ``` - az aks create --name \ - --resource-group \ - --ssh-key-value ssh-key-.pub \ - --node-count 3 \ - --node-vm-size Standard_D2s_v3 \ - --enable-vmss \ - --enable-cluster-autoscaler \ - --min-count 3 \ - --max-count 6 \ - --kubernetes-version 1.12.7 \ - --service-principal $SP_ID \ - --client-secret $SP_PASSWD \ - --dns-service-ip 10.0.0.10 \ - --docker-bridge-address 172.17.0.1/16 \ - --network-plugin azure \ - --network-policy azure \ - --service-cidr 10.0.0.0/16 \ - --vnet-subnet-id $SUBNET_ID \ - --output table - ``` - - where: - - - `--name` is the name you want to use to refer to your cluster - - `--resource-group` is the ResourceGroup you created - - `--ssh-key-value` is the ssh public key created - - `--node-count` is the number of nodes you want in your Kubernetes cluster - - `--node-vm-size` is the size of the nodes you want to use, which varies based on - what you are using your cluster for and how much RAM/CPU each of your users need. - There is a [list of all possible node sizes](https://docs.microsoft.com/en-us/azure/cloud-services/cloud-services-sizes-specs) - for you to choose from, but not all might be available in your location. - If you get an error whilst creating the cluster you can try changing either the region or the node size. - - `--enable-vmss` deploys the cluster as a scale set. - - `--enable-cluster-autoscaler` installs a [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/HEAD/cluster-autoscaler) onto the cluster (though counterintuitively, does not enable it!). - - `--min-count`/`--max-count` are the minimum/maximum number of nodes in the cluster at any time. - - `--kubernetes-version` installs a specific version of Kubernetes onto the cluster. To autoscale, we require `>= v 1.12.4`, though it's recommended to use the most recent version available (you can find out what the most recent version of kubernetes available is by running `az aks get-versions --location `). - - `--service-principal` is the application ID of the service principal we created - - `--client-secret` is the password for the service principal we created - - `--dns-service-ip` is an IP address assigned to the [Kubernetes DNS service](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/) - - `--docker-bridge-address` is a specific IP address and netmask for the Docker bridge, using standard CIDR notation - - `--network-plugin` is the Kubernetes network plugin to use. In this example, we have used Azure's own implementation. - - `--network-policy` is the Kubernetes network policy to use. In this example, we have used Azure's own implementation. - - `--service-cidr` is a CIDR notation IP range from which to assign service cluster IPs - - `vnet-subnet-id` is the application ID of the subnet we created - - This should take a few minutes and provide you with a working Kubernetes cluster! - -9. If you're using the Azure CLI locally, install [kubectl](https://kubernetes.io/docs/reference/kubectl/overview/), a tool - for accessing the Kubernetes API from the commandline: - - ``` - az aks install-cli - ``` - - Note: kubectl is already installed in Azure Cloud Shell. - -10. Get credentials from Azure for `kubectl` to work: - - ``` - az aks get-credentials \ - --name \ - --resource-group \ - --output table - ``` - - where: - - - `--name` is the name you gave your cluster - - `--resource-group` is the ResourceGroup you created - - This automatically updates your Kubernetes client configuration file. - -11. Check if your cluster is fully functional - - ``` - kubectl get node - ``` - - The response should list three running nodes and their Kubernetes versions! - Each node should have the status of `Ready`, note that this may take a - few moments. - -12. Enabling Autoscaling - - We now move to the Azure Portal to enable autoscaling and set rules to manage the Cluster Autoscaler. - - First we need to register [Microsoft Insights](https://docs.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview) for use on the active subscription. - - ``` - az provider register --namespace microsoft.insights - ``` - - To check the status of the registration, run the following command: - - ``` - az provider show -n microsoft.insights - ``` - - Once the application has been registered, navigate to your active subscription on the [Portal](https://portal.azure.com/). - - Under "Resources", select the VMSS. - It should be named something like `aks-nodepool1--vmss`. - - ```{image} ../../_static/images/azure/select_vmss.png - :align: center - ``` - - From the left-hand menu, select "Scaling". - Click the blue "Enable autoscaling" button and an autogenerated form for a scale condition will appear. - We will add two new rules to this condition: - - - Increase the instance count by 1 when the average CPU usage over 10 minutes is greater than 70% - - Decrease the instance count by 1 when the average CPU usage over 10 minutes is less than 5% - - ```{image} ../../_static/images/azure/scale_condition.png - :align: center - ``` - - Make sure the "Scale based on metric" option is selected and click "+ Add new rule", another autogenerated form will appear. - This will be pre-filled with the required settings to fulfill our first rule, so save it by clicking "Update" and click "+ Add new rule" again. - - ```{image} ../../_static/images/azure/scale_out.png - :align: center - ``` - - The second form needs to be edited for the second rule to decrease the instance count by 1 when the average CPU usage over 10 minutes is less than 5%. - Save this rule and then save the overall scale condition, the cluster will be updated automatically. - - ```{image} ../../_static/images/azure/scale_in.png - :align: center - ``` - - This form can also be used to change `--node-count`/`--min-count`/`--max-count` that was set previously by using the "Instance limits" section of the scale condition ("Default", "Minimum" and "Maximum" respectively). - - If you prefer to use the command line, you can run the following: - - ``` - az aks update \ - --name \ - --resource-group \ - --update-cluster-autoscaler \ - --min-count \ - --max-count \ - --output table - ``` - - **Both** `--min-count` and `--max-count` must be defined. - -```{note} -If you create the cluster using the Azure Portal you must enable RBAC. -RBAC is enabled by default when using the command line tools. -``` - -Congrats. Now that you have your Kubernetes cluster running, it's time to -begin {ref}`setup-helm`. - -[azure resource group]: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-overview#resource-groups diff --git a/doc/source/kubernetes/other-infrastructure/.gitkeep b/doc/source/kubernetes/other-infrastructure/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/doc/source/resources/glossary.md b/doc/source/resources/glossary.md deleted file mode 100644 index bf05315bd6..0000000000 --- a/doc/source/resources/glossary.md +++ /dev/null @@ -1,130 +0,0 @@ -(glossary)= - -# Glossary - -A partial glossary of terms used in this guide. For more complete descriptions -of the components in JupyterHub, see {ref}`tools`. Here we try to keep the -definition as succinct and relevant as possible, and provide links to learn more -details. - - - -```{eval-rst} -.. glossary:: - - `admin user `_ - A user who can access the JupyterHub admin panel. They can start/stop user - pods, and potentially access their notebooks. - - `authenticator `_ - The way in which users are authenticated to log into JupyterHub. There - are many authenticators available, like GitHub, Google, MediaWiki, - Dummy (anyone can log in), etc. - - `config.yaml` - The :term:`Helm charts ` templates are rendered with these - :term:`Helm values` as input. The file is written in the `YAML - `_ format. The YAML format is essential - to grasp if working with Kubernetes and Helm. - - container - A container is a isolated working space which for us gives users the - tools, libraries, and capabilities to be productive. - - culler - A separate process in the JupyterHub that stops the user pods of users who - have not been active in a configured interval. - - Dockerfile - A Dockerfile declares how to build a :term:`Docker image`. - - Docker image - A Docker image, built from a :term:`Dockerfile`, allows tools like - ``docker`` to create any number of :term:`containers `. - - image registry - A service for storing Docker images so that they can be stored - and used later. - The default public registry is at https://hub.docker.com, - but you can also run your own private image registry. - Many cloud providers offer private image registry services. - - `environment variables `_ - A set of named values that can affect the way running processes will - behave on a computer. Some common examples are ``PATH``, ``HOME``, and - ``EDITOR``. - - `Helm chart `_ - A Helm chart is a group of :term:`Helm templates ` that - can, given its default values and overrides in provided ``yaml`` files, - render to a set of :term:`Kubernetes resources ` that - can be easily installed to your Kubernetes cluster. In other words a Helm - chart is like a configurable installation of software and infrastructure - to exist on a cloud. - - `Helm template `_ - A Helm template (``.yaml`` files), can given values, render to a - :term:`Kubernetes resource`. - - `Helm values `_ - :term:`Helm charts ` has a set of predefined values - (`values.yaml`) typically overridden by other values in `config.yaml`. The - final values are used to generate :term:`Kubernetes resources ` from :term:`Helm templates ` within a - :term:`Helm chart`. - - Kubernetes - For our purposes, you can think of Kubernetes as a way to speak to a cloud - and describe what you would like it to do, in a manner that isn't specific - for that cloud. - - - `The Illustrated Children's Guide to Kubernetes `_ - - `The official "What is Kubernetes?" text `_ - - Kubernetes API server - The `Kubernetes API - `_ server, - also referred to as the master, will answer questions and update the - desired state of the cluster for you. When you use ``kubectl`` you - communicate with the API server. - - Kubernetes Pod - *Pods* are the smallest deployable units of computing that can be created - and managed in Kubernetes. A pod will use a :term:`Docker image` to create - a container, and most often a controller such as a Deployment will ensure - there is always X running pods of a kind. - - See the `Kubernetes documentation - `__ for more - information. - - Kubernetes resource - A Kubernetes resource can for example be a `Deployment - `_, - `Service - `_ or a - `Secret `_. It - is something you can request by the :term:`Kubernetes API server` to be - present in the cluster. - - persistent storage - A filesystem attached to a user pod that allows the user to store - notebooks and files that persist across multiple logins. - - Node Pool - A *node pool* or *node group* represents a set of nodes of the same kind. - With cluster autoscaling, a node pool can grow and shrink based on demand - allowing you to save computational resources. - - `repo2docker `_ - A tool which lets you quickly convert a Git repository into a - :term:`Docker image`. - - `spawner `_ - A spawner is a separate process created for each active user by - JupyterHub. They are each responsible for one user. This Helm chart relies - on `KubeSpawner - `_. -``` diff --git a/doc/Makefile b/docs/Makefile similarity index 91% rename from doc/Makefile rename to docs/Makefile index ac24d8b004..44b5069fe6 100644 --- a/doc/Makefile +++ b/docs/Makefile @@ -6,7 +6,7 @@ SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build SOURCEDIR = source -BUILDDIR = build +BUILDDIR = _build # Put it first so that "make" without argument is like "make help". help: @@ -27,7 +27,7 @@ help: # - builds and rebuilds html on changes to source # - starts a livereload enabled webserver and opens up a browser devenv: - sphinx-autobuild -b html --open-browser --ignore "*/reference.md" --watch "../jupyterhub/schema.yaml" "$(SOURCEDIR)" "$(BUILDDIR)/html" $(SPHINXOPTS) + sphinx-autobuild -b html --open-browser --ignore "*/reference.md" --watch "../jupyterhub/values.schema.yaml" "$(SOURCEDIR)" "$(BUILDDIR)/html" $(SPHINXOPTS) # For local development and CI: # - verifies that links are valid diff --git a/doc/README.md b/docs/README.md similarity index 98% rename from doc/README.md rename to docs/README.md index 3b2647f4ba..dc0d51c4eb 100644 --- a/doc/README.md +++ b/docs/README.md @@ -8,7 +8,7 @@ in the `readthedocs.yml` file, and made available on ## Local documentation development ```shell -cd doc +cd docs pip install -r requirements.txt ``` diff --git a/doc/make.bat b/docs/make.bat similarity index 90% rename from doc/make.bat rename to docs/make.bat index 4f70416558..0c9af74ba4 100644 --- a/doc/make.bat +++ b/docs/make.bat @@ -8,7 +8,7 @@ if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set SOURCEDIR=source -set BUILDDIR=build +set BUILDDIR=_build if "%1" == "" goto help if "%1" == "devenv" goto devenv @@ -39,7 +39,7 @@ if errorlevel 9009 ( echo.The 'sphinx-autobuild' command was not found. Open and read README.md! exit /b 1 ) -sphinx-autobuild -b html --open-browser --ignore "*/reference.md" --watch "../jupyterhub/schema.yaml" "%SOURCEDIR%" "%BUILDDIR%/html" %SPHINXOPTS% +sphinx-autobuild -b html --open-browser --ignore "*/reference.md" --watch "../jupyterhub/values.schema.yaml" "%SOURCEDIR%" "%BUILDDIR%/html" %SPHINXOPTS% goto end diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000000..baede9d704 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,13 @@ +# FIXME: sphinx is pinned below 7.2 until pydata-sphinx-theme has a release +# newer than 0.13.3. Check for a new release at +# https://github.com/pydata/pydata-sphinx-theme/tags and remove the +# sphinx entry in this requirements file when its released. +sphinx<7.2 +chartpress +myst-parser +pydata-sphinx-theme +pyyaml +sphinx-autobuild +sphinx-copybutton +sphinxext-opengraph +sphinxext-rediraffe diff --git a/doc/source/_static/custom.css b/docs/source/_static/custom.css similarity index 100% rename from doc/source/_static/custom.css rename to docs/source/_static/custom.css diff --git a/doc/source/_static/images/architecture.png b/docs/source/_static/images/architecture.png similarity index 100% rename from doc/source/_static/images/architecture.png rename to docs/source/_static/images/architecture.png diff --git a/doc/source/_static/images/azure/cli_start.png b/docs/source/_static/images/azure/cli_start.png similarity index 100% rename from doc/source/_static/images/azure/cli_start.png rename to docs/source/_static/images/azure/cli_start.png diff --git a/docs/source/_static/images/azure/scale_condition.png b/docs/source/_static/images/azure/scale_condition.png new file mode 100644 index 0000000000..d0cb3a3809 Binary files /dev/null and b/docs/source/_static/images/azure/scale_condition.png differ diff --git a/docs/source/_static/images/azure/scale_in.png b/docs/source/_static/images/azure/scale_in.png new file mode 100644 index 0000000000..89198cd7f6 Binary files /dev/null and b/docs/source/_static/images/azure/scale_in.png differ diff --git a/docs/source/_static/images/azure/scale_out.png b/docs/source/_static/images/azure/scale_out.png new file mode 100644 index 0000000000..a80d756389 Binary files /dev/null and b/docs/source/_static/images/azure/scale_out.png differ diff --git a/doc/source/_static/images/azure/select_vmss.png b/docs/source/_static/images/azure/select_vmss.png similarity index 100% rename from doc/source/_static/images/azure/select_vmss.png rename to docs/source/_static/images/azure/select_vmss.png diff --git a/doc/source/_static/images/data8_audience.jpg b/docs/source/_static/images/data8_audience.jpg similarity index 100% rename from doc/source/_static/images/data8_audience.jpg rename to docs/source/_static/images/data8_audience.jpg diff --git a/doc/source/_static/images/data8_massive_audience.jpg b/docs/source/_static/images/data8_massive_audience.jpg similarity index 100% rename from doc/source/_static/images/data8_massive_audience.jpg rename to docs/source/_static/images/data8_massive_audience.jpg diff --git a/doc/source/_static/images/google/start_interactive_cli.png b/docs/source/_static/images/google/start_interactive_cli.png similarity index 100% rename from doc/source/_static/images/google/start_interactive_cli.png rename to docs/source/_static/images/google/start_interactive_cli.png diff --git a/doc/source/_static/images/ibm/create-free-kubernetes-cluster-ibm-cloud.png b/docs/source/_static/images/ibm/create-free-kubernetes-cluster-ibm-cloud.png similarity index 100% rename from doc/source/_static/images/ibm/create-free-kubernetes-cluster-ibm-cloud.png rename to docs/source/_static/images/ibm/create-free-kubernetes-cluster-ibm-cloud.png diff --git a/doc/source/_static/images/ibm/create-paid-kubernetes-cluster-ibm-cloud.png b/docs/source/_static/images/ibm/create-paid-kubernetes-cluster-ibm-cloud.png similarity index 100% rename from doc/source/_static/images/ibm/create-paid-kubernetes-cluster-ibm-cloud.png rename to docs/source/_static/images/ibm/create-paid-kubernetes-cluster-ibm-cloud.png diff --git a/doc/source/_static/images/ibm/kubectl-cluster-info.png b/docs/source/_static/images/ibm/kubectl-cluster-info.png similarity index 100% rename from doc/source/_static/images/ibm/kubectl-cluster-info.png rename to docs/source/_static/images/ibm/kubectl-cluster-info.png diff --git a/doc/source/_static/images/logo/favicon.ico b/docs/source/_static/images/logo/favicon.ico similarity index 100% rename from doc/source/_static/images/logo/favicon.ico rename to docs/source/_static/images/logo/favicon.ico diff --git a/doc/source/_static/images/logo/logo.png b/docs/source/_static/images/logo/logo.png similarity index 100% rename from doc/source/_static/images/logo/logo.png rename to docs/source/_static/images/logo/logo.png diff --git a/doc/source/_static/images/no-longer-referenced/authenticate.png b/docs/source/_static/images/no-longer-referenced/authenticate.png similarity index 100% rename from doc/source/_static/images/no-longer-referenced/authenticate.png rename to docs/source/_static/images/no-longer-referenced/authenticate.png diff --git a/doc/source/_static/images/no-longer-referenced/authenticate_success.png b/docs/source/_static/images/no-longer-referenced/authenticate_success.png similarity index 100% rename from doc/source/_static/images/no-longer-referenced/authenticate_success.png rename to docs/source/_static/images/no-longer-referenced/authenticate_success.png diff --git a/doc/source/_static/images/no-longer-referenced/cloud_sdk_doc_landing.png b/docs/source/_static/images/no-longer-referenced/cloud_sdk_doc_landing.png similarity index 100% rename from doc/source/_static/images/no-longer-referenced/cloud_sdk_doc_landing.png rename to docs/source/_static/images/no-longer-referenced/cloud_sdk_doc_landing.png diff --git a/doc/source/_static/images/no-longer-referenced/cloud_sdk_landing.png b/docs/source/_static/images/no-longer-referenced/cloud_sdk_landing.png similarity index 100% rename from doc/source/_static/images/no-longer-referenced/cloud_sdk_landing.png rename to docs/source/_static/images/no-longer-referenced/cloud_sdk_landing.png diff --git a/doc/source/_static/images/no-longer-referenced/container_engine_location.jpg b/docs/source/_static/images/no-longer-referenced/container_engine_location.jpg similarity index 100% rename from doc/source/_static/images/no-longer-referenced/container_engine_location.jpg rename to docs/source/_static/images/no-longer-referenced/container_engine_location.jpg diff --git a/doc/source/_static/images/no-longer-referenced/gcloud_cluster_created.png b/docs/source/_static/images/no-longer-referenced/gcloud_cluster_created.png similarity index 100% rename from doc/source/_static/images/no-longer-referenced/gcloud_cluster_created.png rename to docs/source/_static/images/no-longer-referenced/gcloud_cluster_created.png diff --git a/doc/source/_static/images/no-longer-referenced/gcloud_container_clusters_create.png b/docs/source/_static/images/no-longer-referenced/gcloud_container_clusters_create.png similarity index 100% rename from doc/source/_static/images/no-longer-referenced/gcloud_container_clusters_create.png rename to docs/source/_static/images/no-longer-referenced/gcloud_container_clusters_create.png diff --git a/doc/source/_static/images/no-longer-referenced/gcloud_init.png b/docs/source/_static/images/no-longer-referenced/gcloud_init.png similarity index 100% rename from doc/source/_static/images/no-longer-referenced/gcloud_init.png rename to docs/source/_static/images/no-longer-referenced/gcloud_init.png diff --git a/doc/source/_static/images/no-longer-referenced/install_sdk1.png b/docs/source/_static/images/no-longer-referenced/install_sdk1.png similarity index 100% rename from doc/source/_static/images/no-longer-referenced/install_sdk1.png rename to docs/source/_static/images/no-longer-referenced/install_sdk1.png diff --git a/doc/source/_static/images/no-longer-referenced/ovh-project-name.png b/docs/source/_static/images/no-longer-referenced/ovh-project-name.png similarity index 100% rename from doc/source/_static/images/no-longer-referenced/ovh-project-name.png rename to docs/source/_static/images/no-longer-referenced/ovh-project-name.png diff --git a/doc/source/_static/images/no-longer-referenced/service_account_compute_engine.png b/docs/source/_static/images/no-longer-referenced/service_account_compute_engine.png similarity index 100% rename from doc/source/_static/images/no-longer-referenced/service_account_compute_engine.png rename to docs/source/_static/images/no-longer-referenced/service_account_compute_engine.png diff --git a/doc/source/_static/images/ovh/add-nodes.png b/docs/source/_static/images/ovh/add-nodes.png similarity index 100% rename from doc/source/_static/images/ovh/add-nodes.png rename to docs/source/_static/images/ovh/add-nodes.png diff --git a/doc/source/_static/images/ovh/create-cluster-button.png b/docs/source/_static/images/ovh/create-cluster-button.png similarity index 100% rename from doc/source/_static/images/ovh/create-cluster-button.png rename to docs/source/_static/images/ovh/create-cluster-button.png diff --git a/doc/source/_static/images/ovh/create-cluster-options.png b/docs/source/_static/images/ovh/create-cluster-options.png similarity index 100% rename from doc/source/_static/images/ovh/create-cluster-options.png rename to docs/source/_static/images/ovh/create-cluster-options.png diff --git a/doc/source/_static/images/ovh/create-ovh-stack.png b/docs/source/_static/images/ovh/create-ovh-stack.png similarity index 100% rename from doc/source/_static/images/ovh/create-ovh-stack.png rename to docs/source/_static/images/ovh/create-ovh-stack.png diff --git a/doc/source/_static/images/ovh/kubeconfig.png b/docs/source/_static/images/ovh/kubeconfig.png similarity index 100% rename from doc/source/_static/images/ovh/kubeconfig.png rename to docs/source/_static/images/ovh/kubeconfig.png diff --git a/doc/source/_static/images/ovh/payment.png b/docs/source/_static/images/ovh/payment.png similarity index 100% rename from doc/source/_static/images/ovh/payment.png rename to docs/source/_static/images/ovh/payment.png diff --git a/doc/source/_static/images/ovh/public-cloud.png b/docs/source/_static/images/ovh/public-cloud.png similarity index 100% rename from doc/source/_static/images/ovh/public-cloud.png rename to docs/source/_static/images/ovh/public-cloud.png diff --git a/doc/source/_static/images/user_scheduler.png b/docs/source/_static/images/user_scheduler.png similarity index 100% rename from doc/source/_static/images/user_scheduler.png rename to docs/source/_static/images/user_scheduler.png diff --git a/doc/source/administrator/advanced.md b/docs/source/administrator/advanced.md similarity index 97% rename from doc/source/administrator/advanced.md rename to docs/source/administrator/advanced.md index 9c349558d9..9c2c47c460 100644 --- a/doc/source/administrator/advanced.md +++ b/docs/source/administrator/advanced.md @@ -44,6 +44,11 @@ ingress: ### Ingress and Automatic HTTPS with kube-lego & Let's Encrypt +```{warning} +`kube-lego` has been deprecated in favor of `cert-manager`. +See [cert-manager](https://github.com/cert-manager/cert-manager). +``` + When using an ingress object, the default automatic HTTPS support does not work. To have automatic fetch and renewal of HTTPS certificates, you must set it up yourself. @@ -183,7 +188,7 @@ in kubernetes that as a long list of cool use cases. Some example use cases are: 2. Servers / other daemons that are used by code in your `hub.customConfig` The items in this list must be valid kubernetes -[container specifications](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#container-v1-core). +[container specifications](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#container-v1-core). ### Specifying suitable hub storage diff --git a/doc/source/administrator/architecture.md b/docs/source/administrator/architecture.md similarity index 100% rename from doc/source/administrator/architecture.md rename to docs/source/administrator/architecture.md diff --git a/doc/source/administrator/authentication.md b/docs/source/administrator/authentication.md similarity index 59% rename from doc/source/administrator/authentication.md rename to docs/source/administrator/authentication.md index 65e33e59e1..8a410c4c21 100644 --- a/doc/source/administrator/authentication.md +++ b/docs/source/administrator/authentication.md @@ -3,44 +3,47 @@ # Authentication and authorization Authentication is about identity, while _authorization_ is about permissions. In -this section you will learn how to configure both. As an example, you can -configure authentication using GitHub accounts and restrict what users are -authorized based on membership of a GitHub organization. +this section you will learn how to configure both by choosing and configuring a +_JupyterHub Authenticator class_. -Before configuring this, you should have [setup HTTPS](https). +As an example, you can configure JupyterHub to delegate authentication and +authorization to the GitHubOAuthenticator. It enable users to login with GitHub +accounts, where perhaps only a few specific users and other users users part of +a specific GitHub organization is allowed access. + +Before configuring authentication with an external identity provider, you must +have [setup HTTPS](https). ## Useful understanding ### Authenticator classes -JupyterHub by default ships with only one source of authentication: -PAM, the underlying unix authentication of the host system. -To use other sources of authentication, choose _one_ [_authenticator -class_](https://jupyterhub.readthedocs.io/en/stable/reference/authenticators.html) to use. -Several such classes are already available in the hub image through [installed -Python -packages](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/images/hub/requirements.txt). +By default a Z2JH deployment use the +{external:py:class}`jupyterhub.auth.DummyAuthenticator` JupyterHub authenticator +class that allows anyone to login with any username and password. This should +only be used for initial testing purposes. + +You should decide on a [jupyterhub authenticator class] to use. Several such +classes are available in the hub image through [installed Python packages], and +a few of them are described below. -JupyterHub provides a base class, -[`Authenticator`](https://github.com/jupyterhub/jupyterhub/blob/HEAD/jupyterhub/auth.py), -that all other authenticator classes are supposed to derive from. By configuring -this base class, we influence the behavior of the derived class as well. +[authenticator class]: https://jupyterhub.readthedocs.io/en/stable/reference/authenticators.html +[installed python packages]: https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/images/hub/requirements.txt ### The configuration system -We configure JupyterHub to use our chosen authenticator class and the -authenticator class itself through this Helm chart's +First we should configure JupyterHub to use our chosen authenticator class and +the authenticator class itself through this Helm chart's [`hub.config`](schema_hub.config) configuration. ## General configuration -As all authenticator classes derive from the `Authenticator` base class, they -share some configuration options. Below are some common configuration options, -but please refer to the official [configuration -reference](https://jupyterhub.readthedocs.io/en/latest/api/auth.html) for more -details. +As all authenticator classes derive from the +{external:py:class}`jupyterhub.auth.Authenticator` base class, they share some +configuration options. Below are some common configuration options from the base +class. -### [allowed_users](https://jupyterhub.readthedocs.io/en/latest/api/auth.html#jupyterhub.auth.Authenticator.allowed_users) / [admin_users](https://jupyterhub.readthedocs.io/en/latest/api/auth.html#jupyterhub.auth.LocalAuthenticator.admin_users) +### [allowed_users](https://jupyterhub.readthedocs.io/en/stable/reference/api/auth.html#jupyterhub.auth.Authenticator.allowed_users) / [admin_users](https://jupyterhub.readthedocs.io/en/stable/reference/api/auth.html#jupyterhub.auth.LocalAuthenticator.admin_users) Some authenticator classes may have dedicated logic in addition this this to authorize users. @@ -68,7 +71,7 @@ In the above configuration, we have configured three things: 2. anyone will be able to login with username `user1-4` and the password `a-shared-secret-password` 3. `user1` and `user2` will have admin permissions, while `user3` and `user4` will be regular users. -### [auto_login](https://jupyterhub.readthedocs.io/en/latest/api/auth.html#jupyterhub.auth.Authenticator.auto_login) +### [auto_login](https://jupyterhub.readthedocs.io/en/stable/reference/api/auth.html#jupyterhub.auth.Authenticator.auto_login) If you have configured authentication with GitHub for example, the page `/hub/login` will feature a single orange button that users are to press to @@ -82,7 +85,7 @@ hub: auto_login: true ``` -### [enable_auth_state](https://jupyterhub.readthedocs.io/en/latest/api/auth.html#jupyterhub.auth.Authenticator.enable_auth_state) +### [enable_auth_state](https://jupyterhub.readthedocs.io/en/stable/reference/api/auth.html#jupyterhub.auth.Authenticator.enable_auth_state) If you want JupyterHub to persist often sensitive information received as part of logging in, you need to enable it. @@ -95,7 +98,7 @@ hub: ``` For more information about authentication state, see [JupyterHub's own -documentation](https://jupyterhub.readthedocs.io/en/latest/reference/authenticators.html#authentication-state) +documentation](https://jupyterhub.readthedocs.io/en/stable/reference/authenticators.html#authentication-state) about authentication state. ````{note} @@ -127,17 +130,28 @@ documentation. ### OAuth2 based authentication -JupyterHub's [oauthenticator](https://github.com/jupyterhub/oauthenticator) has -support for enabling your users to authenticate via a third-party OAuth2 -_identity provider_ such as GitHub, Google, and CILogon. All of these will -require an OAuth2 _client id_ and _client secret_. +JupyterHub's [oauthenticator](https://github.com/jupyterhub/oauthenticator) +project has support for enabling your users to authenticate via a third-party +OAuth2 _identity provider_ such as GitHub, Google, and CILogon. All of these +will require an OAuth2 _client id_ and _client secret_. For details on how to acquire a client id and client secret, please refer to [oauthenticator's -documentation](https://oauthenticator.readthedocs.io/en/stable/getting-started.html). +documentation](https://oauthenticator.readthedocs.io/en/stable/tutorials/general-setup.html). #### GitHub +```{warning} +This documentation may not have been updated recently. Due to that, please only use this +_as a complement_ to the official [GitHubOAuthenticator documentation]. + +[githuboauthenticator documentation]: https://oauthenticator.readthedocs.io/en/latest/tutorials/provider-specific-setup/providers/github.html + +Going onwards, the goal is to ensure we have good documentation in the +OAuthenticator project and reference that instead of maintaining similar +documentation in this project also. +``` + GitHub is the largest hosting service for git repositories. It is free to create an account at GitHub, and relatively straightforward to set up OAuth credentials so that users can authenticate with their GitHub username/password. @@ -175,7 +189,7 @@ hub: allowed_organizations: - my-github-organization scope: - - read:user + - read:org ``` If you would like to restrict access to a specific team within a GitHub organization, use @@ -192,15 +206,26 @@ hub: ``` ```{admonition} About the choice of scope -The narrower scope `read:user` is sufficient for a configuration of `allowed_organizations` to function if you both list only entire organizations rather than specific teams, and if the users [make their organization membership public](https://docs.github.com/en/github/setting-up-and-managing-your-github-user-account/managing-your-membership-in-organizations/publicizing-or-hiding-organization-membership). +The narrower scope `read:user` is sufficient for a configuration of `allowed_organizations` to function if you both list only entire organizations rather than specific teams, and if the users [make their organization membership public](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-your-membership-in-organizations/publicizing-or-hiding-organization-membership). -The broader scope `read:org` doesn't have the limitations of `read:user`, but will require a one-off approval by the admins of the GitHub organizations' listed in `allowed_organizations`. This kind of approval can be requested by organization users [as documented on GitHub](https://docs.github.com/en/github/setting-up-and-managing-your-github-user-account/managing-your-membership-in-organizations/requesting-organization-approval-for-oauth-apps). +The broader scope `read:org` doesn't have the limitations of `read:user`, but will require a one-off approval by the admins of the GitHub organizations' listed in `allowed_organizations`. This kind of approval can be requested by organization users [as documented on GitHub](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-your-membership-in-organizations/requesting-organization-approval-for-oauth-apps). -For details about GitHub scopes, see [GitHub's documentation](https://docs.github.com/en/developers/apps/scopes-for-oauth-apps). +For details about GitHub scopes, see [GitHub's documentation](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps). ``` #### Google +```{warning} +This documentation may not have been updated recently. Due to that, please only use this +_as a complement_ to the official [GoogleOAuthenticator documentation]. + +[googleoauthenticator documentation]: https://oauthenticator.readthedocs.io/en/latest/tutorials/provider-specific-setup/providers/google.html + +Going onwards, the goal is to ensure we have good documentation in the +OAuthenticator project and reference that instead of maintaining similar +documentation in this project also. +``` + Google authentication is used by many universities (it is part of "G Suite"). If your institution is a [G Suite customer](https://workspace.google.com) that @@ -250,6 +275,17 @@ users which account they are using to login. #### CILogon +```{warning} +This documentation may not have been updated recently. Due to that, please only use this +_as a complement_ to the official [CILogonOAuthenticator documentation]. + +[ciLogonoauthenticator documentation]: https://oauthenticator.readthedocs.io/en/latest/tutorials/provider-specific-setup/providers/cilogon.html + +Going onwards, the goal is to ensure we have good documentation in the +OAuthenticator project and reference that instead of maintaining similar +documentation in this project also. +``` + Please see CyberInfrastructure Logon's [website](https://www.cilogon.org) for more information about what kind of identity is managed by CILogon. @@ -264,18 +300,18 @@ hub: authenticator_class: cilogon ``` -Based on [this -caveat](https://github.com/jupyterhub/oauthenticator/blob/6f239bebecbb3fb0242de7f753ae1c93ed101340/oauthenticator/cilogon.py#L5-L14), -you may need to also set the following. +#### Globus -```yaml -hub: - config: - CILogonOAuthenticator: - username_claim: email -``` +```{warning} +This documentation may not have been updated recently. Due to that, please only use this +_as a complement_ to the official [GlobusOAuthenticator documentation]. -#### Globus +[globusoauthenticator documentation]: https://oauthenticator.readthedocs.io/en/latest/tutorials/provider-specific-setup/providers/globus.html + +Going onwards, the goal is to ensure we have good documentation in the +OAuthenticator project and reference that instead of maintaining similar +documentation in this project also. +``` Globus Auth is a foundational identity and access management platform service designed to address unique needs of the science and engineering @@ -298,7 +334,18 @@ hub: #### Azure Active Directory -[Azure Active Directory](https://docs.microsoft.com/en-us/azure/active-directory/) +```{warning} +This documentation may not have been updated recently. Due to that, please only use this +_as a complement_ to the official [AzureAdOAuthenticator documentation]. + +[azureadoauthenticator documentation]: https://oauthenticator.readthedocs.io/en/latest/tutorials/provider-specific-setup/providers/azuread.html + +Going onwards, the goal is to ensure we have good documentation in the +OAuthenticator project and reference that instead of maintaining similar +documentation in this project also. +``` + +[Azure Active Directory](https://learn.microsoft.com/en-us/azure/active-directory/) is an identity provider from Microsoft Azure. Apart from needing a OAuth2 _client id_ and _client secret_, you will also need a _tenant id_. @@ -316,6 +363,17 @@ hub: #### Auth0 +```{warning} +This documentation may not have been updated recently. Due to that, please only use this +_as a complement_ to the official [Auth0OAuthenticator documentation]. + +[auth0oauthenticator documentation]: https://oauthenticator.readthedocs.io/en/latest/tutorials/provider-specific-setup/providers/auth0.html + +Going onwards, the goal is to ensure we have good documentation in the +OAuthenticator project and reference that instead of maintaining similar +documentation in this project also. +``` + [Auth0](https://auth0.com/) is a commercial provider of identity management. ```yaml @@ -325,58 +383,49 @@ hub: client_id: client-id-from-auth0-here client_secret: client-secret-from-auth0-here oauth_callback_url: https://your-jupyterhub-domain/hub/oauth_callback + auth0_domain: prod-8ua-1yy9.auth0.com scope: - openid - email - auth0_subdomain: prod-8ua-1yy9 - Authenticator: - admin_users: - - devops@example.com - auto_login: true JupyterHub: authenticator_class: auth0 ``` #### GenericOAuthenticator - OpenID Connect +```{warning} +This documentation may not have been updated recently. Due to that, please only use this +_as a complement_ to the official [GenericOAuthenticator documentation]. + +[genericoauthenticator documentation]: https://oauthenticator.readthedocs.io/en/latest/tutorials/provider-specific-setup/providers/generic.html + +Going onwards, the goal is to ensure we have good documentation in the +OAuthenticator project and reference that instead of maintaining similar +documentation in this project also. +``` + [OpenID Connect](https://openid.net/connect) is an identity layer on top of the OAuth 2.0 protocol, implemented by [various servers and -services](https://openid.net/developers/certified/#OPServices). While OpenID +services](https://openid.net/certified-open-id-developer-tools/). While OpenID Connect endpoint discovery is not supported by oauthentiator, you can still configure JupyterHub to authenticate with OpenID Connect providers by specifying all endpoints in the GenericOAuthenticator class. -##### Auth0 +##### KeyCloak -Below is an example on how you can configure the GenericOAuthenticator to -authenticate against Auth0. +```{warning} +This documentation may not have been updated recently. Due to that, please only use this +_as a complement_ to the official [GenericOAuthenticator documentation]. -```yaml -hub: - config: - GenericOAuthenticator: - client_id: your-client-id - client_secret: your-client-secret - oauth_callback_url: https://your-jupyterhub-domain/hub/oauth_callback - authorize_url: https://your-domain.us.auth0.com/authorize - token_url: https://your-domain.us.auth0.com/oauth/token - userdata_url: https://your-domain.us.auth0.com/userinfo - scope: - - openid - - name - - profile - - email - username_key: name - JupyterHub: - authenticator_class: generic-oauth +Going onwards, the goal is to ensure we have good documentation in the +OAuthenticator project and reference that instead of maintaining similar +documentation in this project also. ``` -##### KeyCloak - [KeyCloak](https://www.keycloak.org) is an open source based provider of identity management that you can host yourself. Below is an example on how you can configure the GenericOAuthenticator class to authenticate against a KeyCloak -server. +server (version 17 or later). To configure an OpenID Connect client, see [KeyCloak's own documentation](https://www.keycloak.org/docs/latest/server_admin/index.html#_oidc_clients). @@ -388,19 +437,36 @@ hub: client_id: your-client-id client_secret: your-client-secret oauth_callback_url: https://your-jupyterhub-domain/hub/oauth_callback - authorize_url: https://${host}/auth/realms/${realm}/protocol/openid-connect/auth - token_url: https://${host}/auth/realms/${realm}/protocol/openid-connect/token - userdata_url: https://${host}/auth/realms/${realm}/protocol/openid-connect/userinfo + authorize_url: https://${host}/realms/${realm}/protocol/openid-connect/auth + token_url: https://${host}/realms/${realm}/protocol/openid-connect/token + userdata_url: https://${host}/realms/${realm}/protocol/openid-connect/userinfo login_service: keycloak - username_key: preferred_username + username_claim: preferred_username userdata_params: state: state + # In order to use keycloak client's roles as authorization layer + claim_groups_key: roles + allowed_groups: + - user + admin_groups: + - admin JupyterHub: authenticator_class: generic-oauth ``` ### LDAP and Active Directory +```{warning} +This documentation may not have been updated recently. Due to that, please only use this +_as a complement_ to the official [LDAPAuthenticator documentation]. + +[ldapauthenticator documentation]: https://github.com/jupyterhub/ldapauthenticator#readme + +Going onwards, the goal is to ensure we have good documentation in the +OAuthenticator project and reference that instead of maintaining similar +documentation in this project also. +``` + JupyterHub supports LDAP and Active Directory authentication. Read the [ldapauthenticator](https://github.com/jupyterhub/ldapauthenticator) documentation for a full explanation of the available parameters. diff --git a/doc/source/administrator/cost.md b/docs/source/administrator/cost.md similarity index 100% rename from doc/source/administrator/cost.md rename to docs/source/administrator/cost.md diff --git a/doc/source/administrator/debug.md b/docs/source/administrator/debug.md similarity index 100% rename from doc/source/administrator/debug.md rename to docs/source/administrator/debug.md diff --git a/doc/source/administrator/index.md b/docs/source/administrator/index.md similarity index 96% rename from doc/source/administrator/index.md rename to docs/source/administrator/index.md index 043dd74cc7..c8aa06b419 100644 --- a/doc/source/administrator/index.md +++ b/docs/source/administrator/index.md @@ -14,7 +14,7 @@ authentication services optimization security -upgrading +upgrading/index ../../jupyterhub/customization troubleshooting advanced diff --git a/doc/source/administrator/optimization.md b/docs/source/administrator/optimization.md similarity index 98% rename from doc/source/administrator/optimization.md rename to docs/source/administrator/optimization.md index ee5c23b067..c45f23d5dd 100644 --- a/doc/source/administrator/optimization.md +++ b/docs/source/administrator/optimization.md @@ -120,7 +120,7 @@ situations: generally fail to do so. This is because it will only add a node if one or more pods won't fit on the current nodes but would fit more if a node is added, but at that point users are already waiting. To scale up nodes ahead - of time we can use [user-placeholders](#scaling-up-in-time-user-placeholders). + of time we can use [user-placeholders](scaling-up-in-time-user-placeholders). (images-that-will-be-pulled)= @@ -164,7 +164,7 @@ singleuser: prePuller: extraImages: - myOtherImageIWantPulled: + my-other-image-i-want-pulled: name: jupyter/all-spark-notebook tag: 2343e33dec46 ``` @@ -179,6 +179,8 @@ Autoscaler_](https://github.com/kubernetes/autoscaler/tree/HEAD/cluster-autoscal help to function well. Without help, it will both fail to scale up before users arrive and scale down nodes aggressively enough without disrupting users. +(scaling-up-in-time-user-placeholders)= + ### Scaling up in time (user placeholders) A _Cluster Autoscaler_ (CA) will add nodes when pods don't fit on available @@ -187,7 +189,7 @@ waiting time for the pod, and as a pod can represent a user, it can lead to a long waiting time for a user. There are now options to address this. With Kubernetes 1.11+ (that requires Helm 2.11+), [Pod Priority and -Preemption](https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/) +Preemption](https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/) was introduced. This allows pods with higher priority to preempt / evict pods with lower priority if that would help the higher priority pod fit on a node. @@ -436,7 +438,7 @@ relevant: harder to debug. Various timeouts can be clues to suspect CPU starvation. 1. When scheduling a Pod on a node, the [_effective - requests/limits_](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/#resources) + requests/limits_](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/#resource-sharing-within-containers) are considered. As a Pod's init containers are run in sequence before the Pod's main containers are started, the effective requests/limits are calculated as the highest of the init containers requests/limits and the sum diff --git a/doc/source/administrator/security.md b/docs/source/administrator/security.md similarity index 52% rename from doc/source/administrator/security.md rename to docs/source/administrator/security.md index 91d70cf342..9b34b041e7 100644 --- a/doc/source/administrator/security.md +++ b/docs/source/administrator/security.md @@ -61,7 +61,7 @@ changes to your `config.yaml` file: **NOTE:** -If the proxy service is of type `LoadBalancer`, which it is by default, then a specific static IP address can be requested (if available) instead of a dynamically acquired one. +If the proxy service is of type `LoadBalancer`, which it is by default, then a specific static IP address can be requested (if available) instead of a dynamically acquired one. Although not essential for HTTPS, using a static IP address is a recommended practice for domain names referencing fixed IPs. This ensures the same IP address for multiple deployments. The IP can be provided like: @@ -164,7 +164,29 @@ certificates. One options is to use the [Qualys SSL Labs](https://www.ssllabs.co security report generator. Use the following URL structure to test your domain: ``` -http://ssllabs.com/ssltest/analyze.html?d= +https://ssllabs.com/ssltest/analyze.html?d= +``` + +## Minimal hub image + +The default hub image includes some useful debugging tools. +You can use the slim version of image to minimise your exposure to vulnerabilities in those optional tools. + +```yaml +hub: + image: + # The slim variant excludes a few non-essential packages that are useful + # when debugging something from the hub pod. To use it, apply this + # configuration. + # + name: quay.io/jupyterhub/k8s-hub-slim +``` + +```{note} +We are based on Linux Debian as a base image. There are container +scanners that pick up known vulnerabilities in Debian that the Debian security +team has dismissed. For details about this, see [this +comment](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/issues/2918#issuecomment-1295813128). ``` ## Secure access to Helm @@ -197,7 +219,7 @@ kubectl --namespace=kube-system delete rc kubernetes-dashboard Kubernetes supports, and often requires, using [Role Based Access Control (RBAC)](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) to secure which pods / users can perform what kinds of actions on the cluster. RBAC rules can be set to provide users with minimal necessary access based on their administrative needs. -It is **critical** to understand that if RBAC is disabled, all pods are given `root` equivalent permission on the Kubernetes cluster and all the nodes in it. This opens up very bad vulnerabilites for your security. +It is **critical** to understand that if RBAC is disabled, all pods are given `root` equivalent permission on the Kubernetes cluster and all the nodes in it. This opens up very bad vulnerabilities for your security. As of the Helm chart v0.5 used with JupyterHub and BinderHub, the helm chart can natively work with RBAC enabled clusters. To provide sensible security defaults, we ship appropriate minimal RBAC rules for the various components we use. We **highly recommend** using these minimal or more restrictive RBAC rules. @@ -205,7 +227,7 @@ If you want to disable the RBAC rules, for whatever reason, you can do so with t ```yaml rbac: - enabled: false + create: false ``` We strongly **discourage disabling** the RBAC rules and remind you that this @@ -257,23 +279,29 @@ only need one. (block-metadata-netpol)= -### Block metadata with a NetworkPolicy enforced by a NetworkPolicy controller +### Block cloud metadata API with a NetworkPolicy enforced by a NetworkPolicy controller -If you have _NetworkPolicy controller_ such as Calico in the Kubernetes cluster, -it will enforce the NetworkPolicy resource created by this chart -(`singleuser.networkPolicy.*`) that blocks user access to the metadata server. -We recommend relying on this approach if you you had a NetworkPolicy controller, -and then you can disable the other option. +If you have _NetworkPolicy controller_ such as Calico or Cilium in the +Kubernetes cluster, it will enforce the NetworkPolicy resource created by this +chart (`singleuser.networkPolicy.*`) that by default doesn't allow (and +therefore blocks) user access to the cloud metadata API exposed on a specific IP +(`169.254.169.254`). + +```{note} +If you have a NetworkPolicy controller, we recommend relying on it and setting +`singleuser.cloudMetadata.blockWithIptables` to `false`. +``` (block-metadata-iptables)= -### Block metadata with a privileged initContainer running `iptables` +### Block cloud metadata API with a privileged initContainer running `iptables` -If you can't rely on the NetworkPolicy approach to block access to the metadata -server, we suggest relying on this option. When +If you can't rely on the NetworkPolicy approach to block access to the cloud +metadata API, we suggest relying on this option instead. When `singleuser.cloudMetadata.blockWithIptables` is true as it is by default, an `initContainer` is added to the user pods. It will run with elevated privileges -and use the `iptables` command line tool to block access to the metadata server. +and use the `iptables` command line tool to block all network access to the +cloud metadata server. ```yaml # default configuration @@ -283,120 +311,167 @@ singleuser: ip: 169.254.169.254 ``` -## Kubernetes Network Policies +```{versionchanged} 3.0.0 +This configuration is not allowed to be configured true at the same time as +[`singleuser.networkPolicy.egressAllowRules.cloudMetadataServer`](schema_singleuser.networkPolicy.egressAllowRules.cloudMetadataServer) +to avoid an ambiguous configuration. +``` -**Important**: When using network policies, you should be aware -that a Kubernetes cluster may have partial, full, or no support for network policies. -Kubernetes will **silently ignore** policies that aren't supported. -Please use **caution** before relying on network policy enforcement -and verify the policies behave as expected, -especially if you rely on them to restrict what users can access. +(netpol)= -Kubernetes has optional support for [network -policies](https://kubernetes.io/docs/concepts/services-networking/network-policies/) -which lets you restrict how pods can communicate with each other and the outside -world. This can provide additional security within JupyterHub, and can also be -used to limit network access for users of JupyterHub. +## Kubernetes Network Policies -By default, the JupyterHub helm chart **enables** network policies in 0.10 or later. -They are **disabled** by default in 0.9 and earlier. +```{warning} +Your Kubernetes cluster may silently ignore the network rules described in the +NetworkPolicy resources that this Helm chart can create. NetworkPolicy rules are +enforced by an optional NetworkPolicy controller that often isn't setup as part +of setting up a Kubernetes cluster. +``` -The JupyterHub chart has three network policies, -one for each component (hub, proxy, single-user servers), -which can be enabled and configured separately. +By default this Helm chart creates four different +[NetworkPolicy](https://kubernetes.io/docs/concepts/services-networking/network-policies/) +resources describing what incoming/ingress and outgoing/egress connections are +to be allowed for the pods they target. + +A critical point to understand is that if a pod's ingress or egress connections +respectively aren't targeted by a NetworkPolicy, they won't be constrained by +them at all. If they are though, only what is explicitly allowed for them will +be accepted. In other words, the act of defining a NetworkPolicy targeting a pod +is what is constraining it, but all the rules in the NetworkPolicy are allow +rules. + +### Introduction to the chart's four network policies + +The four network policies declare rules for four kinds of pods created by the +Helm chart. Below are some tables describing what the four network policy do to +some extent. + +| NetworkPolicy | Associated Helm chart config | Influenced pods | Notable software in pods | +| ------------- | ----------------------------- | -------------------- | -------------------------------------------------------------------- | +| `hub` | `hub.networkPolicy` | `hub` | `jupyterhub`, `kubespawner`, `jupyterhub-idle-culler`, Authenticator | +| `proxy` | `proxy.chp.networkPolicy` | `proxy` | `configurable-http-proxy` | +| `autohttps` | `proxy.traefik.networkPolicy` | `autohttps` | `traefik`, `lego` | +| `singleuser` | `singleuser.networkPolicy` | `jupyter-` | `jupyter_server` | + +| NetworkPolicy | Always allowed outbound connections (egress) for core functionality | +| ------------- | ---------------------------------------------------------------------------------------------------------------- | +| `hub` | To `proxy` pod's REST API port (8001), user pods' only port (8888) | +| `proxy` | To `hub` pod's only port (8081), user pods' only port (8888) | +| `autohttps` | To `proxy` pod's http proxy port (8000) | +| `singleuser` | To `hub` pod's only port (8081), `proxy` pod's proxy port (8000), `autohttps` pod's http (8080) and https (8443) | + +| NetworkPolicy | Always allowed inbound connections (ingress) for core functionality, ingress is allowed for specific ports from pods with certain labels | +| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `hub` | From pods labelled `hub.jupyter.org/network-access-hub=true` | +| `proxy` | From pods labelled `hub.jupyter.org/network-access-proxy-http=true` (http proxy port) or `hub.jupyter.org/network-access-proxy-api=true` (REST API port) in the same namespace | +| `autohttps` | From pods labelled `hub.jupyter.org/network-access-proxy-http=true` (http(s) proxy ports) | +| `singleuser` | From pods labelled `hub.jupyter.org/network-access-singleuser=true` (notebook-port) | + +````{warning} Not all functionality summarized above +It has been tricky to document the full behavior of these network policies. For +in depth details, please for now refer to inspecting the Helm chart's templates +and the rendered result given your configuration. + +Below are links to the Helm chart's templates. + +- [`hub` template](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/jupyterhub/templates/hub/netpol.yaml) +- [`proxy` template](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/jupyterhub/templates/proxy/netpol.yaml) +- [`autohttps` template](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/jupyterhub/templates/proxy/autohttps/netpol.yaml) +- [`singleuser` template](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/jupyterhub/templates/singleuser/netpol.yaml) + +Below are commands you can use to render the specific template. + +```shell +# These four commands renders the four NetworkPolicy resource templates of the +# latest release of the JupyterHub Helm chart, with default values. +# +# You can pass `--values ` or `--version ` to +# these commands to inspect the rendered NetworkPolicy resources given your +# specific version and configuration. +# +helm template --repo https://jupyterhub.github.io/helm-chart jupyterhub --show-only templates/hub/netpol.yaml +helm template --repo https://jupyterhub.github.io/helm-chart jupyterhub --show-only templates/proxy/netpol.yaml +helm template --repo https://jupyterhub.github.io/helm-chart jupyterhub --show-only templates/proxy/autohttps/netpol.yaml +helm template --repo https://jupyterhub.github.io/helm-chart jupyterhub --show-only templates/singleuser/netpol.yaml +``` +```` ### Enabling and disabling network policies -By default, the JupyterHub helm chart **enables** network policies in 0.10 or later. -They are **disabled** by default in 0.9 and earlier. - -You can enable or disable enforcement of each network policy in config.yaml: +NetworkPolicy resources are created by default, and with their creation they +restrict inbound and outbound network connections to those explicitly allowed in +the NetworkPolicy resource. To opt-out of creating NetworkPolicy resources, use +configuration like below. ```yaml +# Example configuration on how to disable the creation of all the Helm chart's +# NetworkPolicy resources. hub: networkPolicy: - enabled: true # or false to disable + enabled: false proxy: - networkPolicy: - enabled: true + chp: + networkPolicy: + enabled: false + traefik: + networkPolicy: + enabled: false singleuser: networkPolicy: - enabled: true + enabled: false ``` -### Granting network access to jupyterhub pods (ingress) - -The chart's network policy default behavior ensures that all of the jupyterhub components can talk to each other, -so all of the following connections are allowed: - -- proxy ⇨ hub -- proxy ⇨ singleuser -- hub ⇨ proxy api -- hub ⬄ singleuser -- everything ⇨ DNS - -and by default do not allow any other pods to talk to the jupyterhub components. - -The network policies use label selectors that look like: - -```yaml -ingress: - # allowed pods (hub.jupyter.org/network-access-hub) --> hub - - from: - - podSelector: - matchLabels: - hub.jupyter.org/network-access-hub: "true" +### Allowing additional inbound network connections (ingress) + +While you can add allow arbitrary allow rules with the +[`.networkPolicy.ingress`](schema_hub.networkPolicy.ingress) +configuration besides the rules ensuring core functionality, you can also label +the pods you want to be allowed to establish connections to the Helm chart's +various pods. + +For example, to access the hub pod from another pod in the same namespace, just +add the label `hub.jupyter.org/network-access-hub: "true"` to the pod that +should be able to establish a connection to the hub pod. + +The available access labels are: + +- `hub.jupyter.org/network-access-hub: "true"`, access the hub api +- `hub.jupyter.org/network-access-proxy-http: "true"`, access proxy public http endpoint +- `hub.jupyter.org/network-access-proxy-api: "true"`, access proxy api +- `hub.jupyter.org/network-access-singleuser: "true"`, access singleuser servers directly + +If you wish to access the pod from another namespace with these labels, then +read about +[`.networkPolicy.interNamespaceAccessLabels`](schema_hub.networkPolicy.interNamespaceAccessLabels). + +Finally, the option +[`.networkPolicy.allowedIngressPorts`](schema_hub.networkPolicy.allowedIngressPorts) +enable you to allow incoming connections on certain pods. + +### Allowing additional outbound network connections (egress) + +While you can add allow arbitrary allow rules with the +[`.networkPolicy.egress`](schema_hub.networkPolicy.egress) +configuration besides the rules ensuring core functionality, you can also toggle +some pre-defined allow rules on or off. They are documented in the configuration +reference under +[`.networkPolicy.egressAllowRules`](schema_hub.networkPolicy.egressAllowRules). + +By default, all egress allow rules are enabled for `hub`, `proxy.chp`, and +`proxy.traefik`, but +`singleuser.networkPolicy.egressAllowRules.cloudMetadataServer` and +`singleuser.networkPolicy.egressAllowRules.privateIPs` default to false. In +practice, this can mean no rule allows the user pods to communicate with some +k8s local service with [Private IPv4 +addresses](https://en.wikipedia.org/wiki/Private_network#Private_IPv4_addresses). + +```{versionchanged} 2.0.0 +Before JupyterHub Helm chart 2.0.0 the default configuration was to allow +singleuser pods to establish outbound connections to anything. After 2.0.0 +`singleuser.networkPolicy.egressAllowRules.privateIPs=true` must be explicitly +set for this. ``` -So if you are creating additional pods that want to talk to these, -you can grant them access to jupyterhub components one by one by adding the right labels. -Here is an example set of labels granting access to all jupyterhub components -(i.e. the same behavior as without network policies): - -```yaml -metadata: - name: my-service - labels: - hub.jupyter.org/network-access-hub: "true" # access the hub api - hub.jupyter.org/network-access-proxy-http: "true" # access proxy public http endpoint - hub.jupyter.org/network-access-proxy-api: "true" # access proxy api - hub.jupyter.org/network-access-singleuser: "true" # access single-user servers directly -``` - -You can also add additional `ingress` rules to each network policy in your `config.yaml`. -See the [Kubernetes documentation](https://kubernetes.io/docs/concepts/services-networking/network-policies/) -for how to define ingress rules. - -### Limiting network access from pods (egress) - -By default, all of the pods allow all `egress` traffic, -which means that code in each of the pods may make connections to anywhere in the cluster or on the Internet -(unless that would be blocked by the ingress rules of the destination). -This is very permissive. -The default policy for all components allows all outbound (egress) network traffic, -meaning JupyterHub users are able to connect to all resources inside and outside your network. -You can override the `egress` configuration of each policy -to make it more restrictive. -For example, to restrict user outbound traffic to DNS, HTTP, and HTTPS: - -```yaml -singleuser: - networkPolicy: - enabled: true - egress: - - ports: - - port: 53 - protocol: UDP - - ports: - - port: 80 - - ports: - - port: 443 -``` - -See the [Kubernetes -documentation](https://kubernetes.io/docs/concepts/services-networking/network-policies/) -for further information on defining policies. - ## Restricting Load Balancer Access By default any IP address can access your JupyterHub deployment through the load balancer service. diff --git a/doc/source/administrator/services.md b/docs/source/administrator/services.md similarity index 70% rename from doc/source/administrator/services.md rename to docs/source/administrator/services.md index 1d77430dae..bd75524625 100644 --- a/doc/source/administrator/services.md +++ b/docs/source/administrator/services.md @@ -8,7 +8,7 @@ Services can be run [externally](https://jupyterhub.readthedocs.io/en/stable/get ## Hub-managed services in z2jh -A Hub-managed service will run in the same container/pod as the Hub itself. First, you'll need to install or copy the appropriate files for the service into your Hub image, either by creating a custom image derived from [`jupyterhub/k8s-hub`](https://hub.docker.com/r/jupyterhub/k8s-hub) or the [hub.extraFiles](schema_hub.extraFiles) configuration. Keep in mind that your Hub container may need to install dependency libraries like flask or fastapi, depending on the service. In those cases, you'll need a custom image. +A Hub-managed service will run in the same container/pod as the Hub itself. First, you'll need to install or copy the appropriate files for the service into your Hub image, either by creating a custom image derived from [`jupyterhub/k8s-hub`](https://quay.io/repository/jupyterhub/k8s-hub) or the [hub.extraFiles](schema_hub.extraFiles) configuration. Keep in mind that your Hub container may need to install dependency libraries like flask or fastapi, depending on the service. In those cases, you'll need a custom image. In addition to the code for the service, you need to modify the Hub Kubernetes Service object to include [multiple ports](https://kubernetes.io/docs/concepts/services-networking/service/#multi-port-services), and update the Hub Network Policy. If you want to allow access from all sources, you can use [hub.networkPolicy.allowedIngressPorts](schema_hub.networkPolicy.allowedIngressPorts). Otherwise if you want to more precisely control access, you can use [hub.networkPolicy.ingress](schema_hub.networkPolicy.ingress). @@ -18,11 +18,17 @@ In the following snippet, I'm using a custom image that copies over the applicat ```Dockerfile # Dockerfile -# 0.11.1 is latest stable release at the time of this writing -FROM jupyterhub/k8s-hub:0.11.1 +# 3.1.0 is latest stable release at the time of this writing +# Find all tags in https://quay.io/repository/jupyterhub/k8s-hub?tab=tags +FROM quay.io/jupyterhub/k8s-hub:3.1.0 +# Depending on version, the k8s-hub image may have installed +# pip packages as root, forcing you to install as root as well +USER root COPY ./service-fastapi /usr/src/fastapi RUN python3 -m pip install -r /usr/src/fastapi/requirements.txt + +USER ${NB_USER} ``` ```yaml @@ -63,4 +69,21 @@ hub: - port: 8181 targetPort: 8181 name: fastapi + +# The proxy.chp.networkPolicy.egress configuration below is required if the +# service should be accessible for users. If it shouldn't be, you should instead +# set the chart configuration services.fastapi.display to false as otherwise +# JupyterHub will provide a broken link in the Services menu for users to go to +# /services/fastapi/. +proxy: + chp: + networkPolicy: + egress: + - to: + - podSelector: + matchLabels: + app: jupyterhub + component: hub + ports: + - port: 8181 ``` diff --git a/doc/source/administrator/troubleshooting.md b/docs/source/administrator/troubleshooting.md similarity index 100% rename from doc/source/administrator/troubleshooting.md rename to docs/source/administrator/troubleshooting.md diff --git a/doc/source/administrator/upgrading.md b/docs/source/administrator/upgrading/index.md similarity index 51% rename from doc/source/administrator/upgrading.md rename to docs/source/administrator/upgrading/index.md index bd3001c950..f9c6564252 100644 --- a/doc/source/administrator/upgrading.md +++ b/docs/source/administrator/upgrading/index.md @@ -1,54 +1,43 @@ -# Upgrading your Helm chart +# Upgrading JupyterHub for Kubernetes -This page covers best-practices in upgrading your JupyterHub deployment via updates +This section covers best-practices in upgrading your JupyterHub deployment via updates to the Helm Chart. -Upgrading from one version of the Helm Chart to the -next should be as seamless as possible, and generally shouldn't require major -changes to your deployment. Check the [CHANGELOG](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/CHANGELOG.md) -for each release to find out if there are any breaking changes in the newest version. +Z2JH follows [semantic versioning](https://semver.org/), with each version taking the form `MAJOR.MINOR.PATCH`. +Minor and patch releases should be backwards compatible, and shouldn't require changes to your deployment. +Review the [CHANGELOG](changelog) to find out about new features or bug fixes that affect your deployment, +then follow [](helm-upgrade-command). + +Major releases may contain breaking changes, and will often require changes to your configuration. +They have dedicated instructions for upgrading your deployment in addition to the general instructions on this page. For additional help, feel free to reach out to us on [gitter](https://gitter.im/jupyterhub/jupyterhub) -or the [mailing list](https://groups.google.com/forum/#!forum/jupyter)! +or the [Discourse forum](https://discourse.jupyter.org/). + +(upgrading-major-upgrades)= ## Major helm-chart upgrades +```{toctree} +:maxdepth: 1 +:caption: Major releases guides + +upgrade-1-to-2 +``` + These steps are **critical** before performing a major upgrade. 1. Always backup your database! -2. Review the [CHANGELOG](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/CHANGELOG.md) for incompatible changes and upgrade instructions. +2. Review the appropriate upgrade guide, and/or the [CHANGELOG](changelog) for incompatible changes and upgrade instructions. 3. Update your configuration accordingly. -4. User servers may need be stopped prior to the upgrade, - or restarted after it. +4. User servers may need be stopped prior to the upgrade, or restarted after it. 5. If you are planning an upgrade of a critical major installation, we recommend you test the upgrade out on a staging cluster first before applying it to production. -### v0.5 to v0.6 - -See the [CHANGELOG](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/CHANGELOG.md#06---ellyse-perry---2017-01-29). - -### v0.4 to v0.5 - -Release 0.5 contains a major JupyterHub version bump (from 0.7.2 to 0.8). -Since it is a major upgrade of JupyterHub that changes how authentication is -implemented, user servers must be stopped during the upgrade. -The database schema has also changed, so a database upgrade must be performed. - -See the [documentation for v0.5 for the upgrade process](https://zero-to-jupyterhub.readthedocs.io/en/latest/administrator/upgrading.html#v0-4-to-v0-5) -as well as the [CHANGELOG](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/CHANGELOG.md#05---hamid-hassan---2017-12-05) -for this release for more information about changes. +(helm-upgrade-command)= -## Subtopics - -This section covers upgrade information specific to the following: - -- `helm upgrade` command -- Databases -- RBAC (Role Based Access Control) -- Custom Docker images - -### `helm upgrade` command +## `helm upgrade` command After modifying your `config.yaml` file according to the CHANGELOG, you will need `` to run the upgrade commands. To find ``, run: @@ -72,14 +61,17 @@ For example, to upgrade to version `1.1.1` with a helm release name of `jhub` in helm upgrade --cleanup-on-fail jhub jupyterhub/jupyterhub --version=1.1.1 --values config.yaml --namespace jhub ``` -### Database +## Database -This release contains a major JupyterHub version bump (from 0.7.2 to 0.8). If -you are using the default database provider (SQLite), then the required db upgrades +Major releases of Z2JH may include a major release of JupyterHub that requires an upgrade of the database schema. +If you are using the default database provider (SQLite), then the required db upgrades will be performed automatically when you do a `helm upgrade`. +A backup of the old database is automatically created on the hub volume. + +It is not possible to automatically backup other database providers, so the upgrade is not done automatically. **Default (SQLite)**: The database upgrade will be performed automatically when you -[perform the upgrade](#upgrade-command) +[perform the upgrade](helm-upgrade-command) **MySQL / PostgreSQL**: You will execute the following steps, which includes a manual update of your database: @@ -94,26 +86,34 @@ will be performed automatically when you do a `helm upgrade`. upgrade: true ``` -4. Do a [`helm upgrade`](#upgrade-command). This should perform the database upgrade needed. -5. Remove the lines added in step 3, and do another [`helm upgrade`](#upgrade-command). +4. Do a [`helm upgrade`](helm-upgrade-command). This should perform the database upgrade needed. +5. Remove the lines added in step 3, and do another [`helm upgrade`](helm-upgrade-command) so that future JupyterHub upgrades don't inadvertently upgrade the schema. -### Custom Docker Images: JupyterHub version match +## Custom Docker Images: JupyterHub version match If you are using a custom built image, make sure that the version of the -JupyterHub package installed in it is now 0.8.1. It needs to be 0.8.1 for it to work with -v0.6 of the helm chart. +JupyterHub package installed in it matches the major version of JupyterHub, current 2.\*. For example, if you are using `pip` to install JupyterHub in your custom Docker Image, you would use: ```Dockerfile -RUN pip install --no-cache-dir jupyterhub==0.8.1 +RUN pip install --no-cache-dir jupyterhub==2.3.1 ``` +If you are using conda or mamba: + +```Dockerfile +RUN conda install --channel=conda-forge -y jupyterhub-base=2.3.1 +``` + +Update the configuration to use this new image, which is typically done via +`singleuser.image` or as part of `singleuser.profileList`. + ## JupyterHub versions installed in each Helm Chart Each Helm Chart is packaged with a specific version of JupyterHub (and -other software as well). See the [Helm Chart repository](https://jupyterhub.github.io/helm-chart/) for +other software as well). See the [Helm Chart repository](https://hub.jupyter.org/helm-chart/) for information about the versions of relevant software packages. ## Troubleshooting @@ -125,4 +125,4 @@ deleting the helm chart using: helm delete --namespace ``` -`helm list --namespace ` may be used to find . +`helm list --namespace ` may be used to find ``. diff --git a/docs/source/administrator/upgrading/upgrade-1-to-2.md b/docs/source/administrator/upgrading/upgrade-1-to-2.md new file mode 100644 index 0000000000..edbec4b8f7 --- /dev/null +++ b/docs/source/administrator/upgrading/upgrade-1-to-2.md @@ -0,0 +1,160 @@ +# Major upgrade: 1.\* to 2.\* + +Z2JH 2 contains several breaking changes, including some that affect the security of your deployment. +This guide will help you upgrade from 1.\* to 2.\*. + +(upgrade-1-2-security-breaking-change)= + +## Security: breaking change to `*.networkPolicy.egress` + +NetworkPolicy egress rules have been extended with a new property. +If you have configured any of: + +- `hub.networkPolicy.egress` +- `proxy.chp.networkPolicy.egress` +- `proxy.traefik.networkPolicy.egress` +- `singleuser.networkPolicy.egress` + +you must review your configuration as additional default egress routes have been added. +Previously `*.networkPolicy.egress` controlled all egress but a new property `*.networkPolicy.egressAllowRules` add additional egress rules by default. + +If you have configured `*.networkPolicy.egress` for `hub`, `proxy.chp`, +`proxy.traefik` or `singleuser` to restrict the permissions to establish +outbound network connections, then this upgrade is likely to _escalate those +permissions unless you revise your configuration_. The new configuration +`*.networkPolicy.egressAllowRules` are by default granting most of the egress +permissions previously granted by default via the `*.networkPolicy.egress` +configuration, and `*.networkPolicy.egress` are now by default not providing +any permissions. + +If you for example had overridden the previously very permissive default value +of `singleuser.networkPolicy.egress` to be less permissive, you should consider +disabling all `singleuser.networkPolicy.egressAllowRules` like this +to not risk escalating the permissions. + +```yaml +singleuser: + networkPolicy: + egressAllowRules: + cloudMetadataServer: false + dnsPortsPrivateIPs: false + nonPrivateIPs: false + privateIPs: false +``` + +For more details, see the documentation on [Kubernetes Network Policies](netpol) +and the configuration reference entries under +[`*.networkPolicy.egress`](schema_hub.networkPolicy.egress) and +[`*.networkPolicy.egressAllowRules`](schema_hub.networkPolicy.egressAllowRules). + +## JupyterHub 2 and related hub components + +Z2JH 2.0.0 upgrades from JupyterHub 1 directly to JupyterHub 3, and also upgrades all hub components. +If you are using any custom JupyterHub services, addons, API integrations, or extra configuration, you should review the breaking changes in the +major releases of JupyterHub 2 and 3 in the [JupyterHub changelog](https://jupyterhub.readthedocs.io/en/stable/changelog.html). + +JupyterHub 2 and 3 updates the database schema, which means a migration takes place when you upgrade JupyterHub. +Z2JH automatically handles the upgrade if you are using sqlite (`hub.db.type = 'sqlite-pvc'`, the default), but it may not be possible to downgrade to older releases after this. +When using sqlite, JupyterHub automatically creates a backup in the `hub-db` volume, +which can be restored manually if you need to downgrade. +If you use an external database you need to configure [`hub.db.upgrade`](schema_hub.db.upgrade) to `true` when upgrading. + +JupyterHub 2 adds RBAC for managing permissions in JupyterHub. +The old permissions model of admin/non-admin still works, but we recommend using [RBAC to assign only the required privileges to users or services in future](https://jupyterhub.readthedocs.io/en/stable/rbac/index.html). +Default permissions are mostly unchanged, but a few have: + +- Servers' own API tokens have limited permissions by default, which can be expanded by defining the `server` role. The previous behavior was the maximum permission of `inherit`. +- `admin_access` as a concept is removed, so disabling it has no effect. In 2.0, admins by definition can do everything, including access servers. To limit user permissions, assign them to roles which have only the needed permissions. + +KubeSpawner has replaced the [`kubernetes`] library with [`kubernetes_asyncio`](https://github.com/tomplus/kubernetes_asyncio). +If you have extended the JupyterHub image and you rely on the kubernetes library you will need to modify your extensions. + +See +[Notable dependencies updated](notable-dependencies-200) +for more information on other upgraded hub components. + +## JupyterLab and Jupyter Server + +The default singleuser server is [JupyterLab](https://jupyterlab.readthedocs.io/), running on [Jupyter server](https://jupyter-server.readthedocs.io/en/latest/). +To switch back to Jupyter Notebook either configure/rebuild your singleuser image to default to notebook, or see [the documentation on user interfaces](user-interfaces) + +## KubeSpawner prevents privilege escalation such as sudo by default + +By default processes cannot escalate their privileges. +For example, a user cannot use sudo to switch to root. +If you have configured sudo or some other privilege escalation method inside your singleuser image you must set `singleuser.allowPrivilegeEscalation: true`. + +```yaml +singleuser: + allowPrivilegeEscalation: true +``` + +If you want to add custom arguments to the command, you must specify the full command and any arguments in `singleuser.cmd`, for example: + +```yaml +singleuser: + cmd: + - jupyterhub-singleuser + - "--collaborative" + - "--debug" +``` + +## Configuration in `jupyterhub_config.d` has a higher priority than `hub.config` [#2457](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2457) + +Previously if `hub.config` was used to configure some JupyterHub traitlets it would override any custom configuration files mounted into `jupyterhub_config.d` in the hub container. +In 2.0.0 all extra customisations (e.g. using `hub.extraConfig` to provide in-line configuration, or `hub.extraFiles` to mount files into `jupyterhub_config.d`) will always take precedence over any Helm chart values. + +## User scheduler plugin configuration has changed to match `kubescheduler.config.k8s.io/v1beta3` [#2590](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2590) + +Advanced customisation of the user scheduler using plugins now requires Kubernetes 1.21+, and the configuration must follow `kubescheduler.config.k8s.io/v1beta3`. +Customisation is no longer possible with Kubernetes 1.20. + +If you are using the user scheduler without custom plugin configuration you are not affected. + +## Kubernetes version 1.20+ is required [#2635](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2635) + +This Helm chart uses Kubernetes resources that are not available in Kubernetes versions prior to 1.20. + +## `hub.fsGid` is replaced by `hub.podSecurityContext` [#2720](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2720) + +In previous versions of Z2JH `hub.fsGid` set a supplemental group ID, which is required on some K8s systems to ensure JupyterHub has permissions to read/write files on a volume. +This has been replaced by the more general [`hub.podSecurityContext`](schema_hub.podSecurityContext). +To upgrade set: + +```yaml +hub: + podSecurityContext: + fsGroup: GROUP-ID +``` + +## Hub image is based on Debian instead of Ubuntu [#2733](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2733) + +The hub container base image has switched from `ubuntu:20.04` to `python:3.9-slim-bullseye` which is based on `debian:bullseye-slim`. +If you have extended the Z2JH hub image please review the [hub Dockerfile](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/2.0.0/images/hub/Dockerfile). +Note the singleuser image is not affected. + +## Disabling RBAC requires setting multiple properties, `rbac.enable` is removed [#2736](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2736) [#2739](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2739) + +If you previously disabled RBAC using `rbac.enable: False` you should set + +```yaml +rbac: + create: False +hub: + serviceAccount: + create: false +proxy: + traefik: + serviceAccount: + create: false +scheduling: + userScheduler: + serviceAccount: + create: false +prePuller: + hook: + serviceAccount: + create: false +``` + +When you have updated your configuration follow the rest of the [upgrade guide](upgrading-major-upgrades). diff --git a/docs/source/changelog.md b/docs/source/changelog.md new file mode 100644 index 0000000000..2a7fc07d23 --- /dev/null +++ b/docs/source/changelog.md @@ -0,0 +1,3877 @@ +(changelog)= + +# Changelog + +Here you can find upgrade changes in between releases and upgrade instructions. + +## Unreleased breaking changes + +This Helm chart provides [development releases], and as we merge [breaking +changes in pull requests], this list should be updated. + +[development releases]: https://hub.jupyter.org/helm-chart/#development-releases-jupyterhub +[breaking changes in pull requests]: https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pulls?q=is%3Apr+is%3Aclosed+label%3Abreaking + +## 3.2 + +### 3.2.1 - 2023-11-27 + +#### Maintenance and upkeep improvements + +- Update oauthenticator from 16.2.0 to 16.2.1 [#3278](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3278) ([@consideRatio](https://github.com/consideRatio)) + +### 3.2.0 - 2023-11-27 + +```{warning} If you are upgrading from 3.0.x +A bug in KubeSpawner 5.0-6.0 present in z2jh 3.0.0-3.0.3 made user server pods +risk be orphaned by JupyterHub, making them run indefinitely and cause +unnecessary cloud costs. + +Read more about how to clean up these user server pods in [this forum post]. +``` + +#### Default image registry changed to Quay.io + +We now publish the chart's docker images to both [Quay.io] and [Docker Hub] and +the chart is from now configured to use the images at Quay.io by default. +Previous releases of images (excluding pre-releases) has been copied over to +Quay.io as well. + +The change is to ensure that images can be pulled without a [Docker Hub rate +limit] even if the [JupyterHub organization on Docker Hub] wouldn't be sponsored +by Docker Hub in the future, something we need to apply for each year. + +[docker hub]: https://hub.docker.com +[docker hub rate limit]: https://docs.docker.com/docker-hub/download-rate-limit/ +[jupyterhub organization on docker hub]: https://hub.docker.com/u/jupyterhub +[quay.io]: https://quay.io + +#### Enhancements made + +- Pull images from `singleuser.profileList` found in `profile_options.choices` [#3217](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3217) ([@manfuin](https://github.com/manfuin), [@consideRatio](https://github.com/consideRatio), [@yuvipanda](https://github.com/yuvipanda)) + +#### Maintenance and upkeep improvements + +- Update jupyterhub/configurable-http-proxy version from 4.6.0 to 4.6.1 [#3275](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3275) ([@jupyterhub-bot](https://github.com/jupyterhub-bot), [@consideRatio](https://github.com/consideRatio)) +- Publish to Docker Hub alongside Quay.io [#3272](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3272) ([@consideRatio](https://github.com/consideRatio), [@minrk](https://github.com/minrk)) +- Update oauthenticator from 16.1.1 to 16.2.0, kubespawner from 6.1.0 to 6.2.0, and kubernetes-asyncio from 27.6.0 to 28.2.1 [#3270](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3270) ([@jupyterhub-bot](https://github.com/jupyterhub-bot), [@consideRatio](https://github.com/consideRatio)) +- Update kube-scheduler version from v1.26.9 to v1.26.11 [#3269](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3269), [#3255](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3255) ([@jupyterhub-bot](https://github.com/jupyterhub-bot), [@consideRatio](https://github.com/consideRatio)) +- Use quay.io as source of docker images [#3254](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3254) ([@yuvipanda](https://github.com/yuvipanda), [@minrk](https://github.com/minrk), [@manics](https://github.com/manics), [@mathbunnyru](https://github.com/mathbunnyru)) +- Update library/traefik version from v2.10.4 to v2.10.5 [#3248](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3248) ([@jupyterhub-bot](https://github.com/jupyterhub-bot), [@consideRatio](https://github.com/consideRatio)) + +#### Documentation improvements + +- Document k8s cluster setup using minikube (for learning and development) [#3260](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3260) ([@rgaiacs](https://github.com/rgaiacs), [@consideRatio](https://github.com/consideRatio)) +- Move note box to before list of cloud providers. [#3259](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3259) ([@rgaiacs](https://github.com/rgaiacs), [@consideRatio](https://github.com/consideRatio)) + +#### Continuous integration improvements + +- ci: fetch stable/dev releases using helm show to avoid cache issues [#3256](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3256) ([@consideRatio](https://github.com/consideRatio)) + +#### Contributors to this release + +The following people contributed discussions, new ideas, code and documentation contributions, and review. +See [our definition of contributors](https://github-activity.readthedocs.io/en/latest/#how-does-this-tool-define-contributions-in-the-reports). + +([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2023-09-29&to=2023-11-27&type=c)) + +@consideRatio ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2023-09-29..2023-11-27&type=Issues)) | @elferherrera ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aelferherrera+updated%3A2023-09-29..2023-11-27&type=Issues)) | @jupyterhub-bot ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajupyterhub-bot+updated%3A2023-09-29..2023-11-27&type=Issues)) | @manfuin ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanfuin+updated%3A2023-09-29..2023-11-27&type=Issues)) | @manics ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2023-09-29..2023-11-27&type=Issues)) | @mathbunnyru ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amathbunnyru+updated%3A2023-09-29..2023-11-27&type=Issues)) | @minrk ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aminrk+updated%3A2023-09-29..2023-11-27&type=Issues)) | @rgaiacs ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Argaiacs+updated%3A2023-09-29..2023-11-27&type=Issues)) | @vizeit ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Avizeit+updated%3A2023-09-29..2023-11-27&type=Issues)) | @yuvipanda ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ayuvipanda+updated%3A2023-09-29..2023-11-27&type=Issues)) + +## 3.1 + +### 3.1.0 - 2023-09-29 + +```{warning} Post-upgrade action recommended +A bug in KubeSpawner 5.0-6.0 present in z2jh 3.0.0-3.0.3 made user server pods +risk be orphaned by JupyterHub, making them run indefinitely and cause +unnecessary cloud costs. + +Read more about how to clean up these user server pods in [this forum post]. + +[this forum post]: https://discourse.jupyter.org/t/how-to-cleanup-orphaned-user-pods-after-bug-in-z2jh-3-0-and-kubespawner-6-0/21677 +``` + +#### Notable dependencies updated + +| Dependency | Version in 3.0.3 | Version in 3.1.0 | Changelog link | Note | +| -------------------------------------------------------------------------------- | ---------------- | ---------------- | ----------------------------------------------------------------------------------------- | ---------------------- | +| [kubespawner](https://github.com/jupyterhub/kubespawner) | 6.0.0 | 6.1.0 | [Changelog](https://jupyterhub-kubespawner.readthedocs.io/en/stable/changelog.html) | Run in the `hub` pod | +| [oauthenticator](https://github.com/jupyterhub/oauthenticator) | 16.0.7 | 16.1.0 | [Changelog](https://oauthenticator.readthedocs.io/en/stable/reference/changelog.html) | Run in the `hub` pod | +| [configurable-http-proxy](https://github.com/jupyterhub/configurable-http-proxy) | 4.5.6 | 4.6.0 | [Changelog](https://github.com/jupyterhub/configurable-http-proxy/blob/HEAD/CHANGELOG.md) | Run in the `proxy` pod | + +#### Dependency updates + +- Update jupyterhub/configurable-http-proxy version from 4.5.6 to 4.6.0 [#3224](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3224) ([@jupyterhub-bot](https://github.com/jupyterhub-bot), [@manics](https://github.com/manics)) +- Update kube-scheduler version from v1.26.8 to v1.26.9 [#3220](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3220) ([@jupyterhub-bot](https://github.com/jupyterhub-bot), [@manics](https://github.com/manics)) +- Update oauthenticator from 16.0.7 to 16.1.0, and kubespawner from 6.0.0 to 6.1.0 [#3234](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3234) ([@jupyterhub-bot](https://github.com/jupyterhub-bot), [@consideRatio](https://github.com/consideRatio)) +- Update kubernetes_asyncio from 25.11.0 to 26.9.0 [#3233](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3233) ([@jupyterhub-bot](https://github.com/jupyterhub-bot), [@consideRatio](https://github.com/consideRatio)) +- Update kubernetes_asyncio from 24.2.3 to 25.11.0 [#3228](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3228) ([@jupyterhub-bot](https://github.com/jupyterhub-bot), [@consideRatio](https://github.com/consideRatio)) + +#### Documentation improvements + +- docs: fix changelog date entry for 3.0.3 [#3211](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3211) ([@consideRatio](https://github.com/consideRatio)) + +#### Contributors to this release + +The following people contributed discussions, new ideas, code and documentation contributions, and review. +See [our definition of contributors](https://github-activity.readthedocs.io/en/latest/#how-does-this-tool-define-contributions-in-the-reports). + +([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2023-08-29&to=2023-09-29&type=c)) + +@consideRatio ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2023-08-29..2023-09-29&type=Issues)) | @manics ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2023-08-29..2023-09-29&type=Issues)) | @shaneknapp ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ashaneknapp+updated%3A2023-08-29..2023-09-29&type=Issues)) | @yuvipanda ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ayuvipanda+updated%3A2023-08-29..2023-09-29&type=Issues)) + +## 3.0 + +### 3.0.3 - 2023-08-29 + +Includes a bugfix from the OAuthenticator project for users of +GoogleOAuthenticator with `hosted_domain` and `admin_users` configured. See the +[oauthenticator changelog] for details. + +#### Bugs fixed + +- Update oauthenticator from 16.0.6 to 16.0.7 [#3207](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3207) ([@jupyterhub-bot](https://github.com/jupyterhub-bot), [@consideRatio](https://github.com/consideRatio)) + +### 3.0.2 - 2023-08-17 + +Includes a bugfix from the OAuthenticator project for users that have +`enable_auth_state` enabled with the Google, Globus, or BitBucket OAuthenticator +class. See the [oauthenticator changelog] for details. + +#### Bugs fixed + +- Update oauthenticator from 16.0.5 to 16.0.6 [#3203](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3203) ([@jupyterhub-bot](https://github.com/jupyterhub-bot), [@consideRatio](https://github.com/consideRatio)) + +### 3.0.1 - 2023-08-15 + +#### Bugs fixed + +- Update oauthenticator from 16.0.4 to 16.0.5 and tornado from 6.3.2 to 6.3.3 [#3199](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3199) ([@jupyterhub-bot](https://github.com/jupyterhub-bot), [@consideRatio](https://github.com/consideRatio)) + +#### Documentation improvements + +- docs: fix the jupyterhub managed service example's networking rules [#3200](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3200) ([@Ph0tonic](https://github.com/Ph0tonic), [@consideRatio](https://github.com/consideRatio)) + +#### Contributors to this release + +The following people contributed discussions, new ideas, code and documentation contributions, and review. +See [our definition of contributors](https://github-activity.readthedocs.io/en/latest/#how-does-this-tool-define-contributions-in-the-reports). + +([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2023-08-11&to=2023-08-15&type=c)) + +@consideRatio ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2023-08-11..2023-08-15&type=Issues)) | @Ph0tonic ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3APh0tonic+updated%3A2023-08-11..2023-08-15&type=Issues)) + +### 3.0.0 - 2023-08-11 + +This release updates JupyterHub itself and several dependencies to a new major +version, please read the breaking changes below before upgrading. + +```{warning} Breaking changes since beta releases +Since 3.0.0-beta.1 OAuthenticator was upgraded, and since 3.0.0-beta.3 default +networking rules related to establishing connections to DNS ports changed +slightly. +``` + +#### Breaking changes + +- K8s 1.23 is now required. +- The Helm chart's provided images now use Python 3.11 instead of Python 3.9. +- JupyterHub 3.0.0 is upgraded to 4.0.2. + - Please refer to the [JupyterHub changelog] for details, but note that this + upgrade doesn't require user servers to be restarted or that the user + environments have version 4 of `jupyterhub` (PyPI) or `jupyterhub-base` + (conda-forge). +- KubeSpawner 4.2.0 is upgraded to 6.0.0 + - Please read to the [KubeSpawner changelog]'s breaking changes and be aware + that configuring [`singleuser.extraEnv`](schema_singleuser.extraEnv) is to + configure `KubeSpawner.environment`, and to configure + [`singleuser.profileList`](schema_singleuser.profileList) is to configure + `KubeSpawner.profile_list`. +- OAuthenticator 15.1.0 is upgraded to 16.0.4. + - If you are using a JupyterHub Authenticator class from this project, please + read to the [OAuthenticator changelog]'s breaking changes before upgrading + this Helm chart. +- TmpAuthenticator 0.6 is upgraded to 1.0.0 + - If you are using this JupyterHub Authenticator class, please read to the + [TmpAuthenticator changelog]'s breaking changes before upgrading this Helm + chart. +- Predefined NetworkPolicy egress allow rules + [`dnsPortsCloudMetadataServer`](schema_hub.networkPolicy.egressAllowRules.dnsPortsCloudMetadataServer) + and + [`dnsPortsKubeSystemNamespace`](schema_hub.networkPolicy.egressAllowRules.dnsPortsKubeSystemNamespace) + are introduced and enabled by default for the chart's NetworkPolicy resources. + +[jupyterhub changelog]: https://jupyterhub.readthedocs.io/en/stable/changelog.html +[kubespawner changelog]: https://jupyterhub-kubespawner.readthedocs.io/en/stable/changelog.html +[oauthenticator changelog]: https://oauthenticator.readthedocs.io/en/stable/reference/changelog.html +[tmpauthenticator changelog]: https://jupyterhub-kubespawner.readthedocs.io/en/stable/changelog.html + +#### Notable dependencies updated + +| Dependency | Version in 2.0.0 | Version in 3.0.0 | Changelog link | Note | +| -------------------------------------------------------------------------------- | ---------------- | ---------------- | ----------------------------------------------------------------------------------------- | ---------------------------------- | +| [jupyterhub](https://github.com/jupyterhub/jupyterhub) | 3.0.0 | 4.0.2 | [Changelog](https://jupyterhub.readthedocs.io/en/stable/reference/changelog.html) | Run in the `hub` pod | +| [kubespawner](https://github.com/jupyterhub/kubespawner) | 4.2.0 | 6.0.0 | [Changelog](https://jupyterhub-kubespawner.readthedocs.io/en/stable/changelog.html) | Run in the `hub` pod | +| [oauthenticator](https://github.com/jupyterhub/oauthenticator) | 15.1.0 | 16.0.4 | [Changelog](https://oauthenticator.readthedocs.io/en/stable/reference/changelog.html) | Run in the `hub` pod | +| [ldapauthenticator](https://github.com/jupyterhub/ldapauthenticator) | 1.3.2 | 1.3.2 | [Changelog](https://github.com/jupyterhub/ldapauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [ltiauthenticator](https://github.com/jupyterhub/ltiauthenticator) | 1.2.0 | 1.6.1 | [Changelog](https://github.com/jupyterhub/ltiauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [nativeauthenticator](https://github.com/jupyterhub/nativeauthenticator) | 1.1.0 | 1.2.0 | [Changelog](https://github.com/jupyterhub/nativeauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [tmpauthenticator](https://github.com/jupyterhub/tmpauthenticator) | 0.6 | 1.0.0 | [Changelog](https://github.com/jupyterhub/tmpauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [jupyterhub-idle-culler](https://github.com/jupyterhub/jupyterhub-idle-culler) | 1.2.1 | 1.2.1 | [Changelog](https://github.com/jupyterhub/jupyterhub-idle-culler/blob/main/CHANGELOG.md) | Run in the `hub` pod | +| [configurable-http-proxy](https://github.com/jupyterhub/configurable-http-proxy) | 4.5.3 | 4.5.6 | [Changelog](https://github.com/jupyterhub/configurable-http-proxy/blob/HEAD/CHANGELOG.md) | Run in the `proxy` pod | +| [traefik](https://github.com/traefik/traefik) | v2.8.4 | v2.10.4 | [Changelog](https://github.com/traefik/traefik/blob/HEAD/CHANGELOG.md) | Run in the `autohttps` pod | +| [kube-scheduler](https://github.com/kubernetes/kube-scheduler) | v1.23.10 | v1.26.7 | [Changelog](https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG) | Run in the `user-scheduler` pod(s) | + +For a detailed list of Python dependencies in the `hub` Pod's Docker image, +inspect the [images/hub/requirements.txt] file and use its git history to see +what changes between tagged versions. + +[images/hub/requirements.txt]: https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/images/hub/requirements.txt + +#### New features added + +- Add and enable two egressAllowRules to ensure DNS access [#3179](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3179) ([@consideRatio](https://github.com/consideRatio), [@yuvipanda](https://github.com/yuvipanda), [@vizeit](https://github.com/vizeit)) +- Add a jupyterhub/k8s-hub-slim image alongside jupyterhub/k8s-hub [#2920](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2920) ([@consideRatio](https://github.com/consideRatio)) + +#### Enhancements made + +- Allow `enabled` config, for use by charts depending on this chart conditionally [#3162](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3162) ([@monoakg](https://github.com/monoakg), [@consideRatio](https://github.com/consideRatio), [@manics](https://github.com/manics)) + +#### Bugs fixed + +- Fix bugs related to installing chart multiple times in the same namespace [#3032](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3032) ([@HoseonRyu](https://github.com/HoseonRyu)) + +#### Maintenance and upkeep improvements + +- maint: restrict allowed config with blockWithIpTables, add misc docs [#3192](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3192) ([@consideRatio](https://github.com/consideRatio), [@minrk](https://github.com/minrk)) +- Update kubespawner 5.0.0 to 6.0.0, tmpauthenticator 0.6 to 1.0.0, nativeauthenticator 1.2.0 to 1.2.1, ltiauthenticator 1.5.0 to 1.5.1 [#3129](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3129) ([@jupyterhub-bot](https://github.com/jupyterhub-bot)) +- Update kube-scheduler in user-scheduler from 1.25.9 to 1.26.4 [#3114](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3114) ([@consideRatio](https://github.com/consideRatio)) +- Bump to kubespawner 5.0.0 and tornado 6.3 [#3095](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3095) ([@jupyterhub-bot](https://github.com/jupyterhub-bot)) +- Drop support for k8s 1.22 [#3092](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3092) ([@consideRatio](https://github.com/consideRatio)) +- refactor: rename schema.yaml to values.schema.yaml [#3090](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3090) ([@consideRatio](https://github.com/consideRatio)) +- dependabot: monthly updates of github actions [#3085](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3085) ([@consideRatio](https://github.com/consideRatio)) +- Bump to 3.0.0-0.dev [#3084](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3084) ([@yuvipanda](https://github.com/yuvipanda)) +- Refactor of image-awaiter's dockerfile [#3078](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3078) ([@alekseyolg](https://github.com/alekseyolg)) +- compile psycopg2 in hub image [#3066](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3066) ([@minrk](https://github.com/minrk)) +- satisfy flake8 in jupyterhub_config.py [#3065](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3065) ([@minrk](https://github.com/minrk)) +- Update jupyterhub from 3.1.1 to 4.0.0b1 [#3045](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3045) ([@jupyterhub-bot](https://github.com/jupyterhub-bot)) +- Drop support for k8s 1.21 [#3041](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3041) ([@consideRatio](https://github.com/consideRatio)) +- pre-commit: add flake8 and fix details [#2940](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2940) ([@consideRatio](https://github.com/consideRatio)) +- Drop support for k8s 1.20 [#2936](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2936) ([@consideRatio](https://github.com/consideRatio)) +- Upgrade from python 3.9 to 3.11 in hub and singleuser-sample for performance [#2919](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2919) ([@yuvipanda](https://github.com/yuvipanda)) +- Switch from deprecated k8s.gcr.io to registry.k8s.io [#2910](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2910) ([@consideRatio](https://github.com/consideRatio)) +- secret sync image: use python 3.9 [#2886](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2886) ([@consideRatio](https://github.com/consideRatio)) +- values.yaml: fix link to configurable-http-proxy releases [#2881](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2881) ([@manics](https://github.com/manics)) + +#### Documentation improvements + +- Add deprecation warning for `kube-lego` (https certificates) [#3186](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3186) ([@Ph0tonic](https://github.com/Ph0tonic), [@consideRatio](https://github.com/consideRatio)) +- docs: let auth docs link to authenticator specific docs [#3151](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3151) ([@consideRatio](https://github.com/consideRatio)) +- Enhance keycloak configuration example [#3142](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3142) ([@LucasVanHaaren](https://github.com/LucasVanHaaren)) +- Show default value in configuration reference [#3138](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3138) ([@manics](https://github.com/manics)) +- Helm chart url has changed [#3122](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3122) ([@manics](https://github.com/manics)) +- Remove double word cluster in installation.md [#3119](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3119) ([@cbowman0](https://github.com/cbowman0)) +- Clarify `hub.config` can configure KubeSpawner and more [#3104](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3104) ([@JunaidChaudry](https://github.com/JunaidChaudry)) +- docs: fix readme badge for tests [#3094](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3094) ([@consideRatio](https://github.com/consideRatio)) +- doc: singleuser.uid default is always 1000 [#3079](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3079) ([@manics](https://github.com/manics)) +- Replace IEC prefixes link [#3073](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3073) ([@manics](https://github.com/manics)) +- DOC: Fix invalid names in configuration examples [#3069](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3069) ([@ChristofKaufmann](https://github.com/ChristofKaufmann)) +- Replace microk8s with generic self-hosted doc [#3055](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3055) ([@manics](https://github.com/manics)) +- Revert https://app.gitter.im/#/room/#jupyterhub_jupyterhub:gitter.im … [#3050](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3050) ([@manics](https://github.com/manics)) +- Use jupyterhub docs `stable` instead of `latest` [#3049](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3049) ([@manics](https://github.com/manics)) +- docs: Replace most permanent-redirects from linkcheck [#3048](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3048) ([@manics](https://github.com/manics)) +- docs: user-env default image is not base-image [#3047](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3047) ([@manics](https://github.com/manics)) +- Fix broken link [#3020](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3020) ([@xcompass](https://github.com/xcompass)) +- docs: Update custom image docs to reflect root requirement [#3003](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3003) ([@pnasrat](https://github.com/pnasrat)) +- Documentation fix for running k8s-singleuser-sample locally [#3002](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3002) ([@pnasrat](https://github.com/pnasrat)) +- note at line 554 did not render correctly [#2987](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2987) ([@aaronjnewman](https://github.com/aaronjnewman)) +- docs: AWS master node size needs to be larger than micro [#2956](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2956) ([@arunppsg](https://github.com/arunppsg)) +- docs: update of readthedocs config and docs/source/conf.py [#2909](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2909) ([@consideRatio](https://github.com/consideRatio)) +- docs: Remove unreleased reverted change from 2.0.0 release changelog [#2893](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2893) ([@Uular](https://github.com/Uular)) +- docs: fix git sha lookup for dev builds [#2879](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2879) ([@manics](https://github.com/manics)) +- docs: remove /auth from keycloak URLs [#2878](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2878) ([@manics](https://github.com/manics)) +- docs: auth defaults to dummy [#2877](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2877) ([@manics](https://github.com/manics)) +- docs: backfill early changelog entries based on git tags and github releases [#2862](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2862) ([@consideRatio](https://github.com/consideRatio)) + +#### Continuous integration improvements + +- ci: fix deprecation of set-output and use ubuntu 22.04 and py311 [#3068](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3068) ([@consideRatio](https://github.com/consideRatio)) +- Summarise linkcheck CI output [#3051](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3051) ([@manics](https://github.com/manics)) +- ci: fix for redirect to hub.jupyter.org [#3015](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3015) ([@consideRatio](https://github.com/consideRatio)) +- ci: fix vuln-scan regression following set-output deprecation [#2984](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2984) ([@consideRatio](https://github.com/consideRatio)) +- ci: fix deprecation of set-output in github workflows [#2943](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2943) ([@consideRatio](https://github.com/consideRatio)) +- ci: minimize yamllint-config.yaml's complexity [#2939](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2939) ([@consideRatio](https://github.com/consideRatio)) +- ci: minor refactoring/updates of tools [#2938](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2938) ([@consideRatio](https://github.com/consideRatio)) +- ci: bump docker action versions to v2 from v2.x.y [#2914](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2914) ([@consideRatio](https://github.com/consideRatio)) +- ci: enable buildkit for vuln scan workflow as needed for --mount [#2885](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2885) ([@consideRatio](https://github.com/consideRatio)) +- ci: Auto-create GitHub release when repo is tagged [#2883](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2883) ([@manics](https://github.com/manics)) + +#### Contributors to this release + +The following people contributed discussions, new ideas, code and documentation contributions, and review. +See [our definition of contributors](https://github-activity.readthedocs.io/en/latest/#how-does-this-tool-define-contributions-in-the-reports). + +([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2022-09-09&to=2023-08-11&type=c)) + +@aaronjnewman ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aaaronjnewman+updated%3A2022-09-09..2023-08-11&type=Issues)) | @alekseyolg ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aalekseyolg+updated%3A2022-09-09..2023-08-11&type=Issues)) | @arunppsg ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aarunppsg+updated%3A2022-09-09..2023-08-11&type=Issues)) | @betatim ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abetatim+updated%3A2022-09-09..2023-08-11&type=Issues)) | @bjornjorgensen ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abjornjorgensen+updated%3A2022-09-09..2023-08-11&type=Issues)) | @cbowman0 ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acbowman0+updated%3A2022-09-09..2023-08-11&type=Issues)) | @choldgraf ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acholdgraf+updated%3A2022-09-09..2023-08-11&type=Issues)) | @ChristofKaufmann ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AChristofKaufmann+updated%3A2022-09-09..2023-08-11&type=Issues)) | @consideRatio ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2022-09-09..2023-08-11&type=Issues)) | @dasantonym ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adasantonym+updated%3A2022-09-09..2023-08-11&type=Issues)) | @DeepSkyWonder ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ADeepSkyWonder+updated%3A2022-09-09..2023-08-11&type=Issues)) | @ebebpl ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aebebpl+updated%3A2022-09-09..2023-08-11&type=Issues)) | @HoseonRyu ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AHoseonRyu+updated%3A2022-09-09..2023-08-11&type=Issues)) | @iandesj ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aiandesj+updated%3A2022-09-09..2023-08-11&type=Issues)) | @IceS2 ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AIceS2+updated%3A2022-09-09..2023-08-11&type=Issues)) | @JunaidChaudry ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AJunaidChaudry+updated%3A2022-09-09..2023-08-11&type=Issues)) | @jupyterhub-bot ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajupyterhub-bot+updated%3A2022-09-09..2023-08-11&type=Issues)) | @kanor1306 ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Akanor1306+updated%3A2022-09-09..2023-08-11&type=Issues)) | @LucasVanHaaren ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ALucasVanHaaren+updated%3A2022-09-09..2023-08-11&type=Issues)) | @manics ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2022-09-09..2023-08-11&type=Issues)) | @mathbunnyru ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amathbunnyru+updated%3A2022-09-09..2023-08-11&type=Issues)) | @mdlincoln ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amdlincoln+updated%3A2022-09-09..2023-08-11&type=Issues)) | @minrk ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aminrk+updated%3A2022-09-09..2023-08-11&type=Issues)) | @monoakg ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amonoakg+updated%3A2022-09-09..2023-08-11&type=Issues)) | @Ph0tonic ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3APh0tonic+updated%3A2022-09-09..2023-08-11&type=Issues)) | @pnasrat ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Apnasrat+updated%3A2022-09-09..2023-08-11&type=Issues)) | @Uular ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AUular+updated%3A2022-09-09..2023-08-11&type=Issues)) | @vizeit ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Avizeit+updated%3A2022-09-09..2023-08-11&type=Issues)) | @xcompass ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Axcompass+updated%3A2022-09-09..2023-08-11&type=Issues)) | @yuvipanda ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ayuvipanda+updated%3A2022-09-09..2023-08-11&type=Issues)) + +## 2.0 + +### 2.0.0 - 2022-09-09 + +#### Highlights + +Z2JH 2.0.0 is the first major release since 1.0.0 was released in June 2021, and contains major upgrades to all JupyterHub components, including a jump directly from JupyterHub 1 to JupyterHub 3. + +JupyterHub 2 and 3 includes new RBAC support allowing fine-grained access control to hub services and servers. + +JupyterLab, the next-generation Notebook interface, is now the default interface seen by users. This brings a full development environment with a large number of extensions developed by the Jupyter community. + +This release also includes several smaller changes that help Z2JH interface better with the rest of the Jupyter community such as not overriding a Docker image's command, and using standard Helm chart parameter names to match with other Helm charts. +Although these are breaking changes they will greatly improve the maintainability of the JupyterHub chart in future, and should also make it easier for new users to get started. + +#### Security: breaking change to `*.networkPolicy.egress` + +If you have configured any of: + +- `hub.networkPolicy.egress` +- `proxy.chp.networkPolicy.egress` +- `proxy.traefik.networkPolicy.egress` +- `singleuser.networkPolicy.egress` + +you must review your configuration as additional default egress routes have been added. +See [](upgrade-1-2-security-breaking-change) for details. + +#### Upgrade instructions + +Please read through all breaking changes, then follow the [upgrading guide](administrator/upgrading/index). + +#### Breaking changes + +These breaking changes have been made relative to the 1.\* series of Z2JH releases: + +- Security: breaking change to `*.networkPolicy.egress` +- JupyterHub upgraded from 1.x to 3.x along with related hub components +- JupyterLab and Jupyter Server is now the default singleuser application +- Configuration in `jupyterhub_config.d` has a higher priority than `hub.config` [#2457](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2457) +- User scheduler plugin configuration has changed to match `kubescheduler.config.k8s.io/v1beta3` [#2590](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2590) +- Kubernetes version 1.20+ is required [#2635](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2635) +- `hub.fsGid` is replaced by `hub.podSecurityContext` [#2720](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2720) +- Hub image is based on Debian instead of Ubuntu [#2733](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2733) +- Disabling RBAC requires setting multiple properties, `rbac.enable` is removed [#2736](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2736) [#2739](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2739) + +For information on how to update your configuration see the [](administrator/upgrading/upgrade-1-to-2) guide. + +(notable-dependencies-200)= + +#### Notable dependencies updated + +| Dependency | Version in 1.2.0 | Version in 2.0.0 | Changelog link | Note | +| -------------------------------------------------------------------------------- | ---------------- | ---------------- | ----------------------------------------------------------------------------------------- | ---------------------------------- | +| [jupyterhub](https://github.com/jupyterhub/jupyterhub) | 1.4.2 | 3.0.0 | [Changelog](https://jupyterhub.readthedocs.io/en/stable/changelog.html) | Run in the `hub` pod | +| [kubespawner](https://github.com/jupyterhub/kubespawner) | 1.1.0 | 4.2.0 | [Changelog](https://jupyterhub-kubespawner.readthedocs.io/en/latest/changelog.html) | Run in the `hub` pod | +| [oauthenticator](https://github.com/jupyterhub/oauthenticator) | 14.2.0 | 15.1.0 | [Changelog](https://oauthenticator.readthedocs.io/en/latest/changelog.html) | Run in the `hub` pod | +| [ldapauthenticator](https://github.com/jupyterhub/ldapauthenticator) | 1.3.2 | 1.3.2 | [Changelog](https://github.com/jupyterhub/ldapauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [ltiauthenticator](https://github.com/jupyterhub/ltiauthenticator) | 1.0.0 | 1.2.0 | [Changelog](https://github.com/jupyterhub/ltiauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [nativeauthenticator](https://github.com/jupyterhub/nativeauthenticator) | 0.0.7 | 1.1.0 | [Changelog](https://github.com/jupyterhub/nativeauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [jupyterhub-idle-culler](https://github.com/jupyterhub/jupyterhub-idle-culler) | 1.1 | 1.2.1 | [Changelog](https://github.com/jupyterhub/jupyterhub-idle-culler/blob/main/CHANGELOG.md) | Run in the `hub` pod | +| [configurable-http-proxy](https://github.com/jupyterhub/configurable-http-proxy) | 4.5.0 | 4.5.3 | [Changelog](https://github.com/jupyterhub/configurable-http-proxy/blob/HEAD/CHANGELOG.md) | Run in the `proxy` pod | +| [traefik](https://github.com/traefik/traefik) | v2.4.11 | v2.8.4 | [Changelog](https://github.com/traefik/traefik/blob/HEAD/CHANGELOG.md) | Run in the `autohttps` pod | +| [kube-scheduler](https://github.com/kubernetes/kube-scheduler) | v1.19.13 | v1.23.10 | - | Run in the `user-scheduler` pod(s) | + +For a detailed list of Python dependencies in the `hub` Pod's Docker image, inspect the [images/hub/requirements.txt](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/images/hub/requirements.txt) file and use its git history to see what changes between tagged versions. + +#### New features added + +- Add `labels` config for `scheduling.userScheduler`, `scheduling.userPlaceholder`, and `prePuller` [#2791](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2791) ([@ruben-rodriguez](https://github.com/ruben-rodriguez)) +- Add scheduling.userScheduler.annotations [#2763](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2763) ([@joncotton](https://github.com/joncotton)) +- Add scheduling.userPlaceholder.annotations [#2762](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2762) ([@joncotton](https://github.com/joncotton)) +- Add `.create` and `.name` to serviceAccount config, and decouple `rbac.enable` from the service accounts [#2736](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2736) ([@dingobar](https://github.com/dingobar), [@consideRatio](https://github.com/consideRatio), [@desaintmartin](https://github.com/desaintmartin)) +- breaking: add hub.podSecurityContext, remove hub.fsGid [#2720](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2720) ([@consideRatio](https://github.com/consideRatio), [@yuvipanda](https://github.com/yuvipanda)) +- Add singleuser.allowPrivilegeEscalation for KubeSpawner 2+ [#2713](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2713) ([@consideRatio](https://github.com/consideRatio), [@yuvipanda](https://github.com/yuvipanda)) +- Add `proxy.traefik.extraInitContainers` config [#2670](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2670) ([@gregingenii](https://github.com/gregingenii), [@yuvipanda](https://github.com/yuvipanda)) +- Support idle culler --cull-admin-users [#2578](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2578) ([@manics](https://github.com/manics), [@consideRatio](https://github.com/consideRatio)) +- Unset `singleuser.cmd`, previously `jupyterhub-singleuser`, to instead rely on the image's CMD by default [#2449](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2449) ([@minrk](https://github.com/minrk), [@consideRatio](https://github.com/consideRatio), [@manics](https://github.com/manics), [@meeseeksmachine](https://github.com/meeseeksmachine)) + +#### Enhancements made + +- Enable parent chart's (binderhub etc) to use imagePullSecrets helper [#2546](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2546) ([@consideRatio](https://github.com/consideRatio), [@manics](https://github.com/manics)) +- Add hub.loadRoles configuration [#2405](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2405) ([@consideRatio](https://github.com/consideRatio), [@manics](https://github.com/manics)) +- Add ingress.ingressClassName config option [#2403](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2403) ([@consideRatio](https://github.com/consideRatio)) + +#### Bugs fixed + +- Fix user-scheduler backward compatibility for AWS EKS [#2807](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2807) ([@a3626a](https://github.com/a3626a)) +- Fix for PDBs in k8s 1.20 [#2727](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2727) ([@consideRatio](https://github.com/consideRatio), [@geoffo-dev](https://github.com/geoffo-dev)) +- Enable image-puller pods to evict user-placeholder pods [#2681](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2681) ([@consideRatio](https://github.com/consideRatio), [@yuvipanda](https://github.com/yuvipanda), [@a3626a](https://github.com/a3626a)) +- Fix failure to respect proxy.secretSync.resources configuration [#2628](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2628) ([@jhowton-restor3d](https://github.com/jhowton-restor3d), [@consideRatio](https://github.com/consideRatio)) +- Remove typo " in schema.yaml [#2603](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2603) ([@manics](https://github.com/manics), [@consideRatio](https://github.com/consideRatio)) +- match config load priority for jupyterhub_config.d files and hub.extraConfig [#2457](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2457) ([@minrk](https://github.com/minrk), [@consideRatio](https://github.com/consideRatio), [@MLobo1997](https://github.com/MLobo1997)) +- idle-culler: fix the new restricted scopes to include read:servers [#2446](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2446) ([@consideRatio](https://github.com/consideRatio), [@snickell](https://github.com/snickell)) +- Add config singleuser.networkTools.resources - all containers must have configurable resources [#2439](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2439) ([@consideRatio](https://github.com/consideRatio)) +- Fix implementation of restricted scopes for jupyterhub-idle-culler [#2434](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2434) ([@consideRatio](https://github.com/consideRatio)) +- Fix proxy pod's liveness/readiness probes to be fully configurable [#2421](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2421) ([@consideRatio](https://github.com/consideRatio), [@mriedem](https://github.com/mriedem)) + +#### Maintenance and upkeep improvements + +- hub image: remove workaround for ruamel.yaml.clib on aarch64 [#2846](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2846) ([@consideRatio](https://github.com/consideRatio)) +- Make the singleuser-sample image use python:3.9-slim-bullseye as a base image to retain arm64 support [#2845](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2845) ([@minrk](https://github.com/minrk)) +- Restore jupyterhub-singleuser as the default command [#2820](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2820) ([@minrk](https://github.com/minrk)) + - Reverted unreleased breaking change: Default to using the container image's command instead of `jupyterhub-singleuser` [#2449](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2449) +- Adjust kerning on large JupyterHub in NOTES.txt [#2787](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2787) ([@manics](https://github.com/manics)) +- hub image: remove wheel building aarch64 workaround for pycryptodomex [#2766](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2766) ([@consideRatio](https://github.com/consideRatio)) +- hub image: downgrade to ltiauthenticator 1.2.0 [#2741](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2741) ([@consideRatio](https://github.com/consideRatio)) +- breaking, maint: replace rbac.enabled with rbac.create [#2739](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2739) ([@consideRatio](https://github.com/consideRatio), [@yuvipanda](https://github.com/yuvipanda)) +- breaking: hub image ubuntu->debian, py38->py39, `build-essential` removed, `--build-arg PIP_OVERRIDES=...` removed, images/hub/dependencies removed [#2733](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2733) ([@consideRatio](https://github.com/consideRatio), [@yuvipanda](https://github.com/yuvipanda), [@minrk](https://github.com/minrk)) +- maint: update import statement for py310 compatibility [#2732](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2732) ([@consideRatio](https://github.com/consideRatio)) +- maint: add pre-commit isort hook, and let pyupgrade assume py38+ in hub container [#2730](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2730) ([@consideRatio](https://github.com/consideRatio), [@yuvipanda](https://github.com/yuvipanda)) +- Bump versions of image-awaiter dependencies [#2725](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2725) ([@yuvipanda](https://github.com/yuvipanda), [@consideRatio](https://github.com/consideRatio)) +- maint: cleanup deprecation warning introduced in 0.10.0 (assume users upgrade to v2 from v1) [#2719](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2719) ([@consideRatio](https://github.com/consideRatio)) +- Update pause version from 3.6 to 3.7 [#2700](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2700) ([@github-actions](https://github.com/github-actions), [@consideRatio](https://github.com/consideRatio)) +- Update kube-scheduler version from v1.23.4 to v1.23.6 [#2699](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2699) ([@github-actions](https://github.com/github-actions), [@consideRatio](https://github.com/consideRatio)) +- Update library/traefik version to v2.6.6 [#2695](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2695) ([@github-actions](https://github.com/github-actions), [@consideRatio](https://github.com/consideRatio)) +- Require k8s 1.20+ and small cleanups based on assuming it [#2635](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2635) ([@consideRatio](https://github.com/consideRatio), [@yuvipanda](https://github.com/yuvipanda)) +- Use chart logo from https://jupyterhub.github.io/helm-chart [#2604](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2604) ([@manics](https://github.com/manics), [@consideRatio](https://github.com/consideRatio)) +- Update user-scheduler's kube-scheduler binary and config when in k8s clusters versioned >=1.21 [#2590](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2590) ([@consideRatio](https://github.com/consideRatio), [@manics](https://github.com/manics)) +- image-awaiter: fix known vulns. by updating to golang:1.17 in image build stage [#2562](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2562) ([@nreith](https://github.com/nreith), [@consideRatio](https://github.com/consideRatio)) +- Improved nodeSelector formatting in template [#2554](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2554) ([@ostapkonst](https://github.com/ostapkonst), [@consideRatio](https://github.com/consideRatio)) +- Remove workaround to have PriorityClass resources as helm hooks [#2526](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2526) ([@consideRatio](https://github.com/consideRatio)) +- deps: update traefik, kube-scheduler, and pause image [#2524](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2524) ([@consideRatio](https://github.com/consideRatio)) +- refactor: move doc to docs, use \_build instead of build [#2521](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2521) ([@consideRatio](https://github.com/consideRatio), [@manics](https://github.com/manics)) +- breaking: add ...networkPolicy.egressAllowRules and don't allow singleuser pods to access PrivateIPv4 addresses by default [#2508](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2508) ([@yuvipanda](https://github.com/yuvipanda), [@consideRatio](https://github.com/consideRatio), [@manics](https://github.com/manics), [@minrk](https://github.com/minrk), [@choldgraf](https://github.com/choldgraf)) +- Update with changes introduced in 1.1.4 security patch [#2459](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2459) ([@consideRatio](https://github.com/consideRatio), [@minrk](https://github.com/minrk)) +- Add missing default values for proxy pod's probes [#2423](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2423) ([@consideRatio](https://github.com/consideRatio), [@mriedem](https://github.com/mriedem)) +- Update NOTES.txt [#2411](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2411) ([@consideRatio](https://github.com/consideRatio), [@yuvipanda](https://github.com/yuvipanda)) +- Use f-strings instead of the % pattern [#2408](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2408) ([@consideRatio](https://github.com/consideRatio), [@manics](https://github.com/manics)) +- Remove breaking change messages relevant for upgrading to 1.0.0 [#2397](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2397) ([@consideRatio](https://github.com/consideRatio), [@yuvipanda](https://github.com/yuvipanda)) +- Pin jupyterhub==2.0.0b1 and refreeze dependencies [#2396](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2396) ([@consideRatio](https://github.com/consideRatio)) +- Tighten permissions for jupyterhub-idle-culler [#2395](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2395) ([@consideRatio](https://github.com/consideRatio), [@minrk](https://github.com/minrk), [@manics](https://github.com/manics)) +- pre-commit: add and run pyupgrade [#2394](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2394) ([@consideRatio](https://github.com/consideRatio)) + +#### Documentation improvements + +- Update docs to reflect Azure 2022 process [#2823](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2823) ([@Sieboldianus](https://github.com/Sieboldianus)) +- Fix step-zero-ovh 404 [#2821](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2821) ([@manics](https://github.com/manics)) +- docs: fix misc link redirects [#2816](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2816) ([@consideRatio](https://github.com/consideRatio)) +- Replace jhub with for consistency [#2815](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2815) ([@rickwierenga](https://github.com/rickwierenga)) +- Add breaking KubeSpawner changes to upgrade-1-to-2 [#2810](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2810) ([@manics](https://github.com/manics)) +- docs: fix most broken links in changelog [#2790](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2790) ([@consideRatio](https://github.com/consideRatio)) +- Fix `redirected permanently` linkcheck apart from changelog [#2789](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2789) ([@manics](https://github.com/manics)) +- 2.0.0 upgrade guide [#2779](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2779) ([@manics](https://github.com/manics)) +- docs: remove broken links and use https over http in a few [#2775](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2775) ([@consideRatio](https://github.com/consideRatio)) +- docs: transition rST based glossary to MyST [#2770](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2770) ([@consideRatio](https://github.com/consideRatio)) +- docs: move changelog from pure markdown to sphinx based docs [#2769](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2769) ([@consideRatio](https://github.com/consideRatio)) +- docs: update notes about building wheels in build stage [#2742](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2742) ([@consideRatio](https://github.com/consideRatio)) +- Fix link to authentication guide when viewed via GitHub's UI [#2740](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2740) ([@jdmcbr](https://github.com/jdmcbr), [@consideRatio](https://github.com/consideRatio)) +- Add opengraph tags [#2717](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2717) ([@manics](https://github.com/manics), [@consideRatio](https://github.com/consideRatio), [@choldgraf](https://github.com/choldgraf)) +- docs: how to adjust profile_list dynamically based on user etc [#2697](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2697) ([@consideRatio](https://github.com/consideRatio), [@choldgraf](https://github.com/choldgraf)) +- `proxy.service.type`: link directly to k8s docs [#2672](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2672) ([@manics](https://github.com/manics), [@consideRatio](https://github.com/consideRatio)) +- docs: Remove a false promise regarding CHOWN_HOME [#2640](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2640) ([@dmigo](https://github.com/dmigo), [@yuvipanda](https://github.com/yuvipanda)) +- update step-zero-microk8s.md [#2630](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2630) ([@theomper](https://github.com/theomper), [@minrk](https://github.com/minrk)) +- Fix broken internal references in docs [#2600](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2600) ([@consideRatio](https://github.com/consideRatio)) +- docs: fix syntax error in note directive [#2568](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2568) ([@sunu](https://github.com/sunu), [@consideRatio](https://github.com/consideRatio)) +- Corrected datascience to Data Science. [#2560](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2560) ([@Adam-Antios](https://github.com/Adam-Antios), [@consideRatio](https://github.com/consideRatio)) +- docs: fix broken anchor in link [#2547](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2547) ([@consideRatio](https://github.com/consideRatio)) +- Use chart logo from this repo [#2544](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2544) ([@manics](https://github.com/manics), [@consideRatio](https://github.com/consideRatio)) +- Replace zone to allowedTopologies [#2543](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2543) ([@kindomLee](https://github.com/kindomLee), [@consideRatio](https://github.com/consideRatio)) +- DOC: Expand IAM abbreviation for comprehensibility [#2535](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2535) ([@raybellwaves](https://github.com/raybellwaves), [@consideRatio](https://github.com/consideRatio)) +- Don't pin example jupyter/minimal-notebook [#2522](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2522) ([@manics](https://github.com/manics), [@consideRatio](https://github.com/consideRatio)) +- Link to Discourse instead of the mailing list [#2519](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2519) ([@manics](https://github.com/manics), [@consideRatio](https://github.com/consideRatio)) +- DOC: add extra AWS ssh info [#2518](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2518) ([@raybellwaves](https://github.com/raybellwaves), [@manics](https://github.com/manics), [@consideRatio](https://github.com/consideRatio)) +- docs: document `singleuser.someConfig` by linking to `KubeSpawner.some_config` docs [#2517](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2517) ([@manics](https://github.com/manics), [@consideRatio](https://github.com/consideRatio)) +- Document how to disable some labextensions with config [#2516](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2516) ([@yuvipanda](https://github.com/yuvipanda), [@consideRatio](https://github.com/consideRatio)) +- DOC: instructions for role creation in AWS [#2514](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2514) ([@raybellwaves](https://github.com/raybellwaves), [@consideRatio](https://github.com/consideRatio)) +- Update MetalLB section in step-zero-microk8s.md [#2511](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2511) ([@wyphan](https://github.com/wyphan), [@consideRatio](https://github.com/consideRatio)) +- Fix docs typo [#2489](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2489) ([@mriedem](https://github.com/mriedem), [@consideRatio](https://github.com/consideRatio)) +- Add changelog for 1.2.0 [#2480](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2480) ([@consideRatio](https://github.com/consideRatio)) +- docs: fix syntax errors with directives [#2478](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2478) ([@consideRatio](https://github.com/consideRatio)) +- docs: fix failure to show correct version [#2474](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2474) ([@consideRatio](https://github.com/consideRatio)) +- Fix indentation in local-storage-dir.yaml [#2443](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2443) ([@timotk](https://github.com/timotk), [@consideRatio](https://github.com/consideRatio)) +- auth rework: update forgotten documentation [#2438](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2438) ([@abdelq](https://github.com/abdelq), [@consideRatio](https://github.com/consideRatio)) +- Minor fixes to the Microk8s documentation [#2436](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2436) ([@mike-matera](https://github.com/mike-matera), [@consideRatio](https://github.com/consideRatio)) +- Fixes broken link in chart docs [#2432](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2432) ([@joraff](https://github.com/joraff), [@consideRatio](https://github.com/consideRatio)) +- Retrospectively add breaking change to changelog entry 0.10.0 [#2410](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2410) ([@consideRatio](https://github.com/consideRatio), [@manics](https://github.com/manics)) +- Update links that redirected [#2409](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2409) ([@consideRatio](https://github.com/consideRatio), [@manics](https://github.com/manics)) +- example configurations for UI choices [#2398](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2398) ([@minrk](https://github.com/minrk), [@consideRatio](https://github.com/consideRatio), [@manics](https://github.com/manics), [@willingc](https://github.com/willingc)) +- Add changelog for 1.1.3 [#2361](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2361) ([@consideRatio](https://github.com/consideRatio), [@sgibson91](https://github.com/sgibson91)) +- Documenting Microk8s cluster type. [#2334](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2334) ([@mike-matera](https://github.com/mike-matera), [@consideRatio](https://github.com/consideRatio)) + +#### Continuous integration improvements + +- ci: workaround intermittent test failures pending upstream fix in k3s [#2800](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2800) ([@consideRatio](https://github.com/consideRatio)) +- Test postgres schema upgrade in CI [#2785](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2785) ([@manics](https://github.com/manics)) +- ci: fix permissions for vuln scan workflow [#2754](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2754) ([@consideRatio](https://github.com/consideRatio)) +- ci: revert mistakenly added temp debugging change [#2753](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2753) ([@consideRatio](https://github.com/consideRatio)) +- ci: add a refreeze requirements.txt job and use dedicated gha env [#2748](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2748) ([@consideRatio](https://github.com/consideRatio)) +- ci: reduce frequency of gha/vuln bumps [#2729](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2729) ([@consideRatio](https://github.com/consideRatio)) +- ci: don't trigger 2x tests on bump automation PRs [#2711](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2711) ([@consideRatio](https://github.com/consideRatio)) +- ci: use jupyterhub-bot PAT to trigger github workflow on opened PRs [#2709](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2709) ([@consideRatio](https://github.com/consideRatio), [@sgibson91](https://github.com/sgibson91)) +- ci: fix syntax error in dependabot config [#2707](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2707) ([@consideRatio](https://github.com/consideRatio)) +- ci: followup tweaks to dependency bumping automation [#2703](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2703) ([@consideRatio](https://github.com/consideRatio), [@sgibson91](https://github.com/sgibson91)) +- ci: automatically bump kube-scheduler and pause image tags [#2698](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2698) ([@consideRatio](https://github.com/consideRatio), [@sgibson91](https://github.com/sgibson91)) +- ci: add automation to bump jupyterhub version and refreeze deps while doing it [#2696](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2696) ([@consideRatio](https://github.com/consideRatio), [@sgibson91](https://github.com/sgibson91)) +- ci: add automation to update chp and traefik images [#2694](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2694) ([@consideRatio](https://github.com/consideRatio), [@sgibson91](https://github.com/sgibson91)) +- ci: add support bot [#2618](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2618) ([@manics](https://github.com/manics), [@consideRatio](https://github.com/consideRatio), [@minrk](https://github.com/minrk)) +- ci: remove conditional tmate debugging session action [#2584](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2584) ([@consideRatio](https://github.com/consideRatio), [@manics](https://github.com/manics)) +- ci: test against k8s 1.23 [#2548](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2548) ([@consideRatio](https://github.com/consideRatio)) +- ci: remove workaround installing six [#2527](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2527) ([@consideRatio](https://github.com/consideRatio)) +- ci: vuln-scan, adjust to changes in trivy's json output [#2463](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2463) ([@consideRatio](https://github.com/consideRatio)) +- ci: don't re-install yq - its already available [#2440](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2440) ([@consideRatio](https://github.com/consideRatio)) +- ci: don't run twice for pre-commit PRs [#2425](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2425) ([@consideRatio](https://github.com/consideRatio)) +- ci: update shellcheck [#2420](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2420) ([@consideRatio](https://github.com/consideRatio), [@manics](https://github.com/manics)) +- ci: refresh circleci config [#2418](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2418) ([@consideRatio](https://github.com/consideRatio), [@manics](https://github.com/manics)) +- ci: test against k8s 1.22 [#2404](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2404) ([@consideRatio](https://github.com/consideRatio)) +- ci: use PVCs when testing upgrades [#2401](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2401) ([@manics](https://github.com/manics), [@consideRatio](https://github.com/consideRatio)) +- ci: remove no longer needed arm test adjustment [#2376](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2376) ([@consideRatio](https://github.com/consideRatio), [@manics](https://github.com/manics)) + +#### Contributors to this release + +([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2021-08-25&to=2022-08-16&type=c)) + +[@a3626a](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aa3626a+updated%3A2021-08-25..2022-08-16&type=Issues) | [@abdelq](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aabdelq+updated%3A2021-08-25..2022-08-16&type=Issues) | [@Adam-Antios](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AAdam-Antios+updated%3A2021-08-25..2022-08-16&type=Issues) | [@alex-g-tejada](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aalex-g-tejada+updated%3A2021-08-25..2022-08-16&type=Issues) | [@AlexChung1995](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AAlexChung1995+updated%3A2021-08-25..2022-08-16&type=Issues) | [@BertR](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ABertR+updated%3A2021-08-25..2022-08-16&type=Issues) | [@betatim](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abetatim+updated%3A2021-08-25..2022-08-16&type=Issues) | [@bjornarfjelldal](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abjornarfjelldal+updated%3A2021-08-25..2022-08-16&type=Issues) | [@chancez](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Achancez+updated%3A2021-08-25..2022-08-16&type=Issues) | [@choldgraf](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acholdgraf+updated%3A2021-08-25..2022-08-16&type=Issues) | [@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2021-08-25..2022-08-16&type=Issues) | [@cslovell](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acslovell+updated%3A2021-08-25..2022-08-16&type=Issues) | [@delamart](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adelamart+updated%3A2021-08-25..2022-08-16&type=Issues) | [@dependabot](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adependabot+updated%3A2021-08-25..2022-08-16&type=Issues) | [@dhirschfeld](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adhirschfeld+updated%3A2021-08-25..2022-08-16&type=Issues) | [@dingobar](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adingobar+updated%3A2021-08-25..2022-08-16&type=Issues) | [@dmigo](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Admigo+updated%3A2021-08-25..2022-08-16&type=Issues) | [@Economax](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AEconomax+updated%3A2021-08-25..2022-08-16&type=Issues) | [@ellisonbg](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aellisonbg+updated%3A2021-08-25..2022-08-16&type=Issues) | [@GeorgianaElena](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AGeorgianaElena+updated%3A2021-08-25..2022-08-16&type=Issues) | [@gregingenii](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Agregingenii+updated%3A2021-08-25..2022-08-16&type=Issues) | [@gsemet](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Agsemet+updated%3A2021-08-25..2022-08-16&type=Issues) | [@jdmcbr](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajdmcbr+updated%3A2021-08-25..2022-08-16&type=Issues) | [@jhowton-restor3d](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajhowton-restor3d+updated%3A2021-08-25..2022-08-16&type=Issues) | [@joncotton](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajoncotton+updated%3A2021-08-25..2022-08-16&type=Issues) | [@joraff](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajoraff+updated%3A2021-08-25..2022-08-16&type=Issues) | [@jupyterhub-bot](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajupyterhub-bot+updated%3A2021-08-25..2022-08-16&type=Issues) | [@kindomLee](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AkindomLee+updated%3A2021-08-25..2022-08-16&type=Issues) | [@lucianolacurcia](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Alucianolacurcia+updated%3A2021-08-25..2022-08-16&type=Issues) | [@lud0v1c](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Alud0v1c+updated%3A2021-08-25..2022-08-16&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2021-08-25..2022-08-16&type=Issues) | [@matthew-brett](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amatthew-brett+updated%3A2021-08-25..2022-08-16&type=Issues) | [@mcberma](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amcberma+updated%3A2021-08-25..2022-08-16&type=Issues) | [@mgobec](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amgobec+updated%3A2021-08-25..2022-08-16&type=Issues) | [@mike-matera](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amike-matera+updated%3A2021-08-25..2022-08-16&type=Issues) | [@minrk](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aminrk+updated%3A2021-08-25..2022-08-16&type=Issues) | [@MLobo1997](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AMLobo1997+updated%3A2021-08-25..2022-08-16&type=Issues) | [@mriedem](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amriedem+updated%3A2021-08-25..2022-08-16&type=Issues) | [@nreith](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Anreith+updated%3A2021-08-25..2022-08-16&type=Issues) | [@ostapkonst](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aostapkonst+updated%3A2021-08-25..2022-08-16&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Apre-commit-ci+updated%3A2021-08-25..2022-08-16&type=Issues) | [@pvanliefland](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Apvanliefland+updated%3A2021-08-25..2022-08-16&type=Issues) | [@raybellwaves](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Araybellwaves+updated%3A2021-08-25..2022-08-16&type=Issues) | [@remche](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aremche+updated%3A2021-08-25..2022-08-16&type=Issues) | [@rickwierenga](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Arickwierenga+updated%3A2021-08-25..2022-08-16&type=Issues) | [@ruben-rodriguez](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aruben-rodriguez+updated%3A2021-08-25..2022-08-16&type=Issues) | [@sgibson91](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asgibson91+updated%3A2021-08-25..2022-08-16&type=Issues) | [@Sieboldianus](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ASieboldianus+updated%3A2021-08-25..2022-08-16&type=Issues) | [@snickell](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asnickell+updated%3A2021-08-25..2022-08-16&type=Issues) | [@srggrs](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asrggrs+updated%3A2021-08-25..2022-08-16&type=Issues) | [@sunu](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asunu+updated%3A2021-08-25..2022-08-16&type=Issues) | [@theomper](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Atheomper+updated%3A2021-08-25..2022-08-16&type=Issues) | [@timotk](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Atimotk+updated%3A2021-08-25..2022-08-16&type=Issues) | [@willingc](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Awillingc+updated%3A2021-08-25..2022-08-16&type=Issues) | [@wyphan](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Awyphan+updated%3A2021-08-25..2022-08-16&type=Issues) | [@yuvipanda](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ayuvipanda+updated%3A2021-08-25..2022-08-16&type=Issues) + +## 1.2 + +### 1.2.0 - 2021-11-04 + +Security release! Updates JupyterHub to 1.5 to address a [moderate security vulnerability][ghsa-cw7p-q79f-m2v7] +affecting JupyterLab users, +where logout may not always fully clear credentials from the browser if multiple sessions are open at the time. + +[ghsa-cw7p-q79f-m2v7]: https://github.com/jupyterhub/jupyterhub/security/advisories/GHSA-cw7p-q79f-m2v7 + +A few small features are backported from the upcoming 2.0 release as well. +See [the release notes][juptyerhub-1.5-changelog] for more. + +[juptyerhub-1.5-changelog]: https://jupyterhub.readthedocs.io/en/1.5.0/changelog.html#id1 + +Because the vulnerability is in the single-user environment, +you can get the fix in existing deployments by upgrading JupyterHub to 1.5 in your _user_ environment +without updating the rest of your chart. + +Similarly, upgrading the chart without also upgrading JupyterHub to 1.5 in your user environment **will not** fix the vulnerability. + +JupyterHub 1.5 in the user environment is fully compatible with a Hub running 1.4, and _vice versa_. + +## 1.1 + +### 1.1.4 - 2021-10-28 + +Security release! 1.1.4 release fixes a [critical security vulnerability][ghsa-5xvc-vgmp-jgc3] in jupyterhub-firstuse authenticator. +If you are not using firstuseauthenticator, you are not affected. + +[ghsa-5xvc-vgmp-jgc3]: https://github.com/jupyterhub/firstuseauthenticator/security/advisories/GHSA-5xvc-vgmp-jgc3 + +### 1.1.3 - 2021-08-25 + +#### Maintenance and upkeep improvements + +- refactor: remove redundant trimSuffix of new lines after toYaml [#2358](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2358) ([@consideRatio](https://github.com/consideRatio)) +- build(deps): bump pycurl from 7.44.0 to 7.44.1 in /images/hub [#2352](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2352) ([@dependabot](https://github.com/dependabot)) +- build(deps): bump oauthenticator from 14.1.0 to 14.2.0 in /images/hub [#2350](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2350) ([@dependabot](https://github.com/dependabot)) +- build(deps): bump pycurl from 7.43.0.6 to 7.44.0 in /images/hub [#2347](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2347) ([@dependabot](https://github.com/dependabot)) + +#### Documentation improvements + +- Add docs on GitHub team authentication [#2349](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2349) ([@j0nnyr0berts](https://github.com/j0nnyr0berts)) + +#### Contributors to this release + +([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2021-08-05&to=2021-08-24&type=c)) + +[@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2021-08-05..2021-08-24&type=Issues) | [@j0nnyr0berts](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aj0nnyr0berts+updated%3A2021-08-05..2021-08-24&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2021-08-05..2021-08-24&type=Issues) + +### 1.1.2 - 2021-08-05 + +#### Bugs fixed + +- fix schema: hub.templateVars didn't accept configuration [#2343](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2343) ([@MridulS](https://github.com/MridulS)) + +#### Documentation improvements + +- docs: fix weird helm upgrade example [#2331](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2331) ([@hiroki-sawano](https://github.com/hiroki-sawano)) + +#### Contributors to this release + +([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2021-07-22&to=2021-08-05&type=c)) + +[@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2021-07-22..2021-08-05&type=Issues) | [@hiroki-sawano](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ahiroki-sawano+updated%3A2021-07-22..2021-08-05&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2021-07-22..2021-08-05&type=Issues) | [@MridulS](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AMridulS+updated%3A2021-07-22..2021-08-05&type=Issues) + +### 1.1.1 - 2021-07-22 + +#### Bugs fixed + +- fix hub.services schema regression from 1.1.0 [#2327](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2327) ([@consideRatio](https://github.com/consideRatio)) + +#### Continuous integration improvements + +- ci: misc fixes post 1.1.0 [#2326](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2326) ([@consideRatio](https://github.com/consideRatio)) + +### 1.1.0 - 2021-07-21 + +#### Highlights + +- **hub.services api tokens are now generated** + + The Helm chart now automatically seeds registered services under + `hub.services` with an api token. This is especially helpful for Helm charts + depending on this Helm chart such as `binderhub` or `daskhub`, for more + details see the + [`hub.services`](schema_hub.services) + entry in the configuration reference. + +- **Full arm64 compatebility** + + The Helm chart is fully arm64 compatible, even the `singleuser.image` that + previously wasn't. + +#### Breaking changes + +This breaking change only concerns someone that has configured +`hub.services..name=` so that `` is different +from ``. In that case, the key in the k8s Secret exposing the +registered service's api token is now named `hub.services..apiToken` +instead of `hub.services..apiToken`. + +#### Notable dependencies updated + +| Dependency | Version in 1.0.0 | Version in 1.1.0 | Changelog link | Note | +| -------------------------------------------------------------------------------- | ---------------- | ---------------- | ----------------------------------------------------------------------------------------- | ---------------------------------- | +| [jupyterhub](https://github.com/jupyterhub/jupyterhub) | 1.4.1 | 1.4.2 | [Changelog](https://jupyterhub.readthedocs.io/en/stable/changelog.html) | Run in the `hub` pod | +| [kubespawner](https://github.com/jupyterhub/kubespawner) | 1.0.0 | 1.1.0 | [Changelog](https://jupyterhub-kubespawner.readthedocs.io/en/latest/changelog.html) | Run in the `hub` pod | +| [oauthenticator](https://github.com/jupyterhub/oauthenticator) | 14.0.0 | 14.1.0 | [Changelog](https://oauthenticator.readthedocs.io/en/latest/changelog.html) | Run in the `hub` pod | +| [ldapauthenticator](https://github.com/jupyterhub/ldapauthenticator) | 1.3.2 | 1.3.2 | [Changelog](https://github.com/jupyterhub/ldapauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [ltiauthenticator](https://github.com/jupyterhub/ltiauthenticator) | 1.0.0 | 1.0.0 | [Changelog](https://github.com/jupyterhub/ltiauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [nativeauthenticator](https://github.com/jupyterhub/nativeauthenticator) | 0.0.7 | 0.0.7 | [Changelog](https://github.com/jupyterhub/nativeauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [jupyterhub-idle-culler](https://github.com/jupyterhub/jupyterhub-idle-culler) | 1.1 | 1.1 | - | Run in the `hub` pod | +| [configurable-http-proxy](https://github.com/jupyterhub/configurable-http-proxy) | 4.4.0 | 4.5.0 | [Changelog](https://github.com/jupyterhub/configurable-http-proxy/blob/HEAD/CHANGELOG.md) | Run in the `proxy` pod | +| [traefik](https://github.com/traefik/traefik) | v2.4.8 | v2.4.11 | [Changelog](https://github.com/traefik/traefik/blob/HEAD/CHANGELOG.md) | Run in the `autohttps` pod | +| [kube-scheduler](https://github.com/kubernetes/kube-scheduler) | v1.19.11 | v1.19.13 | - | Run in the `user-scheduler` pod(s) | + +For a detailed list of how Python dependencies have change in the `hub` Pod's Docker image, inspect the [images/hub/requirements.txt](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/images/hub/requirements.txt) file. + +#### New features added + +- Add configuration for arbitrary extra pod spec [#2306](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2306) ([@mallman](https://github.com/mallman)) + +#### Enhancements made + +- Add support for arm64 in singleuser-sample image [#2316](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2316) ([@consideRatio](https://github.com/consideRatio)) +- Seed hub.services' apiTokens [#2312](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2312) ([@consideRatio](https://github.com/consideRatio)) +- Add ingress.pathType config [#2305](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2305) ([@jtrouth](https://github.com/jtrouth)) + +#### Bugs fixed + +- Allow CHP to function in a IPv4 only and/or IPv6 only context [#2318](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2318) ([@consideRatio](https://github.com/consideRatio)) +- fix schema: accept proxy.traefik.extra[Static|Dynamic]Config [#2317](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2317) ([@consideRatio](https://github.com/consideRatio)) +- fix: bug if z2jh is used as a dependency with an alias [#2310](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2310) ([@consideRatio](https://github.com/consideRatio)) +- Fix failure to set imagePullSecrets for user-placeholder pods (scheduling.userPlaceholder.image config added) [#2293](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2293) ([@michaellzc](https://github.com/michaellzc)) + +#### Maintenance and upkeep improvements + +- build(deps): bump jupyterhub-kubespawner from 1.0.0 to 1.1.0 in /images/hub [#2324](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2324) ([@dependabot](https://github.com/dependabot)) +- Bump CHP version to 4.5.0 [#2321](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2321) ([@consideRatio](https://github.com/consideRatio)) +- build(deps): bump oauthenticator from 14.0.0 to 14.1.0 in /images/hub [#2320](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2320) ([@dependabot](https://github.com/dependabot)) +- Bump patch version of: traefik, kube-scheduler, pause [#2315](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2315) ([@consideRatio](https://github.com/consideRatio)) +- build(deps): bump jupyterhub from 1.4.1 to 1.4.2 in /images/hub [#2314](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2314) ([@dependabot](https://github.com/dependabot)) +- Remove deprecation logic for hub.extraConfig as a string [#2307](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2307) ([@consideRatio](https://github.com/consideRatio)) +- hub image: run apt-get upgrade by default to patch known vulns [#2304](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2304) ([@consideRatio](https://github.com/consideRatio)) + +#### Documentation improvements + +- Add changelog for 1.0.1 [#2287](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2287) ([@consideRatio](https://github.com/consideRatio)) +- Docs clarification culling behavior and configs [#2267](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2267) ([@cdibble](https://github.com/cdibble)) + +#### Continuous integration improvements + +- ci: improve lint-and-validate-values.yaml coverage [#2309](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2309) ([@consideRatio](https://github.com/consideRatio)) +- ci: Arm64 circleci test [#2302](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2302) ([@manics](https://github.com/manics)) + +#### Contributors to this release + +([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2021-06-25&to=2021-07-21&type=c)) + +[@cdibble](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acdibble+updated%3A2021-06-25..2021-07-21&type=Issues) | [@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2021-06-25..2021-07-21&type=Issues) | [@jtrouth](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajtrouth+updated%3A2021-06-25..2021-07-21&type=Issues) | [@mallman](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amallman+updated%3A2021-06-25..2021-07-21&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2021-06-25..2021-07-21&type=Issues) | [@michaellzc](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amichaellzc+updated%3A2021-06-25..2021-07-21&type=Issues) | [@minrk](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aminrk+updated%3A2021-06-25..2021-07-21&type=Issues) | [@yuvipanda](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ayuvipanda+updated%3A2021-06-25..2021-07-21&type=Issues) + +## 1.0 + +### 1.0.1 - 2021-06-25 + +#### Bugs fixed + +- Relax extraEnv schema to allow for array values [#2289](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2289) ([@consideRatio](https://github.com/consideRatio)) +- Relax hub.db.type schema to accept unknown database types [#2285](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2285) ([@consideRatio](https://github.com/consideRatio)) +- templates: quote namespace in case they are only contain numbers [#2284](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2284) ([@consideRatio](https://github.com/consideRatio)) +- Corrected scheduler rbac custom naming [#2276](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2276) ([@v1r7u](https://github.com/v1r7u)) +- Fix fullnameOverride for Ingress & PriorityClass resources [#2251](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2251) ([@v1r7u](https://github.com/v1r7u)) + +#### Maintenance and upkeep improvements + +- Bump traefik from 2.4.8 to 2.4.9 [#2288](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2288) ([@consideRatio](https://github.com/consideRatio)) +- singleuser-sample image: bump base image to reduce known vulns [#2286](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2286) ([@consideRatio](https://github.com/consideRatio)) +- schema: force labels and annotations to be strings [#2283](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2283) ([@consideRatio](https://github.com/consideRatio)) +- build(deps): bump nbgitpuller from 0.10.0 to 0.10.1 in /images/singleuser-sample [#2279](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2279) ([@dependabot](https://github.com/dependabot)) +- hub image: add sqlalchemy-cocroachdb dependency [#2262](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2262) ([@weisdd](https://github.com/weisdd)) +- build(deps): bump psycopg2-binary from 2.8.6 to 2.9.1 in /images/hub [#2259](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2259) ([@dependabot](https://github.com/dependabot)) +- build(deps): bump nbgitpuller from 0.9.0 to 0.10.0 in /images/singleuser-sample [#2247](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2247) ([@dependabot](https://github.com/dependabot)) + +#### Documentation improvements + +- docs: de-hardcode mentioned minimum helm version [#2272](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2272) ([@consideRatio](https://github.com/consideRatio)) +- added AWS EKS cluster scaling/auto-scaling documentation for z2jh [#2268](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2268) ([@cdibble](https://github.com/cdibble)) +- Update installation.md [#2249](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2249) ([@enolfc](https://github.com/enolfc)) +- Add participation in study notice to readme [#2248](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2248) ([@sgibson91](https://github.com/sgibson91)) +- Update 1.0.0-beta.1 changelog entry to 1.0.0 [#2245](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2245) ([@consideRatio](https://github.com/consideRatio)) + +#### Continuous integration improvements + +- Transition to use pre-commit hook in jupyterhub/chartpress [#2278](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2278) ([@consideRatio](https://github.com/consideRatio)) +- Remove pre-commit from GHA [#2273](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2273) ([@minrk](https://github.com/minrk)) + +#### Contributors to this release + +([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2021-06-09&to=2021-06-24&type=c)) + +[@cdibble](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acdibble+updated%3A2021-06-09..2021-06-24&type=Issues) | [@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2021-06-09..2021-06-24&type=Issues) | [@dependabot](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adependabot+updated%3A2021-06-09..2021-06-24&type=Issues) | [@enolfc](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aenolfc+updated%3A2021-06-09..2021-06-24&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2021-06-09..2021-06-24&type=Issues) | [@minrk](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aminrk+updated%3A2021-06-09..2021-06-24&type=Issues) | [@sgibson91](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asgibson91+updated%3A2021-06-09..2021-06-24&type=Issues) | [@v1r7u](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Av1r7u+updated%3A2021-06-09..2021-06-24&type=Issues) | [@weisdd](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aweisdd+updated%3A2021-06-09..2021-06-24&type=Issues) + +### 1.0.0 - 2021-06-09 + +This release includes a security announcement, breaking changes, several new +features, and more. Please read through this to be able to help yourself and +others upgrade successfully. + +As of the 1.0.0 version of this Helm chart, we aim to follow [SemVer 2 +versioning scheme](https://semver.org/) where breaking changes, new features, +and small bugfixes will increment the three version numbers. + +#### Highlights + +- **arm64 compatible images** + + All images except the user image (`singleuser.image`) now support the arm64 + architecture. This allows this Helm chart to be installable on a RaspberryPi + based k8s cluster. + +- **`hub.extraFiles` and `singleuser.extraFiles`** + + Have you wanted to mount various files to the hub pod or the user pods, such + as a configuration file or similar? While this could be done by creating a + dedicated ConfigMap that was mounted etc before, you don't need to go through + that trouble. + + Read more in [the configuration reference](schema_hub.extraFiles). + +- **Automatic secret generation** + + Are you explicitly passing `proxy.secretToken`, `hub.config.CryptKeeper.keys`, + `hub.config.JupyterHub.cookie_secret`? Do it one more time when upgrading to + 1.0.0! After that, they will be stored away in a k8s Secret and reused. + + If you install 1.0.0 from scratch, those will be automatically generated for + you if you don't specify them. + +- **Smoother helm upgrades** + + - `prePuller.hook.pullOnlyOnChanges` is now available and enabled by default, + which only intercepts a `helm upgrade` by pulling images if they have + changed since the last upgrade. + + - The `proxy` pod were sometimes restarted when it wasn't needed and that + could cause needless disruptions for users. This is now fixed. + +- **`fullnameOverride` and `nameOverride`** + + These options let you control the naming of the k8s resources created by the + Helm chart, but should _not be used_ unless you install from scratch. + + Read more in [the configuration + reference](schema_fullnameOverride). + +- **Referencing resources from a parent Helm chart's templates** + + Are you a developer of a Helm chart that depends on this Helm chart, and you + want to reference a k8s resource by name from one of your Helm templates? + + Learn how to do it the recommended way by reading [this + documentation](https://zero-to-jupyterhub.readthedocs.io/en/latest/administrator/advanced.html#referencing-resources-from-a-parent-helm-chart-s-templates). + +#### Security announcement + +The documentation for how to setup a Amazon EKS cluster included an insecure +step that would give anyone access to the Kubernetes cluster. If you have +followed these instructions between `0.7.0-beta.1` and `0.11.1`, please see the +[this post in the Jupyter forum](https://discourse.jupyter.org/t/critical-security-vulnerability-in-instructions-on-z2jh-jupyter-org-to-set-up-a-amazon-eks-based-k8s-cluster/9372). + +#### Breaking changes + +- **Kubernetes 1.17+ and Helm 3.5+ are now required** + + Helm 3 (3.5+) is now required. Helm 2 reached end of life last year and we + have started relying on Helm 3.5 specific features. + + Kubernetes 1.17+ is now required. It helped us avoid maintaining two separate + sets of implementations for the the user-scheduler. + +- **Schema validation of chart config** ([#2033](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2033), [#2200](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2200)) + + The Helm chart now bundles with a `values.schema.json` file that will validate + all use of the Helm chart during template rendering. If the Helm chart's + passed values doesn't comply with the schema, then `helm` will error before + the k8s api-server has become involved and anything has changed in the k8s + cluster. + + The most common validation errors are: + + - _Unrecognized config values_ + + For example if you have misspelled something. + + Note that if you want to pass your custom values for inspection by custom + logic in the hub pod, then you should pass these values via the `custom` + config section where anything will be accepted. + + - _Recognized config values with the wrong type_ + + For example if you have passed a numerical value to a configuration that + expected a string. + +- **Breaking changes to config** ([#2211](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2211)) + + As the Helm chart has evolved over time, configuration options have been + renamed and changed in various ways. With the release of 1.0.0, we enforce a + transition from various old configuration options to new that have previously + been ignored or accepted. + + If you are using outdated configuration options you will be informed about it + before any changes have been made to your deployment of the Helm chart. + +- **Default resource requests are no longer set** ([#2034](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2034), [#2226](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2226)) + + The helm chart now follows a common Helm chart practice by not setting default + resource requests or limits. + + To help in this transition, there is documentation with some guidance on + setting explicit resource requests available + [here](https://z2jh.jupyter.org/en/latest/administrator/optimization.html#explicit-memory-and-cpu-allocated-to-core-pods-containers). + + If you want to restore the previous behavior, you can explicitly set the + resource requests like below. + + ```yaml + hub: + resources: + requests: + cpu: 200m + memory: 512Mi + + proxy: + chp: + resources: + requests: + cpu: 200m + memory: 512Mi + + scheduling: + userScheduler: + resources: + requests: + cpu: 50m + memory: 256Mi + + prePuller: + resources: + requests: + cpu: 0 + memory: 0 + hook: + resources: + requests: + cpu: 0 + memory: 0 + ``` + +- **KubeSpawner and deletion of PVCs** ([jupyterhub#3337](https://github.com/jupyterhub/jupyterhub/pull/3337), [kubespawner#475](https://github.com/jupyterhub/kubespawner/pull/475)) + + Deleting a user in JupyterHub's admin interface (/hub/admin) or removing a + named server will now lead to the deletion of the user's or named server's + dynamically created PVC resource if there was one. + + To opt out of this behavior and retain the current behavior where dynamically + created PVC resources will remain, set `KubeSpawner.delete_pvc` to `false`. + + ```yaml + hub: + config: + KubeSpawner: + delete_pvc: false + ``` + + Note that this feature relies on both KubeSpawner 1.0.0+ and JupyterHub 1.4.1+ + which are included in this release. + +- **hub.existingSecret is reworked** ([#2042](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2042)) + + See [the + documentation](schema_hub.existingSecret) + and [pull request + #2042](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2042) for + more details. + +- **configurable-http-proxy statsd metrics removed** ([#2231](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2231)) + + [statsd metrics have been + removed](https://github.com/jupyterhub/configurable-http-proxy/pull/314) in + configurable-http-proxy. This will only affect administrators who have + overridden the CHP command line arguments as statsd is not supported in the + Helm chart. Support for Prometheus metrics will be added in a future release. + +#### Notable dependencies updated + +| Dependency | Version in 0.11.0 | Version in 1.0.0 | Changelog link | Note | +| -------------------------------------------------------------------------------- | ----------------- | ---------------- | ----------------------------------------------------------------------------------------- | ---------------------------------- | +| [jupyterhub](https://github.com/jupyterhub/jupyterhub) | 1.3.0 | 1.4.1 | [Changelog](https://jupyterhub.readthedocs.io/en/stable/changelog.html) | Run in the `hub` pod | +| [kubespawner](https://github.com/jupyterhub/kubespawner) | 0.15.0 | 1.0.0 | [Changelog](https://jupyterhub-kubespawner.readthedocs.io/en/latest/changelog.html) | Run in the `hub` pod | +| [oauthenticator](https://github.com/jupyterhub/oauthenticator) | 0.12.3 | 14.0.0 | [Changelog](https://oauthenticator.readthedocs.io/en/latest/changelog.html) | Run in the `hub` pod | +| [ldapauthenticator](https://github.com/jupyterhub/ldapauthenticator) | 1.3.2 | 1.3.2 | [Changelog](https://github.com/jupyterhub/ldapauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [ltiauthenticator](https://github.com/jupyterhub/ltiauthenticator) | 1.0.0 | 1.0.0 | [Changelog](https://github.com/jupyterhub/ltiauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [nativeauthenticator](https://github.com/jupyterhub/nativeauthenticator) | 0.0.6 | 0.0.7 | [Changelog](https://github.com/jupyterhub/nativeauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [jupyterhub-idle-culler](https://github.com/jupyterhub/jupyterhub-idle-culler) | 1.0 | 1.1 | - | Run in the `hub` pod | +| [configurable-http-proxy](https://github.com/jupyterhub/configurable-http-proxy) | 4.2.2 | 4.4.0 | [Changelog](https://github.com/jupyterhub/configurable-http-proxy/blob/HEAD/CHANGELOG.md) | Run in the `proxy` pod | +| [traefik](https://github.com/traefik/traefik) | v2.3.7 | v2.4.8 | [Changelog](https://github.com/traefik/traefik/blob/HEAD/CHANGELOG.md) | Run in the `autohttps` pod | +| [kube-scheduler](https://github.com/kubernetes/kube-scheduler) | v1.19.7 | v1.19.11 | - | Run in the `user-scheduler` pod(s) | + +For a detailed list of how Python dependencies have change in the `hub` Pod's Docker image, inspect the [images/hub/requirements.txt](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/images/hub/requirements.txt) file. + +#### New features added + +- hub.service.extraPorts config option [#2148](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2148) ([@kafonek](https://github.com/kafonek)) +- Publish Arm64 compatible images [#2125](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2125) ([@manics](https://github.com/manics)) +- Enable opt-out of hub.jupyter.org/dedicated tolerations [#2101](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2101) ([@kafonek](https://github.com/kafonek)) +- Add prePuller.hook.pullOnlyOnChanges flag [#2066](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2066) ([@consideRatio](https://github.com/consideRatio)) +- values.schema.json ships with chart and configuration reference now covers all options [#2033](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2033) ([@consideRatio](https://github.com/consideRatio)) +- Allow extraFiles to be injected to hub / singleuser pods and automatically load config in /usr/local/etc/jupyterhub_config.d [#2006](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2006) ([@consideRatio](https://github.com/consideRatio)) +- Seed secrets (proxy.secretToken, etc) so they don't have to be manually generated [#1993](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1993) ([@consideRatio](https://github.com/consideRatio)) +- Support fullnameOverride / nameOverride and reference resources by named templates [#1923](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1923) ([@consideRatio](https://github.com/consideRatio)) + +#### Enhancements made + +- Add ...serviceAccount.annotations config for our k8s ServiceAccounts [#2236](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2236) ([@AndreaGiardini](https://github.com/AndreaGiardini)) +- upload chart as github artifact [#2086](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2086) ([@minrk](https://github.com/minrk)) +- allow override of CHP defaultTarget, errorTarget [#2079](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2079) ([@minrk](https://github.com/minrk)) +- Don't restart the proxy pod with each deploy [#2077](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2077) ([@yuvipanda](https://github.com/yuvipanda)) +- Add option to disable http port on LoadBalancer service [#2061](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2061) ([@tkislan](https://github.com/tkislan)) +- Add artificathub.io annotations to Chart.yaml before publishing [#2045](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2045) ([@consideRatio](https://github.com/consideRatio)) +- Make use of hub.existingSecret sustainable [#2042](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2042) ([@consideRatio](https://github.com/consideRatio)) +- Allow ingress.hosts to be omitted for a more generic rule [#2027](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2027) ([@consideRatio](https://github.com/consideRatio)) +- Also pull singleuser.initContainers with pre-puller [#1992](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1992) ([@consideRatio](https://github.com/consideRatio)) + +#### Bugs fixed + +- fix: prePuller.hook.pullOnlyOnChanges didn't work, now it does [#2174](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2174) ([@consideRatio](https://github.com/consideRatio)) +- Fix mixup of hook/continuous-image-puller following recent PR [#2100](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2100) ([@consideRatio](https://github.com/consideRatio)) +- Fix schema validation for Spawner.cpu/memory limits/guarantees [#2070](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2070) ([@consideRatio](https://github.com/consideRatio)) +- Support setting resources to null to omit them [#2055](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2055) ([@consideRatio](https://github.com/consideRatio)) +- pdb: default to maxUnavailable=1 instead of minAvailable=1 [#2039](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2039) ([@consideRatio](https://github.com/consideRatio)) +- fix: imagePullSecret.enabled to work alongside imagePullSecret.create [#2038](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2038) ([@consideRatio](https://github.com/consideRatio)) +- hub image build: fix use of PIP_OVERRIDES arg [#2036](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2036) ([@remche](https://github.com/remche)) +- fix: load only .py files in jupyterhub_config.d folder [#2023](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2023) ([@consideRatio](https://github.com/consideRatio)) +- Followup fixes to seed secrets PR (#1993) [#2016](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2016) ([@consideRatio](https://github.com/consideRatio)) +- fix: set tolerations to predefined labels on core pods [#2007](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2007) ([@consideRatio](https://github.com/consideRatio)) + +#### Maintenance and upkeep improvements + +- Test against k8s 1.21 and avoid deprecation warning for old k8s api policy/v1beta1 [#2243](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2243) ([@consideRatio](https://github.com/consideRatio)) +- Rename master branch to main [#2217](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2217) ([@manics](https://github.com/manics)) +- singleuser-sample: update base image [#2213](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2213) ([@consideRatio](https://github.com/consideRatio)) +- Remove deprecated logic and emit clear messages [#2211](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2211) ([@consideRatio](https://github.com/consideRatio)) +- refactor: stop manual hex-to-bytes conversion [#2209](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2209) ([@consideRatio](https://github.com/consideRatio)) +- schema: added details to hub|singleuser.extraFiles [#2198](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2198) ([@consideRatio](https://github.com/consideRatio)) +- Remove extraneous command from secret-sync image [#2182](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2182) ([@manics](https://github.com/manics)) +- maint: revert a workaround to make our priorityclass resources helm hooks [#2180](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2180) ([@consideRatio](https://github.com/consideRatio)) +- enable prePuller.hook.pullOnlyOnChanges by default [#2179](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2179) ([@consideRatio](https://github.com/consideRatio)) +- inline comment: info about the state used by prePuller.hook.pullOnlyOnChanges [#2173](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2173) ([@consideRatio](https://github.com/consideRatio)) +- images/hub - a regular run of script: hub/images/dependencies freeze --upgrade [#2168](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2168) ([@consideRatio](https://github.com/consideRatio)) +- build(deps): bump rsa from 4.6 to 4.7.2 in /images/hub [#2167](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2167) ([@dependabot](https://github.com/dependabot)) +- Update NOTES.txt, including removing "alpha" designation [#2165](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2165) ([@manics](https://github.com/manics)) +- docs: fix docs build for breaking change in sphinx redirection extension [#2156](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2156) ([@consideRatio](https://github.com/consideRatio)) +- Allow hub pod to manage k8s Secrets/Services for KubeSpawner.internal_ssl [#2065](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2065) ([@thomasv314](https://github.com/thomasv314)) +- Don't set default resource requests [#2034](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2034) ([@yuvipanda](https://github.com/yuvipanda)) +- cleanup: remove mistakenly added artifactshub.io config file [#2010](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2010) ([@consideRatio](https://github.com/consideRatio)) +- refactor: consistently use toYaml with annotations/labels [#2008](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2008) ([@consideRatio](https://github.com/consideRatio)) +- Require k8s 1.17+ to reduce complexity [#2005](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2005) ([@consideRatio](https://github.com/consideRatio)) +- refactor: systematically prefer use of with in templates [#2003](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2003) ([@consideRatio](https://github.com/consideRatio)) +- Specify prometheus.io/port for hub service [#2000](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2000) ([@yuvipanda](https://github.com/yuvipanda)) +- Autoformat bash scripts, yaml files, and markdown files with pre-commit [#1996](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1996) ([@manics](https://github.com/manics)) +- Remove deprecated user-scheduler config [#1995](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1995) ([@consideRatio](https://github.com/consideRatio)) +- Require Helm 3 to allow for enhancements [#1994](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1994) ([@consideRatio](https://github.com/consideRatio)) +- Remove unused nameField helper in \_helpers.tpl [#1991](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1991) ([@consideRatio](https://github.com/consideRatio)) + +#### Documentation improvements + +- docs: fix broken link [#2230](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2230) ([@consideRatio](https://github.com/consideRatio)) +- docs: add documentation about resource requests [#2226](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2226) ([@consideRatio](https://github.com/consideRatio)) +- docs: fix syntax error in markdown table [#2225](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2225) ([@consideRatio](https://github.com/consideRatio)) +- Remove setup-helm2.md [#2216](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2216) ([@manics](https://github.com/manics)) +- Add debug.enabled to admin debugging doc [#2215](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2215) ([@manics](https://github.com/manics)) +- Minor documentation fixes [#2206](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2206) ([@consideRatio](https://github.com/consideRatio)) +- Add changelog for 1.0.0-beta.1 [#2175](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2175) ([@consideRatio](https://github.com/consideRatio)) +- docs: we require helm3 not helm2 [#2159](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2159) ([@consideRatio](https://github.com/consideRatio)) +- fix cluster name for DO installation instructions [#2134](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2134) ([@RyanQuey](https://github.com/RyanQuey)) +- update k8 version for DO to currently available version [#2133](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2133) ([@RyanQuey](https://github.com/RyanQuey)) +- Include customisation under "Administrator Guide" [#2123](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2123) ([@manics](https://github.com/manics)) +- Update index.md [#2122](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2122) ([@rommeld](https://github.com/rommeld)) +- Correct the AKS GPU Link in documentation [#2109](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2109) ([@jabbera](https://github.com/jabbera)) +- Update postgres db url dialect in schema docs [#2105](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2105) ([@mriedem](https://github.com/mriedem)) +- Don't hard-code an old tag in customizing/user-environment.md [#2090](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2090) ([@manics](https://github.com/manics)) +- [DOC] Satisfy linkcheck [#2080](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2080) ([@minrk](https://github.com/minrk)) +- Fix spawner env injection example. [#2062](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2062) ([@danielballan](https://github.com/danielballan)) +- update a markdown syntax error [#2058](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2058) ([@yobome](https://github.com/yobome)) +- docs: helm3 compliance, avoid specification of chart versions [#2054](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2054) ([@consideRatio](https://github.com/consideRatio)) +- doc: Update installation docs to refer to current latest version [#2040](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2040) ([@spenczar](https://github.com/spenczar)) +- docs: package chart specific README.md with the chart [#2035](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2035) ([@consideRatio](https://github.com/consideRatio)) +- values.schema.json ships with chart and configuration reference now covers all options [#2033](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2033) ([@consideRatio](https://github.com/consideRatio)) +- Fix schema.yaml jsonschema syntax errors [#2031](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2031) ([@consideRatio](https://github.com/consideRatio)) + +#### Continuous integration improvements + +- ci: update publish/test-chart workflow triggers [#2212](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2212) ([@consideRatio](https://github.com/consideRatio)) +- ci: print pip packages versions for debugging [#2210](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2210) ([@consideRatio](https://github.com/consideRatio)) +- ci: vuln-scan update, less dedicated actions + warning instead of error [#2188](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2188) ([@consideRatio](https://github.com/consideRatio)) +- ci: fix permissions of PR creating action [#2186](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2186) ([@consideRatio](https://github.com/consideRatio)) +- docs/ci: run template tests against least known supported helm version and document that version [#2181](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2181) ([@consideRatio](https://github.com/consideRatio)) +- ci: accept 1 pod restart but not 2, test against k8s 1.21 [#2169](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2169) ([@consideRatio](https://github.com/consideRatio)) +- ci: precautions for security, update github_token permissions, pin actions [#2163](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2163) ([@consideRatio](https://github.com/consideRatio)) +- ci: update network tests as jupyter.org IPs changed [#2162](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2162) ([@consideRatio](https://github.com/consideRatio)) +- ci: Set author and pin SHA in vuln-scan workflow PR [#2153](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2153) ([@manics](https://github.com/manics)) +- publish workflow: build amd64 and arm64 prerequisites added [#2144](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2144) ([@consideRatio](https://github.com/consideRatio)) +- docs/ci: revert docutils pin, myst-parser fixed issue [#2141](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2141) ([@consideRatio](https://github.com/consideRatio)) +- docs: fix rtd build by pinning docutils [#2140](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2140) ([@consideRatio](https://github.com/consideRatio)) +- ci: increase test timeout for test reliability [#2083](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2083) ([@consideRatio](https://github.com/consideRatio)) +- ci: stop accepting test failures in k8s 1.20 [#2060](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2060) ([@consideRatio](https://github.com/consideRatio)) +- vuln-scan: fix all fixable vulns, and bugfix automation, and bump singleuser-sample [#2052](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2052) ([@consideRatio](https://github.com/consideRatio)) +- ci: fix Chart.yaml annotations for artifacthub.io image scanning [#2049](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2049) ([@consideRatio](https://github.com/consideRatio)) +- ci: install pyyaml before publishing to generate json schema [#2037](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2037) ([@consideRatio](https://github.com/consideRatio)) +- ci: use jupyterhub/action-k8s-await-workloads [#2021](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2021) ([@consideRatio](https://github.com/consideRatio)) +- ci: stop using --long as chartpress 1.0.0 makes it not needed [#2018](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2018) ([@consideRatio](https://github.com/consideRatio)) +- ci: use yq to parse version from Chart.yaml and save ~30 seconds [#2017](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2017) ([@consideRatio](https://github.com/consideRatio)) +- ci: accept k8s 1.20 failures until 1.20.3 is out [#2004](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/2004) ([@consideRatio](https://github.com/consideRatio)) + +#### Contributors to this release + +([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2021-01-15&to=2021-05-28&type=c)) + +[@agnewp](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aagnewp+updated%3A2021-01-15..2021-05-28&type=Issues) | [@bbockelm](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abbockelm+updated%3A2021-01-15..2021-05-28&type=Issues) | [@betatim](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abetatim+updated%3A2021-01-15..2021-05-28&type=Issues) | [@choldgraf](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acholdgraf+updated%3A2021-01-15..2021-05-28&type=Issues) | [@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2021-01-15..2021-05-28&type=Issues) | [@damianavila](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adamianavila+updated%3A2021-01-15..2021-05-28&type=Issues) | [@danielballan](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adanielballan+updated%3A2021-01-15..2021-05-28&type=Issues) | [@dependabot](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adependabot+updated%3A2021-01-15..2021-05-28&type=Issues) | [@dhirschfeld](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adhirschfeld+updated%3A2021-01-15..2021-05-28&type=Issues) | [@github-actions](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Agithub-actions+updated%3A2021-01-15..2021-05-28&type=Issues) | [@jabbera](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajabbera+updated%3A2021-01-15..2021-05-28&type=Issues) | [@jgwerner](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajgwerner+updated%3A2021-01-15..2021-05-28&type=Issues) | [@kafonek](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Akafonek+updated%3A2021-01-15..2021-05-28&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2021-01-15..2021-05-28&type=Issues) | [@meeseeksmachine](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ameeseeksmachine+updated%3A2021-01-15..2021-05-28&type=Issues) | [@mhwasil](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amhwasil+updated%3A2021-01-15..2021-05-28&type=Issues) | [@michzimny](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amichzimny+updated%3A2021-01-15..2021-05-28&type=Issues) | [@MickeyShnaiderman-RecoLabs](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AMickeyShnaiderman-RecoLabs+updated%3A2021-01-15..2021-05-28&type=Issues) | [@minrk](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aminrk+updated%3A2021-01-15..2021-05-28&type=Issues) | [@mriedem](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amriedem+updated%3A2021-01-15..2021-05-28&type=Issues) | [@NerdSec](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ANerdSec+updated%3A2021-01-15..2021-05-28&type=Issues) | [@pcfens](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Apcfens+updated%3A2021-01-15..2021-05-28&type=Issues) | [@pvanliefland](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Apvanliefland+updated%3A2021-01-15..2021-05-28&type=Issues) | [@remche](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aremche+updated%3A2021-01-15..2021-05-28&type=Issues) | [@roelbaz](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aroelbaz+updated%3A2021-01-15..2021-05-28&type=Issues) | [@rommeld](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Arommeld+updated%3A2021-01-15..2021-05-28&type=Issues) | [@RyanQuey](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ARyanQuey+updated%3A2021-01-15..2021-05-28&type=Issues) | [@spenczar](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aspenczar+updated%3A2021-01-15..2021-05-28&type=Issues) | [@support](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asupport+updated%3A2021-01-15..2021-05-28&type=Issues) | [@thomasv314](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Athomasv314+updated%3A2021-01-15..2021-05-28&type=Issues) | [@tkislan](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Atkislan+updated%3A2021-01-15..2021-05-28&type=Issues) | [@willingc](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Awillingc+updated%3A2021-01-15..2021-05-28&type=Issues) | [@yobome](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ayobome+updated%3A2021-01-15..2021-05-28&type=Issues) | [@yuvipanda](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ayuvipanda+updated%3A2021-01-15..2021-05-28&type=Issues) + +## 0.11 + +### 0.11.1 - 2021-01-15 + +This release fixes a regression in the Ingress resource and a bump of +jupyterhub-nativeauthenticator from 0.0.6 to 0.0.7. + +#### Bugs fixed + +- fix: fix of ingress regression and improved testing ([@consideRatio](https://github.com/consideRatio)) + +#### Maintenance and upkeep improvements + +- build(deps): bump jupyterhub-nativeauthenticator from 0.0.6 to 0.0.7 in /images/hub [#1988](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1988) ([@dependabot](https://github.com/dependabot)) + +### 0.11.0 - 2021-01-14 + +Please read the _security announcement_ and the _breaking changes_ below, and +also note that this is the last release supporting Helm 2 and k8s versions lower +than 1.16. + +#### Security announcement + +This release contains the patched version of jupyterhub/oauthenticator which +contained a security issue that influenced version 0.10.0 - 0.10.5 (but not +0.10.6) of this Helm chart. + +Please don't use versions 0.10.0 - 0.10.5 and upgrade to 0.10.6 or later. If you +are using OAuthenticator, please check your list of users and [delete any +unauthorized users who may have logged in during usage of version 0.10.0 - +10.10.5](https://jupyterhub.readthedocs.io/en/1.2.2/getting-started/authenticators-users-basics.html#add-or-remove-users-from-the-hub). + +See [the published security +advisory](https://github.com/jupyterhub/oauthenticator/security/advisories/GHSA-384w-5v3f-q499) +for more information, and refer to [this forum +post](https://discourse.jupyter.org/t/collaboration-to-mitigate-issues-of-security-advisory-in-oauthenticator/7520) +to share insights that can be useful to others. + +#### Breaking changes + +- **`auth` configuration moves to `hub.config` - [#1943](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1943)** + + Helm chart configuration under `auth` is now no longer supported. If you make + a `helm upgrade` using `auth` configuration, the upgrade will abort before any + changes are made to the k8s cluster and you will be provided with the + equivalent configuration using the new system under `hub.config`. + + By default, the printed equivalent configuration is censored as it can contain + secrets that shouldn't be exposed. By passing `--global.safeToShowValues=true` + you can get an uncensored version. + +- **Pod Disruption Budget's now disabled by default - [#1938](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1938)** + + A Pod Disruption Budget (PDB) for the hub and proxy pods were created by + default before, but will by default not be created from now on. The + consequence of this is that the pods now can get _evicted_. + + Eviction will happen as part of `kubectl drain` on a node, or by a cluster + autoscaler removing a underused node. + +#### Notable dependencies updated + +| Dependency | Version in 0.10.6 | Version in 0.11.0 | Changelog link | Note | +| -------------------------------------------------------------------------------- | ----------------- | ----------------- | ----------------------------------------------------------------------------------------- | ---------------------------------- | +| [jupyterhub](https://github.com/jupyterhub/jupyterhub) | 1.2.2 | 1.3.0 | [Changelog](https://jupyterhub.readthedocs.io/en/stable/changelog.html) | Run in the `hub` pod | +| [kubespawner](https://github.com/jupyterhub/kubespawner) | 0.14.1 | 0.15.0 | [Changelog](https://jupyterhub-kubespawner.readthedocs.io/en/latest/changelog.html) | Run in the `hub` pod | +| [oauthenticator](https://github.com/jupyterhub/oauthenticator) | 0.12.1 | 0.12.3 | [Changelog](https://oauthenticator.readthedocs.io/en/latest/changelog.html) | Run in the `hub` pod | +| [ldapauthenticator](https://github.com/jupyterhub/ldapauthenticator) | 1.3.2 | 1.3.2 | [Changelog](https://github.com/jupyterhub/ldapauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [ltiauthenticator](https://github.com/jupyterhub/ltiauthenticator) | 0.4.0 | 1.0.0 | [Changelog](https://github.com/jupyterhub/ltiauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [nativeauthenticator](https://github.com/jupyterhub/nativeauthenticator) | 0.0.6 | 0.0.6 | [Changelog](https://github.com/jupyterhub/nativeauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [jupyterhub-idle-culler](https://github.com/jupyterhub/jupyterhub-idle-culler) | 1.0 | 1.0 | - | Run in the `hub` pod | +| [configurable-http-proxy](https://github.com/jupyterhub/configurable-http-proxy) | 4.2.2 | 4.2.2 | [Changelog](https://github.com/jupyterhub/configurable-http-proxy/blob/HEAD/CHANGELOG.md) | Run in the `proxy` pod | +| [traefik](https://github.com/traefik/traefik) | v2.3.2 | v2.3.7 | [Changelog](https://github.com/traefik/traefik/blob/HEAD/CHANGELOG.md) | Run in the `autohttps` pod | +| [kube-scheduler](https://github.com/kubernetes/kube-scheduler) | v1.19.2 | v1.19.7 | - | Run in the `user-scheduler` pod(s) | + +For a detailed list of how Python dependencies have change in the `hub` Pod's Docker image, inspect the [images/hub/requirements.txt](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/images/hub/requirements.txt) file. + +#### Enhancements made + +- ci: automatically scan and patch our images for known vulnerabilities [#1942](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1942) ([@consideRatio](https://github.com/consideRatio)) + +#### Bugs fixed + +- Fix failure to block insecure metadata server IP [#1950](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1950) ([@consideRatio](https://github.com/consideRatio)) +- Enable hub livenessProbe by default and relax hub/proxy probes [#1941](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1941) ([@consideRatio](https://github.com/consideRatio)) +- Disable PDBs for hub/proxy, add PDB for autohttps, and relocate config proxy.pdb to proxy.chp.pdb [#1938](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1938) ([@consideRatio](https://github.com/consideRatio)) + +#### Maintenance and upkeep improvements + +- dep: bump traefik (autohttps pod) from v2.3.2 to v2.3.7 [#1986](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1986) ([@consideRatio](https://github.com/consideRatio)) +- k8s: update Ingress / PriorityClass apiVersions [#1983](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1983) ([@consideRatio](https://github.com/consideRatio)) +- dep: bump kube-scheduler from 1.19.2 to 1.19.7 [#1981](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1981) ([@consideRatio](https://github.com/consideRatio)) +- singleuser-sample image: bump jupyerhub to 1.3.0 [#1961](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1961) ([@consideRatio](https://github.com/consideRatio)) +- build(deps): bump jupyterhub from 1.2.2 to 1.3.0 in /images/hub [#1959](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1959) ([@dependabot](https://github.com/dependabot)) +- Vulnerability patch in network-tools [#1947](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1947) ([@github-actions](https://github.com/github-actions)) +- hub image: bump jupyterhub-kubespawner from 0.14.1 to 0.15.0 in /images/hub [#1946](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1946) ([@dependabot](https://github.com/dependabot)) +- Helm template linting - remove extra space [#1945](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1945) ([@DArtagan](https://github.com/DArtagan)) +- hub image: bump jupyterhub-hmacauthenticator from 0.1 to 1.0 in /images/hub [#1944](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1944) ([@dependabot](https://github.com/dependabot)) +- add hub.config passthrough and use it for all auth config [#1943](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1943) ([@consideRatio](https://github.com/consideRatio)) +- hub image: bump ltiauthenticator to 1.0.0 and oauthenticator to 0.12.3 [#1932](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1932) ([@consideRatio](https://github.com/consideRatio)) +- bump oauthenticator to 0.12.2 [#1925](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1925) ([@minrk](https://github.com/minrk)) + +#### Documentation improvements + +- docs: 100% MyST Markdown [#1974](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1974) ([@consideRatio](https://github.com/consideRatio)) +- docs: remove unused config of esoteric sphinx builders [#1969](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1969) ([@consideRatio](https://github.com/consideRatio)) +- docs: fix the dynamically set version of chart/jupyterhub [#1968](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1968) ([@consideRatio](https://github.com/consideRatio)) +- Adds a linebreak [#1957](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1957) ([@arokem](https://github.com/arokem)) +- Fixes link to authentication guide from user-management.md [#1955](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1955) ([@arokem](https://github.com/arokem)) +- Adds cli command for finding the k8s version on Azure. [#1954](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1954) ([@arokem](https://github.com/arokem)) + +#### Continuous integration improvements + +- ci: accept helm lint --strict failure, but ensure GitHub UI warns [#1985](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1985) ([@consideRatio](https://github.com/consideRatio)) +- ci: replace kubeval with helm template --validate [#1984](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1984) ([@consideRatio](https://github.com/consideRatio)) +- ci: use extracted github action for namespace report [#1980](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1980) ([@consideRatio](https://github.com/consideRatio)) +- ci: add another upgrade test and provide a template rendering diff [#1978](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1978) ([@consideRatio](https://github.com/consideRatio)) +- ci: linkcheck rework: avoid duplicated build, add colors, make it fail loud [#1976](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1976) ([@consideRatio](https://github.com/consideRatio)) +- ci: run tests conditionally on changed paths [#1975](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1975) ([@consideRatio](https://github.com/consideRatio)) +- ci: use k3s-channel instead of k3s-version [#1973](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1973) ([@consideRatio](https://github.com/consideRatio)) +- ci: full_namespace_report improvements for restartCount > 0 [#1971](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1971) ([@consideRatio](https://github.com/consideRatio)) +- pre-commit: chartpress --reset on Chart.yaml/values.yaml changes [#1970](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1970) ([@consideRatio](https://github.com/consideRatio)) +- ci: full_namespace_report function improved [#1967](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1967) ([@consideRatio](https://github.com/consideRatio)) +- ci: dependabot, add notes to config, fix singleuser-sample config [#1966](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1966) ([@consideRatio](https://github.com/consideRatio)) +- ci: let pytest keep running even if one test has failed [#1965](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1965) ([@consideRatio](https://github.com/consideRatio)) +- ci: help dependabot only trigger one set of tests [#1964](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1964) ([@consideRatio](https://github.com/consideRatio)) +- ci: remove yaml anchors from dependabot config [#1963](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1963) ([@consideRatio](https://github.com/consideRatio)) +- ci: Test against k8s 1.20 [#1956](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1956) ([@consideRatio](https://github.com/consideRatio)) +- ci: vuln scan fix [#1953](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1953) ([@consideRatio](https://github.com/consideRatio)) +- ci: let dependabot update used GitHub action's versions [#1949](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1949) ([@consideRatio](https://github.com/consideRatio)) +- ci: let dependabot update jupyterhub, replace JUPYTERHUB_VERSION with PIP_OVERRIDES [#1948](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1948) ([@consideRatio](https://github.com/consideRatio)) +- ci: automatically scan and patch our images for known vulnerabilities [#1942](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1942) ([@consideRatio](https://github.com/consideRatio)) +- ci: action-k3s-helm was moved to jupyterhub [#1939](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1939) ([@manics](https://github.com/manics)) +- ci: fix of intermittent netpol test failure [#1933](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1933) ([@consideRatio](https://github.com/consideRatio)) + +#### Contributors to this release + +([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2020-11-27&to=2021-01-13&type=c)) + +[@arokem](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aarokem+updated%3A2020-11-27..2021-01-13&type=Issues) | [@betatim](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abetatim+updated%3A2020-11-27..2021-01-13&type=Issues) | [@chicocvenancio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Achicocvenancio+updated%3A2020-11-27..2021-01-13&type=Issues) | [@choldgraf](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acholdgraf+updated%3A2020-11-27..2021-01-13&type=Issues) | [@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2020-11-27..2021-01-13&type=Issues) | [@DArtagan](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ADArtagan+updated%3A2020-11-27..2021-01-13&type=Issues) | [@dependabot](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adependabot+updated%3A2020-11-27..2021-01-13&type=Issues) | [@github-actions](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Agithub-actions+updated%3A2020-11-27..2021-01-13&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2020-11-27..2021-01-13&type=Issues) | [@minrk](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aminrk+updated%3A2020-11-27..2021-01-13&type=Issues) | [@naterush](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Anaterush+updated%3A2020-11-27..2021-01-13&type=Issues) | [@rokroskar](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Arokroskar+updated%3A2020-11-27..2021-01-13&type=Issues) | [@yuvipanda](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ayuvipanda+updated%3A2020-11-27..2021-01-13&type=Issues) + +## 0.10 + +### 0.10.6 - 2020-11-27 + +This release is a security workaround for jupyterhub/oauthenticator described in https://github.com/jupyterhub/oauthenticator/security/advisories/GHSA-384w-5v3f-q499. + +Please don't use versions 0.10.0 - 0.10.5 and upgrade to 0.10.6 or later. If any users have been authorized during usage of 0.10.0 - 0.10.5 who should not have been, they must be deleted via the API or admin interface, [per the documentation](https://jupyterhub.readthedocs.io/en/1.2.2/getting-started/authenticators-users-basics.html#add-or-remove-users-from-the-hub). + +### 0.10.5 - 2020-11-27 + +This release bumps the JupyterHub version from 1.2.1 to 1.2.2. See [JupyterHub's +changelog](https://jupyterhub.readthedocs.io/en/stable/changelog.html?highlight=changelog) +for more information. + +#### Bugs fixed + +- image: bump JupyterHub to 1.2.2 from 1.2.1 for bugfixes [#1924](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1924) ([@consideRatio](https://github.com/consideRatio)) + +#### Maintenance and upkeep improvements + +- pre-commit autoformat: black and beautysh [#1920](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1920) ([@manics](https://github.com/manics)) + +#### Contributors to this release + +([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2020-11-21&to=2020-11-27&type=c)) + +[@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2020-11-21..2020-11-27&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2020-11-21..2020-11-27&type=Issues) + +### 0.10.4 - 2020-11-21 + +A patch release to patch a bug in the dependency oauthenticator that made users +have their servers spawn before they had the chance to choose a server +configuration if c.KubeSpawner.profile_list was configured. + +#### Bugs fixed + +- hub image: bump oauthenticator and prometheus-client [#1918](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1918) ([@consideRatio](https://github.com/consideRatio)) + +#### Contributors to this release + +([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2020-11-16&to=2020-11-21&type=c)) + +[@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2020-11-16..2020-11-21&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2020-11-16..2020-11-21&type=Issues) + +### 0.10.3 - 2020-11-16 + +This release contain minor enhancements and bugfix in a dependency that could +have resulted in unwanted hub pod restarts. Helm 2.16+ has been explicitly +required, which it should had been already in 0.10.0. + +Please be aware that Helm 2 has reached its end of life and won't get any +security patches any more. We aim to drop support of Helm 2 soon to be able to +rely on Helm 3 features. + +#### Enhancements made + +- Configurable resource requests for hook-image-awaiter [#1906](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1906) ([@consideRatio](https://github.com/consideRatio)) +- Add use_lookup_dn_username parameter for LDAP [#1903](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1903) ([@JarnoRFB](https://github.com/JarnoRFB)) +- Allow exposing extra ports in autohttps/traefik deployment [#1901](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1901) ([@yuvipanda](https://github.com/yuvipanda)) +- prePuller.extraTolerations added for the image-puller daemonsets [#1883](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1883) ([@jerkern](https://github.com/jerkern)) + +#### Bugs fixed + +- hub image: kubernetes 12.0.1, nativeauth 0.0.6, tornado 6.1 [#1912](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1912) ([@consideRatio](https://github.com/consideRatio)) + +#### Maintenance and upkeep improvements + +- hub image: kubernetes 12.0.1, nativeauth 0.0.6, tornado 6.1 [#1912](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1912) ([@consideRatio](https://github.com/consideRatio)) +- Require helm v2.16.0 explicitly and minor CI updates [#1911](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1911) ([@consideRatio](https://github.com/consideRatio)) +- CI: make upgrades more robust and skip 1m precautionary sleep [#1904](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1904) ([@consideRatio](https://github.com/consideRatio)) +- CI: publish with helpful commit message [#1898](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1898) ([@consideRatio](https://github.com/consideRatio)) +- Replace Travis with GitHub workflow [#1896](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1896) ([@manics](https://github.com/manics)) +- Avoid harmless error in user-scheduler [#1895](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1895) ([@consideRatio](https://github.com/consideRatio)) +- removal: contributors script [#1669](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1669) ([@consideRatio](https://github.com/consideRatio)) + +#### Documentation improvements + +- Update jupyterhub extension documentation to specify namespace [#1909](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1909) ([@plant99](https://github.com/plant99)) +- DOCS: Adding note on limit to guarantee ratio [#1897](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1897) ([@choldgraf](https://github.com/choldgraf)) +- Changelog for 0.10.2 [#1893](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1893) ([@consideRatio](https://github.com/consideRatio)) + +#### Contributors to this release + +([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2020-10-30&to=2020-11-15&type=c)) + +[@betatim](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abetatim+updated%3A2020-10-30..2020-11-15&type=Issues) | [@choldgraf](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acholdgraf+updated%3A2020-10-30..2020-11-15&type=Issues) | [@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2020-10-30..2020-11-15&type=Issues) | [@JarnoRFB](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AJarnoRFB+updated%3A2020-10-30..2020-11-15&type=Issues) | [@jerkern](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajerkern+updated%3A2020-10-30..2020-11-15&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2020-10-30..2020-11-15&type=Issues) | [@minrk](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aminrk+updated%3A2020-10-30..2020-11-15&type=Issues) | [@plant99](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aplant99+updated%3A2020-10-30..2020-11-15&type=Issues) | [@tirumerla](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Atirumerla+updated%3A2020-10-30..2020-11-15&type=Issues) | [@yuvipanda](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ayuvipanda+updated%3A2020-10-30..2020-11-15&type=Issues) + +### 0.10.2 - 2020-10-30 + +A bugfix release to add securityContext configuration on _all_ the containers in the image-puller pods, which can be needed when a k8s PodSecurityPolicy is forcing pods to startup as non-root users. + +Note that whoever need to comply with a strict PodSecurityPolicy will also need to `--set singleuser.cloudMetadata.blockWithIptables=false`, but should read [this documentation](https://zero-to-jupyterhub.readthedocs.io/en/latest/administrator/security.html#audit-cloud-metadata-server-access) before doing so. + +#### Bugs fixed + +- Add securityContext to all image-puller pods' containers [#1892](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1892) ([@consideRatio](https://github.com/consideRatio)) + +#### Documentation improvements + +- Changelog for 0.10.1 [#1890](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1890) ([@consideRatio](https://github.com/consideRatio)) + +#### Contributors to this release + +([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2020-10-30&to=2020-10-30&type=c)) + +[@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2020-10-30..2020-10-30&type=Issues) | [@jatinder91](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajatinder91+updated%3A2020-10-30..2020-10-30&type=Issues) + +### 0.10.1 - 2020-10-30 + +A bugfix release simply updating JupyterHub to 1.2.1. JupyterHub 1.2.1 fixes a regression related to registered JupyterHub services using the `oauth_no_confirm` configuration. + +#### Bugs fixed + +- Use JupyterHub 1.2.1 - fixes regression for external JH services' oauth_no_confirm config [#1889](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1889) ([@minrk](https://github.com/minrk)) + +#### Maintenance and upkeep improvements + +- Fix CI that broke as assumptions changed about latest published version [#1887](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1887) ([@consideRatio](https://github.com/consideRatio)) + +#### Documentation improvements + +- Update changelog for 0.10.0 release [#1886](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1886) ([@consideRatio](https://github.com/consideRatio)) + +#### Contributors to this release + +([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2020-10-29&to=2020-10-30&type=c)) + +[@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2020-10-29..2020-10-30&type=Issues) | [@minrk](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aminrk+updated%3A2020-10-29..2020-10-30&type=Issues) + +### 0.10.0 - 2020-10-29 + +This release makes the deployment more robust, and enhances users ability to +configure the Helm chart in general. Some defaults have been changed allowing +the Helm chart to easier comply with PodSecurityPolicies by default. + +#### Breaking changes: + +- KubeSpawner was updated to include a breaking change influencing users of + named servers. + + > Security fix: CVE-2020-15110 / GHSA-v7m9-9497-p9gr. When named-servers are + > enabled, certain username patterns, depending on authenticator, could allow + > collisions. The default named-server template is changed to prevent + > collisions, meaning that upgrading will lose associations of named-servers + > with their PVCs if the default templates are used. Data should not be lost + > (old PVCs will be ignored, not deleted), but will need manual migration to + > new PVCs prior to deletion of old PVCs. + +- Anyone relying on configuration in the `proxy.https` section are now + explicitly required to set `proxy.https.enabled` to `true`. + +- Anyone using `hub.imagePullSecret` or `singleuser.imagePullSecret` should now + instead use the chart wide `imagePullSecret` with the same syntax which will + be helping all the JupyterHub pod's get images from a private image registry. + For more information, see [the configuration + reference](schema_imagePullSecret). + +- Predefined Kubernetes + [NetworkPolicies](https://kubernetes.io/docs/concepts/services-networking/network-policies/) + are now created by default, explicitly describing allowed incoming (_ingress_) + and outgoing (_egress_) network communication for the hub, proxy, and user + pods. These `NetworkPolicy` resources are very permissive on the outgoing + traffic (egress), but is limiting the incoming traffic to what is known to be + needed. + + Note that these NetworkPolicies only influence network communication in a + Kubernetes cluster if a NetworkPolicy controller enforce them, such as Calico. + + Also note that if network policies are enforced, you can safely stop actively + blocking access to so called cloud metadata servers for the user pods by + setting `singleuser.cloudMetadata.blockWithIptables=false`. + + See the [security + documentation](https://zero-to-jupyterhub.readthedocs.io/en/latest/administrator/security.html#kubernetes-network-policies) + and the [configuration + reference](schema_proxy.chp.networkPolicy) + for more details. + +- The Helm chart configuration `proxy.networkPolicy` has been removed, + `proxy.chp.networkPolicy` (proxy pod) and `proxy.traefik.networkPolicy` + (autohttps pod) must be used instead. + +- The Helm chart configuration `proxy.containerSecurityContext` is renamed to + `proxy.chp.containerSecurityContext`. + +- The k8s ConfigMap `hub-config` k8s Secret `hub-secret` are now merged into + `hub-secret`, which will affect anyone who use the `hub.existingSecret` + option. + +#### Release highlights + +- **Environment variables in pods with K8S config**. An ability to configure environment variables in pods with a k8s native syntax + has been added. This allows you to reference and mount a field in a k8s Secret + as an environment variable for example. For more information, read [about + extraEnv](schema_singleuser.extraEnv) + in the configuration reference. +- **Configure secrets for all pods via the helm chart**. imagePullSecrets for all the pods in the Helm chart can now be configured + chart wide. See the configuration reference about + [imagePullSecret](schema_imagePullSecret) + and + [imagePullSecrets](schema_imagePullSecrets) + for more details. +- **Pod security is easier to use and configure**. Deploying the Helm chart in a cluster with a PodSecurityPolicy active is now + easier, because the pods' containers now have `securityContext` set on them to + run with relatively low permissions which are also configurable if needed. +- **More reliable TLS certificates**. The `autohttps` pod that is running to acquire TLS certificates if + `proxy.https.type=letsencrypt` is now more reliably acquiring certificates. If + you currently have such issue, do `kubectl delete deploy/autohttps` and + `kubectl delete secret proxy-public-tls-acme` and then deploy the Helm chart + again with `helm upgrade`. + +#### Notable dependencies updated + +| Dependency | Version in previous release | Version in this release | Changelog link | Note | +| -------------------------------------------------------------------------------- | --------------------------- | ----------------------- | ----------------------------------------------------------------------------------------- | ---------------------------------- | +| [jupyterhub](https://github.com/jupyterhub/jupyterhub) | 1.1.0 | 1.2.0 | [Changelog](https://jupyterhub.readthedocs.io/en/stable/changelog.html) | Run in the `hub` pod | +| [kubespawner](https://github.com/jupyterhub/kubespawner) | 0.11.1 | 0.14.1 | [Changelog](https://jupyterhub-kubespawner.readthedocs.io/en/latest/changelog.html) | Run in the `hub` pod | +| [oauthenticator](https://github.com/jupyterhub/oauthenticator) | 0.11.0 | 0.12.0 | [Changelog](https://oauthenticator.readthedocs.io/en/latest/changelog.html) | Run in the `hub` pod | +| [ldapauthenticator](https://github.com/jupyterhub/ldapauthenticator) | 1.3.0 | 1.3.2 | [Changelog](https://github.com/jupyterhub/ldapauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [ltiauthenticator](https://github.com/jupyterhub/ltiauthenticator) | 0.4.0 | 0.4.0 | [Changelog](https://github.com/jupyterhub/ltiauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [nativeauthenticator](https://github.com/jupyterhub/nativeauthenticator) | 0.0.5 | 0.0.5 | [Changelog](https://github.com/jupyterhub/nativeauthenticator/blob/HEAD/CHANGELOG.md) | Run in the `hub` pod | +| [jupyterhub-idle-culler](https://github.com/jupyterhub/jupyterhub-idle-culler) | - | v1.0 | - | Run in the `hub` pod | +| [configurable-http-proxy](https://github.com/jupyterhub/configurable-http-proxy) | 4.2.1 | 4.2.2 | [Changelog](https://github.com/jupyterhub/configurable-http-proxy/blob/HEAD/CHANGELOG.md) | Run in the `proxy` pod | +| [traefik](https://github.com/traefik/traefik) | v2.1 | v2.3.2 | [Changelog](https://github.com/traefik/traefik/blob/HEAD/CHANGELOG.md) | Run in the `autohttps` pod | +| [kube-scheduler](https://github.com/kubernetes/kube-scheduler) | v1.13.12 | v1.19.2 | - | Run in the `user-scheduler` pod(s) | + +For a detailed list of how Python dependencies have change in the `hub` Pod's +Docker image, inspect the [images/hub/requirements.txt](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/images/hub/requirements.txt) file. + +#### Enhancements made + +- Allow adding extra labels to the traefik pod [#1862](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1862) ([@yuvipanda](https://github.com/yuvipanda)) +- Add proxy.service.extraPorts to add ports to the k8s Service proxy-public [#1852](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1852) ([@yuvipanda](https://github.com/yuvipanda)) +- netpol: allowedIngressPorts and interNamespaceAccessLabels config added with defaults retaining 0.9.1 current behavior [#1842](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1842) ([@consideRatio](https://github.com/consideRatio)) +- hub.command and hub.args configuration added [#1840](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1840) ([@cbanek](https://github.com/cbanek)) +- Add nodeSelector and tolerations config for all pods of Helm chart [#1827](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1827) ([@stevenstetzler](https://github.com/stevenstetzler)) +- Added config prePuller.pullProfileListImages [#1818](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1818) ([@consideRatio](https://github.com/consideRatio)) +- Added config option: proxy.chp.extraCommandLineFlags [#1813](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1813) ([@consideRatio](https://github.com/consideRatio)) +- Set container securityContext by default [#1798](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1798) ([@consideRatio](https://github.com/consideRatio)) +- Support chart wide and pod specific config of imagePullSecrets [#1794](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1794) ([@consideRatio](https://github.com/consideRatio)) +- Added proxy.chp.extraEnv and proxy.traefik.extraEnv configuration [#1784](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1784) ([@agrahamlincoln](https://github.com/agrahamlincoln)) +- Remove memory / cpu limits for pre-puller [#1780](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1780) ([@yuvipanda](https://github.com/yuvipanda)) +- Add additional liveness and readiness probe properties [#1767](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1767) ([@rmoe](https://github.com/rmoe)) +- Minimal and explicit resource requests for image-puller pods [#1764](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1764) ([@consideRatio](https://github.com/consideRatio)) +- hook-image-puller: -pod-scheduling-wait-duration flag added for reliability during helm upgrades [#1763](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1763) ([@consideRatio](https://github.com/consideRatio)) +- Make continuous image puller pods evictable [#1762](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1762) ([@consideRatio](https://github.com/consideRatio)) +- hub.extraEnv / singleuser.extraEnv in dict format to support k8s EnvVar spec [#1757](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1757) ([@consideRatio](https://github.com/consideRatio)) +- Add config for hub/proxy/autohttps container's securityContext [#1708](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1708) ([@mriedem](https://github.com/mriedem)) +- Add annotations to image puller pods [#1702](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1702) ([@duongnt](https://github.com/duongnt)) +- fix: intentionally error on missing Let's Encrypt contact email configuration [#1701](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1701) ([@consideRatio](https://github.com/consideRatio)) +- Add services API tokens in hub-secret [#1689](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1689) ([@betatim](https://github.com/betatim)) +- Tweaking readiness/liveness probe: faster startup [#1671](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1671) ([@consideRatio](https://github.com/consideRatio)) +- Tighten and flesh out networkpolicies [#1670](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1670) ([@consideRatio](https://github.com/consideRatio)) +- DX: k3s/k3d instead of kind & CI: autohttps testing [#1664](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1664) ([@consideRatio](https://github.com/consideRatio)) +- autohttps: instant secret-sync shutdown [#1659](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1659) ([@consideRatio](https://github.com/consideRatio)) +- Use DNS names instead of IPv4 addresses to be IPv6 friendly [#1643](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1643) ([@stv0g](https://github.com/stv0g)) +- autohttps: traefik's config now configurable and in YAML [#1636](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1636) ([@consideRatio](https://github.com/consideRatio)) +- Feat: autohttps readinessProbe for quicker validated startup and shutdown [#1633](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1633) ([@consideRatio](https://github.com/consideRatio)) +- switching to myst markdown in docs [#1628](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1628) ([@choldgraf](https://github.com/choldgraf)) +- Bind proxy on IPv4 and IPv6 for dual stack support [#1624](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1624) ([@stv0g](https://github.com/stv0g)) +- Do not hardcode IPv4 localhost address for IPv6 compatibility [#1623](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1623) ([@stv0g](https://github.com/stv0g)) +- enable network policy by default [#1271](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1271) ([@minrk](https://github.com/minrk)) +- Allow configuration of Kuberspawner's pod_name_template [#1144](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1144) ([@tmshn](https://github.com/tmshn)) + +#### Bugs fixed + +- Bump KubeSpawner to 0.14.1 to fix a bug in 0.14.0 about image_pull_secrets [#1868](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1868) ([@consideRatio](https://github.com/consideRatio)) +- netpol: allowedIngressPorts and interNamespaceAccessLabels config added with defaults retaining 0.9.1 current behavior [#1842](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1842) ([@consideRatio](https://github.com/consideRatio)) +- user-scheduler: let image locality etc matter again [#1837](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1837) ([@consideRatio](https://github.com/consideRatio)) +- Add retryable HTTP client to image-awaiter [#1830](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1830) ([@bleggett](https://github.com/bleggett)) +- prePuller: fix recently introduced regression [#1817](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1817) ([@consideRatio](https://github.com/consideRatio)) +- userScheduler: only render associated PDB resource if userScheduler itself is enabled [#1812](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1812) ([@consideRatio](https://github.com/consideRatio)) +- Fix same functionality for proxy.traefik.extraEnv as other extraEnv [#1808](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1808) ([@consideRatio](https://github.com/consideRatio)) +- Set container securityContext by default [#1798](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1798) ([@consideRatio](https://github.com/consideRatio)) +- Relax hook-image-puller to make upgrades more reliable [#1787](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1787) ([@consideRatio](https://github.com/consideRatio)) +- Updates to user-scheduler's coupling to the kube-scheduler binary [#1778](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1778) ([@consideRatio](https://github.com/consideRatio)) +- https: Only expose port 443 if we really have HTTPS on [#1758](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1758) ([@yuvipanda](https://github.com/yuvipanda)) +- jupyterhub existing image pull secret configuration load bug fixed [#1727](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1727) ([@mpolatcan](https://github.com/mpolatcan)) +- fix: jupyterhub services without apiToken was ignored [#1721](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1721) ([@consideRatio](https://github.com/consideRatio)) +- fix: autohttps cert acquisition stability fixed [#1719](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1719) ([@consideRatio](https://github.com/consideRatio)) +- Enable the user scheduler to pay attention to CSI volume count [#1699](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1699) ([@rschroll](https://github.com/rschroll)) +- secret-sync: selective write to secret / functional logs [#1678](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1678) ([@consideRatio](https://github.com/consideRatio)) +- Tighten and flesh out networkpolicies [#1670](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1670) ([@consideRatio](https://github.com/consideRatio)) + +#### Maintenance and upkeep improvements + +- use jupyterhub 1.2.0 [#1884](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1884) ([@minrk](https://github.com/minrk)) +- Update Travis CI badge following .org -> com migration [#1882](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1882) ([@consideRatio](https://github.com/consideRatio)) +- Remove globus_sdk and update various Docker images [#1881](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1881) ([@consideRatio](https://github.com/consideRatio)) +- Complementary fix to recent aesthetics PR [#1878](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1878) ([@consideRatio](https://github.com/consideRatio)) +- Helm template aesthetics fixes [#1877](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1877) ([@consideRatio](https://github.com/consideRatio)) +- Added rediraffe redirecgtion [#1876](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1876) ([@NerdSec](https://github.com/NerdSec)) +- Bump OAuthenticator to 0.12.0 from 0.11.0 [#1874](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1874) ([@consideRatio](https://github.com/consideRatio)) +- Dependency: bump proxy pods image of CHP to 4.2.2 for bugfixes and docker image dependency updates [#1873](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1873) ([@consideRatio](https://github.com/consideRatio)) +- Pin Traefik to v2.3.2 for cert acquisition stability [#1859](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1859) ([@consideRatio](https://github.com/consideRatio)) +- CI: Add logs for autohttps pod on failure to debug intermittent issue [#1855](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1855) ([@consideRatio](https://github.com/consideRatio)) +- CI: Try to improve test stability and autohttps cert aquisition reliability [#1854](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1854) ([@consideRatio](https://github.com/consideRatio)) +- CI: bump k3s and helm versions [#1848](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1848) ([@consideRatio](https://github.com/consideRatio)) +- Add dependabot config to update dependencies automatically [#1844](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1844) ([@jgwerner](https://github.com/jgwerner)) +- try out jupyterhub 1.2.0b1 [#1841](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1841) ([@minrk](https://github.com/minrk)) +- Remove unnecessary Dockerfile build step [#1833](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1833) ([@bleggett](https://github.com/bleggett)) +- Add schema.yaml and validate.py to .helmignore [#1832](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1832) ([@consideRatio](https://github.com/consideRatio)) +- CI: reorder ci jobs to provide relevant feedback quickly [#1828](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1828) ([@consideRatio](https://github.com/consideRatio)) +- Revert recent removal of image-pulling related to cloudMetadata blocker [#1826](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1826) ([@consideRatio](https://github.com/consideRatio)) +- Add maintainers / owners to register with Artifact Hub [#1820](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1820) ([@consideRatio](https://github.com/consideRatio)) +- CI: fix RTD builds on push to master [#1816](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1816) ([@consideRatio](https://github.com/consideRatio)) +- deprecation: warn when proxy.https is modified and proxy.https.enabled=true [#1807](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1807) ([@consideRatio](https://github.com/consideRatio)) +- Soft deprecate singleuser.cloudMetadata.enabled in favor of blockWithIptables [#1805](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1805) ([@consideRatio](https://github.com/consideRatio)) +- hub livenessProbe: bump from 1m to 3m delay before probes are sent [#1804](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1804) ([@consideRatio](https://github.com/consideRatio)) +- hub image: bump kubespawner to 0.14.0 [#1802](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1802) ([@consideRatio](https://github.com/consideRatio)) +- ci: bump helm to 3.3.2 and test with k8s 1.19 also [#1783](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1783) ([@consideRatio](https://github.com/consideRatio)) +- user-scheduler: tweak modern configuration [#1782](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1782) ([@consideRatio](https://github.com/consideRatio)) +- Update to newer version of 'pause' container [#1781](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1781) ([@yuvipanda](https://github.com/yuvipanda)) +- Remove memory / cpu limits for pre-puller [#1780](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1780) ([@yuvipanda](https://github.com/yuvipanda)) +- Updates to user-scheduler's coupling to the kube-scheduler binary [#1778](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1778) ([@consideRatio](https://github.com/consideRatio)) +- hub: Switch base image to latest LTS [#1772](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1772) ([@yuvipanda](https://github.com/yuvipanda)) +- CI: Add test for singleuser.extraEnv [#1769](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1769) ([@consideRatio](https://github.com/consideRatio)) +- Bump KubeSpawner to 0.13.0 [#1768](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1768) ([@consideRatio](https://github.com/consideRatio)) +- CI: always publish helm chart on push to master [#1765](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1765) ([@consideRatio](https://github.com/consideRatio)) +- Bump traefik (autohttps pod) to v2.3 [#1756](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1756) ([@consideRatio](https://github.com/consideRatio)) +- Update JupyterHub's python package dependencies [#1752](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1752) ([@jgwerner](https://github.com/jgwerner)) +- Fix travis by pinning docker python package version [#1743](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1743) ([@chancez](https://github.com/chancez)) +- update kubespawner to 0.12 [#1722](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1722) ([@minrk](https://github.com/minrk)) +- k8s api compatibility: add conditional to ingress apiVersion [#1718](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1718) ([@davidsmf](https://github.com/davidsmf)) +- Upgrade libc to patch vulnerability in hub img [#1715](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1715) ([@meneal](https://github.com/meneal)) +- Autohttps reliability fix: bump traefik version [#1714](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1714) ([@consideRatio](https://github.com/consideRatio)) +- k8s-hub img rebuild -> dependencies refrozen [#1713](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1713) ([@consideRatio](https://github.com/consideRatio)) +- removing circleci [#1711](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1711) ([@choldgraf](https://github.com/choldgraf)) +- Complexity reduction - combine passthrough values.yaml data in hub-config (k8s configmap) to hub-secret (k8s secret) [#1682](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1682) ([@consideRatio](https://github.com/consideRatio)) +- secret-sync: selective write to secret / functional logs [#1678](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1678) ([@consideRatio](https://github.com/consideRatio)) +- DX: k3s/k3d instead of kind & CI: autohttps testing [#1664](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1664) ([@consideRatio](https://github.com/consideRatio)) +- cleanup: remove old deploy secret [#1661](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1661) ([@consideRatio](https://github.com/consideRatio)) +- RTD build fix: get correct version of sphinx [#1658](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1658) ([@consideRatio](https://github.com/consideRatio)) +- Force sphinx>=2,<3 for myst_parser [#1657](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1657) ([@consideRatio](https://github.com/consideRatio)) +- Use idle culler from jupyterhub-idle-culler package [#1648](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1648) ([@yuvipanda](https://github.com/yuvipanda)) +- Refactor: reference ports by name instead of repeating the number [#1645](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1645) ([@consideRatio](https://github.com/consideRatio)) +- DX: refactor helm template [#1635](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1635) ([@consideRatio](https://github.com/consideRatio)) +- CI: fix sphinx warnings turned into errors [#1634](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1634) ([@consideRatio](https://github.com/consideRatio)) +- Dep: Bump deploy/autohttps's traefik to v2.2 [#1632](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1632) ([@consideRatio](https://github.com/consideRatio)) +- DX: more recognizable port numbers [#1631](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1631) ([@consideRatio](https://github.com/consideRatio)) + +#### Documentation improvements + +- Add back Helm chart badge for latest pre-release (alpha, beta) [#1879](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1879) ([@consideRatio](https://github.com/consideRatio)) +- Added rediraffe redirecgtion [#1876](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1876) ([@NerdSec](https://github.com/NerdSec)) +- docs: fix edit button, so it doesn't go to a 404 page [#1864](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1864) ([@consideRatio](https://github.com/consideRatio)) +- Fix link to Hub23 docs [#1860](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1860) ([@sgibson91](https://github.com/sgibson91)) +- Provide links to Hub23 deployment guide [#1850](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1850) ([@sgibson91](https://github.com/sgibson91)) +- docs: clarify user-placeholder resource requests [#1835](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1835) ([@consideRatio](https://github.com/consideRatio)) +- Change doc structure [#1825](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1825) ([@NerdSec](https://github.com/NerdSec)) +- Remove mistakenly introduced artifact [#1824](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1824) ([@consideRatio](https://github.com/consideRatio)) +- fixing broken links [#1823](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1823) ([@choldgraf](https://github.com/choldgraf)) +- README.md: badges for the helm chart repo to go directly to the relevant view [#1815](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1815) ([@consideRatio](https://github.com/consideRatio)) +- Docs: fix some sphinx warnings [#1796](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1796) ([@consideRatio](https://github.com/consideRatio)) +- Fix legacy version in DigitalOcean Kubernetes setup doc [#1788](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1788) ([@subwaymatch](https://github.com/subwaymatch)) +- Add terraform resources to the community resources section [#1776](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1776) ([@salvis2](https://github.com/salvis2)) +- Docs: fixes to outdated links found by the linkchecker [#1770](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1770) ([@consideRatio](https://github.com/consideRatio)) +- Leave a comment about where HUB*SERVICE*\* values come from [#1766](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1766) ([@mriedem](https://github.com/mriedem)) +- Unindent lines to fix the bug in "Specify certificate through Secret resource" [#1755](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1755) ([@salvis2](https://github.com/salvis2)) +- [Documentation] Authenticating with Auth0 [#1736](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1736) ([@asubb](https://github.com/asubb)) +- Docs/schema.yaml patches [#1735](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1735) ([@rubdos](https://github.com/rubdos)) +- Fix broken link to Jupyter contributor guide [#1729](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1729) ([@sgibson91](https://github.com/sgibson91)) +- Fix link [#1728](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1728) ([@JarnoRFB](https://github.com/JarnoRFB)) +- docs: myst-parser deprecation adjustment [#1723](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1723) ([@consideRatio](https://github.com/consideRatio)) +- docs: fix linkcheck warning [#1720](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1720) ([@consideRatio](https://github.com/consideRatio)) +- Docs: fix squeezed logo, broken links, and strip unused CSS and templates [#1710](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1710) ([@consideRatio](https://github.com/consideRatio)) +- Add documentation to create a Kubernetes cluster on OVH [#1704](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1704) ([@jtpio](https://github.com/jtpio)) +- DX: final touches on CONTRIBUTING.md [#1696](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1696) ([@consideRatio](https://github.com/consideRatio)) +- Update Google auth to use a list for hosted_domain [#1695](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1695) ([@petebachant](https://github.com/petebachant)) +- Simplify setting up JupyterLab as default [#1690](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1690) ([@yuvipanda](https://github.com/yuvipanda)) +- Use --num-nodes instead of --size to resize gcloud cluster [#1688](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1688) ([@aculich](https://github.com/aculich)) +- docs: fix broken links [#1687](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1687) ([@consideRatio](https://github.com/consideRatio)) +- Change helm chart version in setup documentation [#1685](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1685) ([@ivanpokupec](https://github.com/ivanpokupec)) +- Docs: assume usage of helm3 over deprecated helm2 [#1684](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1684) ([@GeorgianaElena](https://github.com/GeorgianaElena)) +- removal: Vagrant for local dev [#1668](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1668) ([@consideRatio](https://github.com/consideRatio)) +- docs: fixed links [#1666](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1666) ([@consideRatio](https://github.com/consideRatio)) +- DX: k3s/k3d instead of kind & CI: autohttps testing [#1664](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1664) ([@consideRatio](https://github.com/consideRatio)) +- Reference static ip docs [#1663](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1663) ([@GeorgianaElena](https://github.com/GeorgianaElena)) +- Docs: remove too outdated cost-calculator [#1660](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1660) ([@consideRatio](https://github.com/consideRatio)) +- Update create service principle command. [#1654](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1654) ([@superyaniv](https://github.com/superyaniv)) +- proxy.service.type: Default is different from hub.service.type [#1647](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1647) ([@manics](https://github.com/manics)) +- Fix user storage customization variable [#1640](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1640) ([@bibz](https://github.com/bibz)) +- Fix broken links in the Reference documentation [#1639](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1639) ([@bibz](https://github.com/bibz)) +- Update index.rst [#1629](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1629) ([@deinal](https://github.com/deinal)) +- AWS documentation fixes [#1564](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1564) ([@metonymic-smokey](https://github.com/metonymic-smokey)) +- add Auth0 configuration documentation [#1436](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1436) ([@philvarner](https://github.com/philvarner)) + +#### Contributors to this release + +A huge warm thank you for the collaborative effort in this release! Below we +celebrate this specific GitHub repositories contributors, but we have reason to +be thankful to soo many other contributors in the projects we depend on! Thank +you everyone! + +([GitHub contributors page for this release](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/graphs/contributors?from=2020-04-15&to=2020-10-29&type=c)) + +[@01100010011001010110010101110000](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3A01100010011001010110010101110000+updated%3A2020-04-15..2020-10-29&type=Issues) | [@ablekh](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aablekh+updated%3A2020-04-15..2020-10-29&type=Issues) | [@aculich](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aaculich+updated%3A2020-04-15..2020-10-29&type=Issues) | [@adi413](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aadi413+updated%3A2020-04-15..2020-10-29&type=Issues) | [@agrahamlincoln](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aagrahamlincoln+updated%3A2020-04-15..2020-10-29&type=Issues) | [@aguinaldoabbj](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aaguinaldoabbj+updated%3A2020-04-15..2020-10-29&type=Issues) | [@Aisuko](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AAisuko+updated%3A2020-04-15..2020-10-29&type=Issues) | [@akaszynski](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aakaszynski+updated%3A2020-04-15..2020-10-29&type=Issues) | [@albertmichaelj](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aalbertmichaelj+updated%3A2020-04-15..2020-10-29&type=Issues) | [@alexmorley](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aalexmorley+updated%3A2020-04-15..2020-10-29&type=Issues) | [@amanda-tan](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aamanda-tan+updated%3A2020-04-15..2020-10-29&type=Issues) | [@arpitsri3](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aarpitsri3+updated%3A2020-04-15..2020-10-29&type=Issues) | [@asubb](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aasubb+updated%3A2020-04-15..2020-10-29&type=Issues) | [@aydintd](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aaydintd+updated%3A2020-04-15..2020-10-29&type=Issues) | [@bebosudo](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abebosudo+updated%3A2020-04-15..2020-10-29&type=Issues) | [@BertR](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ABertR+updated%3A2020-04-15..2020-10-29&type=Issues) | [@betatim](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abetatim+updated%3A2020-04-15..2020-10-29&type=Issues) | [@betolink](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abetolink+updated%3A2020-04-15..2020-10-29&type=Issues) | [@bibz](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Abibz+updated%3A2020-04-15..2020-10-29&type=Issues) | [@bleggett](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ableggett+updated%3A2020-04-15..2020-10-29&type=Issues) | [@cam72cam](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acam72cam+updated%3A2020-04-15..2020-10-29&type=Issues) | [@carat64](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acarat64+updated%3A2020-04-15..2020-10-29&type=Issues) | [@cbanek](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acbanek+updated%3A2020-04-15..2020-10-29&type=Issues) | [@cboettig](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acboettig+updated%3A2020-04-15..2020-10-29&type=Issues) | [@chancez](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Achancez+updated%3A2020-04-15..2020-10-29&type=Issues) | [@chicocvenancio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Achicocvenancio+updated%3A2020-04-15..2020-10-29&type=Issues) | [@choldgraf](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acholdgraf+updated%3A2020-04-15..2020-10-29&type=Issues) | [@chrisroat](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Achrisroat+updated%3A2020-04-15..2020-10-29&type=Issues) | [@clkao](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aclkao+updated%3A2020-04-15..2020-10-29&type=Issues) | [@conet](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aconet+updated%3A2020-04-15..2020-10-29&type=Issues) | [@consideRatio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AconsideRatio+updated%3A2020-04-15..2020-10-29&type=Issues) | [@craig-willis](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acraig-willis+updated%3A2020-04-15..2020-10-29&type=Issues) | [@cslovell](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Acslovell+updated%3A2020-04-15..2020-10-29&type=Issues) | [@dalonlobo](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adalonlobo+updated%3A2020-04-15..2020-10-29&type=Issues) | [@dalssaso](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adalssaso+updated%3A2020-04-15..2020-10-29&type=Issues) | [@danroliver](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adanroliver+updated%3A2020-04-15..2020-10-29&type=Issues) | [@DarkBlaez](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ADarkBlaez+updated%3A2020-04-15..2020-10-29&type=Issues) | [@davidsmf](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adavidsmf+updated%3A2020-04-15..2020-10-29&type=Issues) | [@deinal](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adeinal+updated%3A2020-04-15..2020-10-29&type=Issues) | [@dimm0](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adimm0+updated%3A2020-04-15..2020-10-29&type=Issues) | [@dkipping](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adkipping+updated%3A2020-04-15..2020-10-29&type=Issues) | [@dmpe](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Admpe+updated%3A2020-04-15..2020-10-29&type=Issues) | [@donotpush](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Adonotpush+updated%3A2020-04-15..2020-10-29&type=Issues) | [@duongnt](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aduongnt+updated%3A2020-04-15..2020-10-29&type=Issues) | [@easel](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aeasel+updated%3A2020-04-15..2020-10-29&type=Issues) | [@echarles](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aecharles+updated%3A2020-04-15..2020-10-29&type=Issues) | [@Edward-liang](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AEdward-liang+updated%3A2020-04-15..2020-10-29&type=Issues) | [@eric-leblouch](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aeric-leblouch+updated%3A2020-04-15..2020-10-29&type=Issues) | [@erinfry6](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aerinfry6+updated%3A2020-04-15..2020-10-29&type=Issues) | [@etheleon](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aetheleon+updated%3A2020-04-15..2020-10-29&type=Issues) | [@farzadz](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Afarzadz+updated%3A2020-04-15..2020-10-29&type=Issues) | [@filippo82](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Afilippo82+updated%3A2020-04-15..2020-10-29&type=Issues) | [@frankgu968](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Afrankgu968+updated%3A2020-04-15..2020-10-29&type=Issues) | [@frouzbeh](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Afrouzbeh+updated%3A2020-04-15..2020-10-29&type=Issues) | [@GeorgianaElena](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AGeorgianaElena+updated%3A2020-04-15..2020-10-29&type=Issues) | [@GergelyKalmar](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AGergelyKalmar+updated%3A2020-04-15..2020-10-29&type=Issues) | [@gsemet](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Agsemet+updated%3A2020-04-15..2020-10-29&type=Issues) | [@Guanzhou-Ke](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AGuanzhou-Ke+updated%3A2020-04-15..2020-10-29&type=Issues) | [@Gungo](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AGungo+updated%3A2020-04-15..2020-10-29&type=Issues) | [@h4gen](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ah4gen+updated%3A2020-04-15..2020-10-29&type=Issues) | [@harsimranmaan](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aharsimranmaan+updated%3A2020-04-15..2020-10-29&type=Issues) | [@hdimitriou](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ahdimitriou+updated%3A2020-04-15..2020-10-29&type=Issues) | [@hickst](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ahickst+updated%3A2020-04-15..2020-10-29&type=Issues) | [@hnykda](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ahnykda+updated%3A2020-04-15..2020-10-29&type=Issues) | [@hqwl159](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ahqwl159+updated%3A2020-04-15..2020-10-29&type=Issues) | [@IamViditAgarwal](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AIamViditAgarwal+updated%3A2020-04-15..2020-10-29&type=Issues) | [@ilhaan](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ailhaan+updated%3A2020-04-15..2020-10-29&type=Issues) | [@ivanpokupec](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aivanpokupec+updated%3A2020-04-15..2020-10-29&type=Issues) | [@jacobtomlinson](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajacobtomlinson+updated%3A2020-04-15..2020-10-29&type=Issues) | [@jahstreet](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajahstreet+updated%3A2020-04-15..2020-10-29&type=Issues) | [@JarnoRFB](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AJarnoRFB+updated%3A2020-04-15..2020-10-29&type=Issues) | [@jeremievallee](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajeremievallee+updated%3A2020-04-15..2020-10-29&type=Issues) | [@jgerardsimcock](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajgerardsimcock+updated%3A2020-04-15..2020-10-29&type=Issues) | [@jgwerner](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajgwerner+updated%3A2020-04-15..2020-10-29&type=Issues) | [@josibake](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajosibake+updated%3A2020-04-15..2020-10-29&type=Issues) | [@JPMoresmau](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AJPMoresmau+updated%3A2020-04-15..2020-10-29&type=Issues) | [@jreadey](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajreadey+updated%3A2020-04-15..2020-10-29&type=Issues) | [@jtlz2](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajtlz2+updated%3A2020-04-15..2020-10-29&type=Issues) | [@jtpio](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajtpio+updated%3A2020-04-15..2020-10-29&type=Issues) | [@julienchastang](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajulienchastang+updated%3A2020-04-15..2020-10-29&type=Issues) | [@jzf2101](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ajzf2101+updated%3A2020-04-15..2020-10-29&type=Issues) | [@kinow](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Akinow+updated%3A2020-04-15..2020-10-29&type=Issues) | [@kristofmartens](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Akristofmartens+updated%3A2020-04-15..2020-10-29&type=Issues) | [@kyprifog](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Akyprifog+updated%3A2020-04-15..2020-10-29&type=Issues) | [@leolb-aphp](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aleolb-aphp+updated%3A2020-04-15..2020-10-29&type=Issues) | [@loki1978](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aloki1978+updated%3A2020-04-15..2020-10-29&type=Issues) | [@ltupin](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Altupin+updated%3A2020-04-15..2020-10-29&type=Issues) | [@lxylxy123456](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Alxylxy123456+updated%3A2020-04-15..2020-10-29&type=Issues) | [@manics](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amanics+updated%3A2020-04-15..2020-10-29&type=Issues) | [@mathematicalmichael](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amathematicalmichael+updated%3A2020-04-15..2020-10-29&type=Issues) | [@meeseeksmachine](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ameeseeksmachine+updated%3A2020-04-15..2020-10-29&type=Issues) | [@meneal](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ameneal+updated%3A2020-04-15..2020-10-29&type=Issues) | [@metonymic-smokey](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ametonymic-smokey+updated%3A2020-04-15..2020-10-29&type=Issues) | [@mhwasil](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amhwasil+updated%3A2020-04-15..2020-10-29&type=Issues) | [@minrk](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aminrk+updated%3A2020-04-15..2020-10-29&type=Issues) | [@mjuric](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amjuric+updated%3A2020-04-15..2020-10-29&type=Issues) | [@moorepants](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amoorepants+updated%3A2020-04-15..2020-10-29&type=Issues) | [@mpolatcan](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ampolatcan+updated%3A2020-04-15..2020-10-29&type=Issues) | [@mriedem](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amriedem+updated%3A2020-04-15..2020-10-29&type=Issues) | [@mrocklin](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Amrocklin+updated%3A2020-04-15..2020-10-29&type=Issues) | [@NerdSec](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ANerdSec+updated%3A2020-04-15..2020-10-29&type=Issues) | [@nscozzaro](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Anscozzaro+updated%3A2020-04-15..2020-10-29&type=Issues) | [@openthings](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aopenthings+updated%3A2020-04-15..2020-10-29&type=Issues) | [@pcfens](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Apcfens+updated%3A2020-04-15..2020-10-29&type=Issues) | [@perllaghu](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aperllaghu+updated%3A2020-04-15..2020-10-29&type=Issues) | [@petebachant](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Apetebachant+updated%3A2020-04-15..2020-10-29&type=Issues) | [@peterrmah](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Apeterrmah+updated%3A2020-04-15..2020-10-29&type=Issues) | [@philvarner](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aphilvarner+updated%3A2020-04-15..2020-10-29&type=Issues) | [@prateekkhera](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aprateekkhera+updated%3A2020-04-15..2020-10-29&type=Issues) | [@rabernat](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Arabernat+updated%3A2020-04-15..2020-10-29&type=Issues) | [@RAbraham](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ARAbraham+updated%3A2020-04-15..2020-10-29&type=Issues) | [@remche](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aremche+updated%3A2020-04-15..2020-10-29&type=Issues) | [@rkdarst](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Arkdarst+updated%3A2020-04-15..2020-10-29&type=Issues) | [@rkevin-arch](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Arkevin-arch+updated%3A2020-04-15..2020-10-29&type=Issues) | [@rmoe](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Armoe+updated%3A2020-04-15..2020-10-29&type=Issues) | [@rnestler](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Arnestler+updated%3A2020-04-15..2020-10-29&type=Issues) | [@rschroll](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Arschroll+updated%3A2020-04-15..2020-10-29&type=Issues) | [@rubdos](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Arubdos+updated%3A2020-04-15..2020-10-29&type=Issues) | [@ryanlovett](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Aryanlovett+updated%3A2020-04-15..2020-10-29&type=Issues) | [@salvis2](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asalvis2+updated%3A2020-04-15..2020-10-29&type=Issues) | [@sampathkethineedi](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asampathkethineedi+updated%3A2020-04-15..2020-10-29&type=Issues) | [@scivm](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ascivm+updated%3A2020-04-15..2020-10-29&type=Issues) | [@Sefriol](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ASefriol+updated%3A2020-04-15..2020-10-29&type=Issues) | [@sgibson91](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asgibson91+updated%3A2020-04-15..2020-10-29&type=Issues) | [@sgloutnikov](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asgloutnikov+updated%3A2020-04-15..2020-10-29&type=Issues) | [@shenghu](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ashenghu+updated%3A2020-04-15..2020-10-29&type=Issues) | [@snickell](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asnickell+updated%3A2020-04-15..2020-10-29&type=Issues) | [@sstarcher](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asstarcher+updated%3A2020-04-15..2020-10-29&type=Issues) | [@stefansedich](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Astefansedich+updated%3A2020-04-15..2020-10-29&type=Issues) | [@stevenstetzler](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Astevenstetzler+updated%3A2020-04-15..2020-10-29&type=Issues) | [@stv0g](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Astv0g+updated%3A2020-04-15..2020-10-29&type=Issues) | [@subwaymatch](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asubwaymatch+updated%3A2020-04-15..2020-10-29&type=Issues) | [@summerswallow-whi](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asummerswallow-whi+updated%3A2020-04-15..2020-10-29&type=Issues) | [@superyaniv](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asuperyaniv+updated%3A2020-04-15..2020-10-29&type=Issues) | [@support](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asupport+updated%3A2020-04-15..2020-10-29&type=Issues) | [@suryag10](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Asuryag10+updated%3A2020-04-15..2020-10-29&type=Issues) | [@TiemenSch](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ATiemenSch+updated%3A2020-04-15..2020-10-29&type=Issues) | [@tirumerla](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Atirumerla+updated%3A2020-04-15..2020-10-29&type=Issues) | [@tjcrone](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Atjcrone+updated%3A2020-04-15..2020-10-29&type=Issues) | [@tmshn](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Atmshn+updated%3A2020-04-15..2020-10-29&type=Issues) | [@TomasBeuzen](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3ATomasBeuzen+updated%3A2020-04-15..2020-10-29&type=Issues) | [@tracek](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Atracek+updated%3A2020-04-15..2020-10-29&type=Issues) | [@verdurin](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Averdurin+updated%3A2020-04-15..2020-10-29&type=Issues) | [@vindvaki](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Avindvaki+updated%3A2020-04-15..2020-10-29&type=Issues) | [@vishwesh5](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Avishwesh5+updated%3A2020-04-15..2020-10-29&type=Issues) | [@welcome](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Awelcome+updated%3A2020-04-15..2020-10-29&type=Issues) | [@willingc](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Awillingc+updated%3A2020-04-15..2020-10-29&type=Issues) | [@yuvipanda](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3Ayuvipanda+updated%3A2020-04-15..2020-10-29&type=Issues) | [@zxcGrace](https://github.com/search?q=repo%3Ajupyterhub%2Fzero-to-jupyterhub-k8s+involves%3AzxcGrace+updated%3A2020-04-15..2020-10-29&type=Issues) + +## 0.9 + +### 0.9.0 - 2020-04-15 + +#### Release summary + +This Helm chart release is mainly a maintenance release featuring the latest +JupyterHub (1.1.0) and authenticators along with bug fixes and some additional +helpful configuration options. + +Noteworthy: + +- An issue with automatic acquisition of HTTPS certificates has been resolved + since 0.9.0-beta.3. +- Fixed a compatibility issue with Kubernetes 1.16+ +- The `images/hub/requirements.txt` file in this repo can now be used to track + what specific version has been used at any point in time. +- [jupyterhub-nativeauthenticator](https://native-authenticator.readthedocs.io/en/latest/) added to the JupyterHub Docker image. + +Bumped dependencies: + +- jupyterhub version 1.1.0 +- jupyterhub-ldapauthenticator version 1.3.0 +- jupyterhub-kubespawner version 0.11.1 +- oauthenticator version 0.11.0 +- kubernetes version 10.0.1 + +#### Upgrade instructions (IMPORTANT) + +1. If you are using Helm 2, upgrade to the latest Helm 2 version. And if you are + using Helm 3, upgrade to the latest Helm 3 version. + + Upgrading to Helm 3 from Helm 2 requires additional steps not covered here, + so for now please stay with your current major version of helm (2 or 3). + + ``` + # Figure out what version you currently have locally, you should use + # release of the same major version you have used before. + helm version + ``` + + Install either the latest [Helm + 2](https://v2.helm.sh/docs/using_helm/#installing-helm) or [Helm + 3](https://helm.sh/docs/intro/install/) depending on what major version you + currently had worked with. + + ``` + # verify you successfully upgraded helm + helm version + + # if you just upgraded helm 2, also upgrade tiller + helm init --upgrade --service-account=tiller + ``` + +2. Use `--cleanup-on-fail` when using `helm upgrade`. + + Helm can enter a problematic state by a `helm` install or upgrade process + which started creating Kubernetes resources, but then didn't finish at all or + didn't finish successfully. It can cause resources created that helm will + later come in conflict with. + + To mitigate this, we suggest always using `--cleanup-on-fail` with this Helm + chart, it is a solid behavior that reduce a lot of head ache. + +3. If you use `--wait`, or `--atomic` which implies `--wait`: do not manually + cancel the upgrade! + + If you would abort the upgrade when using `--wait` and Kubernetes resources + has been created, resources will have been created that can cause conflict + with future upgrades and require you to manually clean them up. + +4. Delete resources that could cause issues before upgrading. + + ```shell + # replace below with where jupyterhub is installed + kubectl delete -n clusterrole,clusterrolebinding,role,rolebinding,serviceaccount,deployment,configmap,service -l component=autohttps + ``` + +#### Troubleshooting upgrade + +If you get an error similar to the one below, it is a symptom of having +attempted a `helm upgrade` that failed where helm lost track of some newly +created resources. A good solution is to delete all of these resources and try +again. + +```shell +# replace below with where jupyterhub is installed +kubectl delete -n clusterrole,clusterrolebinding,role,rolebinding,serviceaccount,deployment,configmap,service -l component=autohttps +``` + +To avoid this in the future, use `--cleanup-on-fail` with the `helm upgrade` +command. It is not a fool proof way to avoid it, but . And note that even if that flag is used, an interupption for example during `--wait` or `--atomic` which implies `--wait`, be +aware of an interruption while waiting can very likely cause this to arise on +the following upgrade attempt. + +> ``` +> error: kind ConfigMap with the name "traefik-proxy-config" already exists in +> the cluster and wasn't defined in the previous release. Before upgrading, +> please either delete the resource from the cluster or remove it from the chart +> ``` + +#### Dependency updates + +- Bump configurable-http-proxy image [#1598](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1598) ([@consideRatio](https://github.com/consideRatio)) +- fix: Bump to base-notebook with JH 1.1.0 etc [#1588](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1588) ([@bitnik](https://github.com/bitnik)) + +#### Maintenance + +- Docs: refactor/docs for local development of docs [#1617](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1617) ([@consideRatio](https://github.com/consideRatio)) +- [MRG] sphinx: linkcheck in travis (allowed to fail) [#1611](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1611) ([@manics](https://github.com/manics)) +- [MRG] Sphinx: warnings are errors [#1610](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1610) ([@manics](https://github.com/manics)) +- pydata theme [#1608](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1608) ([@choldgraf](https://github.com/choldgraf)) +- Small typo fix in doc [#1591](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1591) ([@sebastianpfischer](https://github.com/sebastianpfischer)) +- [MRG] Pin sphinx theme [#1589](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1589) ([@manics](https://github.com/manics)) +- init helm and tiller with history-max settings [#1587](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1587) ([@bitnik](https://github.com/bitnik)) +- Changelog for 0.9.0-beta.4 [#1585](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1585) ([@manics](https://github.com/manics)) +- freeze environment in hub image [#1562](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1562) ([@minrk](https://github.com/minrk)) + +### 0.9.0-beta.4 - 2020-02-26 + +#### Added + +- Add nativeauthenticator to hub image [#1583](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1583) ([@consideRatio](https://github.com/consideRatio)) +- Add option to remove named server when culling [#1558](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1558) ([@betatim](https://github.com/betatim)) + +#### Dependency updates + +- jupyterhub-ldapauthenticator==1.3 [#1576](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1576) ([@manics](https://github.com/manics)) +- First-class azuread support, oauth 0.11 [#1563](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1563) ([@minrk](https://github.com/minrk)) +- simplify hub-requirements [#1560](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1560) ([@minrk](https://github.com/minrk)) +- Bump to base-notebook with JH 1.1.0 etc [#1549](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1549) ([@consideRatio](https://github.com/consideRatio)) + +#### Fixed + +- Fix removing of named servers when culled [#1567](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1567) ([@consideRatio](https://github.com/consideRatio)) + +#### Maintenance + +- Added gitlab URL [#1577](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1577) ([@metonymic-smokey](https://github.com/metonymic-smokey)) +- Fix reference doc link [#1570](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1570) ([@clkao](https://github.com/clkao)) +- Add contributor badge [#1559](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1559) ([@GeorgianaElena](https://github.com/GeorgianaElena)) +- Trying to clean up formatting [#1555](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1555) ([@jeremycadams](https://github.com/jeremycadams)) +- Remove unneeded directive in traefik config [#1554](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1554) ([@yuvipanda](https://github.com/yuvipanda)) +- Added documentation of secret https mode [#1553](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1553) ([@RossRKK](https://github.com/RossRKK)) +- Helm 3 preview [#1543](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1543) ([@manics](https://github.com/manics)) + +### 0.9.0-beta.3 - 2020-01-17 + +#### Dependency updates + +- Deploy jupyterhub 1.1.0 stable [#1548](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1548) ([@minrk](https://github.com/minrk)) +- Bump chartpress for Helm 3 compatible dev releases [#1542](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1542) ([@consideRatio](https://github.com/consideRatio)) + +#### Fixed + +- Replace kube-lego + nginx ingress with traefik [#1539](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1539) ([@yuvipanda](https://github.com/yuvipanda)) + +#### Maintenance + +- Update step zero for Azure docs with commands to setup an VNet and network policy [#1527](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1527) ([@sgibson91](https://github.com/sgibson91)) +- Fix duplicate docs label [#1544](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1544) ([@manics](https://github.com/manics)) +- Made GCP docs of compute zone names generic [#1431](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1431) ([@metonymic-smokey](https://github.com/metonymic-smokey)) + +### 0.9.0-beta.2 - 2019-12-26 + +#### Fixed + +- Fix major breaking change if all HTTPS options was disabled introduced just before beta.1 [#1534](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1534) ([@dirkcgrunwald](https://github.com/dirkcgrunwald)) + +### 0.9.0-beta.1 - 2019-12-26 + +Some highlights of relevance for this release are: + +- The default configuration is now catering to autoscaling clusters where nodes + can be added and removed, as compared to fixed clusters where there is only a + fixed amount of nodes. Set `scheduling.userScheduler.enabled` to false if you + are on a fixed size cluster. +- Kubernetes 1.16 compatibility achieved +- Updated dependencies + - jupyterhub==1.1.0b1 + - kubernetes==0.10.1 + - kubespawner==0.11.1 + - oauthenticator==0.10.0 + +#### Added + +- Added ability to configure liveness/readiness probes on the hub/proxy [#1480](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1480) ([@mrow4a](https://github.com/mrow4a)) +- Added ability to use an existing/shared image pull secret for hub and image pullers [#1426](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1426) ([@LaurentGoderre](https://github.com/LaurentGoderre)) +- Added ability to configure the proxy's load balancer service's access restrictions (`loadBalancerSourceRanges`) [#1418](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1418) ([@GergelyKalmar](https://github.com/GergelyKalmar)) +- Added `user-scheduler` pod->node scheduling policy configuration [#1409](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1409) ([@yuvipanda](https://github.com/yuvipanda)) +- Added ability to add additional ingress rules to k8s NetworkPolicy resources [#1380](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1380) ([@yuvipanda](https://github.com/yuvipanda)) +- Enabled the continuous image puller by default [#1276](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1276) ([@consideRatio](https://github.com/consideRatio)) +- Added ability to configure initContainers of the hub pod [#1274](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1274) ([@scottyhq](https://github.com/scottyhq)) +- Enabled the user-scheduler by default [#1272](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1272) ([@minrk](https://github.com/minrk)) +- Added ability to use an existing jupyterhub configuration k8s secret for hub (not recommended) [#1142](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1142) ([@koen92](https://github.com/koen92)) +- Added use of liveness/readinessProbe by default [#1004](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1004) ([@tmshn](https://github.com/tmshn)) + +#### Dependency updates + +- Bump JupyterHub to 1.1.0b1 [#1533](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1533) ([@consideRatio](https://github.com/consideRatio)) +- Update JupyterHub version [#1524](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1524) ([@bitnik](https://github.com/bitnik)) +- Re-add ltiauthenticator 0.4.0 to hub image [#1519](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1519) ([@consideRatio](https://github.com/consideRatio)) +- Fix hub image dependency versions, disable ltiauthenticator, use chartpress==0.5.0 [#1518](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1518) ([@consideRatio](https://github.com/consideRatio)) +- Update hub image dependencies and RELEASE.md regarding dependencies [#1484](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1484) ([@consideRatio](https://github.com/consideRatio)) +- Bump kubespawner to 0.11.1 for spawner progress bugfix [#1502](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1502) ([@consideRatio](https://github.com/consideRatio)) +- Updated hub image dependencies [#1484](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1484) ([@consideRatio](https://github.com/consideRatio)) +- Updated kube-scheduler binary used by user-scheduler, kubespawner, kubernetes python client, and oauthenticator [#1483](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1483) ([@consideRatio](https://github.com/consideRatio)) +- Bump CHP to 4.2.0 - we get quicker chart upgrades now [#1481](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1481) ([@consideRatio](https://github.com/consideRatio)) +- Bump singleuser-sample [#1473](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1473) ([@consideRatio](https://github.com/consideRatio)) +- Bump python-kubernetes to 9.0._ (later also to 10.0._) [#1454](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1454) ([@clkao](https://github.com/clkao)) +- Bump tmpauthenticator to 0.6 (needed for jupyterhub 1.0) [#1299](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1299) ([@manics](https://github.com/manics)) +- Include jupyter-firstuseauthenticator. [#1288](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1288) ([@danielballan](https://github.com/danielballan)) +- Bump jupyterhub to 1.0.0 (later also to a post 1.0.0 commit) [#1263](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1263) ([@minrk](https://github.com/minrk)) +- Bump CHP image to 4.1.0 from 3.0.0 (later to 4.2.0) [#1246](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1246) ([@consideRatio](https://github.com/consideRatio)) +- Bump oauthenticator 0.8.2 (later to 0.10.0) [#1239](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1239) ([@minrk](https://github.com/minrk)) +- Bump jupyterhub to 1.0b2 (later to an post 1.0.0 commit) [#1224](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1224) ([@minrk](https://github.com/minrk)) + +#### Fixed + +- Workaround upstream kubernetes issue regarding https health check [#1531](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1531) ([@sstarcher](https://github.com/sstarcher)) +- User-scheduler RBAC permissions for local-path-provisioner + increase robustness of hub.baseUrl interaction with the hub deployments health endpoint [#1530](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1530) ([@cutiechi](https://github.com/cutiechi)) +- Fixing #1300 User-scheduler doesn't work with rancher/local-path-provisioner [#1516](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1516) ([@cgiraldo](https://github.com/cgiraldo)) +- Move z2jh.py to a python and linux distribution agnostic path [#1478](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1478) ([@mrow4a](https://github.com/mrow4a)) +- Bugfix for proxy upgrade strategy in PR #1401 [#1404](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1404) ([@consideRatio](https://github.com/consideRatio)) +- Use recreate CHP proxy pod's deployment strategy [#1401](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1401) ([@consideRatio](https://github.com/consideRatio)) +- Proxy deployment: Change probes to https port [#1378](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1378) ([@chicocvenancio](https://github.com/chicocvenancio)) +- Readiness and liveness probes re-added [#1361](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1361) ([@consideRatio](https://github.com/consideRatio)) +- Use 443 as https port or redirection. FIX #806 [#1341](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1341) ([@chicocvenancio](https://github.com/chicocvenancio)) +- Revert "Configure liveness/readinessProbe" [#1356](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1356) ([@consideRatio](https://github.com/consideRatio)) +- Ensure helm chart configuration is passed to JupyterHub where needed [#1338](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1338) ([@bitnik](https://github.com/bitnik)) +- Make proxy redirect to the service port 443 instead of the container port 8443 [#1337](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1337) ([@LucidNeko](https://github.com/LucidNeko)) +- Disable becoming root inside hub and proxy containers [#1280](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1280) ([@yuvipanda](https://github.com/yuvipanda)) +- Configure KubeSpawner with the `singleuser.image.pullPolicy` properly [#1248](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1248) ([@vmarkovtsev](https://github.com/vmarkovtsev)) +- Supply `hub.runAsUser` for the hub at the container level instead of the pod level [#1240](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1240) ([@tmc](https://github.com/tmc)) +- Relax HSTS requirement on subdomains [#1219](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1219) ([@yuvipanda](https://github.com/yuvipanda)) + +#### Maintenance + +- typo [#1529](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1529) ([@raybellwaves](https://github.com/raybellwaves)) +- fix link to Helm chart best practices [#1523](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1523) ([@rpwagner](https://github.com/rpwagner)) +- Adding Globus to the list of users [#1522](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1522) ([@rpwagner](https://github.com/rpwagner)) +- Missing page link for our RBAC documentation #1508 [#1514](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1514) ([@n3o-Bhushan](https://github.com/n3o-Bhushan)) +- Correction of warnings from: make html [#1513](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1513) ([@consideRatio](https://github.com/consideRatio)) +- Fixing URL for user-management documentation #1511 [#1512](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1512) ([@n3o-Bhushan](https://github.com/n3o-Bhushan)) +- DOC: fixing authentication link in user customization guide [#1510](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1510) ([@n3o-Bhushan](https://github.com/n3o-Bhushan)) +- DOC: fix kubernetes setup link [#1505](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1505) ([@raybellwaves](https://github.com/raybellwaves)) +- Update changelog for 0.9.0-beta.1 [#1503](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1503) ([@consideRatio](https://github.com/consideRatio)) +- Fix broken link in architecture.rst [#1488](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1488) ([@amcnicho](https://github.com/amcnicho)) +- Bump kind to 0.6.0 and kindest/node versions [#1487](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1487) ([@clkao](https://github.com/clkao)) +- Avoid rate limiting for k8s resource validation [#1485](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1485) ([@consideRatio](https://github.com/consideRatio)) +- Switching to the Pandas Sphinx theme [#1472](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1472) ([@choldgraf](https://github.com/choldgraf)) +- Add vi / less to hub image [#1471](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1471) ([@yuvipanda](https://github.com/yuvipanda)) +- Added existing pull secrets changes from PR #1426 to schema [#1461](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1461) ([@sgloutnikov](https://github.com/sgloutnikov)) +- Chart upgrade tests [#1459](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1459) ([@consideRatio](https://github.com/consideRatio)) +- Replaced broken links in authentication document #1449 [#1457](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1457) ([@n3o-Bhushan](https://github.com/n3o-Bhushan)) +- Fix typo in home page of docs [#1456](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1456) ([@celine168](https://github.com/celine168)) +- Use helm 2.15.1 [#1453](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1453) ([@consideRatio](https://github.com/consideRatio)) +- Support CD with git tags [#1450](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1450) ([@consideRatio](https://github.com/consideRatio)) +- Added Laurent Goderre as contributor [#1443](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1443) ([@LaurentGoderre](https://github.com/LaurentGoderre)) +- Note about future hard deprecation [#1441](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1441) ([@consideRatio](https://github.com/consideRatio)) +- Fix link formatting for ingress.enabled [#1438](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1438) ([@jtpio](https://github.com/jtpio)) +- CI rework - use kind, validate->test->publish, contrib and release rework [#1422](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1422) ([@consideRatio](https://github.com/consideRatio)) +- Mounting jupyterhub_config.py etc. [#1407](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1407) ([@consideRatio](https://github.com/consideRatio)) +- Ignore venv files [#1388](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1388) ([@GeorgianaElena](https://github.com/GeorgianaElena)) +- Added example for populating notebook user home directory [#1382](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1382) ([@gareth-j](https://github.com/gareth-j)) +- Fix typo in jupyterhub_config.py comment [#1376](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1376) ([@loganlinn](https://github.com/loganlinn)) +- Fixed formatting error in links [#1363](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1363) ([@tlkh](https://github.com/tlkh)) +- Instructions for adding GPUs and increasing shared memory [#1358](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1358) ([@tlkh](https://github.com/tlkh)) +- delete redundant prepuller documentation [#1348](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1348) ([@bitnik](https://github.com/bitnik)) +- Add py-spy to hub image [#1327](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1327) ([@yuvipanda](https://github.com/yuvipanda)) +- Changing Azure Container Service to Azure Kubernetes Service [#1322](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1322) ([@seanmck](https://github.com/seanmck)) +- add explanation for lifecycle_hooks in kubespawner_override [#1309](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1309) ([@clancychilds](https://github.com/clancychilds)) +- Update chart version to 0.8.2 in the docs [#1304](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1304) ([@jtpio](https://github.com/jtpio)) +- Fix azure cli VMSSPreview feature register command [#1298](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1298) ([@dazzag24](https://github.com/dazzag24)) +- Unbreak git build [#1294](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1294) ([@joshbode](https://github.com/joshbode)) +- Update Dockerfile to JH 1.0 [#1291](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1291) ([@vilhelmen](https://github.com/vilhelmen)) +- Fix a couple of mistakes in Google Kubernetes instructions [#1290](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1290) ([@astrofrog](https://github.com/astrofrog)) +- Suggest quotes around tag. [#1289](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1289) ([@danielballan](https://github.com/danielballan)) +- hub: Add useful debugging tools to hub image [#1279](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1279) ([@yuvipanda](https://github.com/yuvipanda)) +- Clean up a line in the CI logs [#1278](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1278) ([@consideRatio](https://github.com/consideRatio)) +- Fix prePuller.extraImages linting etc [#1275](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1275) ([@consideRatio](https://github.com/consideRatio)) +- Fixed minor bug in google pricing calculator [#1264](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1264) ([@noahbjohnson](https://github.com/noahbjohnson)) +- [MRG] Update to Docs: Deploying an Autoscaling Kubernetes cluster on Azure [#1258](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1258) ([@sgibson91](https://github.com/sgibson91)) +- Update to Docs: Add Azure scale command to Expanding/Contracting Cluster section [#1256](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1256) ([@sgibson91](https://github.com/sgibson91)) +- removing extra buttons [#1254](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1254) ([@choldgraf](https://github.com/choldgraf)) +- test appVersion in Chart.yaml [#1238](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1238) ([@minrk](https://github.com/minrk)) +- Adjusts whitespace for a code block in AWS instructions. [#1237](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1237) ([@arokem](https://github.com/arokem)) +- Change heading of multiple-profiles section [#1236](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1236) ([@moschlar](https://github.com/moschlar)) +- Suggest Discourse in issue template [#1234](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1234) ([@manics](https://github.com/manics)) +- Added OAuth callback URL to keycloak OIDC example [#1232](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1232) ([@sgloutnikov](https://github.com/sgloutnikov)) +- Updated notes, pod status to Running [#1231](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1231) ([@sgloutnikov](https://github.com/sgloutnikov)) +- Updated AWS EKS region-availability statement. [#1223](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1223) ([@javabrett](https://github.com/javabrett)) +- Fix the default value of lifecycleHooks [#1218](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1218) ([@consideRatio](https://github.com/consideRatio)) +- Update user-environment.rst [#1217](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1217) ([@manycoding](https://github.com/manycoding)) +- Add Digital Ocean Cloud Instructions for Kubernetes [#1192](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1192) ([@alexmorley](https://github.com/alexmorley)) + +## 0.8 + +### 0.8.2 - 2019-04-01 + +Bumped the underlying JupyterHub to 0.9.6. + +### 0.8.1 - 2019-03-28 + +Bumped the underlying JupyterHub to 0.9.5. + +### 0.8.0 - [Richie Benaud](https://en.wikipedia.org/wiki/Richie_Benaud) - 2019-01-24 + +This release contains JupyterHub version 0.9.4. It requires Kubernetes >= 1.11 and Helm >= 2.11.0. +See [the Helm Chart repository](https://github.com/jupyterhub/helm-chart#release-notes) for +a list of relevant dependencies for all Helm Chart versions. + +It contains new features, additional configuration options, and bug fixes. + +#### Upgrading from 0.7 + +To upgrade your cluster: + +1. backup your hub-db-dir persistent volume and previous configuration files, to be safe +2. read changes here and make any needed updates to your configuration +3. upgrade the chart: + + helm repo update + helm upgrade $RELEASE --force --version 0.8.0 --values config.yaml + +The `--force` flag allows deletion and recreation of objects +that have certain changes, such as different labels, +which are forbidden otherwise. + +#### Breaking changes + +- Github organisation OAuth: `auth.github.org_whitelist` has been renamed to `auth.github.orgWhitelist` to be consistent with helm's camelCase style + +#### Troubleshooting + +If you encounter issues with upgrades, check for changed configuration in this document, and make sure your config is up to date. + +If you aren't able to get the upgrade to work, +you can [rollback](https://helm.sh/docs/helm/helm_rollback/) +to a previous version with: + + helm rollback $RELEASE + +Feel free to [ping us on gitter](https://gitter.im/jupyterhub/jupyterhub) +if you have problems or questions. + +#### New Features + +##### Easier user-selectable profiles upon login + +Profile information is now passed through to KubeSpawner. This means you can +[specify multiple user profiles that users can select from](schema_singleuser.profileList) +when they log in. ([#402](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/issues/402)) + +##### Configurable image pull secrets + +Improvements to the Helm Chart to let users specify private information that lets +the Hub pull from private Docker registries. New information includes +Kubernetes Secrets, an email field, large JSON blobs in the password field (required +in order to pull from a private gcr.io registry from an external cluster). + +It also ensures that the image puller DaemonSets have the same credentials to pull the images. + +(thanks to @AlexMorreale) #851 + +##### Improved user scheduling and resource management + +#891 + +Want to make your autoscheduler work efficiently? Then you should schedule pods to pack tight instead of spread out. The user scheduler accomplishes this. + +- **Pod priority and User placeholders** - #929 + +Want to scale up before users arrive so they don't end up waiting for the node to pull an image of several gigabytes in size? By adding a configurable fixed amount of user placeholder pods with a lower [pod priority](https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/) than real user pods, we can accomplish this. It requires k8s v1.11 though. + +- **preferScheduleNextToRealUsers - improves autoscaling** - #930 + This setting slightly improves the ability for a cluster autoscaler to scale down by increasing the likelihood of user placeholders being left alone on a node rather than real users. Real users can't be moved around while user placeholder pods can + +#### Minor upgrades and development improvements + +- **Update jupyterhub to 0.9.4** +- **Update kubespawner to 0.10.1** +- **Allow setting of storage labels** - #924 +- **Tolerations for node taints** - #925 +- **Making the core and user pods affinity have configurable presets** - #927 +- **Improved linting and validation + CI integration** - #844 +- **Improved CI tests** - #846 +- **Cleanup of orphaned files** - #842 + Two files were left unused in the repo. +- **cull.maxAge bugfix** - #853 + `cull.maxAge` previously didn't influence the culler service, as the value was never consumed. This is fixed by a single one line commit in a PR. +- **No more duplicates of puller pods** - #854 + Nobody wants pods running that does nothing. By using the new `before-hook-creation` value for the `deletion-policy` Helm hook together with a single name for our Helm hook resources, we can ensure never having orphaned image pullers. +- **Remove pod-culler image** - #890 #919 + Before JupyterHub 0.9 the pod-culler was a standalone pod with a custom image. But now it is a internal service of the JupyterHub pod, so in this PR we slim the remnant code. +- **Upgrade to k8s 1.9 APIs** - #920 + Migrate to more stable K8s resource APIs from `beta`. +- **Update of the singleuser-sample image** - #888 + `git` and `nbgitpuller` are now available by default +- **Switch to using a StatefulSet for the Hub** **\*** + The Hub should perhaps be a StatefulSet rather than a Deployment as it tends to be tied to a PV that can only be mounted by one single Hub. See this issue: https://github.com/helm/charts/issues/1863 +- Show users deprecation and error messages when they use certain deprecated + configuration (e.g. `hub.extraConfig` as a single string) + or incompatible combinations. +- **Updates to the guide** - #850 +- **Updates to inline documentation** - #939 + +#### Richie Benaud(https://www.cricket.com.au/players/richie-benaud/gvp5xSjUp0q6Qd7IM5TbCg) + +_(excerpt from https://www.cricket.com.au/players/richie-benaud/gvp5xSjUp0q6Qd7IM5TbCg)_ + +Possibly the most iconic man in Australian cricket, Richie Benaud enjoyed a career spanning nearly +70 years in the game. On the field, he scored 767 runs at 19.66 in his 27 matches against England, +while he also picked up 83 wickets. Off the field, +he has been just as important. His commentary has been second to none since making his radio debut in 1960. + +While playing for Australia, fans flocked to the cricket to watch Benaud led sides +dominate whoever they played. The late 1950’s to early 1960’s was a golden period in +Australian cricket, with players such as Simpson, Lawry and Harvey +scoring runs, while Benaud and Davidson did the damage with the ball. + +Richie Benaud was responsible for resurrecting cricket in this country. The world was +changing at that time, and so was cricket. It was being shown on television for the +first time, while radio coverage was becoming more advanced. Benaud +felt he had a duty to the Australian public to make the game more entertaining. Sure, +you could argue that the 1961 series was dull, but at least Australia +retained the Ashes. Nobody will forget the tied Test against the West Indies, or Benaud’s +audacious move to bowl around the wicket in Manchester. + +Benaud is credited with popularising the tactics we see today. Huddles after a wicket +were born in the Benaud era. Declaring just before stumps in a bid to steal a late wicket +was something he thrived upon. Bowling into the rough is now seen +as common practice. + +Benaud was also prepared to try new things with the ball. He worked very hard on +perfecting his wrong’un, the flipper and the top-spinner. His leg-spinner even had variety +to it, making him one of the most complete tweakers at the time. + +His leadership earned him respect immediately. Players loved being guided the +likeable larrikin from Penrith. He looked after everyone both as a team, but also on an +individual basis. His teammates trusted his innovative ideas, while +he trusted them to execute them to the fullest. + +For most Australians, summer means cricket. And cricket means hearing the dulcet +tones of their favourite commentator, Richie Benaud. From the cream coloured suit, to the +witty repartee with his colleagues, Benaud is the complete package + +#### Contributors + +This release wouldn't have been possible without the wonderful contributors +to the [zero-to-jupyterhub](https://github.com/jupyterhub/zero-to-jupyterhub-k8s), +and [KubeSpawner](https://github.com/jupyterhub/kubespawner) repos. +We'd like to thank everyone who contributed in any form - Issues, commenting +on issues, PRs and reviews since the last Zero to JupyterHub release. + +[(Frank) Yu Cheng Gu](https://github.com/frankgu968) +[1160300422-RenQJ](https://github.com/1160300422) +[1kastner](https://github.com/1kastner) +[2efper](https://github.com/2efPer) +[A. Tan ](https://github.com/amanda-tan) +[Aadi Deshpande](https://github.com/cilquirm) +[abremirata28](https://github.com/abremirata28) +[AcademicAdmin](https://github.com/AcademicAdmin) +[Adam Huffman](https://github.com/verdurin) +[Adrian Wilke](https://github.com/adibaba) +[Akanksha Bhardwaj](https://github.com/sashafierce) +[Akhil Lawrence](https://github.com/akhilputhiry) +[Al Johri](https://github.com/AlJohri) +[AlbanWende](https://github.com/AlbanWende) +[Alejandro del Castillo](https://github.com/adelcast) +[Aleksandr Blekh](https://github.com/ablekh) +[Alex Morreale](https://github.com/AlexMorreale) +[Alex Newman](https://github.com/posix4e) +[Alexander Comerford](https://github.com/cmrfrd) +[Alexander Sadleir](https://github.com/maxious) +[amangarg96](https://github.com/amangarg96) +[Amirahmad Khordadi](https://github.com/khordadi) +[Andreas Hilboll](https://github.com/andreas-h) +[andregouveiasantana](https://github.com/andregouveiasantana) +[Andrew](https://github.com/feriat) +[Andrew Catellier](https://github.com/whlteXbread) +[angelikamukhina](https://github.com/angelikamukhina) +[Anton Khodak](https://github.com/anton-khodak) +[arcady-genkin](https://github.com/arcady-genkin) +[Ariel Rokem](https://github.com/arokem) +[Arne Küderle](https://github.com/AKuederle) +[atne2008](https://github.com/atne2008) +[awalther](https://github.com/awalther) +[Ben Zipperer](https://github.com/benzipperer) +[Beneath](https://github.com/beneathcrypto) +[Benjamin Egelund-Müller](https://github.com/bem7) +[BertR](https://github.com/BertR) +[bharathwgl](https://github.com/bharathwgl) +[bing-he](https://github.com/bing-he) +[bjyxmas](https://github.com/bjyxmas) +[bpoettinger](https://github.com/bpoettinger) +[Brad Skaggs](https://github.com/bskaggs) +[Braden](https://github.com/brasie) +[Brian E. Granger](https://github.com/ellisonbg) +[Bruno P. Kinoshita](https://github.com/kinow) +[brynjsmith](https://github.com/brynjsmith) +[Calvin Canh Tran](https://github.com/canhtran) +[camer314](https://github.com/camer314) +[Carol Willing](https://github.com/willingc) +[Caspian](https://github.com/Cas-pian) +[cfoisy-osisoft](https://github.com/cfoisy-osisoft) +[ChanakyaBandara](https://github.com/ChanakyaBandara) +[chang-zhijie](https://github.com/chang-zhijie) +[Chao Wang](https://github.com/wangxiaoxiao88) +[Chen Zhiwei](https://github.com/chenzhiwei) +[Chester Li](https://github.com/chaoleili) +[Chia-liang Kao](https://github.com/clkao) +[Chris Holdgraf](https://github.com/choldgraf) +[Chris Seal](https://github.com/cmseal) +[Christian Alis](https://github.com/ianalis) +[Christian Mesh](https://github.com/cam72cam) +[chrlunden](https://github.com/chrlunden) +[Clancy Childs](https://github.com/clancychilds) +[Clemens Tolboom](https://github.com/clemens-tolboom) +[cmw2196](https://github.com/cmw2196) +[Cody Scott](https://github.com/Siecje) +[Craig Willis](https://github.com/craig-willis) +[cristofercri](https://github.com/cristofercri) +[Curtis Maves](https://github.com/cmaves) +[cybertony](https://github.com/cybertony) +[Daisuke Taniwaki](https://github.com/dtaniwaki) +[Dalon Lobo](https://github.com/dalonlobo) +[danamer](https://github.com/danamer) +[Daniel Bachler](https://github.com/danyx23) +[Daniel Chalef](https://github.com/danielchalef) +[Daniel Hnyk](https://github.com/hnykda) +[danielpcs](https://github.com/danielpcs) +[Danny H](https://github.com/toblender) +[DataVictorEngineer](https://github.com/DataVictorEngineer) +[Dave Hirschfeld](https://github.com/dhirschfeld) +[Dave Porter](https://github.com/porterde) +[David Andersen](https://github.com/dtandersen) +[David John Gagne](https://github.com/djgagne) +[Davide](https://github.com/davidedelvento) +[Deleted user](https://github.com/ghost) +[Denis Shestakov](https://github.com/denshe) +[Dennis Kipping](https://github.com/dkipping) +[Derek Ludwig](https://github.com/dsludwig) +[DerekHeldtWerle](https://github.com/DerekHeldtWerle) +[DewinGoh](https://github.com/DewinGoh) +[Diogo](https://github.com/dmvieira) +[djknight1](https://github.com/djknight1) +[DmitrII Gerasimenko](https://github.com/kidig) +[Doug Blank](https://github.com/dsblank) +[Dr. Di Prodi](https://github.com/robomotic) +[Dr. Zoltán Katona](https://github.com/zkatona) +[Dylan Nelson](https://github.com/dnelson86) +[ebebpl](https://github.com/ebebpl) +[Eliran Bivas](https://github.com/bivas) +[eode](https://github.com/eode) +[Eran Pinhas](https://github.com/eran-pinhas) +[eric-leblouch](https://github.com/eric-leblouch) +[ericblau](https://github.com/ericblau) +[Erik LaBianca](https://github.com/easel) +[Erik Sundell](https://github.com/consideRatio) +[Ermakov Petr](https://github.com/ermakovpetr) +[erolosty](https://github.com/erolosty) +[Evan Savage](https://github.com/candu) +[Evert Rol](https://github.com/evertrol) +[Ezequiel Gioia](https://github.com/eze1981) +[fahadabbas91](https://github.com/fahadabbas91) +[farzadz](https://github.com/farzadz) +[foxlisimulation](https://github.com/foxlisimulation) +[frouzbeh](https://github.com/frouzbeh) +[Félix-Antoine Fortin](https://github.com/cmd-ntrf) +[Gabriel Abdalla Cavalcante](https://github.com/gcavalcante8808) +[Gabriel Fair](https://github.com/gabefair) +[Gaetan Semet](https://github.com/gsemet) +[Gang Chen](https://github.com/ssword) +[Gary Lucas](https://github.com/luck02) +[Georgiana Elena](https://github.com/GeorgianaElena) +[gerroon](https://github.com/gerroon) +[Giuseppe Attardi](https://github.com/attardi) +[Glen A Knight](https://github.com/glenak1911) +[Gonzalo Fernandez ordas](https://github.com/rainmanh) +[Guilherme Oenning](https://github.com/goenning) +[Guo Zhang](https://github.com/Guo-Zhang) +[gweis](https://github.com/gweis) +[Gábor Lipták](https://github.com/gliptak) +[Hagen Hoferichter](https://github.com/h4gen) +[hani1814](https://github.com/hani1814) +[Hans Permana](https://github.com/hans-permana) +[hhuuggoo](https://github.com/hhuuggoo) +[hichemken](https://github.com/hichemken) +[HT-Moh](https://github.com/HT-Moh) +[HuangHenghua](https://github.com/HuangHenghua) +[HuiWang](https://github.com/scially) +[Ian Carroll](https://github.com/itcarroll) +[Ian Stuart](https://github.com/perllaghu) +[Ivan Brezina](https://github.com/ibre5041) +[J Forde](https://github.com/jzf2101) +[J Gerard](https://github.com/jgerardsimcock) +[j08rebelo](https://github.com/j08rebelo) +[Jacob Matuskey](https://github.com/jmatuskey) +[Jacob Tomlinson](https://github.com/jacobtomlinson) +[Jaime Ferrando Huertas](https://github.com/jiwidi) +[James Swineson](https://github.com/Jamesits) +[jameshgrn](https://github.com/jameshgrn) +[Jan Niederau](https://github.com/Japhiolite) +[Jason Belsky](https://github.com/jbelsky) +[Jason Hu](https://github.com/Jameshzc) +[Jason Rigby](https://github.com/jasonrig) +[jason4zhu](https://github.com/jason4zhu) +[Jeff Whitworth](https://github.com/jwhitwo) +[Jeffrey Bush](https://github.com/coderforlife) +[jeffwji](https://github.com/jeffwji) +[Jessica B. Hamrick](https://github.com/jhamrick) +[jfleury-eidos](https://github.com/jfleury-eidos) +[Ji Ma](https://github.com/ma-ji) +[Jiren Jin](https://github.com/jinjiren) +[jiyer2016](https://github.com/jiyer2016) +[jlc175](https://github.com/jlc175) +[jmabry](https://github.com/jmabry) +[jmchandonia](https://github.com/jmchandonia) +[jmf](https://github.com/jmfcodes) +[Joe Hamman](https://github.com/jhamman) +[Joerg Klein](https://github.com/joergklein) +[John Chase](https://github.com/johnchase) +[John Readey](https://github.com/jreadey) +[John Shojaei](https://github.com/titan550) +[Jonathan Terhorst](https://github.com/terhorst) +[Jordan Miller](https://github.com/LegitStack) +[Josh Bode](https://github.com/joshbode) +[Joshua Milas](https://github.com/DeepHorizons) +[JP Moresmau](https://github.com/JPMoresmau) +[jpays](https://github.com/jpays) +[Juan Cruz-Benito](https://github.com/cbjuan) +[Julian Rüth](https://github.com/saraedum) +[Julien Chastang](https://github.com/julienchastang) +[Justin Ray Vrooman](https://github.com/vroomanj) +[Jürgen Hermann](https://github.com/jhermann) +[Kah Mun](https://github.com/kavemun) +[kangzebin](https://github.com/kangzebin) +[Kelly L. Rowland](https://github.com/kellyrowland) +[Kenan Erdogan](https://github.com/bitnik) +[Kerwin Sun](https://github.com/00Kai0) +[kevbutler](https://github.com/kevbutler) +[Kevin Bates](https://github.com/kevin-bates) +[khawarhere](https://github.com/khawarhere) +[kide007](https://github.com/kide007) +[Kim-Seonghyeon](https://github.com/Kim-Seonghyeon) +[kishitaku0630](https://github.com/kishitaku0630) +[Koshmaar](https://github.com/Koshmaar) +[Koustuv Sinha](https://github.com/koustuvsinha) +[krinsman](https://github.com/krinsman) +[Kristian Gregorius Hustad](https://github.com/KGHustad) +[Kristiyan](https://github.com/katsar0v) +[KSHITIJA SAHARAN](https://github.com/kshitija08) +[Kuriakin Zeng](https://github.com/kuriakinzeng) +[Kyla Harper](https://github.com/kyla-harper) +[Lachlan Musicman](https://github.com/datakid) +[Laurent Abbal](https://github.com/laurentabbal) +[Leo Gallucci](https://github.com/elgalu) +[Leopold Talirz](https://github.com/ltalirz) +[Li-Xian Chen](https://github.com/twbrandon7) +[Lisa Stillwell](https://github.com/lstillwe) +[ljb445300387](https://github.com/ljb445300387) +[Loïc Antoine Gombeaud](https://github.com/LoicAG) +[Loïc Estève](https://github.com/lesteve) +[Lucas Durand](https://github.com/lucasdurand) +[Lukasz Tracewski](https://github.com/tracek) +[m.fab](https://github.com/go-bears) +[Ma](https://github.com/ma010) +[mangecoeur](https://github.com/mangecoeur) +[Manish Kushwaha](https://github.com/manish0749) +[Marc Illien](https://github.com/jackblackCH) +[marinalopez2110](https://github.com/marinalopez2110) +[Mark Mirmelstein](https://github.com/markm42) +[Marlene Silva Marchena](https://github.com/msmarchena) +[Martin Gergov](https://github.com/marto1) +[Martin Zugnoni](https://github.com/martinzugnoni) +[Marvin Solano](https://github.com/marvin-solano) +[Marwan Baghdad](https://github.com/MrwanBaghdad) +[Matthias Bussonnier](https://github.com/Carreau) +[Matthias Klan](https://github.com/mklan) +[Matthias Lee](https://github.com/matthiaslee) +[Matthieu Boileau](https://github.com/boileaum) +[Max Mensing](https://github.com/madmax2012) +[mdivk](https://github.com/mdivk) +[Meesam Shah](https://github.com/meesam15) +[Michael Carroll](https://github.com/neffo) +[Michael Huttner](https://github.com/mhuttner) +[Michael Lovci](https://github.com/mlovci) +[Michael McCarthy](https://github.com/RonanMcCarthy) +[Michael Milligan](https://github.com/mbmilligan) +[Michael Pilosov](https://github.com/mathematicalmichael) +[michec81](https://github.com/michec81) +[Mike Croucher](https://github.com/mikecroucher) +[MikeSpark](https://github.com/MikeSpark) +[Min RK](https://github.com/minrk) +[MisterZ](https://github.com/Misteur-Z) +[Moritz Kirschner](https://github.com/cellador) +[Moritz Schlarb](https://github.com/moschlar) +[moskiGithub](https://github.com/moskiGithub) +[mpolidori](https://github.com/mpolidori) +[mrclttnz](https://github.com/mrclttnz) +[MubashirullahD](https://github.com/MubashirullahD) +[Muhammad-Imtiaz](https://github.com/Muhammad-Imtiaz) +[mxcheng2011](https://github.com/mxcheng2011) +[myidealab](https://github.com/myidealab) +[Naineel Shah](https://github.com/naineel) +[narala558](https://github.com/narala558) +[newturok](https://github.com/newturok) +[Ney Torres](https://github.com/Neyt) +[Nic Wayand](https://github.com/NicWayand) +[Nico Bellack](https://github.com/bellackn) +[nifuki](https://github.com/nifuki) +[Nils Werner](https://github.com/nils-werner) +[not4everybody](https://github.com/not4everybody) +[NotSharath](https://github.com/NotSharath) +[nschiraldi](https://github.com/nschiraldi) +[Nujjy](https://github.com/Nujjy) +[oscar6echo](https://github.com/oscar6echo) +[Paperone80](https://github.com/Paperone80) +[Patafix](https://github.com/Patafix) +[Paul Mazzuca](https://github.com/PaulMazzuca) +[Paul Shealy](https://github.com/paulshealy1) +[Paulo Roberto de Oliveira Castro](https://github.com/prcastro) +[Pav K](https://github.com/kalaytan) +[payalbhatia](https://github.com/payalbhatia) +[Peter Parente](https://github.com/parente) +[Peter Reid](https://github.com/ReidWeb) +[Phil Elson](https://github.com/pelson) +[Phil Fenstermacher](https://github.com/pcfens) +[Philipp Kats](https://github.com/Casyfill) +[phpdistiller](https://github.com/phpdistiller) +[phxedmond](https://github.com/phxedmond) +[Piotr](https://github.com/karpikpl) +[Pouria Hadjibagheri](https://github.com/xenatisch) +[powerLeePlus](https://github.com/powerLeePlus) +[Pratik Lal](https://github.com/pratik-lal) +[pydeepak](https://github.com/Deepakdubey90) +[Qcy](https://github.com/chaoyue729) +[R. C. Thomas](https://github.com/rcthomas) +[raghav130593](https://github.com/raghav130593) +[Rahul Sharma](https://github.com/rahulswimmer) +[Rama Krishna Jinka](https://github.com/rjinka) +[RBALAJI5](https://github.com/RBALAJI5) +[rbq](https://github.com/rbq) +[Richard C Gerkin](https://github.com/rgerkin) +[Richard Darst](https://github.com/rkdarst) +[Richard Huntrods](https://github.com/huntrods) +[richyanicky](https://github.com/richyanicky) +[Rob Nagler](https://github.com/robnagler) +[robin](https://github.com/rollbackchen) +[robotsp](https://github.com/robotsp) +[rothwewi](https://github.com/rothwewi) +[rushikeshraut777](https://github.com/rushikeshraut777) +[Ryan](https://github.com/ev1lm0nk3y) +[Ryan Abernathey](https://github.com/rabernat) +[Ryan Lovett](https://github.com/ryanlovett) +[Ryan McGuire](https://github.com/EnigmaCurry) +[rzuidhof](https://github.com/rzuidhof) +[Saiprasad Balasubramanian](https://github.com/backtrackbaba) +[Sam Manzer](https://github.com/samuelmanzer) +[samRddhimat](https://github.com/samRddhimat) +[Santosh](https://github.com/sdandey) +[Saranya411](https://github.com/Saranya411) +[Scott Crooks](https://github.com/sc250024) +[sdementen](https://github.com/sdementen) +[SeaDude](https://github.com/SeaDude) +[SergeyK1](https://github.com/SergeyK1) +[Shannon](https://github.com/jingsong-liu) +[Shi Pengcheng](https://github.com/shipengcheng1230) +[shibbas](https://github.com/shibbas) +[Shinichi TAMURA](https://github.com/tmshn) +[Shiva1789](https://github.com/Shiva1789) +[sidebo](https://github.com/sidebo) +[Sigurður Baldursson](https://github.com/sigurdurb) +[Simon Li](https://github.com/manics) +[Sindre Gulseth](https://github.com/sgulseth) +[SivaMaplelabs](https://github.com/SivaMaplelabs) +[sjillidimudi](https://github.com/sjillidimudi) +[skruse](https://github.com/skruse) +[smoulderme](https://github.com/smoulderme) +[Solaris](https://github.com/SolarisYan) +[Spencer Ogden](https://github.com/spencerogden) +[sreekanthmg](https://github.com/sreekanthmg) +[Steven B](https://github.com/sblack4) +[Steven Silvester](https://github.com/blink1073) +[StudyQuant](https://github.com/studyquant) +[Subhash](https://github.com/signinred) +[Suchit](https://github.com/asuchit) +[summerswallow](https://github.com/summerswallow) +[summerswallow-whi](https://github.com/summerswallow-whi) +[Søren Fuglede Jørgensen](https://github.com/fuglede) +[Taewon](https://github.com/tkang007) +[Tania Allard](https://github.com/trallard) +[Taposh Dutta Roy](https://github.com/taposh) +[techie879](https://github.com/techie879) +[ThibTrip](https://github.com/ThibTrip) +[Thomas Mendoza](https://github.com/tgmachina) +[thomas-rabiller-azimut](https://github.com/thomas-rabiller-azimut) +[Thong Kuah](https://github.com/kuahyeow) +[thongnnguyen](https://github.com/thongnnguyen) +[Tim Crone](https://github.com/tjcrone) +[Tim Head](https://github.com/betatim) +[Timothy Griffiths](https://github.com/timgriffiths) +[Timothy Liu](https://github.com/tlkh) +[Todd Gamblin](https://github.com/tgamblin) +[Tom](https://github.com/T0mWz) +[Tomer Leibovich](https://github.com/tomerleib) +[tregin](https://github.com/tregin) +[Tren Huang](https://github.com/spiketren) +[Tuhina Chatterjee](https://github.com/tuhina2020) +[Tyler Gregory](https://github.com/01100010011001010110010101110000) +[Uday](https://github.com/udaynaik) +[Udit Arora](https://github.com/uditarora) +[Vasu Gaur](https://github.com/gaurcs) +[Victor Lopez](https://github.com/victorcete) +[Vidit Agarwal](https://github.com/IamViditAgarwal) +[VidJa](https://github.com/VidJa) +[Vincent Feng](https://github.com/iVincentFeng) +[vishal49naik49](https://github.com/vishal49naik49) +[Vivek](https://github.com/II-VSB-II) +[Vivek Rai](https://github.com/raivivek) +[vivekbiet](https://github.com/vivekbiet) +[Vlad-Mihai Sima](https://github.com/vladmihaisima) +[Volker Braun](https://github.com/vbraun) +[wangcong](https://github.com/congfairy) +[Wangsoo Kim](https://github.com/wangsookim) +[whositwhatnow](https://github.com/whositwhatnow) +[Will](https://github.com/xuwaters) +[Will Starms](https://github.com/vilhelmen) +[Willem Pienaar](https://github.com/woop) +[Xavier Lange](https://github.com/xrl) +[YborBorn](https://github.com/YborBorn) +[YizTian](https://github.com/tony-tian) +[Yoav Tzelnick](https://github.com/yoavtzelnick) +[YoongHM](https://github.com/yoonghm) +[yugushihuang](https://github.com/yugushihuang) +[Yuvi Panda](https://github.com/yuvipanda) +[Yuze Ma](https://github.com/bobmayuze) +[Zac Flamig](https://github.com/zflamig) +[Zach Day](https://github.com/zacharied) +[Zachary Sailer](https://github.com/Zsailer) +[Zafer Cesur](https://github.com/zcesur) +[zmkhazi](https://github.com/zmkhazi) +[zneudl](https://github.com/zneudl) +[田进](https://github.com/EndlessTJ) +[邱雨波](https://github.com/CraftHeart) +[高彦涛](https://github.com/gytlinux) + +## 0.7 + +### 0.7.0 - [Alex Blackwell](https://en.wikipedia.org/wiki/Alex_Blackwell) - 2018-09-03 + +This release contains JupyterHub version 0.9.2, additional configuration options +and various bug fixes. + +**IMPORTANT:** This upgrade will require your users to stop their work at some +point and have their pod restarted. You may want to give them a heads up ahead +of time or do it during nighttime if none are active then. + +#### Upgrading from v0.6 + +If you are running `v0.5` of the chart, you should upgrade to `v0.6` first +before upgrading to `0.7.0`. You can find out what version you are using by +running `helm list`. + +Follow the steps below to upgrade from `v0.6` to `0.7.0`. + +##### 1. (Optional) Ensure the hub's and users' data isn't lost + +This step is optional, but a recommended safeguard when the hub's and users' +data is considered important. The changes makes the PersistentVolumes (PVs), +which represent storage (user data and hub database) remain even if the +PersistentVolumeClaims (PVCs) are deleted. The downside of this is that it +requires you to perform manual cleanup of PVs when you want to stop spending +money for the storage. + +```sh +# The script is a saftey measure and patches your PersistentVolumes (PV) to +# not be garbage collected if the PersistentVolumeClaim (PVC) are deleted. +NAMESPACE= + +# Ensure the hub's and users' data isn't lost +hub_and_user_pvs=($(kubectl get persistentvolumeclaim --no-headers --namespace $NAMESPACE | awk '{print $3}')) +for pv in ${hub_and_user_pvs[@]}; +do + kubectl patch persistentvolume $pv --patch '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}' +done +``` + +##### 2. Update Helm (v2.9.1+ required) + +```sh +# Update helm +curl https://raw.githubusercontent.com/kubernetes/helm/HEAD/scripts/get | bash + +# Update tiller (on the cluster) +helm init --upgrade --service-account=tiller + +# Verify the update +# NOTE: you may need to cancel and re-run the command, it should work within 30 +# seconds. +helm version +# VERIFY: Did it return both the client and server version? +# Client: &version.Version{SemVer:"v2.10.0", GitCommit:"9ad53aac42165a5fadc6c87be0dea6b115f93090", GitTreeState:"clean"} +# Server: &version.Version{SemVer:"v2.10.0", GitCommit:"9ad53aac42165a5fadc6c87be0dea6b115f93090", GitTreeState:"clean"} +``` + +##### 3. (Optional) Clean up pre-puller resources + +The pre-puller component of v0.6 could leave leftover resources after it finished, +instead of cleaning up after itself. +This script removes the pre-puller resources created by v0.6. + +```sh +# This script will delete resources that were meant to be temporary +# The bug that caused this is fixed in version 0.7.0 of the Helm chart +NAMESPACE= + +resource_types="daemonset,serviceaccount,clusterrole,clusterrolebinding,job" +for bad_resource in $(kubectl get $resource_types --namespace $NAMESPACE | grep '/pre-pull' | awk '{print $1}'); +do + kubectl delete $bad_resource --namespace $NAMESPACE --now +done + +kubectl delete $resource_types --selector hub.jupyter.org/deletable=true --namespace $NAMESPACE --now +``` + +##### 4. (Recommended) Clean up problematic revisions in your Helm release + +This step is recommended due to bugs in Helm that could cause your JupyterHub +Helm chart installation (release) to get stuck in an invalid state. +The symptoms are often that `helm upgrade` commands fail with the reason that some resource does or doesn't exist. + +```sh +# Look up the name of your Helm release (installation of a Helm chart) +helm list + +# Store the name of the Helm release +RELEASE_NAME= + +# Give yourself an overview of this release's revisions +helm history $RELEASE_NAME + +# Check if you have multiple revisions in a DEPLOYED status (a bug), or if you +# have old PENDING_UPGRADES or FAILED revisions (may be problematic). +helm history $RELEASE_NAME | grep --extended-regexp "DEPLOYED|FAILED|PENDING_UPGRADE" + +# If you have multiple revisions in DEPLOYED status, this script will clean up +# all configmaps except the latest with DEPLOYED status. +deployed_revisions=($(helm history $RELEASE_NAME | grep DEPLOYED | awk '{print $1}')) +for revision in ${deployed_revisions[@]::${#deployed_revisions[@]}-1}; +do + kubectl delete configmap $RELEASE_NAME.v$revision --namespace kube-system +done + +# It seems plausible that upgrade failures could have to do with revisions +# having a PENDING_UPGRADE or FAILED status in the revision history. To delete +# them run the following command. +kubectl delete configmap --selector "NAME=$RELEASE_NAME,STATUS in (FAILED,PENDING_UPGRADE)" --namespace kube-system +``` + +##### 5. Perform the upgrade + +**IMPORTANT:** Do not miss out on the `--force` flag! +`--force` is required due to changes in labelling of jupyterhub resources +in 0.7. +Helm cannot upgrade from the labelling scheme in 0.6 to that in 0.7 without `--force`, which deletes and recreates the deployments. + +```sh +RELEASE_NAME= +NAMESPACE= + +helm repo add jupyterhub https://hub.jupyter.org/helm-chart/ +helm repo update + +# NOTE: We need the --force flag to allow recreation of resources that can't be +# upgraded to the new state by a patch. +helm upgrade $RELEASE_NAME jupyterhub/jupyterhub --install \ + --force \ + --version=0.7.0 \ + --namespace=$NAMESPACE \ + --values config.yaml \ + --timeout 1800 +``` + +##### 6. Manage active users + +Active users with running pods must restart their pods. If they don't the next +time they attempt to access their server they may end up with `{“error”: “invalid_redirect_uri”, “error_description”: “Invalid redirect URI”}`. + +You have the power to force this to happen, but it will abort what they are +doing right now. If you want them to be able to do it in their own pace, you +could use the `/hub/admin` path and shut them down manually when they are done. + +``` +NAMESPACE= + +# Inspect what users are currently running +kubectl get pod --selector component=singleuser-server --namespace $NAMESPACE + +# Force all of them to shutdown their servers, and ensure the hub gets to +# realize that happened through a restart. +kubectl delete pod --selector component=singleuser-server --namespace $NAMESPACE +kubectl delete pod --selector component=hub --namespace $NAMESPACE +``` + +##### Troubleshooting - Cleanup of cluster + +If things fail, you can try the following before installing the chart. If you +decide to take these steps, we recommend step 1 is taken first in order to not +loose data and that you ensure the old data is made available by the +troubleshooting step below. + +```sh +RELEASE_NAME= + +# WARNING: Deletes everything installed by the Helm chart! +# WARNING: If you have not changed the reclaim policy of the hub in step 1, the +# hub never be able to remember anything about past users. Also note +# that even if you have taken step 1, you must also make the PVs become +# `Available` again before the hub starts up again. +# NOTE: This does not include user pods or user storage PVCs as they have been +# indirectly created by KubeSpawner +helm delete $RELEASE_NAME --purge + +# WARNING: Deletes everything within the namespace! +# WARNING: If you have not changed the reclaim policy of the hub and users in +# step 1, the hub's stored information about the users and the user's +# storage will be lost forever. Also note that even if you have taken +# step 1, you must also make the hub and users PVs become `Available` +# before the hub and users startup again. +kubectl delete namespace +``` + +If you took these steps and step 1, you should probably right now continue with +the next troubleshooting section about making `Released` PVs `Available` for +reuse. + +##### Troubleshooting - Make `Released` PVs `Available` for reuse + +If you followed step 1 and 2, you can after cleanup of a cluster reuse the old +hub's and users' storage if you do this step before you installs the Helm chart +again. + +In more technical words: if you have deleted PVCs such as `hub-db-dir` or +`claim-anyusername`, their PVs will end in a `Released` state assuming they had +a `reclaimPolicy` set to `Retain`. To make use of these PVs again, we must make +them `Available` for the to future PVCs that needs a PV to bind to. + +```sh +NAMESPACE= + +# Ensure the hub's and users' PVs are made `Available` again +hub_and_user_pvs=($(kubectl get persistentvolume | grep -E "Released.+$NAMESPACE/(hub-db-dir|claim-)" | awk '{print $1}')) +for pv in ${hub_and_user_pvs[@]}; +do + kubectl patch persistentvolume $pv --patch '{"spec":{"claimRef":{"uid":null}}}}' +done + +# Ensure you don't have any PVCs in the lost state +lost_pvcs=($(kubectl get persistentvolumeclaim --namespace $NAMESPACE | grep -E "(hub-db-dir|claim-).+Lost" | awk '{print $1}')) +for pvc in ${lost_pvcs[@]}; +do + echo kubectl delete persistentvolumeclaim $pvc --namespace $NAMESPACE +done +``` + +#### Contributors + +[A. Tan ](https://github.com/amanda-tan) +[Aaron Culich](https://github.com/aculich) +[abhismvit](https://github.com/abhismvit) +[AC](https://github.com/miramar-labs) +[AcademicAdmin](https://github.com/AcademicAdmin) +[Adam Grant](https://github.com/harmon) +[Adam Huffman](https://github.com/verdurin) +[Adam Thornton](https://github.com/athornton) +[Adam Tilghman](https://github.com/agt-ucsd) +[Adam-Origamiiris](https://github.com/Adam-Origamiiris) +[Afreen Rahman](https://github.com/Afreen04) +[agustaf](https://github.com/agustaf) +[agustiin](https://github.com/agustiin) +[aisensiy](https://github.com/aisensiy) +[Ajay Changulani](https://github.com/Ajay-Changulani) +[Akhil Lawrence](https://github.com/akhilputhiry) +[akkibatra](https://github.com/akkibatra) +[Alan King](https://github.com/kingaj12) +[Albert J. de Vera](https://github.com/ajdevera) +[Alejandro del Castillo](https://github.com/adelcast) +[Alejandro Gastón Alvarez](https://github.com/alealv) +[Aleksandr Blekh](https://github.com/ablekh) +[Alex Leith](https://github.com/alexgleith) +[Alex Marandon](https://github.com/amarandon) +[Alex Mellnik](https://github.com/amellnik) +[Alex Moore](https://github.com/Akmoore7) +[Alex Morreale](https://github.com/AlexMorreale) +[Alex Tasioulis](https://github.com/alex1x) +[Alexander](https://github.com/bzz) +[Alexander Hendorf](https://github.com/alanderex) +[Alexander Kruzhkov](https://github.com/YOxan) +[Alexander Morley](https://github.com/alexmorley) +[Alexander Schwartzberg](https://github.com/aeksco) +[Allen Downey](https://github.com/AllenDowney) +[AlphaSRE](https://github.com/AlphaSRE) +[Alramzey](https://github.com/Alramzey) +[amangarg96](https://github.com/amangarg96) +[Amirahmad Khordadi](https://github.com/khordadi) +[Amit Rathi](https://github.com/amit1rrr) +[Analect](https://github.com/Analect) +[anasos](https://github.com/anasos) +[Andre Celere](https://github.com/acelere) +[Andrea Abelli](https://github.com/abelliae) +[Andrea Turrini](https://github.com/andreat) +[Andrea Zonca](https://github.com/zonca) +[Andreas Heider](https://github.com/ah-) +[Andrew Berger](https://github.com/rueberger) +[Andrew Melo](https://github.com/PerilousApricot) +[andrewcheny](https://github.com/andrewcheny) +[András Tóth](https://github.com/tothandras) +[André Luiz Diniz](https://github.com/andrelu) +[Andy Berner](https://github.com/andybrnr) +[Andy Doddington](https://github.com/Andy-Doddington) +[angus evans](https://github.com/joingithubkor) +[Anirudh Vyas](https://github.com/AnirudhVyas) +[Ankit ](https://github.com/ankitml) +[Ankit Sharma](https://github.com/ankitksharma) +[ankit2894](https://github.com/ankit2894) +[Anthony Suen](https://github.com/anthonysuen) +[Anton Akhmerov](https://github.com/akhmerov) +[Antonino Ingargiola](https://github.com/tritemio) +[Antonio Serrano](https://github.com/AntonioSerrano) +[AranVinkItility](https://github.com/AranVinkItility) +[Arda Aytekin](https://github.com/aytekinar) +[Ariel Balter](https://github.com/abalter) +[Ariel Rokem](https://github.com/arokem) +[arkroop](https://github.com/arkroop) +[Arthur](https://github.com/konfiot) +[arthur](https://github.com/ppLorins) +[Arthur Koziel](https://github.com/arthurk) +[ArvinSiChuan](https://github.com/ArvinSiChuan) +[aseishas](https://github.com/aseishas) +[at-cchaloux](https://github.com/at-cchaloux) +[atullo2](https://github.com/atullo2) +[Bastian Greshake Tzovaras](https://github.com/gedankenstuecke) +[bbarney213](https://github.com/bbarney213) +[bbrauns](https://github.com/bbrauns) +[Ben Chuanlong Du](https://github.com/dclong) +[Benjamin Paz](https://github.com/bendavidpaz) +[Benoit Rospars](https://github.com/brospars) +[BerserkerTroll](https://github.com/BerserkerTroll) +[BhagyasriYella](https://github.com/BhagyasriYella) +[bhavybarca](https://github.com/bhavybarca) +[Birgetit](https://github.com/Birgetit) +[bitnik](https://github.com/bitnik) +[Borislav Aymaliev](https://github.com/aymaliev) +[Botty Dimanov](https://github.com/bottydim) +[Brad Skaggs](https://github.com/bskaggs) +[Brandon Sharitt](https://github.com/bsharitt) +[Brent](https://github.com/xuande) +[Brian E. Granger](https://github.com/ellisonbg) +[Brian Ray](https://github.com/brianray) +[Bruce Beauchamp](https://github.com/Prettyfield) +[Bruce Chiarelli](https://github.com/bccomm) +[Byă](https://github.com/hungbya) +[Camilla](https://github.com/Winterflower) +[Camilo Núñez Fernández](https://github.com/camilo-nunez) +[Cara](https://github.com/cara-a-k) +[carluri](https://github.com/carluri) +[Carol Willing](https://github.com/willingc) +[Caspian](https://github.com/Cas-pian) +[chack05](https://github.com/chack05) +[chang-zhijie](https://github.com/chang-zhijie) +[chaomaer](https://github.com/chaomaer) +[chaoyue729](https://github.com/chaoyue729) +[Charles Forelle](https://github.com/cforelle) +[chenyg0911](https://github.com/chenyg0911) +[Chester Li](https://github.com/chaoleili) +[Chia-liang Kao](https://github.com/clkao) +[Chico Venancio](https://github.com/chicocvenancio) +[Chris Fournier](https://github.com/cfournie) +[Chris Holdgraf](https://github.com/choldgraf) +[Chris Seal](https://github.com/cmseal) +[Chris Van Pelt](https://github.com/vanpelt) +[Christiaan Swanepoel](https://github.com/christiaanjs) +[Christian Alis](https://github.com/ianalis) +[Christian Hotz-Behofsits](https://github.com/inkrement) +[Christian Mesh](https://github.com/cam72cam) +[Christian Moscardi](https://github.com/cmoscardi) +[Christine Banek](https://github.com/cbanek) +[Christopher Hench](https://github.com/henchc) +[ckbhatt](https://github.com/ckbhatt) +[Claudius Mbemba](https://github.com/User1m) +[cloud-science](https://github.com/cloud-science) +[Cody Scott](https://github.com/Siecje) +[Cord](https://github.com/CordThomas) +[Cory Johns](https://github.com/johnsca) +[cqzlxl](https://github.com/cqzlxl) +[Craig Willis](https://github.com/craig-willis) +[Curtis Maves](https://github.com/cmaves) +[cyberquasar](https://github.com/cyberquasar) +[cybertony](https://github.com/cybertony) +[cyberyor](https://github.com/cyberyor) +[Daisuke Taniwaki](https://github.com/dtaniwaki) +[daleshsd](https://github.com/daleshsd) +[Dan Allan](https://github.com/danielballan) +[Dan Hoerst](https://github.com/DanHoerst) +[Dan Lidral-Porter](https://github.com/aperiodic) +[Daniel](https://github.com/daniel-ciocirlan) +[Daniel Morrison](https://github.com/draker42) +[danielmaitre](https://github.com/danielmaitre) +[danielrychel](https://github.com/danielrychel) +[Dario Romero](https://github.com/darioromero) +[darky2004](https://github.com/darky2004) +[DataVictorEngineer](https://github.com/DataVictorEngineer) +[Dave Aitken](https://github.com/actionshrimp) +[Dave Hirschfeld](https://github.com/dhirschfeld) +[David Bath](https://github.com/davidbath) +[David Doherty](https://github.com/dado0583) +[David Kügler](https://github.com/dkuegler) +[David Maxson](https://github.com/scnerd) +[David Napier](https://github.com/dnapier) +[David Pérez Comendador](https://github.com/perez1987) +[David Pérez-Suárez](https://github.com/dpshelio) +[David Sanftenberg](https://github.com/dbsanfte) +[Davide](https://github.com/davidedelvento) +[deep-42-thought](https://github.com/deep-42-thought) +[Deleted user](https://github.com/ghost) +[DerekHeldtWerle](https://github.com/DerekHeldtWerle) +[Dhawal Patel](https://github.com/dhawal55) +[disimone](https://github.com/disimone) +[DmitrII Gerasimenko](https://github.com/kidig) +[Dmitry Mishin](https://github.com/dimm0) +[Dominic Suciu](https://github.com/domsooch) +[Don Kelly](https://github.com/karfai) +[Doug Holt](https://github.com/dholt) +[Dragos Cojocari](https://github.com/dragos-cojocari) +[dturaev](https://github.com/dturaev) +[Dwight Townsend](https://github.com/townsenddw) +[Dylan Lentini](https://github.com/dyltini) +[Eamon Keane](https://github.com/EamonKeane) +[Eddy Elbrink](https://github.com/elbrinke) +[Emmanuel Gomez](https://github.com/emmanuel) +[Enol Fernández](https://github.com/enolfc) +[epoch1970](https://github.com/epoch1970) +[Eric Charles](https://github.com/echarles) +[Erik Sundell](https://github.com/consideRatio) +[Ermakov Petr](https://github.com/ermakovpetr) +[ernestmartinez](https://github.com/ernestmartinez) +[EtienneDesticourt](https://github.com/EtienneDesticourt) +[Evan](https://github.com/eexe1) +[Evan Van Dam](https://github.com/evandam) +[Evert Rol](https://github.com/evertrol) +[eylenth](https://github.com/eylenth) +[Ezequiel Gioia](https://github.com/eze1981) +[fahadabbas91](https://github.com/fahadabbas91) +[Faras Sadek](https://github.com/farassadek) +[forbxy](https://github.com/forbxy) +[Francisco Zamora-Martinez](https://github.com/pakozm) +[FU Zhipeng](https://github.com/gavin971) +[Fyodor](https://github.com/lgg) +[Félix-Antoine Fortin](https://github.com/cmd-ntrf) +[G YASHASVI](https://github.com/iamyashasvi) +[Gaetan Semet](https://github.com/gsemet) +[Gaëtan Lehmann](https://github.com/glehmann) +[gbrahmi](https://github.com/gbrahmi) +[George Jose](https://github.com/G2Jose) +[Gerben Welter](https://github.com/GerbenWelter) +[Gerhard Burger](https://github.com/burgerga) +[GladysNalvarte](https://github.com/GladysNalvarte) +[Glen A Knight](https://github.com/glenak1911) +[Graham Dumpleton](https://github.com/GrahamDumpleton) +[grant-guo](https://github.com/grant-guo) +[GRC](https://github.com/gaorongchao) +[Guillaume EB](https://github.com/guillaumeeb) +[guimou](https://github.com/guimou) +[Guo Zhang](https://github.com/Guo-Zhang) +[gweis](https://github.com/gweis) +[Hagen Hoferichter](https://github.com/h4gen) +[hanbeibei](https://github.com/hanbeibei) +[hani1814](https://github.com/hani1814) +[Hans Petter Bieker](https://github.com/hpbieker) +[happytest143](https://github.com/happytest143) +[Hassan Mudassir](https://github.com/hassanmudassir-rzt) +[Helder Rodrigues](https://github.com/HelderGualberto) +[hemantasingh](https://github.com/hemantasingh) +[Henddher Pedroza](https://github.com/wjehenddher) +[hjclub123](https://github.com/hjclub123) +[huhuhang](https://github.com/huhuhang) +[Hunter Jackson](https://github.com/hunterjackson) +[Ian](https://github.com/yfc845) +[Indrajeet Singh](https://github.com/itsindra) +[ironv](https://github.com/ironv) +[IssacPan](https://github.com/IssacPan) +[Ivan Grbavac](https://github.com/grbinho) +[J Forde](https://github.com/jzf2101) +[J Gerard](https://github.com/jgerardsimcock) +[Jacob Tomlinson](https://github.com/jacobtomlinson) +[James Curtin](https://github.com/jamescurtin) +[James Davidheiser](https://github.com/jdavidheiser) +[James Londal](https://github.com/jlondal) +[James Veitch](https://github.com/darth-veitcher) +[Jan Kalo](https://github.com/JanKalo) +[Jason Kuruzovich](https://github.com/jkuruzovich) +[Jason Williams](https://github.com/JasonJWilliamsNY) +[jason4zhu](https://github.com/jason4zhu) +[javin-gn](https://github.com/javin-gn) +[Jeremie Vallee](https://github.com/jeremievallee) +[Jeremy Lewi](https://github.com/jlewi) +[Jeremy Tuloup](https://github.com/jtpio) +[Jerry Schuman](https://github.com/pingthings) +[Jesse Cai](https://github.com/jcaip) +[Jesse Kinkead](https://github.com/jkinkead) +[Jesse Zhang](https://github.com/EmptyCrown) +[Jessica Wong](https://github.com/jessawong) +[Jim Basney](https://github.com/jbasney) +[Jim Hendricks](https://github.com/jhendric98) +[Jiri Kuncar](https://github.com/jirikuncar) +[jlsimms](https://github.com/jlsimms) +[jm2004](https://github.com/jm2004) +[Joakim](https://github.com/Sefriol) +[JocelynDelalande](https://github.com/JocelynDelalande) +[Joe Hamman](https://github.com/jhamman) +[Joel Pfaff](https://github.com/joelpfaff) +[John Kaltenbach](https://github.com/jkbach) +[John Readey](https://github.com/jreadey) +[johnbotsis](https://github.com/johnbotsis) +[johnkpark](https://github.com/johnkpark) +[johnpaulantony](https://github.com/johnpaulantony) +[Jonas Adler](https://github.com/adler-j) +[Jonathan](https://github.com/yocode) +[Jonathan Brant](https://github.com/jbrant) +[Jonathan Wheeler](https://github.com/jondoesntgit) +[jonny86](https://github.com/jonny86) +[Joost W. Döbken](https://github.com/JWDobken) +[Jose Manuel Monsalve Diaz](https://github.com/josemonsalve2) +[Josh Barnes](https://github.com/jcb91) +[Josh Temple](https://github.com/joshtemple) +[João Barreto](https://github.com/JoaoBarreto) +[jpolchlo](https://github.com/jpolchlo) +[JPUnD](https://github.com/JPUnD) +[Juan Cabanela](https://github.com/JuanCab) +[Julien Chastang](https://github.com/julienchastang) +[Jurian Kuyvenhoven](https://github.com/JurianK) +[Justin Holmes](https://github.com/sherl0cks) +[Justin Moen](https://github.com/superquest) +[justkar4u](https://github.com/justkar4u) +[JYang25](https://github.com/JYang25) +[Jürgen Hermann](https://github.com/jhermann) +[kakzhetak](https://github.com/kakzhetak) +[kaliko](https://github.com/mxjeff) +[Kam Kasravi](https://github.com/kkasravi) +[Kannan Kumar](https://github.com/kannankumar) +[karthikpitchaimani](https://github.com/karthikpitchaimani) +[Kenneth Lyons](https://github.com/ixjlyons) +[Kevin P. Fleming](https://github.com/kpfleming) +[kevkid](https://github.com/kevkid) +[Kirill Dubovikov](https://github.com/kdubovikov) +[Knarfux](https://github.com/fbessou) +[Ko Ohashi](https://github.com/kouohhashi) +[krinsman](https://github.com/krinsman) +[KrisL](https://github.com/gixita) +[Kristiyan](https://github.com/katsar0v) +[lambertjosh](https://github.com/lambertjosh) +[Lars Biemans](https://github.com/lbiemans) +[Leo Gallucci](https://github.com/elgalu) +[leolurunhe](https://github.com/leolurunhe) +[Leopold Talirz](https://github.com/ltalirz) +[LeoPsidom](https://github.com/leopsidom) +[lfzyx](https://github.com/lfzyx) +[lgc019](https://github.com/lgc019) +[Lifubang](https://github.com/lifubang) +[liusztc09](https://github.com/liusztc09) +[liuzhliang](https://github.com/liuzhliang) +[llancellotti](https://github.com/llancellotti) +[lmerli84](https://github.com/lmerli84) +[loginoff](https://github.com/loginoff) +[Louis Garman](https://github.com/leg100) +[Luca De Feo](https://github.com/defeo) +[Luca Grazioli](https://github.com/Luke035) +[Lucas Durand](https://github.com/lucasdurand) +[Lucas Kushner](https://github.com/lphk92) +[Lukasz Lempart](https://github.com/wookasz) +[Lukasz Tracewski](https://github.com/tracek) +[Lutz Behnke](https://github.com/cypherfox) +[M Pacer](https://github.com/mpacer) +[Maciej Sawicki](https://github.com/viroos) +[madsi1m](https://github.com/madsi1m) +[mak-aravind](https://github.com/mak-aravind) +[Malin Aandahl](https://github.com/MalinAan) +[Manjukb](https://github.com/Manjukb) +[Marc BUFFAT](https://github.com/mbuffat) +[marciocourense](https://github.com/marciocourense) +[Marco Pleines](https://github.com/MarcoMeter) +[Marcus Hunger](https://github.com/fnordian) +[Marcus Levine](https://github.com/marcusianlevine) +[Mario Campos](https://github.com/mario-campos) +[Marius van Niekerk](https://github.com/mariusvniekerk) +[Mark Mirmelstein](https://github.com/markm42) +[marmaduke woodman](https://github.com/maedoc) +[Martin Forde](https://github.com/mforde84) +[Martín Anzorena](https://github.com/martjanz) +[maryamdev](https://github.com/maryamdev) +[Mas](https://github.com/airtime166) +[mascarom](https://github.com/mascarom) +[Mathew Blonc](https://github.com/blonc) +[Matt Hansen](https://github.com/hansen-m) +[Matteo Ipri](https://github.com/matteoipri) +[matthdan](https://github.com/matthdan) +[Matthew Bray](https://github.com/mattjbray) +[Matthew Rocklin](https://github.com/mrocklin) +[Matthias Bussonnier](https://github.com/Carreau) +[Matthias Klan](https://github.com/mklan) +[mattvw](https://github.com/mattvw) +[Max Joseph](https://github.com/mbjoseph) +[Maxim Moinat](https://github.com/MaximMoinat) +[mdivk](https://github.com/mdivk) +[Mereep](https://github.com/Mereep) +[merlin1608](https://github.com/merlin1608) +[Micah](https://github.com/micahscopes) +[Micah Smith](https://github.com/micahjsmith) +[Michael Huttner](https://github.com/mhuttner) +[Michael Milligan](https://github.com/mbmilligan) +[Michael Ransley](https://github.com/mransley) +[michec81](https://github.com/michec81) +[Michele Bertasi](https://github.com/mbrt) +[Miguel Caballer](https://github.com/micafer) +[Mike Hamer](https://github.com/mikehamer) +[Min RK](https://github.com/minrk) +[MincingWords](https://github.com/MincingWords) +[MisterZ](https://github.com/david-dumas) +[mohanamurali7](https://github.com/mohanamurali7) +[Mohit](https://github.com/Mohitsharma44) +[Monica Dessole](https://github.com/mdessole) +[moskiGithub](https://github.com/moskiGithub) +[mrkjones1979](https://github.com/mrkjones1979) +[mzilinski](https://github.com/mzilinski) +[n3f](https://github.com/n3f) +[Naeem Rashid](https://github.com/naeemkhan12) +[Naineel Shah](https://github.com/naineel) +[NaizEra](https://github.com/NaizEra) +[nauhpc](https://github.com/nauhpc) +[ndiy](https://github.com/ndiy) +[Neelanshu92](https://github.com/Neelanshu92) +[Nehemiah I. Dacres](https://github.com/dacresni) +[Neth Six](https://github.com/nethsix) +[ngokhoa96](https://github.com/ngokhoa96) +[Nick Brown](https://github.com/uptownnickbrown) +[Nickolaus D. Saint](https://github.com/NickolausDS) +[nickray](https://github.com/nickray) +[Nico Bellack](https://github.com/bellackn) +[Nicolas M. Thiéry](https://github.com/nthiery) +[Nikolay Dandanov](https://github.com/ndandanov) +[Nikolay Voronchikhin](https://github.com/nikolayvoronchikhin) +[niveau0](https://github.com/niveau0) +[Norman Gray](https://github.com/nxg) +[ogre0403](https://github.com/ogre0403) +[Ola Tarkowska](https://github.com/ola-t) +[oneklc](https://github.com/oneklc) +[OpenThings](https://github.com/openthings) +[ormskirk77](https://github.com/ormskirk77) +[P.J. Little](https://github.com/pjlittle) +[Pat W](https://github.com/patwoowong) +[Patafix](https://github.com/Patafix) +[Paul Adams](https://github.com/p5a0u9l) +[Paul Laskowski](https://github.com/paul-laskowski) +[Paul Mazzuca](https://github.com/PaulMazzuca) +[Paulo Roberto de Oliveira Castro](https://github.com/prcastro) +[Pav K](https://github.com/kalaytan) +[pedrovgp](https://github.com/pedrovgp) +[pekosro](https://github.com/pekosro) +[Peter Majchrak](https://github.com/petoknm) +[pgarapon](https://github.com/pgarapon) +[Phil Fenstermacher](https://github.com/pcfens) +[philippschw](https://github.com/philippschw) +[Phuong Cao](https://github.com/pmcao) +[picca](https://github.com/picca) +[Pierre Accorsi](https://github.com/paccorsi) +[Pinakibiswasdevops](https://github.com/Pinakibiswasdevops) +[Pius Nyakoojo](https://github.com/PiusNyakoojo) +[pjamason](https://github.com/pjamason) +[Pouria Hadjibagheri](https://github.com/xenatisch) +[Prabhu Kasinathan](https://github.com/prabhu1984) +[Pramod Rizal](https://github.com/prkriz) +[Pranay Hasan Yerra](https://github.com/pranayhasan) +[Prateek](https://github.com/prateekpg2455) +[prateek2408](https://github.com/prateek2408) +[Prerak Mody](https://github.com/prerakmody) +[Przybyszo](https://github.com/Przybyszo) +[psnx](https://github.com/psnx) +[pydo](https://github.com/yonghuming) +[pyjones1](https://github.com/pyjones1) +[R. C. Thomas](https://github.com/rcthomas) +[Rachidramadan1990](https://github.com/Rachidramadan1990) +[radudragusin](https://github.com/radudragusin) +[Rafael Ladislau](https://github.com/rafael-ladislau) +[Rafael Mejia](https://github.com/rafmesal) +[raghu20ram](https://github.com/raghu20ram) +[raja](https://github.com/raksja) +[Ramin](https://github.com/transfluxus) +[Ranjit](https://github.com/ranjitiyer) +[Raphael Nestler](https://github.com/rnestler) +[RaRam](https://github.com/RaRam) +[Raviraju Vysyaraju](https://github.com/ravirajuv) +[reddyvenu](https://github.com/reddyvenu) +[Ricardo Rocha](https://github.com/rochaporto) +[Rich Signell](https://github.com/rsignell-usgs) +[Richard Caunt](https://github.com/psyvision) +[Richard Darst](https://github.com/rkdarst) +[Richard England](https://github.com/renglandatsmu) +[Richard Ting](https://github.com/richardtin) +[Rizwan Saeed](https://github.com/rizwansaeed) +[Rob](https://github.com/rtruxal) +[Robert Casey](https://github.com/rcasey-iris) +[Robert Drysdale](https://github.com/robdrysdale) +[Robert Jiang ](https://github.com/robert-juang) +[Robert Schroll](https://github.com/rschroll) +[robin](https://github.com/rollbackchen) +[Robin](https://github.com/robmarkcole) +[Robin Scheibler](https://github.com/fakufaku) +[roemer2201](https://github.com/roemer2201) +[Rok Roškar](https://github.com/rokroskar) +[Roman Gorodeckij](https://github.com/holms) +[roversne](https://github.com/roversne) +[Roy Wedge](https://github.com/rwedge) +[Royi](https://github.com/RoyiAvital) +[Rui Zhang](https://github.com/zhangruiskyline) +[Ruslan Usifov](https://github.com/tantra35) +[Ryan Abernathey](https://github.com/rabernat) +[Ryan Lovett](https://github.com/ryanlovett) +[rydeng](https://github.com/rydeng) +[sabarnwa](https://github.com/sabarnwa) +[sabyasm](https://github.com/sabyasm) +[sadanand25](https://github.com/sadanand25) +[Sam Manzer](https://github.com/samuelmanzer) +[Sambaiah Kilaru](https://github.com/ksambaiah) +[samy](https://github.com/goforthanddie) +[Sangram Gaikwad](https://github.com/sangramga) +[sanjaydatasciencedojo](https://github.com/sanjaydatasciencedojo) +[Sanmati Jain](https://github.com/jainsanmati) +[saransha](https://github.com/saransha) +[Saranya411](https://github.com/Saranya411) +[sarath145p](https://github.com/sarath145p) +[Satendra Kumar](https://github.com/satendrakumar) +[saurav maharjan](https://github.com/saurssauravjs) +[saurs saurav](https://github.com/isaurssaurav) +[SB](https://github.com/SofianeB) +[sbailey-auro](https://github.com/sbailey-auro) +[Scott Crooks](https://github.com/sc250024) +[Scott Sanderson](https://github.com/ssanderson) +[SeaDude](https://github.com/SeaDude) +[semanticyongjia](https://github.com/semanticyongjia) +[serlina](https://github.com/serlina) +[Seshadri Ramaswami](https://github.com/sesh1989) +[shalan7](https://github.com/shalan7) +[Shana Matthews](https://github.com/shanamatthews) +[Shannon](https://github.com/jingsong-liu) +[Shantanu Singh](https://github.com/shantanusingh16) +[Shengxin Huang](https://github.com/FukoH) +[shilpam11](https://github.com/shilpam11) +[Shiva Prasanth](https://github.com/cedric05) +[shreddd](https://github.com/shreddd) +[Shuo YU](https://github.com/collinwo) +[Sigurður Baldursson](https://github.com/sigurdurb) +[Simon Li](https://github.com/manics) +[Sirawit Pongnakintr](https://github.com/s6007589) +[SivaMaplelabs](https://github.com/SivaMaplelabs) +[smiller5678](https://github.com/smiller5678) +[srican](https://github.com/srican) +[srini_b](https://github.com/Srinivasb0) +[Stanislav Nazmutdinov](https://github.com/PrintScr) +[stczwd](https://github.com/stczwd) +[Stefano Nicotri](https://github.com/stefanonicotri) +[Stefano Taschini](https://github.com/taschini) +[Stephanie Gott](https://github.com/gottsme) +[Stephen Lecrenski](https://github.com/slecrenski) +[Stephen Pascoe](https://github.com/stephenpascoe) +[Stephen Sackett](https://github.com/ssackett) +[Steven Silvester](https://github.com/blink1073) +[Stéphane Pouyllau](https://github.com/spouyllau) +[sudheer0553](https://github.com/sudheer0553) +[Sugu Sougoumarane](https://github.com/sougou) +[Suman Addanki](https://github.com/suman724) +[summerswallow](https://github.com/summerswallow) +[summerswallow-whi](https://github.com/summerswallow-whi) +[sundeepChandhoke](https://github.com/sundeepChandhoke) +[Sunip Mukherjee](https://github.com/sunipkmukherjee) +[svzdvdoptum](https://github.com/svzdvdoptum) +[swgong](https://github.com/sw-gong) +[Sylvain Desroziers](https://github.com/sdesrozis) +[syutbai](https://github.com/syutbai) +[T. George](https://github.com/tgeorgeux) +[tankeryang](https://github.com/tankeryang) +[TapasSpark](https://github.com/TapasSpark) +[Tassos Sarbanes](https://github.com/sarbanes) +[teddy Kossoko](https://github.com/KOSSOKO) +[tgamal](https://github.com/tgamal) +[Thomas Ashish Cherian](https://github.com/PandaWhoCodes) +[Thomas Kluyver](https://github.com/takluyver) +[Thomas Mendoza](https://github.com/tgmachina) +[thongnnguyen](https://github.com/thongnnguyen) +[Thoralf Gutierrez](https://github.com/thoralf-gutierrez) +[Tim Crone](https://github.com/tjcrone) +[Tim Freund](https://github.com/timfreund) +[Tim Head](https://github.com/betatim) +[Tim Kennell Jr.](https://github.com/tikenn) +[Tim Klever](https://github.com/tklever) +[Tim Shi](https://github.com/strin) +[TimKreuzer](https://github.com/TimKreuzer) +[Tirthankar Chakravarty](https://github.com/tchakravarty) +[titansmc](https://github.com/titansmc) +[Tobias Morville](https://github.com/TMorville) +[tobiaskaestner](https://github.com/tobiaskaestner) +[Tom Davidson](https://github.com/tjd2002) +[Tom Kwong](https://github.com/tk3369) +[Tom O'Connor](https://github.com/ichasepucks) +[Tomas Barton](https://github.com/deric) +[Tommaso Fabbri](https://github.com/tfabbri) +[Tyler Erickson](https://github.com/tylere) +[tzujan](https://github.com/tzujan) +[uday2002](https://github.com/uday2002) +[Umar Sikander](https://github.com/umar-sik) +[UsDAnDreS](https://github.com/UsDAnDreS) +[Vaclav Pavlin](https://github.com/vpavlin) +[Varun M S](https://github.com/meranamvarun) +[Victor Paraschiv](https://github.com/vicpara) +[vishwesh5](https://github.com/vishwesh5) +[Vladimir Kozhukalov](https://github.com/kozhukalov) +[vpvijay87](https://github.com/vpvijay87) +[W.](https://github.com/ManifoldFR) +[wangaiwudi](https://github.com/wangaiwudi) +[Wei Hao](https://github.com/whao) +[weih1121](https://github.com/weih1121) +[weimindong2016](https://github.com/weimindong2016) +[whitebluecloud](https://github.com/whitebluecloud) +[whositwhatnow](https://github.com/whositwhatnow) +[will](https://github.com/zsluedem) +[Will Starms](https://github.com/vilhelmen) +[William H](https://github.com/sylus) +[William Hosford](https://github.com/whosford) +[wtsyang](https://github.com/wtsyang) +[XIAHUALOU](https://github.com/XIAHUALOU) +[xuhuijun](https://github.com/xuhuijun) +[Y-L-18](https://github.com/Y-L-18) +[yee379](https://github.com/yee379) +[yeisonseverinopucv](https://github.com/yeisonseverinopucv) +[Yiding](https://github.com/wydwww) +[Yifan Li](https://github.com/Eagles2F) +[yougha54](https://github.com/yougha54) +[Youri Noel Nelson](https://github.com/ynnelson) +[yuandongfang](https://github.com/yuandongfang) +[Yueqi Wang](https://github.com/yueqiw) +[yugushihuang](https://github.com/yugushihuang) +[Yuhi Ishikura](https://github.com/uphy) +[Yuval Kalugny](https://github.com/kalugny) +[Yuvi Panda](https://github.com/yuvipanda) +[Zac Flamig](https://github.com/zflamig) +[Zachary Sailer](https://github.com/Zsailer) +[Zachary Zhao](https://github.com/zacharyzhao) +[ZachGlassman](https://github.com/ZachGlassman) +[zaf](https://github.com/zafeirakopoulos) +[Zafer Cesur](https://github.com/zcesur) +[zearaujo07](https://github.com/zearaujo07) +[Zeb Nicholls](https://github.com/znicholls) +[Zelphir Kaltstahl](https://github.com/ZelphirKaltstahl) +[ZenRay](https://github.com/ZenRay) +[zero](https://github.com/zero-88) +[zeusal](https://github.com/zeusal) +[Zhongyi](https://github.com/zhongyiio) +[Zhou (Joe) Yuan](https://github.com/yuanzhou) +[ziedbouf](https://github.com/ziedbouf) +[zlshi](https://github.com/zlshi) +[zmkhazi](https://github.com/zmkhazi) +[Zoltan Fedor](https://github.com/zoltan-fedor) +[zyc](https://github.com/499244188) +[Øystein Efterdal](https://github.com/oefterdal) +[孙永乐](https://github.com/cattei) +[张旭](https://github.com/zhangxu999) +[武晨光](https://github.com/mission-young) +[陈镇秋](https://github.com/ChenZhenQiu) + +## 0.6 + +### 0.6 - [Ellyse Perry](https://en.wikipedia.org/wiki/Ellyse_Perry) - 2017-01-29 + +This release is primarily focused on better support +for Autoscaling, Microsoft Azure support & better +default security. There are also a number of bug fixes +and configurability improvements! + +#### Breaking changes + +##### Pre-puller configuration + +In prior versions (v0.5), if you wanted to disable the pre-puller, +you would use: + +```yaml +prePuller: + enabled: false +``` + +Now, to disable the pre-puller, you need to use: + +```yaml +prePuller: + hook: + enabled: false +``` + +See the [pre-puller docs](pulling-images-before-users-arrive) for more info! + +#### Upgrading from 0.5 + +This release does not require any special steps to upgrade from v0.5. See the [upgrade documentation](https://zero-to-jupyterhub.readthedocs.io/en/latest/upgrading.html) +for general upgrading steps. + +If you are running v0.4 of the chart, you should upgrade to v0.5 first +before upgrading to v0.6. You can find out what version you are using +by running `helm list`. + +##### Troubleshooting + +If your helm upgrade fails due to the error `no Ingress with the name "jupyterhub-internal" found`, +you may be experiencing a [helm bug](https://github.com/helm/helm/issues/3275). To work +around this, run `kubectl --namespace= delete ingress jupyterhub-internal` and +re-run the `helm upgrade` command. Note that this will cause a short unavailability of your hub +over HTTPS, which will resume normal availability once the deployment upgrade completes. + +#### New Features + +##### More secure by default + +z2jh is more secure by default with 0.6. We now +block access to cloud security metadata endpoints by +default. + +See the [security documentation](security) for more details. It has seen a number of improvements, and we recommend +you read through it! + +##### Autoscaling improvements + +Some cloud providers support the [kubernetes node autoscaler](https://github.com/kubernetes/autoscaler/tree/HEAD/cluster-autoscaler), +which can add / remove nodes depending on how much your +cluster is being used. In this release, we made a few +changes to let z2jh interact better with the autoscaler! + +- Configure z2jh to ['pack' your users](optimization) + onto nodes, rather than 'spread' them across nodes. +- A ['continuous' pre-puller](pulling-images-before-users-arrive) + that allows user images to + be pulled on new nodes easily, leading to faster startup + times for users on new nodes. ([link]) +- Hub and Proxy pod will not be disrupted by autoscaler, + by using [PodDisruptionBudget](https://kubernetes.io/docs/tasks/run-application/configure-pdb/)s. The Hub & Proxy will also stick + together if possible, thus minimizing the number of nodes + that can not be downsized by the autoscaler. + +There is more work to be done for good autoscaling support, +but this is a good start! + +##### Better Azure support + +Azure's new managed Kubernetes service ([AKS](https://learn.microsoft.com/en-us/azure/aks/)) is much +better supported by this version! + +- We have much better documentation on using z2jh with Azure! +- We rewrote our pre-puller so it works on Azure (previously it did not) + +Azure AKS is still in preview mode, so be aware of that +before using it in any production workloads! + +See the [setting up Kubernetes on Microsoft AKS](microsoft-azure) section for more information. + +##### Better configurability + +We now have better documentation and bug fixes for configurability! + +- `extraConfig` can be a dictionary instead of just a + string. This helps when you have to split your `config.yaml` + into multiple files for complex deployments +- How user storage works by default is [better documented](user-storage) +- Reading config in `extraConfig` from `extraConfigMap` now actually works! +- You can configure the URL that users are directed to after they log in. + This allows [defaulting users to JupyterLab](jupyterlab-by-default) +- You can pre-pull multiple images now, for custom configuration that needs multiple images +- [Better instructions](use-nbgitpuller) + on pre-populating your user's filesystem using [nbgitpuller](https://github.com/jupyterhub/nbgitpuller) + +#### [Ellyse Perry](https://en.wikipedia.org/wiki/Ellyse_Perry) + +_(excerpt from https://www.cricket.com.au/players/ellyse-perry/1aMxKNyEOUiJqhq7N5Tlwg)_ + +Arguably the best athlete in Australia, Ellyse Perry’s profile continues to rise +with the dual cricket and soccer international having played World Cups for both sports. + +Perry became the youngest Australian ever to play senior international cricket when +she made her debut in the second ODI of the Rose Bowl Series in Darwin in July 2007 +before her 17th birthday. + +She went on to make her domestic debut in the 2007-08 Women’s National Cricket League +season, taking 2-29 from 10 overs in her first match. + +Since her national debut, Perry has become a regular fixture for the Southern Stars, +playing in the 2009 ICC Women’s World Cup and the ICC Women’s World Twenty20 in the same year. + +Leading Australia’s bowling attack, Perry played a crucial role in the ICC Women’s +World Twenty20 Final in the West Indies in 2010. + +The match came down to the wire, with New Zealand requiring five runs off the last +ball to claim the title. Under immense pressure, Perry bowled the final ball of the +tournament, which New Zealand’s Sophie Devine struck straight off the bat. + +The talented footballer stuck out her boot to deflect the ball to Lisa Sthalekar at +mid-on, securing the trophy for Australia. Perry’s figures of 3-18 in the final saw +her take home the Player of the Match award. + +Perry featured prominently in Australia's three-peat of World T20 victories, +selected for the Team of the Tournament in 2012 and 2014. + +She was named [ICC Female Cricketer of the Year](https://www.abc.net.au/news/2017-12-22/ellyse-perry-named-iccs-womens-cricketer-of-the-year/9280538) in 2017. + +#### Contributors + +This release wouldn't have been possible without the wonderful contributors +to the [zero-to-jupyterhub](https://github.com/jupyterhub/zero-to-jupyterhub-k8s), +and [KubeSpawner](https://github.com/jupyterhub/kubespawner) repos. +We'd like to thank everyone who contributed in any form - Issues, commenting +on issues, PRs and reviews since the last Zero to JupyterHub release. + +In alphabetical order, + +- [Aaron Culich](https://github.com/aculich) +- [Anirudh Ramanathan](https://github.com/foxish) +- [Antoine Dao](https://github.com/twanito) +- [BerserkerTroll](https://github.com/BerserkerTroll) +- [Carol Willing](https://github.com/willingc) +- [Chris Holdgraf](https://github.com/choldgraf) +- [Christian Mesh](https://github.com/cam72cam) +- [Erik Sundell](https://github.com/consideRatio) +- [forbxy](https://github.com/forbxy) +- [Graham Dumpleton](https://github.com/GrahamDumpleton) +- [gweis](https://github.com/gweis) +- [Ian Allison](https://github.com/ianabc) +- [Jason Kuruzovich](https://github.com/jkuruzovich) +- [Jesse Kinkead](https://github.com/jkinkead) +- [madanam1](https://github.com/madanam1) +- [Matthew Rocklin](https://github.com/mrocklin) +- [Matthias Bussonnier](https://github.com/Carreau) +- [Min RK](https://github.com/minrk) +- [Ryan Lovett](https://github.com/ryanlovett) +- [Simon Li](https://github.com/manics) +- [Steve Buckingham](https://github.com/stevebuckingham) +- [Steven Normore](https://github.com/snormore) +- [Tim Head](https://github.com/betatim) +- [Yuvi Panda](https://github.com/yuvipanda) +- [ZachGlassman](https://github.com/ZachGlassman) + +## 0.5 + +### 0.5 - [Hamid Hassan](https://www.espncricinfo.com/cricketers/hamid-hassan-311427) - 2017-12-05 + +JupyterHub 0.8, HTTPS & scalability. + +#### Upgrading from 0.4 + +See the [upgrade documentation](https://zero-to-jupyterhub.readthedocs.io/en/latest/upgrading.html) for upgrade steps. + +#### New Features + +##### JupyterHub 0.8 + +JupyterHub 0.8 is full of new features - see [CHANGELOG](https://jupyterhub.readthedocs.io/en/0.8.1/changelog.html#id1) +for more details. Specific features made to benefit this chart are: + +1. No more 'too many redirects' errors at scale. +2. Lots of performance improvements, we now know we can handle up to 4k active users +3. Concurrent spawn limits (set via `hub.concurrentSpawnLimit`) can be used to limit the concurrent + number of users who can try to launch on the hub at any given time. This can be + tuned to avoid crashes when hundreds of users try to launch at the same time. It gives + them a friendly error message + asks them to try later, rather than spinning forever. +4. Active Server limit (set via `hub.activeServerLimit`) can be used to limit the + total number of active users that can be using the hub at any given time. This allows + admins to control the size of their clusters. +5. Memory limits & guarantees (set via `singleuser.memory`) can now contain fractional + units. So you can say `0.5G` instead of having to use `512M`. + +And lots more! + +##### Much easier HTTPS + +It is our responsibility as software authors to make it very easy for admins to set up +HTTPS for their users. v0.5 makes this much easier than v0.4. You can find the new +instructions [here](https) and +they are much simpler! + +You can also now use your own HTTPS certificates & keys rather than using Let's Encrypt. + +##### More authenticators supported + +The following new authentication providers have been added: + +1. GitLab +2. CILogon +3. Globus + +You can also set up a whitelist of users by adding to the list in `auth.whitelist.users`. + +##### Easier customization of `jupyterhub_config.py` + +You can always put extra snippets of `jupyterhub_config.py` configuration in +`hub.extraConfig`. Now you can also add extra environment variables to the hub +in `hub.extraEnv` and extra configmap items via `hub.extraConfigMap`. ConfigMap +items can be arbitrary YAML, and you can read them via the `get_config` function in +your `hub.extraConfig`. This makes it cleaner to customize the hub's config in +ways that's not yet possible with config.yaml. + +##### Hub Services support + +You can also add [external JupyterHub Services](https://jupyterhub.readthedocs.io/en/latest/reference/services.html) +by adding them to `hub.services`. Note that you are still responsible for actually +running the service somewhere (perhaps as a deployment object). + +##### More customization options for user server environments + +More options have been added under `singleuser` to help you customize the environment +that the user is spawned in. You can change the uid / gid of the user with `singleuser.uid` +and `singleuser.fsGid`, mount extra volumes with `singleuser.storage.extraVolumes` & +`singleuser.storage.extraVolumeMounts` and provide extra environment variables with +`singleuser.extraEnv`. + +#### Hamid Hassan + +Hamid Hassan is a fast bowler who currently plays for the Afghanistan National +Cricket Team. With nicknames ranging from +["Afghanistan's David Beckham"](https://www.rferl.org/a/interview-afghan-cricketer-living-the-dream/24752618.html) to +["Rambo"](https://www.nzherald.co.nz/nz/cricket-world-cup-rambo-ready-to-rumble/QAORUQEH6BHMOLRDABVXISQPPA/?c_id=1&objectid=11413633), +he is considered by many to be Afghanistan's first Cricket Superhero. Currently +known for fast (145km/h+) deliveries, cartwheeling celebrations, war painted +face and having had to flee Afghanistan as a child to escape from war. He [says](https://www.nzherald.co.nz/nz/cricket-world-cup-rambo-ready-to-rumble/QAORUQEH6BHMOLRDABVXISQPPA/?c_id=1&objectid=11413633) +he plays because "We are ambassadors for our country and we want to show the +world that Afghanistan is not like people recognise it by terrorists and these +things. We want them to know that we have a lot of talent as well" + +#### Contributors + +This release wouldn't have been possible without the wonderful contributors +to the [zero-to-jupyterhub-k8s](https://github.com/jupyterhub/zero-to-jupyterhub-k8s), +[JupyterHub](https://github.com/jupyterhub/jupyterhub), [KubeSpawner](https://github.com/jupyterhub/kubespawner) +and [OAuthenticator](https://github.com/jupyterhub/oauthenticator) repos. +We'd like to thank everyone who contributed in any form - Issues, commenting +on issues, PRs and reviews since the last Zero to JupyterHub release. + +In alphabetical order, + +- [Aaron Culich](https://github.com/aculich) +- [abeche](https://github.com/alexxxxx) +- [Abhinandan Dubey](https://github.com/alivcor) +- [Adam Thornton](https://github.com/athornton) +- [Adrin Jalali](https://github.com/adrinjalali) +- [Aidis Stukas](https://github.com/aidiss) +- [Aleksandr Blekh](https://github.com/ablekh) +- [Alessandro Vozza](https://github.com/ams0) +- [Alex Hilson](https://github.com/alexhilson) +- [Analect](https://github.com/Analect) +- [Andrea Zonca](https://github.com/zonca) +- [Andreas](https://github.com/Jibbow) +- [Andrew Berger](https://github.com/rueberger) +- [András Tóth](https://github.com/tothandras) +- [angrylandmammal](https://github.com/angrylandmammal) +- [Anirudh Ramanathan](https://github.com/foxish) +- [Antonino Ingargiola](https://github.com/tritemio) +- [apachipa](https://github.com/apachipa) +- [Ariel Rokem](https://github.com/arokem) +- [astrodb](https://github.com/astrodb) +- [Ayushi Agarwal](https://github.com/ayushiagarwal) +- [batchku](https://github.com/batchku) +- [bbhopesh](https://github.com/bbhopesh) +- [Bill Major](https://github.com/rwmajor2) +- [Brad Svee](https://github.com/sveesible) +- [Brian E. Granger](https://github.com/ellisonbg) +- [BrianVanEtten](https://github.com/BrianVanEtten) +- [calz1](https://github.com/calz1) +- [Camilo Núñez Fernández](https://github.com/camilo-nunez) +- [Carol Willing](https://github.com/willingc) +- [Chris Holdgraf](https://github.com/choldgraf) +- [Christian Barra](https://github.com/barrachri) +- [Christian Moscardi](https://github.com/cmoscardi) +- [Christophe Lecointe](https://github.com/christophelec) +- [Christopher Hench](https://github.com/henchc) +- [Christopher Ostrouchov](https://github.com/costrouc) +- [ckbhatt](https://github.com/ckbhatt) +- [Cody Scott](https://github.com/Siecje) +- [Colin Goldberg](https://github.com/colingoldberg) +- [daleshsd](https://github.com/daleshsd) +- [danroliver](https://github.com/danroliver) +- [Dave Hirschfeld](https://github.com/dhirschfeld) +- [David](https://github.com/davidXire) +- [Davide](https://github.com/davidedelvento) +- [deisi](https://github.com/deisi) +- [Dennis Pfisterer](https://github.com/pfisterer) +- [Dennis Verspuij](https://github.com/dennisverspuij) +- [Diogo](https://github.com/dmvieira) +- [dmceballosg](https://github.com/dmceballosg) +- [Dominic Follett-Smith](https://github.com/dominicfollett) +- [Doug Blank](https://github.com/dsblank) +- [Enol Fernández](https://github.com/enolfc) +- [Erik Sundell](https://github.com/consideRatio) +- [erolosty](https://github.com/erolosty) +- [FalseProtagonist](https://github.com/FalseProtagonist) +- [fmilano1975](https://github.com/fmilano1975) +- [Forrest Collman](https://github.com/fcollman) +- [Fred Mitchell](https://github.com/fm75) +- [Gil Forsyth](https://github.com/gforsyth) +- [Goutham Balaraman](https://github.com/gouthambs) +- [gryslik](https://github.com/gryslik) +- [gweis](https://github.com/gweis) +- [haasad](https://github.com/haasad) +- [hani1814](https://github.com/hani1814) +- [Hanno Rein](https://github.com/hannorein) +- [harschware](https://github.com/harschware) +- [Ian Allison](https://github.com/ianabc) +- [Isaiah Leonard](https://github.com/ihleonard-c3) +- [J Forde](https://github.com/jzf2101) +- [Jacob Tomlinson](https://github.com/jacobtomlinson) +- [jai11](https://github.com/jai11) +- [jbmarcille](https://github.com/jbmarcille) +- [Jeet Shah](https://github.com/iamjeet) +- [Jeroen Vuurens](https://github.com/jeroenvuurens) +- [Jessica B. Hamrick](https://github.com/jhamrick) +- [jiamicu](https://github.com/jiamicu) +- [jiancai1992](https://github.com/jiancai1992) +- [jm2004](https://github.com/jm2004) +- [joefromct](https://github.com/joefromct) +- [John Haley](https://github.com/johnhaley81) +- [jonny86](https://github.com/jonny86) +- [Joshua Milas](https://github.com/DeepHorizons) +- [JoshuaC3](https://github.com/JoshuaC3) +- [João Vítor Amaro](https://github.com/joaoamaro70) +- [Justin Ray Vrooman](https://github.com/vroomanj) +- [Keith Callenberg](https://github.com/keithcallenberg) +- [KenB](https://github.com/y2kbowen) +- [Kenneth Lyons](https://github.com/ixjlyons) +- [krak3nnn](https://github.com/krak3nnn) +- [Kristiyan](https://github.com/katsar0v) +- [Kuisong Tong](https://github.com/ktong) +- [kuldeepyadav](https://github.com/kuldeepyadav) +- [Kyle Kelley](https://github.com/rgbkrk) +- [lcfcefyn](https://github.com/lcfcefyn) +- [Leo Gallucci](https://github.com/elgalu) +- [lesiano](https://github.com/lesiano) +- [Lorena A. Barba](https://github.com/labarba) +- [lrob](https://github.com/lrob) +- [Lukasz Tracewski](https://github.com/tracek) +- [Mahesh Vangala](https://github.com/vangalamaheshh) +- [Marco Sirabella](https://github.com/mjsir911) +- [marcostrullato](https://github.com/marcostrullato) +- [Marius van Niekerk](https://github.com/mariusvniekerk) +- [MarkusTeufelberger](https://github.com/MarkusTeufelberger) +- [Matt Koken](https://github.com/patback66) +- [Matteo Cerutti](https://github.com/m4ce) +- [Matthias Bussonnier](https://github.com/Carreau) +- [Michael Li](https://github.com/tianhuil) +- [Mike](https://github.com/s-t-e-a-l-t-h) +- [MikeM](https://github.com/mmacny) +- [Min RK](https://github.com/minrk) +- [misolietavec](https://github.com/misolietavec) +- [Moiz Sajid](https://github.com/moizsajid) +- [Morgan Jones](https://github.com/mogthesprog) +- [mraky](https://github.com/mraky) +- [mrinmoyprasad](https://github.com/mrinmoyprasad) +- [nabriis](https://github.com/nabriis) +- [Nickolaus D. Saint](https://github.com/NickolausDS) +- [Nocturnal316](https://github.com/Nocturnal316) +- [Olivier Cloarec](https://github.com/ocloarec) +- [Pedro Henriques dos Santos Teixeira](https://github.com/pedroteixeira) +- [Pranay Hasan Yerra](https://github.com/pranayhasan) +- [prof-schacht](https://github.com/prof-schacht) +- [Puneet Jindal](https://github.com/puneetjindal) +- [R. C. Thomas](https://github.com/rcthomas) +- [ramonberger](https://github.com/ramonberger) +- [Randy Guthrie](https://github.com/randguth) +- [Richard Caunt](https://github.com/psyvision) +- [richmoore1962](https://github.com/richmoore1962) +- [Rishika Sinha](https://github.com/rsinha25) +- [Robert Wlodarczyk](https://github.com/SimplicityGuy) +- [Ruben Orduz](https://github.com/rdodev) +- [Ryan Lovett](https://github.com/ryanlovett) +- [Ryan Wang](https://github.com/rwangr) +- [rydeng](https://github.com/rydeng) +- [SarunasG](https://github.com/SarunasG) +- [Saul Shanabrook](https://github.com/saulshanabrook) +- [Scott Calabrese Barton](https://github.com/scbarton) +- [Scott Sanderson](https://github.com/ssanderson) +- [Simon Li](https://github.com/manics) +- [Stefano Nicotri](https://github.com/stefanonicotri) +- [surma-lodur](https://github.com/surma-lodur) +- [Sven Mayer](https://github.com/SamyStyle) +- [swigicat](https://github.com/swigicat) +- [SY_Wang](https://github.com/kiwi0217) +- [Thomas Kluyver](https://github.com/takluyver) +- [Thomas Mendoza](https://github.com/tgmachina) +- [Tim Head](https://github.com/betatim) +- [toddpfaff](https://github.com/toddpfaff) +- [Tom O'Connor](https://github.com/ichasepucks) +- [toncek87](https://github.com/toncek87) +- [Tony ](https://github.com/Montereytony) +- [Travis Sturzl](https://github.com/tsturzl) +- [Tyler Cloutier](https://github.com/cloutiertyler) +- [uday2002](https://github.com/uday2002) +- [Udita Bose](https://github.com/uditabose) +- [uttamkumar123](https://github.com/uttamkumar123) +- [will](https://github.com/zsluedem) +- [Wilmer Ramirez](https://github.com/will17cr) +- [xgdgsc](https://github.com/xgdgsc) +- [Yan Zhao](https://github.com/yan130) +- [Yinan Li](https://github.com/liyinan926) +- [yoryicopo](https://github.com/yoryicopo) +- [Yu-Hang "Maxin" Tang](https://github.com/yhtang) +- [Yuvi Panda](https://github.com/yuvipanda) +- [Zachary Ogren](https://github.com/zogren) +- [Zhenwen Zhang](https://github.com/zhangzhenwen) +- [Zoltan Fedor](https://github.com/zoltan-fedor) + +## 0.4 + +### 0.4 - Akram - 2017-06-23 + +Stability, HTTPS & breaking changes. + +#### Installation and upgrades + +We **recommend** that you delete prior versions of the package and install the +latest version. If you are very familiar with Kubernetes, you can upgrade from +an older version, but we still suggest deleting and recreating your +installation. + +#### Breaking changes + +- The **name of a user pod** and a **dynamically created home directory [PVC (PersistentVolumeClaim)](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims)** no longer include + the `userid` in them by default. If you are using dynamic PVCs for `home` + directories (which is the default), you will need to _manually rename_ these + directories before upgrading. + Otherwise, new PVCs will be created, and users might freak out when viewing the newly created directory and think that their home directory appears empty. + + See [PR #56](https://github.com/jupyterhub/kubespawner/pull/56) on + what needs to change. + +- A **[StorageClass](https://kubernetes.io/docs/concepts/storage/storage-classes/)** + is no longer created by default. This shouldn't affect most new installs, + since most cloud provider installations have a default (as of Kubernetes 1.6). + If you are using an older version of Kubernetes, the easiest thing to do is to + upgrade to a newer version. If not, you can create a StorageClass manually + and everything should continue to work. + +- `token.proxy` is removed. Use **`proxy.secretToken`** instead. + If your `config.yaml` contains something that looks like the following: + + ```yaml + token: + proxy: + ``` + + you should change that to: + + ```yaml + proxy: + secretToken: + ``` + +#### Added + +- Added **GitHub Authentication support**, thanks to [Jason Kuruzovich](https://github.com/jkuruzovich). +- Added **[Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) support**! + If your cluster already has Ingress support (with automatic Let's Encrypt support, perhaps), + you can easily use that now. +- We now add a **label** to user pods / PVCs with their usernames. +- Support using a **static PVC** for user `home` directories or for the hub database. This makes this release usable + with clusters where you only have one NFS share that must be used for the whole hub. +- **PostgreSQL** is now a supported hub database backend provider. +- You can set annotations & labels on the **proxy-public service** now. + +#### Changed + +- We now use the official [configurable http proxy](https://github.com/jupyterhub/configurable-http-proxy) + (CHP) as the proxy, rather than the unofficial + [nchp](https://github.com/yuvipanda/jupyterhub-nginx-chp). This should be a + no-op (or require no changes) for the most part. JupyterHub errors might + display a nicer error page. +- The version of KubeSpawner uses the official Kubernetes + [python client](https://github.com/kubernetes-client/python) rather + than [pycurl](http://pycurl.io/). This helps with scalability a little. + +#### Removed + +- The deprecated `createNamespace` parameter no longer works, alongside the + deprecated `name` parameter. You probably weren't using these anyway - they + were kept only for backwards compatibility with very early versions. + +#### Contributors + +This release made possible by the awesome work of the following contributors +(in alphabetical order): + +- [Analect](https://github.com/analect) +- [Carol Willing](https://github.com/willingc) +- [Jason Kuruzovich](https://github.com/jkuruzovich) +- [Min RK](https://github.com/minrk/) +- [Yuvi Panda](https://github.com/yuvipanda/) + +<3 + +#### Akram + +[Wasim Akram](https://en.wikipedia.org/wiki/Wasim_Akram) (وسیم اکرم) is considered by many to be +the greatest pace bowler of all time and a founder of the fine art of +[reverse swing bowling](https://en.wikipedia.org/wiki/Swing_bowling#Reverse_swing). + +## 0.3 + +### 0.3.1 - 2017-05-19 + +KubeSpawner updates. + +- KubeSpawner has gained several new features, thanks + to the work of Daniel Rodriguez and ktongsc! Specifically, + we have support for init containers, node selectors, + pod lifecycle hooks, etc. These can be used with the + extraConfig override for now +- Add easy ability to specify pod lifecycle hooks via the + helm chart! + +### 0.3 - 2017-05-15 + +Deployer UX fixes. + +- No need to restart hub manually after some changes - it is + automatically restarted now. You can disable an automatic + restart of hub after an upgrade with the following: + + 1. Finding out the current helm release's revision + 2. Adding '--set revisionOverride=' to your + upgrade command. + + Only do this if you know exactly what you are doing :) + +- Base images for everything upgraded to ubuntu 17.04. We can + define the support lifecycle for the helm chart in the future, + and decide on the base images at that point. +- Add a timestamp to the job name for the pre-puller job. This + prevents having to manually delete it when an install fails and + has to be tried again. Because the Release Revision hadn't changed + when the upgrade fails, trying again will cause it to fail with a + 'job already exists' error. Adding the Timestamp to job name should + hopefully fix that + +## 0.2 + +### 0.2 - 2017-05-01 + +Minor cleanups and features. + +- Get rid of cull pod, move it inside the hub pod as a + managed service +- Set a default 1G memory guarantee for user pods +- Allow setting a static global password for Dummy Authenticator +- Allow setting extra static environment variables for user pods + from the helm config +- Upgrade kubespawner version (no major functional changes) + +## 0.1 + +### 0.1 - 2017-04-10 + +Initial Public Release. diff --git a/doc/source/conf.py b/docs/source/conf.py similarity index 58% rename from doc/source/conf.py rename to docs/source/conf.py index 7043d38e17..3a05d33dc1 100644 --- a/doc/source/conf.py +++ b/docs/source/conf.py @@ -2,64 +2,59 @@ # # Configuration reference: https://www.sphinx-doc.org/en/master/usage/configuration.html # - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) - - -# -- Project specific imports ------------------------------------------------ - import datetime +import json import os import re import subprocess import yaml - -# -- Sphinx setup function --------------------------------------------------- -# ref: http://www.sphinx-doc.org/en/latest/extdev/tutorial.html#the-setup-function - - -def setup(app): - app.add_css_file("custom.css") +# -- Project information ----------------------------------------------------- +# ref: https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information +# +project = "Zero to JupyterHub with Kubernetes" +copyright = f"{datetime.date.today().year}, Project Jupyter Contributors" +author = "Project Jupyter Contributors" -# -- Referencable variables -------------------------------------------------- +# -- General Sphinx configuration --------------------------------------------------- +# ref: https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration +# +extensions = [ + "myst_parser", + "sphinx_copybutton", + "sphinx.ext.intersphinx", + "sphinx.ext.mathjax", + "sphinxext.opengraph", + "sphinxext.rediraffe", +] +root_doc = "index" +source_suffix = [".md"] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] -def _get_latest_tag(): - """Get the latest tag on a commit in branch or return None.""" - try: - # If the git command output is my-tag-14-g0aed65e, - # then the return value will become my-tag. - return ( - subprocess.check_output(["git", "describe", "--tags", "--long"]) - .decode("utf-8") - .strip() - .rsplit("-", maxsplit=2)[0] - ) - except subprocess.CalledProcessError: - return None +# -- General MyST configuration ----------------------------------------------------- +# ref: https://myst-parser.readthedocs.io/en/latest/configuration.html +# +myst_enable_extensions = [ + "substitution", +] +# -- Referenceable variables -------------------------------------------------- +# def _get_git_ref_from_chartpress_based_version(version): """ Get a git ref from a chartpress set version of format like - 1.2.3-beta.1.n123.h1234567, 1.2.3-n123.h1234567, or 1.2.3. + - 2.0.1-0.dev.git.5810.hf475e7a4 return git hash + - 2.0.0-beta.1 return tag + - 2.0.0 return tag """ - tag_hash_split = re.split("[\.|-]n\d\d\d\.h", version) - if len(tag_hash_split) == 2: - return tag_hash_split[1] - else: - return tag_hash_split[0] + m = re.match(r"\d+\.\d+\.\d+(-.+\.h([0-9a-f]+))$", version) + if m: + return m.group(2) + return version # FIXME: Stop relying on chartpress to modify Chart.yaml (and values.yaml) by @@ -71,75 +66,188 @@ def _get_git_ref_from_chartpress_based_version(version): chart = yaml.safe_load(f) subprocess.run(["chartpress", "--reset"], cwd=os.path.abspath("../..")) -latest_tag = _get_latest_tag() -chart_version = chart["version"] -chart_version_git_ref = _get_git_ref_from_chartpress_based_version(chart_version) -jupyterhub_version = chart["appVersion"] -# FIXME: kubeVersion contain >=, but by having > in the string we substitute we -# run into this issue: -# https://github.com/executablebooks/MyST-Parser/issues/282 -kube_version = chart["kubeVersion"].split("-", 1)[0][2:] -helm_version = "3.5" # minimum helm cli version - # These substitution variables only work in markdown contexts, and does not work # within links etc. Reference using {{ variable_name }} # # myst_substitutions ref: https://myst-parser.readthedocs.io/en/latest/using/syntax-optional.html#substitutions-with-jinja2 myst_substitutions = { - "latest_tag": latest_tag, - "chart_version": chart_version, - "chart_version_git_ref": chart_version_git_ref, - "jupyterhub_version": jupyterhub_version, - "kube_version": kube_version, - "helm_version": helm_version, - "requirements": f"[hub/images/requirements.txt](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/{chart_version_git_ref}/images/hub/requirements.txt)", + "chart_version": chart["version"], + "jupyterhub_version": chart["appVersion"], + # FIXME: kubeVersion contain >=, but by having > in the string we substitute + # we run into this issue: + # https://github.com/executablebooks/MyST-Parser/issues/282 + "kube_version": chart["kubeVersion"].split("-", 1)[0][2:], + "helm_version": "3.5", + "requirements": f"[hub/images/requirements.txt](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/{_get_git_ref_from_chartpress_based_version(chart['version'])}/images/hub/requirements.txt)", } -# -- General MyST configuration ----------------------------------------------------- +# -- Generate the Helm chart configuration reference from a schema file ------ +# +# header +with open("resources/reference.txt") as f: + header_md = f.readlines() +header_md = header_md[1:] +header_md = [ln.strip("\n") for ln in header_md] -# myst_enable_extensions ref: https://myst-parser.readthedocs.io/en/latest/using/syntax-optional.html -myst_enable_extensions = [ - "substitution", -] +# schema +with open("../../jupyterhub/values.schema.yaml") as f: + data = yaml.safe_load(f) -# -- Project information ----------------------------------------------------- -# ref: https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information +# default_values +with open("../../jupyterhub/values.yaml") as f: + default_values = yaml.safe_load(f) -project = "Zero to JupyterHub with Kubernetes" -copyright = f"{datetime.date.today().year}, Project Jupyter Contributors" -author = "Project Jupyter Contributors" +def get_default_value(k): + """ + Get the default value from values.yaml + """ + v = default_values + for key in k.split("."): + v = v[key] + return v -# -- General Sphinx configuration --------------------------------------------------- -# ref: https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration -# Set the default role so we can use `foo` instead of ``foo`` -default_role = "literal" +def parse_schema(d, md=[], depth=0, pre=""): + """ + Generate markdown headers from a passed python dictionary created by + parsing a values.schema.yaml file. + """ + if "then" in d: + d = d["then"] -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - "sphinx.ext.mathjax", - "sphinx_copybutton", - "myst_parser", - "sphinxext.rediraffe", + if "properties" in d: + depth += 1 + # Create markdown headers for each schema level + for key, val in d["properties"].items(): + md.append(f"(schema_{pre}{key})=") + md.append("#" * (depth + 1) + f" {pre}{key}") + md.append("") + if "description" in val: + for ln in val["description"].split("\n"): + md.append(ln) + try: + def_value = get_default_value(f"{pre}{key}") + if ( + def_value is not None + and not isinstance(def_value, dict) + and def_value + not in ( + "set-by-chartpress", + "", + ) + ): + # Use the JSON string representation instead of Python + md.append(f"_Default:_ `{json.dumps(def_value)}`") + md.append("") + except KeyError: + # TODO: Should we error if the property isn't in values.yaml? + pass + + parse_schema(val, md, depth, f"{pre}{key}.") + depth -= 1 + return md + + +schema_md = parse_schema(data) + +# reference = header + schema +reference_md = header_md + schema_md +with open("resources/reference.md", "w") as f: + f.write("\n".join(reference_md)) + + +# -- Options for intersphinx extension --------------------------------------- +# ref: https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html#configuration +# +# The extension makes us able to link like to other projects like below. +# +# rST - :external:py:class:`tornado.httpclient.AsyncHTTPClient` +# MyST - {external:py:class}`tornado.httpclient.AsyncHTTPClient` +# +# To see what we can link to, do the following where "objects.inv" is appended +# to the sphinx based website: +# +# python -m sphinx.ext.intersphinx https://jupyterhub.readthedocs.io/en/stable/objects.inv +# +intersphinx_mapping = { + "jupyterhub": ("https://jupyterhub.readthedocs.io/en/stable/", None), + "oauthenticator": ("https://oauthenticator.readthedocs.io/en/stable/", None), + "kubespawner": ("https://jupyterhub-kubespawner.readthedocs.io/en/stable/", None), +} + +# intersphinx_disabled_reftypes set based on recommendation in +# https://docs.readthedocs.io/en/stable/guides/intersphinx.html#using-intersphinx +intersphinx_disabled_reftypes = ["*"] + + +# -- Options for HTML output ------------------------------------------------- +# ref: https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output +# +html_logo = "_static/images/logo/logo.png" +html_favicon = "_static/images/logo/favicon.ico" +html_static_path = ["_static"] +html_css_files = ["custom.css"] + +# pydata_sphinx_theme reference: https://pydata-sphinx-theme.readthedocs.io/en/latest/ +html_theme = "pydata_sphinx_theme" +html_theme_options = { + "github_url": "https://github.com/jupyterhub/zero-to-jupyterhub-k8s/", + "use_edit_page_button": True, +} +html_context = { + "github_user": "jupyterhub", + "github_repo": "zero-to-jupyterhub-k8s", + "github_version": "main", + "doc_path": "docs/source", +} + + +# -- Options for linkcheck builder ------------------------------------------- +# ref: https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-the-linkcheck-builder +# +linkcheck_ignore = [ + r"(.*)github\.com(.*)#", # javascript based anchors + r"(.*)/#%21(.*)/(.*)", # /#!forum/jupyter - encoded anchor edge case + r"https://github.com/[^/]*$", # too many github usernames / searches in changelog + "https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/", # too many PRs in changelog + "https://github.com/jupyterhub/zero-to-jupyterhub-k8s/compare/", # too many comparisons in changelog + "https://your-domain.com", # example + "https://your-domain-name.com", # example + "https://kubernetes.io/docs/tutorials/kubernetes-basics/", # works + "https://cloud.ibm.com/kubernetes/catalog/create", # works + "https://github.com/traefik/traefik/blob/HEAD/CHANGELOG.md", # works + "https://portal.azure.com", # sign-in redirect noise + "https://console.cloud.google.com", # sign-in redirect noise + "https://console.developers.google.com", # sign-in redirect noise +] +linkcheck_anchors_ignore = [ + "/#!", + "/#%21", ] -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = [] -# The master toctree document. -master_doc = "index" +# -- Options for the opengraph extension ------------------------------------- +# ref: https://github.com/wpilibsuite/sphinxext-opengraph#options +# +# This extension help others provide better thumbnails and link descriptions +# when they link to this documentation from other websites, such as +# https://discourse.jupyter.org. +# +# ogp_site_url is set automatically by RTD +ogp_image = "_static/logo.png" +ogp_use_first_image = True -# The suffix(es) of source filenames. -source_suffix = [".md", ".rst"] -# Rediraffe redirects to ensure proper redirection +# -- Options for the rediraffe extension ------------------------------------- +# ref: https://github.com/wpilibsuite/sphinxext-rediraffe#readme +# +# This extensions help us relocated content without breaking links. If a +# document is moved internally, we should configure a redirect like below. +# +rediraffe_branch = "main" rediraffe_redirects = { "customizing/user-management": "jupyterhub/customizing/user-management", "customizing/user-storage": "jupyterhub/customizing/user-storage", @@ -162,9 +270,10 @@ def _get_git_ref_from_chartpress_based_version(version): "redhat/step-zero-openshift": "kubernetes/redhat/step-zero-openshift", "amazon/step-zero-aws-eks": "kubernetes/amazon/step-zero-aws-eks", "amazon/step-zero-aws": "kubernetes/amazon/step-zero-aws", - "microsoft/step-zero-azure-autoscale": "kubernetes/microsoft/step-zero-azure-autoscale", + "microsoft/step-zero-azure-autoscale": "kubernetes/microsoft/step-zero-azure", "microsoft/step-zero-azure": "kubernetes/microsoft/step-zero-azure", "google/step-zero-gcp": "kubernetes/google/step-zero-gcp", + "kubernetes/other-infrastructure/step-zero-microk8s": "kubernetes/other-infrastructure/step-zero-other", "create-k8s-cluster": "kubernetes/setup-kubernetes", "turn-off": "jupyterhub/uninstall", "setup-jupyterhub": "jupyterhub/index", @@ -184,7 +293,7 @@ def _get_git_ref_from_chartpress_based_version(version): "tips": "community/tips", "index-community-resources": "resources/community", "additional-resources": "resources/community", - "upgrading": "administrator/upgrading", + "upgrading": "administrator/upgrading/index", "troubleshooting": "administrator/troubleshooting", "security": "administrator/security", "optimization": "administrator/optimization", @@ -195,96 +304,3 @@ def _get_git_ref_from_chartpress_based_version(version): "architecture": "administrator/architecture", "advanced": "administrator/advanced", } - - -# -- Generate the Helm chart configuration reference from a schema file ------ - -# header -with open("resources/reference.txt", "r") as f: - header_md = f.readlines() -header_md = header_md[1:] -header_md = [ln.strip("\n") for ln in header_md] - -# schema -with open("../../jupyterhub/schema.yaml", "r") as f: - data = yaml.safe_load(f) - - -def parse_schema(d, md=[], depth=0, pre=""): - """ - Generate markdown headers from a passed python dictionary created by - parsing a schema.yaml file. - """ - if "then" in d: - d = d["then"] - - if "properties" in d: - depth += 1 - # Create markdown headers for each schema level - for key, val in d["properties"].items(): - md.append("(schema_%s)=" % (pre + key)) - md.append("#" * (depth + 1) + " " + pre + key) - md.append("") - if "description" in val: - for ln in val["description"].split("\n"): - md.append(ln) - md.append("") - - parse_schema(val, md, depth, pre + "{}.".format(key)) - depth -= 1 - return md - - -schema_md = parse_schema(data) - -# reference = header + schema -reference_md = header_md + schema_md -with open("resources/reference.md", "w") as f: - f.write("\n".join(reference_md)) - - -# -- Options for linkcheck builder ------------------------------------------- -# ref: http://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-the-linkcheck-builder -linkcheck_ignore = [ - r"(.*)github\.com(.*)#", # javascript based anchors - r"(.*)/#%21(.*)/(.*)", # /#!forum/jupyter - encoded anchor edge case - "https://your-domain.com", # example - "https://your-domain-name.com", # example - "https://kubernetes.io/docs/tutorials/kubernetes-basics/", # works - "https://cloud.ibm.com/kubernetes/catalog/create", # works - "https://portal.azure.com", # sign-in redirect noise - "https://console.cloud.google.com", # sign-in redirect noise - "https://console.developers.google.com", # sign-in redirect noise -] -linkcheck_anchors_ignore = [ - "/#!", - "/#%21", -] - - -# -- Options for HTML output ------------------------------------------------- -# ref: http://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# - -html_theme = "pydata_sphinx_theme" -html_theme_options = { - "github_url": "https://github.com/jupyterhub/zero-to-jupyterhub-k8s/", - "use_edit_page_button": True, -} -html_context = { - "github_user": "jupyterhub", - "github_repo": "zero-to-jupyterhub-k8s", - "github_version": "main", - "doc_path": "doc/source", -} - -html_favicon = "_static/images/logo/favicon.ico" -html_logo = "_static/images/logo/logo.png" - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] diff --git a/doc/source/index.md b/docs/source/index.md similarity index 96% rename from doc/source/index.md rename to docs/source/index.md index 489cbdb694..f316d889fb 100644 --- a/doc/source/index.md +++ b/docs/source/index.md @@ -138,3 +138,14 @@ the organizations that support them!) - [Berkeley Institute for Data Science](https://bids.berkeley.edu/) - [Cal Poly, San Luis Obispo](https://www.calpoly.edu/) - [Simula Research Institute](https://www.simula.no/) +- [2i2c](https://2i2c.org) + +## Changelog + +This section holds describes the changes between versions and how to upgrade +between them. + +```{toctree} +:maxdepth: 1 +changelog +``` diff --git a/doc/source/jupyterhub/customization.md b/docs/source/jupyterhub/customization.md similarity index 100% rename from doc/source/jupyterhub/customization.md rename to docs/source/jupyterhub/customization.md diff --git a/doc/source/jupyterhub/customizing/extending-jupyterhub.md b/docs/source/jupyterhub/customizing/extending-jupyterhub.md similarity index 100% rename from doc/source/jupyterhub/customizing/extending-jupyterhub.md rename to docs/source/jupyterhub/customizing/extending-jupyterhub.md diff --git a/doc/source/jupyterhub/customizing/user-environment.md b/docs/source/jupyterhub/customizing/user-environment.md similarity index 61% rename from doc/source/jupyterhub/customizing/user-environment.md rename to docs/source/jupyterhub/customizing/user-environment.md index 90c8343ea5..8c9b2c4017 100644 --- a/doc/source/jupyterhub/customizing/user-environment.md +++ b/docs/source/jupyterhub/customizing/user-environment.md @@ -23,15 +23,16 @@ To get started customizing the user environment, see the topics below. ## Choose and use an existing Docker image +This chart uses a minimal default singleuser image intended for quick tests. +You will need to choose a different image or build your own for real use. + Project Jupyter maintains the [jupyter/docker-stacks repository](https://github.com/jupyter/docker-stacks/), which contains ready to use Docker images. Each image includes a set of commonly used science and data science libraries and tools. They also provide excellent documentation on [how to choose a suitable image](https://jupyter-docker-stacks.readthedocs.io/en/latest/using/selecting.html). -If you wish to use another image from jupyter/docker-stacks than the -[base-notebook](https://jupyter-docker-stacks.readthedocs.io/en/latest/using/selecting.html#jupyter-base-notebook) -used by default, such as the [datascience-notebook](https://jupyter-docker-stacks.readthedocs.io/en/latest/using/selecting.html#jupyter-datascience-notebook) -image containing useful tools and libraries for datascience, complete these steps: +For example, to use the [datascience-notebook](https://jupyter-docker-stacks.readthedocs.io/en/latest/using/selecting.html#jupyter-datascience-notebook) +image containing useful tools and libraries for data science, complete these steps: 1. Modify your `config.yaml` file to specify the image. For example: @@ -44,6 +45,9 @@ image containing useful tools and libraries for datascience, complete these step # https://github.com/jupyter/docker-stacks/tree/HEAD/datascience-notebook/Dockerfile name: jupyter/datascience-notebook tag: latest + # `cmd: null` allows the custom CMD of the Jupyter docker-stacks to be used + # which performs further customization on startup. + cmd: null ``` ```{note} @@ -69,21 +73,96 @@ If you'd like users to select an environment from **multiple docker images**, see {ref}`multiple-profiles`. ``` +(user-interfaces)= + +## Selecting a user interface + +[JupyterLab][] is the new user interface for Jupyter, +which is meant to replace the classic notebook user interface (UI). +Users can already interchange `/tree` and `/lab` in the URL to switch between +the classic UI and JupyterLab if both are installed. +Deployments using JupyterHub 1.x and earlier default to the classic UI, +while JupyterHub 2.0 makes JupyterLab the default. + +[jupyterlab]: https://jupyterlab.readthedocs.io + +To pick a user interface to launch by default for users, two customization items need to be set: + +1. the preferred default user interface (UI) +2. the server program to launch + +There are two main Jupyter server implementations +(_Most deployments will not see a difference, +but there can be issues for certain server extensions. If unsure, new applications should choose `jupyter_server`._): + +1. the modern `jupyter server`, + which is launched when you use `jupyter lab` or other recent Jupyter applications, and +2. the 'classic' legacy notebook server (`jupyter notebook`) + +In general, the default UI is selected in {term}`config.yaml` by + +```yaml +singleuser: + defaultUrl: ... +``` + +and the default server by: + +```yaml +singleuser: + extraEnv: + JUPYTERHUB_SINGLEUSER_APP: "..." +``` + +Specifically, use one of these options to select the modern server: + +```yaml +# this is the default with JupyterHub 2.0 +singleuser: + extraEnv: + JUPYTERHUB_SINGLEUSER_APP: "jupyter_server.serverapp.ServerApp" +``` + +or the classic notebook server: + +```yaml +# the default with JupyterHub 1.x +singleuser: + extraEnv: + JUPYTERHUB_SINGLEUSER_APP: "notebook.notebookapp.NotebookApp" +``` + +You only need the above configuration when it is different from the default. +JupyterHub 2.0 changes the default server from `NotebookApp` to `ServerApp`, +so here we make the choice explicit in each example, +so the same configuration produces the same result with JupyterHub 1.x and 2.x. +That way, your choice will be preserved across upgrades. + (jupyterlab-by-default)= ## Use JupyterLab by default -[JupyterLab](https://jupyterlab.readthedocs.io/en/stable/index.html) is a new -user interface for Jupyter about to replace the classic user interface (UI). -While users already can interchange `/tree` and `/lab` in the URL to switch between -the classic UI and JupyterLab, they will default to use the classic UI. +```{note} +This is the default in JupyterHub 2.0 and Helm chart 2.0. +``` + +You can choose JupyterLab as the default UI with the following config in your {term}`config.yaml`: + +```yaml +singleuser: + defaultUrl: "/lab" + extraEnv: + JUPYTERHUB_SINGLEUSER_APP: "jupyter_server.serverapp.ServerApp" +``` -The classic Jupyter Notebook UI is the default provided, but you can change it to -JupyterLab with the following config in your {term}`config.yaml`: +You can also make JupyterLab the default UI _without_ upgrading to the newer server implementation. +This may help users who need to stick to the legacy UI with extensions that may not work on the new server. ```yaml singleuser: defaultUrl: "/lab" + extraEnv: + JUPYTERHUB_SINGLEUSER_APP: "notebook.notebookapp.NotebookApp" ``` ```{note} @@ -91,6 +170,60 @@ You need the `jupyterlab` package (installable via `pip` or `conda`) for this to work. All images in the [jupyter/docker-stacks repository](https://github.com/jupyter/docker-stacks/) come pre-installed with it. ``` +(classic-by-default)= + +### Use classic notebook by default + +```{note} +This is the default in JupyterHub 1.x and helm chart 1.x. +``` + +If you aren't ready to upgrade to JupyterLab, +especially for those who depend on custom notebook extensions without an equivalent in JupyterLab, +you can always stick with the legacy notebook server (`jupyter notebook`): + +```yaml +# the default with JupyterHub 1.x +singleuser: + extraEnv: + JUPYTERHUB_SINGLEUSER_APP: "notebook.notebookapp.NotebookApp" +``` + +This will start the exact same server and UI as before. + +If you install the `nbclassic` package, +you can also default to the classic UI, running on the new server: +This may be the best way to support users on both classic and new environments. + +```yaml +singleuser: + defaultUrl: /tree/ + extraEnv: + JUPYTERHUB_SINGLEUSER_APP: "jupyter_server.serverapp.ServerApp" +``` + +### Alternative interfaces + +There are more Jupyter server extensions providing alternate UI choices, +which can be used with JupyterHub. + +For example, [retrolab][] is a different notebook interface, built on JupyterLab, +but which may be more comfortable for those coming from the classic Jupyter UI. + +[retrolab]: https://blog.jupyter.org/retrolab-a-jupyterlab-distribution-with-a-retro-look-and-feel-8096b8b223d0 + +To install such an extension: + +1. install the package (`pip install retrolab` or `conda install retrolab`) in your user container image +2. configure the default URL, and make sure ServerApp is used: + +```yaml +singleuser: + defaultUrl: /retro/ + extraEnv: + JUPYTERHUB_SINGLEUSER_APP: "jupyter_server.serverapp.ServerApp" +``` + (custom-docker-image)= ## Customize an existing Docker image @@ -105,14 +238,19 @@ image. This file can be built to a {term}`Docker image`, and pushed to a by the Helm chart. ```Dockerfile -FROM jupyter/minimal-notebook:177037d09156 -# Get the latest image tag at: +FROM jupyter/minimal-notebook:latest +# Replace `latest` with an image tag from to ensure reproducible builds: # https://hub.docker.com/r/jupyter/minimal-notebook/tags/ # Inspect the Dockerfile at: # https://github.com/jupyter/docker-stacks/tree/HEAD/minimal-notebook/Dockerfile # install additional package... RUN pip install --no-cache-dir astropy + +# set the default command of the image, +# if you want to launch more complex startup than the default `juptyerhub-singleuser`. +# To launch an image's custom CMD instead of the default `jupyterhub-singleuser` +# set `singleuser.cmd: null` in your config.yaml. ``` ```{note} @@ -297,10 +435,10 @@ of configuration options that override your JupyterHub's default configuration Docker images, to select the hardware on which they want their jobs to run, or to configure default interfaces such as Jupyter Lab vs. RStudio. -Each configuration is a set of options for [Kubespawner](https://github.com/jupyterhub/kubespawner), +Each configuration is a set of options for [KubeSpawner](https://github.com/jupyterhub/kubespawner), which defines how Kubernetes should launch a new user server pod. Any configuration options passed to the `profileList` configuration will -overwrite the defaults in Kubespawner (or any configuration you've +overwrite the defaults in KubeSpawner (or any configuration you've added elsewhere in your helm chart). Profiles are stored under `singleuser.profileList`, and are defined as @@ -366,9 +504,97 @@ hooks in `kubespawner_override`, the configuration is for `lifecycle_hooks` (sna how it is used directly under the `singleuser` configuration section. [A further explanation for this can be found in this github issue.](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/issues/1242#issuecomment-484895216) +### User-dependent profile options + +It is also possible to configure the profile choices presented to the user depending on the user. +You can do this by defining a custom **pre-spawn hook** that populates the profile list based on user identity. +See [this discourse post](https://discourse.jupyter.org/t/tailoring-spawn-options-and-server-configuration-to-certain-users/8449) for some examples of how this works. + ```{note} You can also **control the HTML used for the profile selection page** by using the Kubespawner `profile_form_template` configuration. See the [Kubespawner configuration reference](https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html) for more information. ``` + +(set-cmd)= + +## Set command to launch + +Ultimately, a single-user server should launch the `jupyterhub-singleuser` command. +However, an image may have a custom CMD that does this, +with some preparation steps, or adding additional command-line arguments, +or launching a custom wrapper command, etc. + +```{note} +If you have environment preparation at startup in your image, +this is best done in the ENTRYPOINT of the image, +and not in the CMD, so that overriding the command does not skip your preparation. +``` + +By default, zero-to-jupyterhub will launch the command `jupyterhub-singleuser`. +If you have an image (such as `jupyter/scipy-notebook` and other Jupyter Docker stacks) +that defines a CMD with startup customization and ultimately launches `jupyterhub-singleuser`, +you can chose to launch the image's default CMD instead by setting: + +```yaml +singleuser: + cmd: null +``` + +Alternately, you can specify an explicit custom command as a string or list of strings: + +```yaml +singleuser: + cmd: + - /usr/local/bin/custom-command + - "--flag" + - "--other-flag" +``` + +```{note} +Docker has `ENTRYPOINT` and `CMD`, +which k8s calls `command` and `args`. +zero-to-jupyterhub always respects the ENTRYPOINT of the image, +and setting `singleuser.cmd` only overrides the CMD. +``` + +## Disable specific JupyterLab extensions + +Sometimes you want to temporarily disable a JupyterLab extension on a JupyterHub +by default, without having to rebuild your docker image. This can be very +easily done with [`singleuser.extraFiles`](schema_singleuser.extraFiles). +and JupyterLab's [page_config.json](https://jupyterlab.readthedocs.io/en/stable/user/directories.html#labconfig-directories) + +JupyterLab's `page_config.json` lets you set page configuration by dropping JSON files +under a `labconfig` directory inside any of the directories listed when you run `jupyter --paths`. +We just use `singleuser.extraFiles` to provide this file! + +```yaml +singleuser: + extraFiles: + lab-config: + mountPath: /etc/jupyter/labconfig/page_config.json + data: + disabledExtensions: + jupyterlab-link-share: true +``` + +This will disable the [link-share](https://github.com/jupyterlab-contrib/jupyterlab-link-share) +labextension, both in JupyterLab and RetroLab. You can find the name of the +extension, as well as its current status, with `jupyter labextension list`. + +``` +jovyan@jupyter-yuvipanda:~$ jupyter labextension list +JupyterLab v3.2.4 +/opt/conda/share/jupyter/labextensions + jupyterlab-plotly v5.4.0 enabled OK + jupyter-matplotlib v0.9.0 enabled OK + jupyterlab-link-share v0.2.4 disabled OK (python, jupyterlab-link-share) + @jupyter-widgets/jupyterlab-manager v3.0.1 enabled OK (python, jupyterlab_widgets) + @jupyter-server/resource-usage v0.6.0 enabled OK (python, jupyter-resource-usage) + @retrolab/lab-extension v0.3.13 enabled OK +``` + +This is extremely helpful if the same image is being shared across hubs, and +you want some of the hubs to have some of the extensions disabled. diff --git a/doc/source/jupyterhub/customizing/user-management.md b/docs/source/jupyterhub/customizing/user-management.md similarity index 91% rename from doc/source/jupyterhub/customizing/user-management.md rename to docs/source/jupyterhub/customizing/user-management.md index 25dec19a62..611ed3ce5e 100644 --- a/doc/source/jupyterhub/customizing/user-management.md +++ b/docs/source/jupyterhub/customizing/user-management.md @@ -84,7 +84,7 @@ are being used as expected. ## Admin Users JupyterHub has the concept of -[admin users](https://jupyterhub.readthedocs.io/en/latest/getting-started/authenticators-users-basics.html#configure-admins-admin-users) +[admin users](https://jupyterhub.readthedocs.io/en/stable/tutorial/getting-started/authenticators-users-basics.html#configure-admins-admin-users) who have special rights. They can start / stop other user's servers, and optionally access user's notebooks. They will see a new **Admin** button in their Control Panel which will take them to an **Admin Panel** where they can @@ -93,23 +93,25 @@ perform all these actions. You can specify a list of admin users in your `config.yaml`: ```yaml -auth: - admin: - users: - - adminuser1 - - adminuser2 +hub: + config: + Authenticator: + admin_users: + - adminuser1 + - adminuser2 ``` By default, admins can access user's notebooks. If you wish to disable this, use this in your `config.yaml`: ```yaml -auth: - admin: - access: false +hub: + config: + JupyterHub: + admin_access: false ``` ## Authenticating Users For information on authenticating users in JupyterHub, see -[the Authentication guide](../../administrator/authentication). +[the Authentication guide](../../administrator/authentication.md). diff --git a/doc/source/jupyterhub/customizing/user-resources.md b/docs/source/jupyterhub/customizing/user-resources.md similarity index 99% rename from doc/source/jupyterhub/customizing/user-resources.md rename to docs/source/jupyterhub/customizing/user-resources.md index 595950fd58..9d05b785d3 100644 --- a/doc/source/jupyterhub/customizing/user-resources.md +++ b/docs/source/jupyterhub/customizing/user-resources.md @@ -95,7 +95,7 @@ provider. Here are a few links to help you get started: - [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine/docs/how-to/gpus) - [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/blogs/compute/running-gpu-accelerated-kubernetes-workloads-on-p3-and-p2-ec2-instances-with-amazon-eks/) -- [Azure Kubernetes Service (AKS)](https://docs.microsoft.com/en-us/azure/aks/gpu-cluster) +- [Azure Kubernetes Service (AKS)](https://learn.microsoft.com/en-us/azure/aks/gpu-cluster) You will also need to deploy the k8s-device-plugin following the instructions [here](https://github.com/NVIDIA/k8s-device-plugin#quick-start). diff --git a/doc/source/jupyterhub/customizing/user-storage.md b/docs/source/jupyterhub/customizing/user-storage.md similarity index 95% rename from doc/source/jupyterhub/customizing/user-storage.md rename to docs/source/jupyterhub/customizing/user-storage.md index 7ea48fad15..100faaf1c4 100644 --- a/doc/source/jupyterhub/customizing/user-storage.md +++ b/docs/source/jupyterhub/customizing/user-storage.md @@ -138,7 +138,11 @@ metadata: provisioner: kubernetes.io/gce-pd parameters: type: pd-ssd - zones: +allowedTopologies: + - matchLabelExpressions: + - key: failure-domain.beta.kubernetes.io/zone + values: + - ``` Replace `` with the Zone in which you created your cluster (you can find @@ -179,9 +183,12 @@ singleuser: This will request a `2Gi` volume per user. The default requests a `10Gi` volume per user. -We recommend you use the [IEC Prefixes](https://physics.nist.gov/cuu/Units/binary.html) -(Ki, Mi, Gi, etc) for specifying how much storage you want. `2Gi` (IEC Prefix) is -`(2 * 1024 * 1024 * 1024)` bytes, while `2G` (SI Prefix) is `(2 * 1000 * 1000 * 1000)` bytes. +We recommend you use the [IEC binary prefixes] (Ki, Mi, Gi, etc) for specifying +how much storage you want. `2Gi` (IEC binary prefix) is `(2 * 1024 * 1024 * +1024)` bytes, while `2G` (SI decimal prefix) is `(2 * 1000 * 1000 * 1000)` +bytes. + +[iec binary prefixes]: https://en.wikipedia.org/wiki/Binary_prefix ## Turn off per-user persistent storage diff --git a/doc/source/jupyterhub/index.md b/docs/source/jupyterhub/index.md similarity index 100% rename from doc/source/jupyterhub/index.md rename to docs/source/jupyterhub/index.md diff --git a/doc/source/jupyterhub/installation.md b/docs/source/jupyterhub/installation.md similarity index 84% rename from doc/source/jupyterhub/installation.md rename to docs/source/jupyterhub/installation.md index 6b30f04ade..4f3fe1f0d2 100644 --- a/doc/source/jupyterhub/installation.md +++ b/docs/source/jupyterhub/installation.md @@ -2,9 +2,9 @@ # Installing JupyterHub -With a {doc}`Kubernetes cluster ` cluster -available and {doc}`Helm ` installed, we can install -JupyterHub in the Kubernetes cluster using the JupyterHub Helm chart. +With a {doc}`Kubernetes cluster ` available +and {doc}`Helm ` installed, we can install JupyterHub +in the Kubernetes cluster using the JupyterHub Helm chart. ## Initialize a Helm chart configuration file @@ -35,7 +35,7 @@ just create a `config.yaml` file with some helpful comments. # Introduction to YAML: https://www.youtube.com/watch?v=cdLNKUoMc6c # Chart config reference: https://zero-to-jupyterhub.readthedocs.io/en/stable/resources/reference.html # Chart default values: https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/HEAD/jupyterhub/values.yaml -# Available chart versions: https://jupyterhub.github.io/helm-chart/ +# Available chart versions: https://hub.jupyter.org/helm-chart/ # ``` @@ -44,11 +44,11 @@ can try with `nano config.yaml`. ## Install JupyterHub -1. Make Helm aware of the [JupyterHub Helm chart repository](https://jupyterhub.github.io/helm-chart/) so you can install the +1. Make Helm aware of the [JupyterHub Helm chart repository](https://hub.jupyter.org/helm-chart/) so you can install the JupyterHub chart from it without having to use a long URL name. ``` - helm repo add jupyterhub https://jupyterhub.github.io/helm-chart/ + helm repo add jupyterhub https://hub.jupyter.org/helm-chart/ helm repo update ``` @@ -101,13 +101,13 @@ can try with `nano config.yaml`. Helm chart is paired with a specific version of JupyterHub. E.g., `0.11.1` of the Helm chart runs JupyterHub `1.3.0`. For a list of which JupyterHub version is installed in each version - of the JupyterHub Helm Chart, see the [Helm Chart repository](https://jupyterhub.github.io/helm-chart/). + of the JupyterHub Helm Chart, see the [Helm Chart repository](https://hub.jupyter.org/helm-chart/). 3. While Step 2 is running, you can see the pods being created by entering in a different terminal: ``` - kubectl get pod --namespace jhub + kubectl get pod --namespace ``` To remain sane we recommend that you enable autocompletion for kubectl @@ -128,26 +128,23 @@ can try with `nano config.yaml`. proxy-7cb9bc4cc-9bdlp 1/1 Running 0 37s ``` -5. Find the IP we can use to access the JupyterHub. Run the following command - until the `EXTERNAL-IP` of the `proxy-public` [service](https://kubernetes.io/docs/concepts/services-networking/service/) is - available like in the example output. +5. Find the IP we can use to access the JupyterHub. Run the following + command until the `EXTERNAL-IP` of the `proxy-public` [service](https://kubernetes.io/docs/concepts/services-networking/service/) + is available like in the example output. ``` - kubectl get service --namespace + kubectl --namespace get service proxy-public ``` ``` - NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE - hub ClusterIP 10.51.243.14 8081/TCP 1m - proxy-api ClusterIP 10.51.247.198 8001/TCP 1m + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE proxy-public LoadBalancer 10.51.248.230 104.196.41.97 80:31916/TCP 1m ``` - If the IP for `proxy-public` is too long to fit into the window, you - can find the longer version by calling: + Or, use the short form: ``` - kubectl describe service proxy-public --namespace + kubectl --namespace get service proxy-public --output jsonpath='{.status.loadBalancer.ingress[].ip}' ``` 6. To use JupyterHub, enter the external IP for the `proxy-public` service in diff --git a/doc/source/jupyterhub/uninstall.md b/docs/source/jupyterhub/uninstall.md similarity index 100% rename from doc/source/jupyterhub/uninstall.md rename to docs/source/jupyterhub/uninstall.md diff --git a/doc/source/kubernetes/amazon/efs_storage.md b/docs/source/kubernetes/amazon/efs_storage.md similarity index 98% rename from doc/source/kubernetes/amazon/efs_storage.md rename to docs/source/kubernetes/amazon/efs_storage.md index e2a9e793f0..9005319f17 100644 --- a/doc/source/kubernetes/amazon/efs_storage.md +++ b/docs/source/kubernetes/amazon/efs_storage.md @@ -113,7 +113,7 @@ Procedure: ``` The image setting overrides the default pinned jh base image since it has not yet been updated - to include the CHOWN_HOME setting. This will be fixed in Z2JH 0.7. + to include the CHOWN_HOME setting. type static tells jh not to use a storage class and instead use a PVC defined below. diff --git a/doc/source/kubernetes/amazon/step-zero-aws-eks.md b/docs/source/kubernetes/amazon/step-zero-aws-eks.md similarity index 94% rename from doc/source/kubernetes/amazon/step-zero-aws-eks.md rename to docs/source/kubernetes/amazon/step-zero-aws-eks.md index 05dbd3c71b..bcc5769221 100644 --- a/doc/source/kubernetes/amazon/step-zero-aws-eks.md +++ b/docs/source/kubernetes/amazon/step-zero-aws-eks.md @@ -9,7 +9,9 @@ This guide uses AWS to set up a cluster. This mirrors the steps found at [Gettin ## Procedure 1. Create a IAM Role for EKS Service Role. - It should have the following policies + Instructions for creating a role can be found + [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create.html). + It should have the following policies: - AmazonEKSClusterPolicy - AmazonEKSServicePolicy @@ -85,6 +87,5 @@ This guide uses AWS to set up a cluster. This mirrors the steps found at [Gettin ## Cluster Autoscaler -If you'd like to do some {ref}`optimizations `, you need to deploy Cluster Autoscaler (CA) first. - -See +If you'd like to do some {ref}`optimizations `, +you need to deploy Cluster Autoscaler (CA) first. diff --git a/doc/source/kubernetes/amazon/step-zero-aws.md b/docs/source/kubernetes/amazon/step-zero-aws.md similarity index 94% rename from doc/source/kubernetes/amazon/step-zero-aws.md rename to docs/source/kubernetes/amazon/step-zero-aws.md index 085da10771..18bd3599bd 100644 --- a/doc/source/kubernetes/amazon/step-zero-aws.md +++ b/docs/source/kubernetes/amazon/step-zero-aws.md @@ -11,10 +11,12 @@ template you will use to setup and shape your cluster. ## The Procedure -1. Create an IAM Role +1. Create an IAM (Identity and Access Management) Role. This role will be used to give your CI host permission to create and destroy - resources on AWS + resources on AWS. Instructions for creating a role can be found + [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create.html). + The following policies are required: - AmazonEC2FullAccess - IAMFullAccess @@ -29,9 +31,15 @@ template you will use to setup and shape your cluster. When creating it, assign the IAM role created in step 1. - Once created, download ssh keys. + Once created, download ssh keys (.pem file). Ensure permissions are restrictive on the file: + + ``` + chmod 400 name.pem + ``` + +3. SSH to your CI host. Instructions on how to do this are given + [here](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AccessingInstancesLinux.html). -3. SSH to your CI host 4. Install kops and kubectl on your CI host - Follow the instructions here: @@ -92,9 +100,9 @@ template you will use to setup and shape your cluster. kops create cluster $NAME \ --zones "$ZONES" \ --authorization RBAC \ - --master-size t2.micro \ + --master-size t3a.small \ --master-volume-size 10 \ - --node-size t2.medium \ + --node-size t3.medium \ --node-volume-size 10 \ --yes ``` diff --git a/doc/source/kubernetes/digital-ocean/step-zero-digital-ocean.md b/docs/source/kubernetes/digital-ocean/step-zero-digital-ocean.md similarity index 100% rename from doc/source/kubernetes/digital-ocean/step-zero-digital-ocean.md rename to docs/source/kubernetes/digital-ocean/step-zero-digital-ocean.md diff --git a/doc/source/kubernetes/google/step-zero-gcp.md b/docs/source/kubernetes/google/step-zero-gcp.md similarity index 98% rename from doc/source/kubernetes/google/step-zero-gcp.md rename to docs/source/kubernetes/google/step-zero-gcp.md index 683bdc3e7d..ead03588e0 100644 --- a/doc/source/kubernetes/google/step-zero-gcp.md +++ b/docs/source/kubernetes/google/step-zero-gcp.md @@ -5,7 +5,7 @@ [Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine/) (GKE) is the simplest and most common way of setting up a Kubernetes Cluster. You may be able to receive [free credits](https://cloud.google.com/free/) for trying it out (though note that a -free account [comes with limitations](https://cloud.google.com/free/docs/gcp-free-tier#free-tier-usage-limits)). +free account [comes with limitations](https://cloud.google.com/free/docs/free-cloud-features#free-tier-usage-limits)). Either way, you will need to connect your credit card or other payment method to your google cloud account. @@ -68,7 +68,7 @@ your google cloud account. - Replace `` with a name that can be used to refer to this cluster in the future. - `--machine-type` specifies the amount of CPU and RAM in each node within - this default node pool. There is a [variety of types](https://cloud.google.com/compute/docs/machine-types) to choose from. + this default node pool. There is a [variety of types](https://cloud.google.com/compute/docs/machine-resource) to choose from. - `--num-nodes` specifies how many nodes to spin up. You can change this later through the cloud console or using the `gcloud` command line tool. - `--zone` specifies the data center zone where your cluster will be created. diff --git a/doc/source/kubernetes/ibm/step-zero-ibm.md b/docs/source/kubernetes/ibm/step-zero-ibm.md similarity index 94% rename from doc/source/kubernetes/ibm/step-zero-ibm.md rename to docs/source/kubernetes/ibm/step-zero-ibm.md index 5ed4ac6fa5..b92e35960d 100644 --- a/doc/source/kubernetes/ibm/step-zero-ibm.md +++ b/docs/source/kubernetes/ibm/step-zero-ibm.md @@ -48,7 +48,7 @@ Procedure: Or, if you prefer, create the cluster using the [IBM Cloud CLI tools](https://cloud.ibm.com/docs/containers?topic=containers-cs_cli_install)) 2. Configure kubectl - [kubectl](https://kubernetes.io/docs/reference/kubectl/overview/) is a CLI tool to interact with a Kubernetes cluster. In this occasion, you will use it to point forward to the created Kubernetes cluster. + [kubectl](https://kubernetes.io/docs/reference/kubectl/) is a CLI tool to interact with a Kubernetes cluster. In this occasion, you will use it to point forward to the created Kubernetes cluster. 1. Use `ibmcloud login` to log in interactively into the IBM Cloud. Provide the organization (org), location and space under which the cluster is created. You can reconfirm the details by running `ibmcloud target` command. 2. When the cluster is ready, retrieve the cluster configuration by using the cluster's name: diff --git a/doc/source/kubernetes/index.md b/docs/source/kubernetes/index.md similarity index 100% rename from doc/source/kubernetes/index.md rename to docs/source/kubernetes/index.md diff --git a/doc/source/kubernetes/microsoft/step-zero-azure.md b/docs/source/kubernetes/microsoft/step-zero-azure.md similarity index 66% rename from doc/source/kubernetes/microsoft/step-zero-azure.md rename to docs/source/kubernetes/microsoft/step-zero-azure.md index aca090d839..e578f36afe 100644 --- a/doc/source/kubernetes/microsoft/step-zero-azure.md +++ b/docs/source/kubernetes/microsoft/step-zero-azure.md @@ -2,10 +2,10 @@ # Kubernetes on Microsoft Azure Kubernetes Service (AKS) -You can create a Kubernetes cluster [either through the Azure portal website, or using the Azure command line tools](https://docs.microsoft.com/en-us/azure/aks/). +You can create a Kubernetes cluster [either through the Azure portal website, or using the Azure command line tools](https://learn.microsoft.com/en-us/azure/aks/). This page describes the commands required to setup a Kubernetes cluster using the command line. -If you prefer to use the Azure portal see the [Azure Kubernetes Service quickstart](https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough-portal). +If you prefer to use the Azure portal see the [Azure Kubernetes Service quickstart](https://learn.microsoft.com/en-us/azure/aks/learn/quick-kubernetes-deploy-portal). 1. Prepare your Azure shell environment. You have two options, one is to use the Azure interactive shell, the other is to install the Azure command-line @@ -30,7 +30,7 @@ If you prefer to use the Azure portal see the [Azure Kubernetes Service quicksta - **Install command-line tools locally**. You can access the Azure CLI via a package that you can install locally. - To do so, first follow the [installation instructions](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest) in the + To do so, first follow the [installation instructions](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest) in the Azure documentation. Then run the following command to connect your local CLI with your account: @@ -77,12 +77,15 @@ If you prefer to use the Azure portal see the [Azure Kubernetes Service quicksta `` of `ucb_2018sp_data100_hub`. - `--location` specifies the location of the data center you want your resource to be in. In this case, we used the `centralus` location. For other options, see the - [Azure list of locations that support AKS](https://docs.microsoft.com/en-us/azure/aks/quotas-skus-regions#region-availability). + [Azure list of locations that support AKS](https://learn.microsoft.com/en-us/azure/aks/quotas-skus-regions#region-availability). + Note that not all locations offer all VM sizes. To see a list of recommended locations, go to + [Azure Portal > Virtual Machines](https://portal.azure.com/#view/HubsExtension/BrowseResource/resourceType/Microsoft.Compute%2FVirtualMachines), + click on "create.." and see the list of recommended locations in the drop down list for `Region`. - `--output table` specifies that the output should be in human readable format, rather than the default JSON output. We shall use this with most commands when executing them by hand. - Consider [setting a cloud budget](https://docs.microsoft.com/en-us/partner-center/set-an-azure-spending-budget-for-your-customers) + Consider [setting a cloud budget](https://learn.microsoft.com/en-us/partner-center/set-an-azure-spending-budget-for-your-customers) for your Azure account in order to make sure you don't accidentally spend more than you wish to. @@ -120,9 +123,9 @@ If you prefer to use the Azure portal see the [Azure Kubernetes Service quicksta Kubernetes does not by default come with a controller that enforces `networkpolicy` resources. `networkpolicy` resources are important as they define how Kubernetes pods can securely communicate with one another and the outside sources, for example, the internet. - To enable this in Azure, we must first create a [Virtual Network](https://docs.microsoft.com/en-gb/azure/virtual-network/virtual-networks-overview) with Azure's own network policies enabled. + To enable this in Azure, we must first create a [Virtual Network](https://learn.microsoft.com/en-gb/azure/virtual-network/virtual-networks-overview) with Azure's own network policies enabled. - This section of the documentation is following the Microsoft Azure tutorial on [creating an AKS cluster and enabling network policy](https://docs.microsoft.com/en-us/azure/aks/use-network-policies#create-an-aks-cluster-and-enable-network-policy), which includes information on using [Calico](https://docs.projectcalico.org) network policies. + This section of the documentation is following the Microsoft Azure tutorial on [creating an AKS cluster and enabling network policy](https://learn.microsoft.com/en-us/azure/aks/use-network-policies#create-an-aks-cluster-and-enable-network-policy), which includes information on using [Calico](https://docs.tigera.io/) network policies. ``` az network vnet create \ @@ -157,7 +160,7 @@ If you prefer to use the Azure portal see the [Azure Kubernetes Service quicksta --output tsv) ``` - We will create an Azure Active Directory (Azure AD) [service principal](https://docs.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals) for use with the cluster, and assign the [Contributor role](https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#contributor) for use with the VNet. + We will create an Azure Active Directory (Azure AD) [service principal](https://learn.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals) for use with the cluster, and assign the [Contributor role](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#contributor) for use with the VNet. Make sure `SERVICE-PRINCIPAL-NAME` is something recognisable, for example, `binderhub-sp`. ``` @@ -167,9 +170,9 @@ If you prefer to use the Azure portal see the [Azure Kubernetes Service quicksta --scopes $VNET_ID \ --query password \ --output tsv) - SP_ID=$(az ad sp show \ - --id http:// \ - --query appId \ + SP_ID=$(az ad app list \ + --filter "displayname eq ''" \ + --query [0].appId \ --output tsv) ``` @@ -212,7 +215,7 @@ If you prefer to use the Azure portal see the [Azure Kubernetes Service quicksta - `--node-count` is the number of nodes you want in your Kubernetes cluster - `--node-vm-size` is the size of the nodes you want to use, which varies based on what you are using your cluster for and how much RAM/CPU each of your users need. - There is a [list of all possible node sizes](https://docs.microsoft.com/en-us/azure/cloud-services/cloud-services-sizes-specs) + There is a [list of all possible node sizes](https://learn.microsoft.com/en-us/azure/cloud-services/cloud-services-sizes-specs) for you to choose from, but not all might be available in your location. If you get an error whilst creating the cluster you can try changing either the region or the node size. - `--service-principal` is the application ID of the service principal we created @@ -227,7 +230,47 @@ If you prefer to use the Azure portal see the [Azure Kubernetes Service quicksta This should take a few minutes and provide you with a working Kubernetes cluster! -8. If you're using the Azure CLI locally, install [kubectl](https://kubernetes.io/docs/reference/kubectl/overview/), a tool + Optionally, prepare autoscaling, where: + + - `--vm-set-type VirtualMachineScaleSets` deploys the cluster as a scale set. + - `--enable-cluster-autoscaler` enables autoscaling feature for your cluster + - `--min-count 3` is the minimum node count + - `--max-count 6` is the maximum node count + + You can also enable autoscaling feature later, with: + + ```bash + SP_POOLNAME=$(az aks nodepool list \ + --resource-group \ + --cluster-name \ + --query [0].name \ + --output tsv) + az aks nodepool update \ + --name $SP_POOLNAME \ + --cluster-name \ + --resource-group \ + --enable-cluster-autoscaler \ + --min-count \ + --max-count + ``` + + or update the parameters with `--update-cluster-autoscaler`. + + ```bash + az aks update \ + --name \ + --resource-group \ + --update-cluster-autoscaler \ + --min-count \ + --max-count \ + --output table + ``` + + **Both** `--min-count` and `--max-count` must be defined. + + Read more about available options for the autoscaler [here](https://github.com/MicrosoftDocs/azure-docs/blob/main/articles/aks/cluster-autoscaler.md). + +8. If you're using the Azure CLI locally, install [kubectl](https://kubernetes.io/docs/reference/kubectl/), a tool for accessing the Kubernetes API from the commandline: ``` @@ -267,7 +310,48 @@ If you create the cluster using the Azure Portal you must enable RBAC. RBAC is enabled by default when using the command line tools. ``` +11. Enabling Autoscaling (Optional) + + If your cluster is prepared for autoscaling (`--enable-cluster-autoscaler`), + move to the Azure Portal to enable autoscaling and set rules to manage the Cluster Autoscaler. + + Navigate to your active subscription on the [Portal](https://portal.azure.com/). + + Under "Resources", select the VMSS. + It should be named something like `aks-nodepool1--vmss`. + + ```{image} ../../_static/images/azure/select_vmss.png + :align: center + ``` + + From the left-hand menu, select "Scaling". + Click the blue "Custom autoscale" button and an autogenerated form for a scale condition will appear. + We will add two new rules to this condition: + + - Increase the instance count by 1 when the average CPU usage over 10 minutes is greater than 70% + - Decrease the instance count by 1 when the average CPU usage over 10 minutes is less than 5% + + ```{image} ../../_static/images/azure/scale_condition.png + :align: center + ``` + + Make sure the "Scale based on metric" option is selected and click "+ Add new rule", another autogenerated form will appear. + This will be pre-filled with the required settings to fulfill our first rule, so save it by clicking "Update" and click "+ Add new rule" again. + + ```{image} ../../_static/images/azure/scale_out.png + :align: center + ``` + + The second form needs to be edited for the second rule to decrease the instance count by 1 when the average CPU usage over 10 minutes is less than 5%. + Save this rule and then save the overall scale condition, the cluster will be updated automatically. + + ```{image} ../../_static/images/azure/scale_in.png + :align: center + ``` + + This form can also be used to change `--node-count`/`--min-count`/`--max-count` that was set previously by using the "Instance limits" section of the scale condition ("Default", "Minimum" and "Maximum" respectively). + Congrats. Now that you have your Kubernetes cluster running, it's time to begin {ref}`setup-helm`. -[azure resource group]: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-overview#resource-groups +[azure resource group]: https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-overview#resource-groups diff --git a/docs/source/kubernetes/minikube/step-zero-minikube.md b/docs/source/kubernetes/minikube/step-zero-minikube.md new file mode 100644 index 0000000000..31f63f0b93 --- /dev/null +++ b/docs/source/kubernetes/minikube/step-zero-minikube.md @@ -0,0 +1,46 @@ +(minikube-k8s) + +# Kubernetes on minikube (for learning and development only) + +[minikube] can setup a Kubernetes cluster on a single computer. minikube be suitable in order to learn about Kubernetes and to develop and test changes, but its not meant to be used for production purposes. + +```{important} +The Zero to JupyterHub guide assumes you're using a managed Kubernetes service with one of the main cloud platforms and **[minikube] is not officially supported**. You may be able to get help on the [Jupyter community forum](https://discourse.jupyter.org/c/jupyterhub/10). +``` + +[minikube]: https://minikube.sigs.k8s.io/docs/ + +## Kubernetes cluster requirements + +All the requirements are implemented in minikube >= v1.31.2: + +- [Dynamic Volume Provisioning](https://kubernetes.io/docs/concepts/storage/dynamic-provisioning/) for persistent storage +- [LoadBalancer](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer) or [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) for managing external access to JupyterHub + +## minikube installation + +Follow the installation steps in the [minikube's "Get Started!" page](https://minikube.sigs.k8s.io/docs/start/). + +## Kubernetes cluster creation + +From a terminal, run + +```bash +minikube start \ +--kubernetes-version stable \ +--nodes 2 \ +--cpus 2 \ +--memory 2000 \ +--cni calico +``` + +To test if your cluster is initialized, run: + +```bash +kubectl get node +``` + +The response should list two running nodes (or however many nodes you set with ``--nodes` above). + +Congrats. Now that you have your Kubernetes cluster running, it's time to +begin {ref}`setup-helm`. diff --git a/doc/source/kubernetes/openstack/.gitkeep b/docs/source/kubernetes/openstack/.gitkeep similarity index 100% rename from doc/source/kubernetes/openstack/.gitkeep rename to docs/source/kubernetes/openstack/.gitkeep diff --git a/docs/source/kubernetes/other-infrastructure/step-zero-other.md b/docs/source/kubernetes/other-infrastructure/step-zero-other.md new file mode 100644 index 0000000000..9a75cfb23c --- /dev/null +++ b/docs/source/kubernetes/other-infrastructure/step-zero-other.md @@ -0,0 +1,23 @@ +(self-hosted-k8s) + +# Self-hosted Kubernetes + +The Zero to JupyterHub guide assumes you're using a managed Kubernetes service with one of the main cloud platforms. + +JupyterHub can be deployed on a self-hosted Kubernetes cluster, but this is not officially supported. +However you may be able to get help, and find examples of other self-hosted deployments, on the [Jupyter community forum](https://discourse.jupyter.org/c/jupyterhub/10). + +## Kubernetes cluster requirements + +Z2JH assumes your Kubernetes cluster has the following features: + +- [Dynamic Volume Provisioning](https://kubernetes.io/docs/concepts/storage/dynamic-provisioning/) for persistent storage +- [LoadBalancer](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer) or [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) for managing external access to JupyterHub + +Z2JH assumes you have full administrator access to the cluster. + +In many cases you need to consult your Kubernetes provider's documentation to find out how to enable these features. +Please test all these features with a simple deployment before proceeding with the Zero to JupyterHub guide. +Z2JH has several interacting components which makes it much more difficult to debug Kubernetes problems, so you will save a lot of time by verifying your cluster is working correctly first. + +It is possible to deploy Z2JH without some features, for example by [disabling persistent storage](schema_singleuser.storage.type) or using [NodePort](schema_proxy.service.type), but this is only suitable for testing. diff --git a/doc/source/kubernetes/ovh/step-zero-ovh.md b/docs/source/kubernetes/ovh/step-zero-ovh.md similarity index 93% rename from doc/source/kubernetes/ovh/step-zero-ovh.md rename to docs/source/kubernetes/ovh/step-zero-ovh.md index c8fe419f3c..95be1cb2c6 100644 --- a/doc/source/kubernetes/ovh/step-zero-ovh.md +++ b/docs/source/kubernetes/ovh/step-zero-ovh.md @@ -1,8 +1,8 @@ (ovh)= -# Kubernetes on [OVHcloud](https://www.ovh.ie/) (OVH) +# Kubernetes on [OVHcloud](https://www.ovhcloud.com/) (OVH) -[OVHcloud](https://www.ovh.ie/) is a leader in the hosted private cloud services space in Europe. +[OVHcloud](https://www.ovhcloud.com/) is a leader in the hosted private cloud services space in Europe. They offer a managed Kubernetes service as well as a managed private registry for Docker images. diff --git a/doc/source/kubernetes/redhat/step-zero-openshift.md b/docs/source/kubernetes/redhat/step-zero-openshift.md similarity index 77% rename from doc/source/kubernetes/redhat/step-zero-openshift.md rename to docs/source/kubernetes/redhat/step-zero-openshift.md index c93fbc15cb..816d8f7c8b 100644 --- a/doc/source/kubernetes/redhat/step-zero-openshift.md +++ b/docs/source/kubernetes/redhat/step-zero-openshift.md @@ -7,10 +7,10 @@ For setting up JupyterHub on OpenShift, check out the [JupyterHub on OpenShift](https://github.com/jupyter-on-openshift/jupyterhub-quickstart) project. It provides an OpenShift template based JupyterHub deployment. Zero to JupyterHub uses [helm](https://helm.sh) which is currently usable with OpenShift; yet deploying helm on OpenShift -is somewhat complicated (see RedHat's blog post on [Getting Started with Helm on OpenShift](https://www.openshift.com/blog/getting-started-helm-openshift)). +is somewhat complicated (see RedHat's blog post on [Getting Started with Helm on OpenShift](https://cloud.redhat.com/blog/getting-started-helm-openshift)). ## Additional resources about Jupyter on OpenShift - An excellent series of OpenShift blog posts on Jupyter and OpenShift authored by Red Hat developer, Graham Dumpleton, are - available on the [OpenShift blog](https://www.openshift.com/blog/jupyter-openshift-using-openshift-data-analytics). + available on the [OpenShift blog](https://cloud.redhat.com/blog/jupyter-openshift-using-openshift-data-analytics). diff --git a/doc/source/kubernetes/setup-helm.md b/docs/source/kubernetes/setup-helm.md similarity index 100% rename from doc/source/kubernetes/setup-helm.md rename to docs/source/kubernetes/setup-helm.md diff --git a/doc/source/kubernetes/setup-kubernetes.md b/docs/source/kubernetes/setup-kubernetes.md similarity index 92% rename from doc/source/kubernetes/setup-kubernetes.md rename to docs/source/kubernetes/setup-kubernetes.md index abb13b7325..86a5c93765 100644 --- a/doc/source/kubernetes/setup-kubernetes.md +++ b/docs/source/kubernetes/setup-kubernetes.md @@ -6,26 +6,27 @@ Kubernetes' documentation describes the many [ways to set up a cluster][ways to We attempt to provide quick instructions for the most painless and popular ways of setting up a Kubernetes cluster on various cloud providers and on other infrastructure. +```{note} +During the process of setting up JupyterHub, you'll be creating some +files for configuration purposes. It may be helpful to create a folder +for your JuypterHub deployment to keep track of these files. +``` + Choose one option and proceed. ```{toctree} :titlesonly: +minikube/step-zero-minikube google/step-zero-gcp microsoft/step-zero-azure -microsoft/step-zero-azure-autoscale amazon/step-zero-aws amazon/step-zero-aws-eks redhat/step-zero-openshift ibm/step-zero-ibm digital-ocean/step-zero-digital-ocean ovh/step-zero-ovh -``` - -```{note} -During the process of setting up JupyterHub, you'll be creating some -files for configuration purposes. It may be helpful to create a folder -for your JuypterHub deployment to keep track of these files. +other-infrastructure/step-zero-other ``` [ways to set up a cluster]: https://kubernetes.io/docs/setup/ diff --git a/doc/source/repo2docker.md b/docs/source/repo2docker.md similarity index 95% rename from doc/source/repo2docker.md rename to docs/source/repo2docker.md index 94e8f0bf41..c43a8a4d26 100644 --- a/doc/source/repo2docker.md +++ b/docs/source/repo2docker.md @@ -72,7 +72,7 @@ to configure JupyterHub to build off of this image: 4. **Get credentials for a docker repository.** The image you will build for your JupyterHub must be made available by being - published to some container registry. You could for example use [Docker Hub](https://hub.docker.com/) or [Google Container Registry](https://cloud.google.com/container-registry/). + published to some container registry. You could for example use [quay.io](https://quay.io) or [Docker Hub](https://hub.docker.com/). In the next step, you need an image reference for you and others to find your image with. @@ -83,10 +83,10 @@ to configure JupyterHub to build off of this image: /: ``` - An image reference on Google Container Registry: + An image reference on quay.io: ``` - gcr.io//: + quay.io//: ``` - Your image name can be anything memorable. diff --git a/doc/source/resources/community.md b/docs/source/resources/community.md similarity index 98% rename from doc/source/resources/community.md rename to docs/source/resources/community.md index af3838ee36..08d0d51595 100644 --- a/doc/source/resources/community.md +++ b/docs/source/resources/community.md @@ -19,7 +19,7 @@ JupyterHub guide, please see the [issues page](https://github.com/jupyterhub/zer We hope that you will use this section to share deployments with on a variety of infrastructure and for different use cases. -There is also a [community maintained list](#users-list) of users of this +There is also a [community maintained list](users-list) of users of this Guide and the JupyterHub Helm Chart. Please submit an [issue/pull request](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/issues) to add to this section. Thanks. @@ -111,7 +111,7 @@ kubectl --namespace= get pod -o ``` You can find more information on what kinds of output you can generate at -[the kubectl information page](https://kubernetes.io/docs/reference/kubectl/overview/). +[the kubectl information page](https://kubernetes.io/docs/reference/kubectl/). (click and search for the text "Output Options") This is a community maintained list of organizations / people using the Zero to diff --git a/docs/source/resources/glossary.md b/docs/source/resources/glossary.md new file mode 100644 index 0000000000..bdd833e07c --- /dev/null +++ b/docs/source/resources/glossary.md @@ -0,0 +1,122 @@ +(glossary)= + +# Glossary + +A partial glossary of terms used in this guide. For more complete descriptions +of the components in JupyterHub, see {ref}`tools`. Here we try to keep the +definition as succinct and relevant as possible, and provide links to learn more +details. + + + +```{glossary} +[admin user](https://jupyterhub.readthedocs.io/en/stable/getting-started/authenticators-users-basics.html?highlight=admin) + A user who can access the JupyterHub admin panel. They can start/stop user + pods, and potentially access their notebooks. + +[authenticator](https://jupyterhub.readthedocs.io/en/stable/reference/authenticators.html) + The way in which users are authenticated to log into JupyterHub. There + are many authenticators available, like GitHub, Google, MediaWiki, + Dummy (anyone can log in), etc. + +`config.yaml` + The {term}`Helm charts ` templates are rendered with these + {term}`Helm values` as input. The file is written in the [YAML](https://en.wikipedia.org/wiki/YAML) format. The YAML format is essential + to grasp if working with Kubernetes and Helm. + +container + A container is a isolated working space which for us gives users the + tools, libraries, and capabilities to be productive. + +culler + A separate process in the JupyterHub that stops the user pods of users who + have not been active in a configured interval. + +Dockerfile + A Dockerfile declares how to build a {term}`Docker image`. + +Docker image + A Docker image, built from a {term}`Dockerfile`, allows tools like + `docker` to create any number of {term}`containers `. + +image registry + A service for storing Docker images so that they can be stored + and used later. + The default public registry is at https://hub.docker.com, + but you can also run your own private image registry. + Many cloud providers offer private image registry services. + +[environment variables](https://en.wikipedia.org/wiki/Environment_variable) + A set of named values that can affect the way running processes will + behave on a computer. Some common examples are `PATH`, `HOME`, and + `EDITOR`. + +[Helm chart](https://helm.sh/docs/topics/charts/) + A Helm chart is a group of {term}`Helm templates ` that + can, given its default values and overrides in provided `yaml` files, + render to a set of {term}`Kubernetes resources ` that + can be easily installed to your Kubernetes cluster. In other words a Helm + chart is like a configurable installation of software and infrastructure + to exist on a cloud. + +[Helm template](https://helm.sh/docs/chart_template_guide/) + A Helm template (`.yaml` files), can given values, render to a + {term}`Kubernetes resource`. + +[Helm values](https://helm.sh/docs/chart_template_guide/values_files/) + {term}`Helm charts ` has a set of predefined values + (`values.yaml`) typically overridden by other values in `config.yaml`. The + final values are used to generate {term}`Kubernetes resources ` from {term}`Helm templates ` within a + {term}`Helm chart`. + +Kubernetes + For our purposes, you can think of Kubernetes as a way to speak to a cloud + and describe what you would like it to do, in a manner that isn't specific + for that cloud. + + - [The Illustrated Children's Guide to Kubernetes](https://www.youtube.com/watch?v=4ht22ReBjno) + - [The official "What is Kubernetes?" text](https://kubernetes.io/docs/concepts/overview/) + +Kubernetes API server + The [Kubernetes API](https://kubernetes.io/docs/concepts/overview/kubernetes-api/) server, + also referred to as the master, will answer questions and update the + desired state of the cluster for you. When you use `kubectl` you + communicate with the API server. + +Kubernetes Pod + *Pods* are the smallest deployable units of computing that can be created + and managed in Kubernetes. A pod will use a {term}`Docker image` to create + a container, and most often a controller such as a Deployment will ensure + there is always X running pods of a kind. + + See the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/pods/) for more + information. + +Kubernetes resource + A Kubernetes resource can for example be a [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/), + [Service](https://kubernetes.io/docs/concepts/services-networking/service/) or a + [Secret](https://kubernetes.io/docs/concepts/configuration/secret/). It + is something you can request by the {term}`Kubernetes API server` to be + present in the cluster. + +persistent storage + A filesystem attached to a user pod that allows the user to store + notebooks and files that persist across multiple logins. + +Node Pool + A *node pool* or *node group* represents a set of nodes of the same kind. + With cluster autoscaling, a node pool can grow and shrink based on demand + allowing you to save computational resources. + +[repo2docker](https://github.com/jupyterhub/repo2docker) + A tool which lets you quickly convert a Git repository into a + {term}`Docker image`. + +[spawner](https://jupyterhub.readthedocs.io/en/stable/getting-started/spawners-basics.html) + A spawner is a separate process created for each active user by + JupyterHub. They are each responsible for one user. This Helm chart relies + on [KubeSpawner](https://jupyterhub-kubespawner.readthedocs.io/en/latest/). +``` diff --git a/doc/source/resources/index.md b/docs/source/resources/index.md similarity index 100% rename from doc/source/resources/index.md rename to docs/source/resources/index.md diff --git a/doc/source/resources/reference-docs.md b/docs/source/resources/reference-docs.md similarity index 80% rename from doc/source/resources/reference-docs.md rename to docs/source/resources/reference-docs.md index 9c3f91ceda..116c2f20b7 100644 --- a/doc/source/resources/reference-docs.md +++ b/docs/source/resources/reference-docs.md @@ -2,10 +2,10 @@ # Related Projects -- The [JupyterHub Documentation](https://jupyterhub.readthedocs.io/en/latest/) +- The [JupyterHub Documentation](https://jupyterhub.readthedocs.io/en/stable/) provides information about JupyterHub itself (not the Kubernetes deployment). - [Binder](https://mybinder.org) allows users to create sharable computational environments on-the-fly. It makes heavy use of JupyterHub. -- The [2016 JupyterHub Workshop](https://github.com/jupyter-resources/jupyterhub-2016-workshop) +- The [2016 JupyterHub Workshop](https://github.com/jupyter/jupyterhub-2016-workshop) was an informal gathering to share experience in deploying JupyterHub for various use-cases, including teaching and high-performance computing. diff --git a/doc/source/resources/reference.txt b/docs/source/resources/reference.txt similarity index 100% rename from doc/source/resources/reference.txt rename to docs/source/resources/reference.txt diff --git a/doc/source/resources/tools.md b/docs/source/resources/tools.md similarity index 100% rename from doc/source/resources/tools.md rename to docs/source/resources/tools.md diff --git a/images/hub/Dockerfile b/images/hub/Dockerfile index f45713c60a..20a69439b8 100644 --- a/images/hub/Dockerfile +++ b/images/hub/Dockerfile @@ -1,82 +1,131 @@ -FROM ubuntu:20.04 - -# VULN_SCAN_TIME=2021-08-27_01:05:08 - -ENV DEBIAN_FRONTEND=noninteractive \ - LANG=C.UTF-8 - -# psycopg2-binary in requirements.txt is not compiled for linux/arm64 -# TODO: Use build stages to compile psycopg2-binary separately instead of -# bloating the image size -RUN EXTRA_APT_PACKAGES=; \ - if [ `uname -m` != 'x86_64' ]; then EXTRA_APT_PACKAGES=libpq-dev; fi; \ - apt-get update && \ - apt-get upgrade -y && \ - apt-get install -y --no-install-recommends \ - git \ - vim \ - less \ - python3 \ - python3-dev \ - python3-pip \ - python3-setuptools \ - python3-wheel \ - libssl-dev \ - libcurl4-openssl-dev \ - build-essential \ - sqlite3 \ - curl \ - dnsutils \ - npm \ - $EXTRA_APT_PACKAGES \ - && \ - rm -rf /var/lib/apt/lists/* - -ARG NB_USER=jovyan -ARG NB_UID=1000 -ARG HOME=/home/jovyan - -RUN adduser --disabled-password \ - --gecos "Default user" \ - --uid ${NB_UID} \ - --home ${HOME} \ - --force-badname \ - ${NB_USER} +# syntax = docker/dockerfile:1.3 +# VULN_SCAN_TIME=2023-10-16_05:13:59 + +# The build stage +# --------------- +# This stage is building Python wheels for use in later stages by using a base +# image that has more pre-requisites to do so, such as a C++ compiler. +# +# NOTE: If the image version is updated, also update it in ci/refreeze and +# singleuser-sample's Dockerfile! +# +FROM python:3.11-bullseye as build-stage + +# Build wheels +# +# We set pip's cache directory and expose it across build stages via an +# ephemeral docker cache (--mount=type=cache,target=${PIP_CACHE_DIR}). We use +# the same technique for the directory /tmp/wheels. +# +COPY requirements.txt requirements.txt +ARG PIP_CACHE_DIR=/tmp/pip-cache +RUN apt-get update && apt-get install -y nodejs npm +RUN npm install --global yarn +RUN --mount=type=cache,target=${PIP_CACHE_DIR} \ + pip install --upgrade pip \ + pip install build \ + && pip wheel \ + --wheel-dir=/tmp/wheels \ + -r requirements.txt \ + # Additional wheels for default-stage. Updates below should be repeated + # in default-stage. + # + py-spy + + +# The final stage - slim version +# ------------------------------ +# This stage is built and published as quay.io/jupyterhub/k8s-hub-slim. It is meant to +# provide no non-essential packages. +# +FROM python:3.11-slim-bullseye as slim-stage +ENV DEBIAN_FRONTEND=noninteractive + +ARG NB_USER=jovyan \ + NB_UID=1000 \ + HOME=/home/jovyan +RUN adduser \ + --disabled-password \ + --gecos "Default user" \ + --uid ${NB_UID} \ + --home ${HOME} \ + --force-badname \ + ${NB_USER} + +RUN apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y --no-install-recommends \ + # requirement for pycurl + libcurl4 \ + # requirement for using postgres database + libpq5 \ + # requirement for using a local sqlite database + sqlite3 \ + tini \ + git \ + curl \ + gpg \ + npm \ + && rm -rf /var/lib/apt/lists/* + +# install wheels built in the build stage COPY requirements.txt /tmp/requirements.txt -RUN pip3 install --upgrade --no-cache-dir \ - setuptools \ - pip - -RUN pip install --no-cache-dir cliapp -RUN curl -sL https://deb.nodesource.com/setup_14.x | bash -RUN apt install -y --no-install-recommends nodejs && \ - rm -rf /var/lib/apt/lists/* + +RUN mkdir -m 0755 /etc/apt/keyrings +RUN apt-get update +RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg +RUN chmod a+r /etc/apt/keyrings/nodesource.gpg + +ENV NODE_MAJOR=21 +RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | \ + tee /etc/apt/sources.list.d/nodesource.list + +RUN apt update +RUN apt install -y nodejs RUN npm install --global yarn -RUN PYCURL_SSL_LIBRARY=openssl \ - pip install --no-cache-dir \ +ARG PIP_CACHE_DIR=/tmp/pip-cache +RUN --mount=type=cache,target=${PIP_CACHE_DIR} \ + --mount=type=cache,from=build-stage,source=/tmp/wheels,target=/tmp/wheels \ + pip install \ + --find-links=/tmp/wheels/ \ -r /tmp/requirements.txt -# Support overriding a package or two through passed docker --build-args. -# ARG PIP_OVERRIDES="jupyterhub==1.3.0 git+https://github.com/consideratio/kubespawner.git" -ARG PIP_OVERRIDES= -RUN if test -n "$PIP_OVERRIDES"; then \ - pip install --no-cache-dir $PIP_OVERRIDES; \ - fi - WORKDIR /srv/jupyterhub - -# So we can actually write a db file here RUN chown ${NB_USER}:${NB_USER} /srv/jupyterhub +USER ${NB_USER} -# JupyterHub API port EXPOSE 8081 +ENTRYPOINT ["tini", "--"] +CMD ["jupyterhub", "--config", "/usr/local/etc/jupyterhub/jupyterhub_config.py"] -# when building the dependencies image -# add pip-tools necessary for computing dependencies -# this is not done in production builds by chartpress -ARG PIP_TOOLS= -RUN test -z "$PIP_TOOLS" || pip install --no-cache pip-tools==$PIP_TOOLS + +# The final stage - default version +# --------------------------------- +# We add a few non-critical packages on top of the slim version to provide some +# additional utility. +# +FROM slim-stage as default-stage + +USER root + +ARG PIP_CACHE_DIR=/tmp/pip-cache +RUN --mount=type=cache,target=${PIP_CACHE_DIR} \ + --mount=type=cache,from=build-stage,source=/tmp/wheels,target=/tmp/wheels \ + pip install \ + --find-links=/tmp/wheels/ \ + # Updates below should be repeated in build-stage. + # + # py-spy is useful for profiling performance of running hubs + py-spy + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + curl \ + dnsutils \ + git \ + less \ + vim \ + && rm -rf /var/lib/apt/lists/* USER ${NB_USER} -CMD ["jupyterhub", "--config", "/usr/local/etc/jupyterhub/jupyterhub_config.py"] diff --git a/images/hub/README.md b/images/hub/README.md new file mode 100644 index 0000000000..4dd81fae13 --- /dev/null +++ b/images/hub/README.md @@ -0,0 +1,11 @@ +# About this folder + +The Dockerfile in this folder is built by +[chartpress](https://github.com/jupyterhub/chartpress#readme), using the +requirements.txt file. The requirements.txt file is updated based on the +requirements.in file using [`pip-compile`](https://pip-tools.readthedocs.io). + +## How to update requirements.txt + +Use the "Run workflow" button at +https://github.com/jupyterhub/zero-to-jupyterhub-k8s/actions/workflows/watch-dependencies.yaml. diff --git a/images/hub/dependencies b/images/hub/dependencies deleted file mode 100755 index ade4ed93d8..0000000000 --- a/images/hub/dependencies +++ /dev/null @@ -1,201 +0,0 @@ -#!/usr/bin/env python3 -"""automatically manage requirements.txt dependencies with pip-tools - -See - - ./dependencies --help for commands and arguments - -How it works: - -- the image used in the helm chart installs a frozen environment from requirements.txt -- `pip-compile` is used to generate frozen `requirements.txt` from our actual requirements - in requirements.in. -- `pip list --outdated` is used to report available updates for packages - in the frozen environment -- pip-compile etc. are run *inside the image* to ensure consistent behavior, - rather than running on host systems, which can vary. -- When building the image to be used for running dependency-management commands, - chartpress configuration is loaded to ensure the environment is the same - as when chartpress builds the tagged image to be published. -""" - -from functools import lru_cache -import json -import os -from subprocess import check_call, check_output - -import click -from ruamel.yaml import YAML - -yaml = YAML() -here = os.path.dirname(os.path.abspath(__file__)) -chartpress_yaml = os.path.join(here, os.pardir, os.pardir, "chartpress.yaml") -values_yaml = os.path.join(here, os.pardir, os.pardir, "jupyterhub", "values.yaml") -dependencies_image = "hub-dependencies" -pip_tools_version = "5.*" - - -@lru_cache() -def build_args(image_name="hub"): - """retrieve docker build arguments from chartpress.yaml config file - - Args: - - image_name (str): - the name of the image to be built in chartpress.yaml - """ - with open(chartpress_yaml) as f: - chartpress_config = yaml.load(f) - chart = chartpress_config["charts"][0] - image_config = chart["images"][image_name] - return image_config.get("buildArgs", {}) - - -def build_image(): - """Build the docker image used for computing dependencies - - This runs the chartpress build of the current image - with the addition of pip-tools, used for computing dependencies. - - The image is built with the current frozen environment in requirements.txt - and pip-tools commands are available for updating requirements.txt from requirements.in. - """ - click.echo(f"Building docker image {dependencies_image}") - build_arg_dict = build_args() - build_arg_list = ["--build-arg", f"PIP_TOOLS={pip_tools_version}"] - for key in sorted(build_arg_dict): - value = build_arg_dict[key] - build_arg_list.append("--build-arg") - build_arg_list.append(f"{key}={value}") - check_call(["docker", "build", "-t", dependencies_image] + build_arg_list + [here]) - - -@click.group() -def cli(): - """Manage the Python dependencies in this image.""" - pass - - -@click.command() -@click.option( - "--build/--no-build", - help="add --no-build to skip building the dependencies image prior to upgrading", - default=True, -) -@click.option( - "--upgrade/--no-upgrade", - help="--upgrade to upgrade all dependencies within the range specified in requirements.in", - default=False, -) -@click.option( - "--upgrade-package", - help="specify individual packages to upgrade within the range specified in requirements.in", - multiple=True, -) -def freeze(build, upgrade, upgrade_package): - """Freeze the environment, updating requirements.txt from requirements.in - - Individual packages can be updated, or the whole environment. - - This command: - - 1. builds the image with the current frozen environment - 2. runs pip-compile in the image to update requirements.txt from requirements.in, - passing through additional arguments to pip-compile - """ - if build: - build_image() - click.echo("freezing dependencies with pip-compile") - upgrade_args = [] - if upgrade: - upgrade_args.append("--upgrade") - for pkg in upgrade_package: - upgrade_args.append("--upgrade-package") - upgrade_args.append(pkg) - check_call( - [ - "docker", - "run", - "--rm", - "-it", - "-e", - "CUSTOM_COMPILE_COMMAND=./dependencies freeze --upgrade", - "--volume", - f"{here}:/io", - "--workdir", - "/io", - dependencies_image, - "pip-compile", - ] - + upgrade_args - ) - - -cli.add_command(freeze) - - -@click.command() -@click.option("--build/--no-build", default=True) -def outdated(build): - """Check for outdated dependencies with pip. - - This command: - - 1. builds the image with the current frozen environment - 2. runs `pip list --outdated` to report any outdated packages - that could be candidates for upgrade - """ - if build: - build_image() - click.echo("Checking for outdated dependencies with pip.") - outdated_json = check_output( - [ - "docker", - "run", - "--rm", - "-it", - dependencies_image, - "pip", - "list", - "--outdated", - "--format=json", - ] - ).decode("utf8") - outdated = json.loads(outdated_json) - have_outdated = False - for pkg in outdated: - name = pkg["name"] - # ignore some common packages that aren't relevant to our requirements.txt - if name in {"pip", "setuptools", "wheel"}: - continue - have_outdated = True - version = pkg["version"] - latest = pkg["latest_version"] - # TODO: parser requirements.in to check if latest is in-range? - # If they are in-range, running freeze again is enough, - # but if they are outside the range, requirements.in needs to be updated - # first to pick them up - # for now, print as much so humans can decide - print(f"Have {name}=={version}, latest is {name}=={latest}") - - if have_outdated: - print("There are outdated dependencies!") - print( - "To pick up any versions outside the range(s) specified in requirements.in," - ) - print("update the pinning(s) in that file.") - print( - "To update the whole environment within the given ranges, run `./dependencies freeze --upgrade`" - ) - print( - "To update one or more specific packages, run `./dependencies freeze --upgrade-package pkg1 [--upgrade-package pkg2]`" - ) - else: - print("Everything appears to be up-to-date!") - - -cli.add_command(outdated) - - -if __name__ == "__main__": - cli() diff --git a/images/hub/requirements.in b/images/hub/requirements.in index 07622a55f6..69816c00fe 100644 --- a/images/hub/requirements.in +++ b/images/hub/requirements.in @@ -1,17 +1,18 @@ -# This file is automatically maintained by Dependabot, as configured in -# .github/dependabot.yaml. It can also be updated by... -# -# ./dependencies freeze --upgrade -# +# This file is the input to requirements.txt, +# which is a frozen version of this. To update +# requirements.txt, use the "Run workflow" button at +# https://github.com/jupyterhub/zero-to-jupyterhub-k8s/actions/workflows/watch-dependencies.yaml +# that will also update the jupyterhub version if needed. +# README.md file. # JupyterHub itself git+https://github.com/RCOSDP/CS-jupyterhub.git@master ## Authenticators -jupyterhub-firstuseauthenticator +jupyterhub-firstuseauthenticator>=1 jupyterhub-hmacauthenticator jupyterhub-ldapauthenticator -jupyterhub-ltiauthenticator +jupyterhub-ltiauthenticator!=1.3.0 jupyterhub-nativeauthenticator jupyterhub-tmpauthenticator nullauthenticator @@ -30,15 +31,10 @@ git+https://github.com/RCOSDP/CS-jhub_sendgrid_notifier.git ## Other optional dependencies for additional features pymysql # mysql -psycopg2-binary # postgres +psycopg2 # postgres pycurl # internal http requests handle more load with pycurl sqlalchemy-cockroachdb # cocroachdb statsd # statsd metrics collection (TODO: remove soon, since folks use prometheus) # The idle culler service jupyterhub-idle-culler - -## Useful tools - -# py-spy is useful for profiling running hubs -py-spy diff --git a/images/hub/requirements.txt b/images/hub/requirements.txt index fcb7305cbb..2a28f8b5a3 100644 --- a/images/hub/requirements.txt +++ b/images/hub/requirements.txt @@ -1,55 +1,64 @@ # -# This file is autogenerated by pip-compile -# To update, run: +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: # -# ./dependencies freeze --upgrade +# Use the "Run workflow" button at https://github.com/jupyterhub/zero-to-jupyterhub-k8s/actions/workflows/watch-dependencies.yaml # -alembic==1.6.5 +aiohttp==3.9.1 + # via kubernetes-asyncio +aiosignal==1.3.1 + # via aiohttp +alembic==1.12.1 # via jupyterhub async-generator==1.10 + # via jupyterhub +attrs==23.1.0 # via - # jupyterhub - # jupyterhub-kubespawner -attrs==21.2.0 - # via jsonschema -bcrypt==3.2.0 + # aiohttp + # jsonschema + # referencing +bcrypt==4.0.1 # via # jupyterhub-firstuseauthenticator # jupyterhub-nativeauthenticator -cachetools==4.2.2 - # via google-auth -certifi==2021.5.30 +certifi==2023.11.17 # via - # kubernetes + # kubernetes-asyncio # requests certipy==0.1.3 # via jupyterhub -cffi==1.14.5 - # via - # bcrypt - # cryptography -chardet==4.0.0 +cffi==1.16.0 + # via cryptography +charset-normalizer==3.3.2 # via requests -cryptography==3.4.7 - # via pyopenssl -entrypoints==0.3 - # via jupyterhub +cryptography==41.0.5 + # via + # pyjwt + # pyopenssl escapism==1.0.1 - # via jupyterhub-kubespawner -google-auth==1.31.0 - # via kubernetes -greenlet==1.1.0 + # via + # jupyterhub-kubespawner + # jupyterhub-ltiauthenticator +frozenlist==1.4.0 + # via + # aiohttp + # aiosignal +greenlet==3.0.1 # via sqlalchemy -idna==2.10 - # via requests -ipython-genutils==0.2.0 - # via traitlets -jinja2==3.0.1 +idna==3.6 + # via + # requests + # yarl +jinja2==3.1.2 # via # jupyterhub # jupyterhub-kubespawner -jsonschema==3.2.0 - # via jupyter-telemetry +jsonschema==4.20.0 + # via + # jupyter-telemetry + # oauthenticator +jsonschema-specifications==2023.11.1 + # via jsonschema jupyter-telemetry==0.1.0 # via jupyterhub git+https://github.com/RCOSDP/CS-jupyterhub.git@master @@ -62,43 +71,47 @@ git+https://github.com/RCOSDP/CS-jupyterhub.git@master # jupyterhub-nativeauthenticator # nullauthenticator # oauthenticator -jupyterhub-firstuseauthenticator==0.14.1 +jupyterhub-firstuseauthenticator==1.0.0 # via -r requirements.in jupyterhub-hmacauthenticator==1.0 # via -r requirements.in -jupyterhub-idle-culler==1.1 +jupyterhub-idle-culler==1.2.1 # via -r requirements.in -jupyterhub-kubespawner==1.1.0 +jupyterhub-kubespawner==5.0.0 # via -r requirements.in jupyterhub-ldapauthenticator==1.3.2 # via -r requirements.in -jupyterhub-ltiauthenticator==1.0.0 +jupyterhub-ltiauthenticator==1.6.1 # via -r requirements.in -jupyterhub-nativeauthenticator==0.0.7 +jupyterhub-nativeauthenticator==1.2.0 # via -r requirements.in -jupyterhub-tmpauthenticator==0.6 +jupyterhub-tmpauthenticator==1.0.0 # via -r requirements.in git+https://github.com/RCOSDP/CS-jhub_remote_user_authenticator.git # via -r requirements.in git+https://github.com/RCOSDP/CS-jhub_sendgrid_notifier.git # via -r requirements.in -kubernetes==17.17.0 +kubernetes-asyncio==28.2.1 # via jupyterhub-kubespawner -ldap3==2.9 +ldap3==2.9.1 # via jupyterhub-ldapauthenticator -mako==1.1.4 +mako==1.3.0 # via alembic -markupsafe==2.0.1 +markupsafe==2.1.3 # via # jinja2 # mako -mwoauth==0.3.7 +multidict==6.0.4 + # via + # aiohttp + # yarl +mwoauth==0.4.0 # via -r requirements.in nullauthenticator==1.0.0 # via -r requirements.in -oauthenticator==14.2.0 +oauthenticator==16.2.1 # via -r requirements.in -oauthlib==3.1.1 +oauthlib==3.2.2 # via # jupyterhub # jupyterhub-ltiauthenticator @@ -106,105 +119,105 @@ oauthlib==3.1.1 # requests-oauthlib onetimepass==1.0.1 # via jupyterhub-nativeauthenticator -pamela==1.0.0 +packaging==23.2 # via jupyterhub -prometheus-client==0.11.0 +pamela==1.1.0 # via jupyterhub -psycopg2-binary==2.9.1 - # via -r requirements.in -py-spy==0.3.8 +prometheus-client==0.19.0 + # via jupyterhub +psycopg2==2.9.9 # via -r requirements.in -pyasn1==0.4.8 - # via - # ldap3 - # pyasn1-modules - # rsa -pyasn1-modules==0.2.8 - # via google-auth -pycparser==2.20 +pyasn1==0.5.1 + # via ldap3 +pycparser==2.21 # via cffi -pycurl==7.44.1 +pycurl==7.45.2 # via -r requirements.in -pyjwt==1.7.1 +pyjwt[crypto]==2.8.0 # via # -r requirements.in + # jupyterhub-ltiauthenticator # mwoauth -pymysql==1.0.2 +pymysql==1.1.0 # via -r requirements.in -pyopenssl==20.0.1 +pyopenssl==23.3.0 # via certipy -pyrsistent==0.17.3 - # via jsonschema -python-dateutil==2.8.1 +python-dateutil==2.8.2 # via - # alembic # jupyterhub # jupyterhub-idle-culler - # kubernetes -python-editor==1.0.4 - # via alembic -python-json-logger==2.0.1 + # kubernetes-asyncio +python-json-logger==2.0.7 # via jupyter-telemetry -python-slugify==5.0.2 +python-slugify==8.0.1 # via jupyterhub-kubespawner -pyyaml==5.4.1 +pyyaml==6.0.1 # via # jupyterhub-kubespawner - # kubernetes -requests==2.25.1 + # kubernetes-asyncio +referencing==0.31.0 + # via + # jsonschema + # jsonschema-specifications +requests==2.31.0 # via # jupyterhub - # kubernetes # mwoauth + # oauthenticator # requests-oauthlib -requests-oauthlib==1.3.0 +requests-oauthlib==1.3.1 + # via mwoauth +rpds-py==0.13.1 # via - # kubernetes - # mwoauth -rsa==4.7.2 - # via google-auth -ruamel.yaml==0.17.9 - # via jupyter-telemetry -ruamel.yaml.clib==0.2.2 - # via ruamel.yaml + # jsonschema + # referencing +ruamel-yaml==0.18.5 + # via + # jupyter-telemetry + # oauthenticator +ruamel-yaml-clib==0.2.8 + # via ruamel-yaml six==1.16.0 # via - # bcrypt - # google-auth - # jsonschema - # kubernetes - # mwoauth + # kubernetes-asyncio # onetimepass - # pyopenssl # python-dateutil -sqlalchemy==1.4.18 +sqlalchemy==2.0.23 # via # alembic # jupyterhub # sqlalchemy-cockroachdb -sqlalchemy-cockroachdb==1.4.0 +sqlalchemy-cockroachdb==2.0.1 # via -r requirements.in -statsd==3.3.0 +statsd==4.0.1 # via -r requirements.in text-unidecode==1.3 # via python-slugify -tornado==6.1 +tornado==6.3.3 # via # jupyterhub # jupyterhub-idle-culler # jupyterhub-ldapauthenticator -traitlets==5.0.5 + # oauthenticator +traitlets==5.13.0 # via # jupyter-telemetry # jupyterhub + # jupyterhub-kubespawner # jupyterhub-ldapauthenticator -urllib3==1.26.5 + # jupyterhub-ltiauthenticator + # oauthenticator +typing-extensions==4.8.0 + # via + # alembic + # sqlalchemy +urllib3==2.1.0 # via # jupyterhub-kubespawner - # kubernetes + # kubernetes-asyncio # requests -websocket-client==1.1.0 - # via kubernetes +yarl==1.9.3 + # via aiohttp # The following packages are considered to be unsafe in a requirements file: # setuptools diff --git a/images/image-awaiter/Dockerfile b/images/image-awaiter/Dockerfile index 8eeac1f8e9..4a0735fd8a 100644 --- a/images/image-awaiter/Dockerfile +++ b/images/image-awaiter/Dockerfile @@ -1,21 +1,21 @@ # compile the code to an executable using an intermediary image -FROM golang:1.15 +FROM golang:1.18 # VULN_SCAN_TIME= -RUN mkdir -p /build/ -COPY *.mod *.go *.sum /build/ WORKDIR /build -RUN CGO_ENABLED=0 GOOS=linux go build -ldflags '-w -s' -installsuffix cgo -a -o out/image-awaiter +COPY *.mod \ + *.go \ + *.sum \ + . +RUN CGO_ENABLED=0 GOOS=linux go build -ldflags '-w -s' -installsuffix cgo -a -o out/image-awaiter # present the result within a slimmed image FROM scratch COPY --from=0 /build/out/image-awaiter /image-awaiter - - # To debug / develop this code # ---------------------------- # 1. Setup a kubectl proxy diff --git a/images/image-awaiter/README.md b/images/image-awaiter/README.md index 96f088e5d6..891cd7fb8f 100644 --- a/images/image-awaiter/README.md +++ b/images/image-awaiter/README.md @@ -16,7 +16,7 @@ minutes to a few seconds. ### What technical knowledge is needed to understand this? -You need to know about [Kubernetes Jobs](https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/) and [Kubernetes DaemonSets](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/), about [Helm and helm hooks](https://github.com/kubernetes/helm/blob/HEAD/docs/charts_hooks.md), +You need to know about [Kubernetes Jobs](https://kubernetes.io/docs/concepts/workloads/controllers/job/) and [Kubernetes DaemonSets](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/), about [Helm and helm hooks](https://helm.sh/docs/topics/charts_hooks/), and about the programming language Go. ### Why is this project in Go? Isn't the Jupyter Infrastructure ecosystem mostly Python? diff --git a/images/image-awaiter/go.mod b/images/image-awaiter/go.mod index 84a65f3978..bbc772f13c 100644 --- a/images/image-awaiter/go.mod +++ b/images/image-awaiter/go.mod @@ -1,5 +1,7 @@ module github.com/jupyterhub/zero-to-jupyterhub-k8s/image-awaiter -go 1.15 +go 1.18 -require github.com/hashicorp/go-retryablehttp v0.6.7 +require github.com/hashicorp/go-retryablehttp v0.7.1 + +require github.com/hashicorp/go-cleanhttp v0.5.1 // indirect diff --git a/images/image-awaiter/go.sum b/images/image-awaiter/go.sum index 00f0cc1641..270b259c4a 100644 --- a/images/image-awaiter/go.sum +++ b/images/image-awaiter/go.sum @@ -1,8 +1,9 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-retryablehttp v0.6.7 h1:8/CAEZt/+F7kR7GevNHulKkUjLht3CPmn7egmhieNKo= -github.com/hashicorp/go-retryablehttp v0.6.7/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ= +github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= diff --git a/images/network-tools/Dockerfile b/images/network-tools/Dockerfile index 87711ee7eb..508cc0712e 100644 --- a/images/network-tools/Dockerfile +++ b/images/network-tools/Dockerfile @@ -1,5 +1,11 @@ FROM alpine:3 -# VULN_SCAN_TIME=2021-08-28_00:55:50 +# VULN_SCAN_TIME=2023-06-19_05:12:47 -RUN apk add --no-cache iptables +#RUN apk add --no-cache iptables + +# Use iptables-legacy as workaround. +# cf. https://github.com/tailscale/tailscale/issues/10540 +RUN apk add --no-cache ca-certificates iptables iptables-legacy +RUN rm /sbin/iptables && ln -s /sbin/iptables-legacy /sbin/iptables +RUN rm /sbin/ip6tables && ln -s /sbin/ip6tables-legacy /sbin/ip6tables diff --git a/images/secret-sync/Dockerfile b/images/secret-sync/Dockerfile index 601c305903..09f8398867 100644 --- a/images/secret-sync/Dockerfile +++ b/images/secret-sync/Dockerfile @@ -1,6 +1,6 @@ -FROM python:3.8-alpine +FROM python:3.11-alpine -# VULN_SCAN_TIME=2021-08-28_00:56:18 +# VULN_SCAN_TIME=2023-11-06_05:12:59 # Note that we use tini-static, it embeds dependencies missing in alpine RUN ARCH=`uname -m`; \ diff --git a/images/secret-sync/acme-secret-sync.py b/images/secret-sync/acme-secret-sync.py index b06cf7e27d..034daaea7f 100755 --- a/images/secret-sync/acme-secret-sync.py +++ b/images/secret-sync/acme-secret-sync.py @@ -36,13 +36,10 @@ """ import argparse import base64 -import io import json import logging import os -import subprocess import sys -import tarfile import time from kubernetes import client, config @@ -65,7 +62,7 @@ def update_secret(namespace, secret_name, labels, key, value): secret = client.V1Secret( metadata=client.V1ObjectMeta(name=secret_name, labels=labels), data={} ) - resp = v1.create_namespaced_secret(namespace=namespace, body=secret) + v1.create_namespaced_secret(namespace=namespace, body=secret) logging.info(f"Created secret {secret_name} since it does not exist") else: raise diff --git a/images/singleuser-sample/Dockerfile b/images/singleuser-sample/Dockerfile index 301dd68633..9c7e73850c 100644 --- a/images/singleuser-sample/Dockerfile +++ b/images/singleuser-sample/Dockerfile @@ -1,38 +1,72 @@ -FROM jupyter/base-notebook:latest -# Built from... https://hub.docker.com/r/jupyter/base-notebook/ -# https://github.com/jupyter/docker-stacks/blob/HEAD/base-notebook/Dockerfile -# Built from... Ubuntu 20.04 +# syntax = docker/dockerfile:1.3 +# VULN_SCAN_TIME=2023-10-16_05:14:00 -# VULN_SCAN_TIME=2021-08-27_01:04:20 -# The jupyter/docker-stacks images contains jupyterhub and jupyterlab already. +# The build stage +# --------------- +# This stage is building Python wheels for use in later stages by using a base +# image that has more pre-requisites to do so, such as a C++ compiler. +# +# NOTE: If the image version is updated, also update it in ci/refreeze and +# hub's Dockerfile! +# +FROM python:3.11-bullseye as build-stage + +# Build wheels +# +# We set pip's cache directory and expose it across build stages via an +# ephemeral docker cache (--mount=type=cache,target=${PIP_CACHE_DIR}). We use +# the same technique for the directory /tmp/wheels. +# +COPY requirements.txt requirements.txt +ARG PIP_CACHE_DIR=/tmp/pip-cache +RUN --mount=type=cache,target=${PIP_CACHE_DIR} \ + pip install build \ + && pip wheel \ + --wheel-dir=/tmp/wheels \ + -r requirements.txt + + +# The final stage +# --------------- +# +FROM python:3.11-slim-bullseye +ENV DEBIAN_FRONTEND=noninteractive + +ENV NB_USER=jovyan \ + NB_UID=1000 \ + HOME=/home/jovyan +RUN adduser \ + --disabled-password \ + --gecos "Default user" \ + --uid ${NB_UID} \ + --home ${HOME} \ + --force-badname \ + ${NB_USER} -# Example install of git and nbgitpuller. -# NOTE: git is already available in the jupyter/minimal-notebook image. -USER root RUN apt-get update \ - && apt-get upgrade -y \ - && apt-get install -y --no-install-recommends \ + && apt-get upgrade --yes \ + && apt-get install --yes --no-install-recommends \ + ca-certificates \ dnsutils \ - git \ iputils-ping \ + tini \ + # requirement for nbgitpuller + git \ && rm -rf /var/lib/apt/lists/* -USER $NB_USER +# install wheels built in the build-stage COPY requirements.txt /tmp/requirements.txt -RUN python -m pip install --no-cache-dir \ - -r /tmp/requirements.txt - -# Support overriding a package or two through passed docker --build-args. -# ARG PIP_OVERRIDES="jupyterhub==1.3.0" -ARG PIP_OVERRIDES= -RUN if [[ -n "$PIP_OVERRIDES" ]]; then \ - pip install --no-cache-dir $PIP_OVERRIDES; \ - fi - -RUN jupyter serverextension enable --py nbgitpuller --sys-prefix +ARG PIP_CACHE_DIR=/tmp/pip-cache +RUN --mount=type=cache,target=${PIP_CACHE_DIR} \ + --mount=type=cache,from=build-stage,source=/tmp/wheels,target=/tmp/wheels \ + pip install \ + --find-links=/tmp/wheels/ \ + -r /tmp/requirements.txt -# Uncomment the line below to make nbgitpuller default to start up in JupyterLab -#ENV NBGITPULLER_APP=lab +WORKDIR ${HOME} +USER ${NB_USER} -# conda/pip/apt install additional packages here, if desired. +EXPOSE 8888 +ENTRYPOINT ["tini", "--"] +CMD ["jupyter", "lab"] diff --git a/images/singleuser-sample/README.md b/images/singleuser-sample/README.md index 8063985ac4..1a6e692a89 100644 --- a/images/singleuser-sample/README.md +++ b/images/singleuser-sample/README.md @@ -6,7 +6,7 @@ fundamentals only so that it can get pulled quickly. It is based on the from Project Jupyter's [jupyter/docker-stacks repository](https://github.com/jupyter/docker-stacks) which also contains many other images suitable for use with the Helm chart. To help you choose another one see [the docker-stacks documentation on selecting a -user image](http://jupyter-docker-stacks.readthedocs.io/en/latest/using/selecting.html). +user image](https://jupyter-docker-stacks.readthedocs.io/en/latest/using/selecting.html). For a brief introduction to _Dockerfiles_, _images_ and _containers_, see [the guide's summary about container technology.](https://z2jh.jupyter.org/en/latest/tools.html#container-technology). @@ -16,17 +16,14 @@ guide's summary about container technology.](https://z2jh.jupyter.org/en/latest/ To quickly try out this Docker image on your computer: ```sh -# with the classic UI -docker run -it --rm -p 8888:8888 jupyterhub/k8s-singleuser-sample:0.7.0 - # with JupyterLab -docker run -it --rm -p 8888:8888 -e JUPYTER_ENABLE_LAB=true jupyterhub/k8s-singleuser-sample:0.7.0 +docker run -it --rm -p 8888:8888 quay.io/jupyterhub/k8s-singleuser-sample:2.0.0 -- jupyter lab --ip 0.0.0.0 ``` -This image available tags can be found [here](https://hub.docker.com/r/jupyterhub/k8s-singleuser-sample/tags/). +This image available tags can be found [here](https://quay.io/repository/jupyterhub/k8s-singleuser-sample?tab=tags). ## In the base-notebook image - Ubuntu Linux - v18.04 aka. Bionic - JupyterHub - required by with Helm chart since KubeSpawner requires it -- [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) and [JupyterLab-Hub extension](https://jupyterlab.readthedocs.io/en/stable/user/jupyterhub.html) - to activate it over the classical UI by default, see [the guide's instructions](https://z2jh.jupyter.org/en/latest/user-environment.html#use-jupyterlab-by-default). +- [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) and [JupyterLab-Hub extension](https://jupyterlab.readthedocs.io/en/stable/user/jupyterhub.html) - to activate it over the classical UI by default, see [the guide's instructions](https://z2jh.jupyter.org/en/latest/jupyterhub/customizing/user-environment.html#use-jupyterlab-by-default). diff --git a/images/singleuser-sample/requirements.in b/images/singleuser-sample/requirements.in new file mode 100644 index 0000000000..4666759bf0 --- /dev/null +++ b/images/singleuser-sample/requirements.in @@ -0,0 +1,17 @@ +# This file is the input to requirements.txt, +# which is a frozen version of this. To update +# requirements.txt, use the "Run workflow" button at +# https://github.com/jupyterhub/zero-to-jupyterhub-k8s/actions/workflows/watch-dependencies.yaml +# that will also update the jupyterhub version if needed. +# README.md file. + +# JupyterHub itself, update this version pinning by running the workflow +# mentioned above. +jupyterhub==4.0.2 + +# UI +jupyterlab +nbclassic + +# plugins +nbgitpuller diff --git a/images/singleuser-sample/requirements.txt b/images/singleuser-sample/requirements.txt index bb666576df..efbd361c7d 100644 --- a/images/singleuser-sample/requirements.txt +++ b/images/singleuser-sample/requirements.txt @@ -1,5 +1,337 @@ -# This file is automatically maintained by Dependabot, as configured in -# .github/dependabot.yaml. - -jupyterhub==1.4.2 -nbgitpuller==0.10.2 +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# Use the "Run workflow" button at https://github.com/jupyterhub/zero-to-jupyterhub-k8s/actions/workflows/watch-dependencies.yaml +# +alembic==1.12.1 + # via jupyterhub +anyio==4.1.0 + # via jupyter-server +argon2-cffi==23.1.0 + # via + # jupyter-server + # nbclassic +argon2-cffi-bindings==21.2.0 + # via argon2-cffi +arrow==1.3.0 + # via isoduration +asttokens==2.4.1 + # via stack-data +async-generator==1.10 + # via jupyterhub +async-lru==2.0.4 + # via jupyterlab +attrs==23.1.0 + # via + # jsonschema + # referencing +babel==2.13.1 + # via jupyterlab-server +beautifulsoup4==4.12.2 + # via nbconvert +bleach==6.1.0 + # via nbconvert +certifi==2023.11.17 + # via requests +certipy==0.1.3 + # via jupyterhub +cffi==1.16.0 + # via + # argon2-cffi-bindings + # cryptography +charset-normalizer==3.3.2 + # via requests +comm==0.2.0 + # via ipykernel +cryptography==41.0.5 + # via pyopenssl +debugpy==1.8.0 + # via ipykernel +decorator==5.1.1 + # via ipython +defusedxml==0.7.1 + # via nbconvert +executing==2.0.1 + # via stack-data +fastjsonschema==2.19.0 + # via nbformat +fqdn==1.5.1 + # via jsonschema +greenlet==3.0.1 + # via sqlalchemy +idna==3.6 + # via + # anyio + # jsonschema + # requests +ipykernel==6.26.0 + # via + # jupyterlab + # nbclassic +ipython==8.18.1 + # via ipykernel +ipython-genutils==0.2.0 + # via nbclassic +isoduration==20.11.0 + # via jsonschema +jedi==0.19.1 + # via ipython +jinja2==3.1.2 + # via + # jupyter-server + # jupyterhub + # jupyterlab + # jupyterlab-server + # nbclassic + # nbconvert +json5==0.9.14 + # via jupyterlab-server +jsonpointer==2.4 + # via jsonschema +jsonschema[format-nongpl]==4.20.0 + # via + # jupyter-events + # jupyter-telemetry + # jupyterlab-server + # nbformat +jsonschema-specifications==2023.11.1 + # via jsonschema +jupyter-client==8.6.0 + # via + # ipykernel + # jupyter-server + # nbclassic + # nbclient +jupyter-core==5.5.0 + # via + # ipykernel + # jupyter-client + # jupyter-server + # jupyterlab + # nbclassic + # nbclient + # nbconvert + # nbformat +jupyter-events==0.9.0 + # via jupyter-server +jupyter-lsp==2.2.1 + # via jupyterlab +jupyter-server==2.10.1 + # via + # jupyter-lsp + # jupyterlab + # jupyterlab-server + # nbclassic + # nbgitpuller + # notebook-shim +jupyter-server-terminals==0.4.4 + # via jupyter-server +jupyter-telemetry==0.1.0 + # via jupyterhub +jupyterhub==4.0.2 + # via -r requirements.in +jupyterlab==4.0.9 + # via -r requirements.in +jupyterlab-pygments==0.3.0 + # via nbconvert +jupyterlab-server==2.25.2 + # via jupyterlab +mako==1.3.0 + # via alembic +markupsafe==2.1.3 + # via + # jinja2 + # mako + # nbconvert +matplotlib-inline==0.1.6 + # via + # ipykernel + # ipython +mistune==3.0.2 + # via nbconvert +nbclassic==1.0.0 + # via -r requirements.in +nbclient==0.9.0 + # via nbconvert +nbconvert==7.11.0 + # via + # jupyter-server + # nbclassic +nbformat==5.9.2 + # via + # jupyter-server + # nbclassic + # nbclient + # nbconvert +nbgitpuller==1.2.0 + # via -r requirements.in +nest-asyncio==1.5.8 + # via + # ipykernel + # nbclassic +notebook-shim==0.2.3 + # via + # jupyterlab + # nbclassic +oauthlib==3.2.2 + # via jupyterhub +overrides==7.4.0 + # via jupyter-server +packaging==23.2 + # via + # ipykernel + # jupyter-server + # jupyterhub + # jupyterlab + # jupyterlab-server + # nbconvert +pamela==1.1.0 + # via jupyterhub +pandocfilters==1.5.0 + # via nbconvert +parso==0.8.3 + # via jedi +pexpect==4.9.0 + # via ipython +platformdirs==4.0.0 + # via jupyter-core +prometheus-client==0.19.0 + # via + # jupyter-server + # jupyterhub + # nbclassic +prompt-toolkit==3.0.41 + # via ipython +psutil==5.9.6 + # via ipykernel +ptyprocess==0.7.0 + # via + # pexpect + # terminado +pure-eval==0.2.2 + # via stack-data +pycparser==2.21 + # via cffi +pygments==2.17.2 + # via + # ipython + # nbconvert +pyopenssl==23.3.0 + # via certipy +python-dateutil==2.8.2 + # via + # arrow + # jupyter-client + # jupyterhub +python-json-logger==2.0.7 + # via + # jupyter-events + # jupyter-telemetry +pyyaml==6.0.1 + # via jupyter-events +pyzmq==25.1.1 + # via + # ipykernel + # jupyter-client + # jupyter-server + # nbclassic +referencing==0.31.0 + # via + # jsonschema + # jsonschema-specifications + # jupyter-events +requests==2.31.0 + # via + # jupyterhub + # jupyterlab-server +rfc3339-validator==0.1.4 + # via + # jsonschema + # jupyter-events +rfc3986-validator==0.1.1 + # via + # jsonschema + # jupyter-events +rpds-py==0.13.1 + # via + # jsonschema + # referencing +ruamel-yaml==0.18.5 + # via jupyter-telemetry +ruamel-yaml-clib==0.2.8 + # via ruamel-yaml +send2trash==1.8.2 + # via + # jupyter-server + # nbclassic +six==1.16.0 + # via + # asttokens + # bleach + # python-dateutil + # rfc3339-validator +sniffio==1.3.0 + # via anyio +soupsieve==2.5 + # via beautifulsoup4 +sqlalchemy==2.0.23 + # via + # alembic + # jupyterhub +stack-data==0.6.3 + # via ipython +terminado==0.18.0 + # via + # jupyter-server + # jupyter-server-terminals + # nbclassic +tinycss2==1.2.1 + # via nbconvert +tornado==6.3.3 + # via + # ipykernel + # jupyter-client + # jupyter-server + # jupyterhub + # jupyterlab + # nbclassic + # nbgitpuller + # terminado +traitlets==5.13.0 + # via + # comm + # ipykernel + # ipython + # jupyter-client + # jupyter-core + # jupyter-events + # jupyter-server + # jupyter-telemetry + # jupyterhub + # jupyterlab + # matplotlib-inline + # nbclassic + # nbclient + # nbconvert + # nbformat +types-python-dateutil==2.8.19.14 + # via arrow +typing-extensions==4.8.0 + # via + # alembic + # sqlalchemy +uri-template==1.3.0 + # via jsonschema +urllib3==2.1.0 + # via requests +wcwidth==0.2.12 + # via prompt-toolkit +webcolors==1.13 + # via jsonschema +webencodings==0.5.1 + # via + # bleach + # tinycss2 +websocket-client==1.6.4 + # via jupyter-server diff --git a/jupyterhub/.helmignore b/jupyterhub/.helmignore index 05f3c9858d..c784d7ca6d 100644 --- a/jupyterhub/.helmignore +++ b/jupyterhub/.helmignore @@ -6,7 +6,7 @@ # # Here are files that we intentionally ignore to avoid them being packaged, # because we don't want to reference them from our templates anyhow. -schema.yaml +values.schema.yaml # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and diff --git a/jupyterhub/Chart.yaml b/jupyterhub/Chart.yaml index fe73cbc118..17b1ada78b 100644 --- a/jupyterhub/Chart.yaml +++ b/jupyterhub/Chart.yaml @@ -2,13 +2,13 @@ apiVersion: v2 name: jupyterhub version: 0.0.1-set.by.chartpress -appVersion: 1.4.2 +appVersion: "3.1.1" description: Multi-user Jupyter installation keywords: [jupyter, jupyterhub, z2jh] home: https://z2jh.jupyter.org sources: [https://github.com/jupyterhub/zero-to-jupyterhub-k8s] -icon: https://jupyter.org/assets/hublogo.svg -kubeVersion: ">=1.17.0-0" +icon: https://hub.jupyter.org/helm-chart/images/hublogo.svg +kubeVersion: ">=1.23.0-0" maintainers: # Since it is a requirement of Artifact Hub to have specific maintainers # listed, we have added some below, but in practice the entire JupyterHub team diff --git a/jupyterhub/README.md b/jupyterhub/README.md index 9c0527e051..954d4653a0 100644 --- a/jupyterhub/README.md +++ b/jupyterhub/README.md @@ -5,9 +5,9 @@ [![Discourse](https://img.shields.io/badge/Help_forum-discourse-blue?logo=discourse&logoColor=white)](https://discourse.jupyter.org/c/jupyterhub/z2jh-k8s) [![Gitter](https://img.shields.io/badge/Social_chat-gitter-blue?logo=gitter&logoColor=white)](https://gitter.im/jupyterhub/jupyterhub)
-[![Latest stable release of the Helm chart](https://img.shields.io/badge/dynamic/json.svg?label=Latest%20stable%20release&url=https://jupyterhub.github.io/helm-chart/info.json&query=$.jupyterhub.stable&logo=helm&logoColor=white)](https://jupyterhub.github.io/helm-chart#jupyterhub) -[![Latest pre-release of the Helm chart](https://img.shields.io/badge/dynamic/json.svg?label=Latest%20pre-release&url=https://jupyterhub.github.io/helm-chart/info.json&query=$.jupyterhub.pre&logo=helm&logoColor=white)](https://jupyterhub.github.io/helm-chart#development-releases-jupyterhub) -[![Latest development release of the Helm chart](https://img.shields.io/badge/dynamic/json.svg?label=Latest%20dev%20release&url=https://jupyterhub.github.io/helm-chart/info.json&query=$.jupyterhub.latest&logo=helm&logoColor=white)](https://jupyterhub.github.io/helm-chart#development-releases-jupyterhub) +[![Latest stable release of the Helm chart](https://img.shields.io/badge/dynamic/json.svg?label=Latest%20stable%20release&url=https://hub.jupyter.org/helm-chart/info.json&query=$.jupyterhub.stable&logo=helm&logoColor=white)](https://jupyterhub.github.io/helm-chart#jupyterhub) +[![Latest pre-release of the Helm chart](https://img.shields.io/badge/dynamic/json.svg?label=Latest%20pre-release&url=https://hub.jupyter.org/helm-chart/info.json&query=$.jupyterhub.pre&logo=helm&logoColor=white)](https://jupyterhub.github.io/helm-chart#development-releases-jupyterhub) +[![Latest development release of the Helm chart](https://img.shields.io/badge/dynamic/json.svg?label=Latest%20dev%20release&url=https://hub.jupyter.org/helm-chart/info.json&query=$.jupyterhub.latest&logo=helm&logoColor=white)](https://jupyterhub.github.io/helm-chart#development-releases-jupyterhub) The JupyterHub Helm chart is accompanied with an installation guide at [z2jh.jupyter.org](https://z2jh.jupyter.org). Together they enable you to deploy [JupyterHub](https://jupyterhub.readthedocs.io) in a Kubernetes cluster that can make Jupyter environments available to several thousands of simultaneous users. @@ -15,4 +15,4 @@ The JupyterHub Helm chart is accompanied with an installation guide at [z2jh.jup Much of the initial groundwork for this documentation is information learned from the successful use of JupyterHub and Kubernetes at UC Berkeley in their [Data 8](http://data8.org/) program. -![](https://raw.githubusercontent.com/jupyterhub/zero-to-jupyterhub-k8s/HEAD/doc/source/_static/images/data8_massive_audience.jpg) +![](https://raw.githubusercontent.com/jupyterhub/zero-to-jupyterhub-k8s/HEAD/docs/source/_static/images/data8_massive_audience.jpg) diff --git a/jupyterhub/files/hub/jupyterhub_config.py b/jupyterhub/files/hub/jupyterhub_config.py index c75838ce4f..41987837a8 100644 --- a/jupyterhub/files/hub/jupyterhub_config.py +++ b/jupyterhub/files/hub/jupyterhub_config.py @@ -1,13 +1,14 @@ +# load the config object (satisfies linters) +c = get_config() # noqa + import glob import os import re import sys -from binascii import a2b_hex - -from tornado.httpclient import AsyncHTTPClient -from kubernetes import client from jupyterhub.utils import url_path_join +from kubernetes_asyncio import client +from tornado.httpclient import AsyncHTTPClient # Make sure that modules placed in the same directory as the jupyterhub config are added to the pythonpath configuration_directory = os.path.dirname(os.path.realpath(__file__)) @@ -15,10 +16,10 @@ from z2jh import ( get_config, - set_config_if_not_none, get_name, get_name_env, get_secret_value, + set_config_if_not_none, ) @@ -105,7 +106,7 @@ def camelCaseify(s): f'http://{get_name("hub")}:{get_name_env("hub", "_SERVICE_PORT")}' ) -env_url = os.environ.get('HUB_CONNECT_URL') +env_url = os.environ.get("HUB_CONNECT_URL") if env_url: c.JupyterHub.hub_connect_url = env_url @@ -146,6 +147,7 @@ def camelCaseify(s): ("events_enabled", "events"), ("extra_labels", None), ("extra_annotations", None), + # ("allow_privilege_escalation", None), # Managed manually below ("uid", None), ("fs_gid", None), ("service_account", "serviceAccountName"), @@ -202,10 +204,19 @@ def camelCaseify(s): if image: tag = get_config("singleuser.image.tag") if tag: - image = "{}:{}".format(image, tag) + image = f"{image}:{tag}" c.KubeSpawner.image = image +# allow_privilege_escalation defaults to False in KubeSpawner 2+. Since its a +# property where None, False, and True all are valid values that users of the +# Helm chart may want to set, we can't use the set_config_if_not_none helper +# function as someone may want to override the default False value to None. +# +c.KubeSpawner.allow_privilege_escalation = get_config( + "singleuser.allowPrivilegeEscalation" +) + # Combine imagePullSecret.create (single), imagePullSecrets (list), and # singleuser.image.pullSecrets (list). image_pull_secrets = [] @@ -251,7 +262,7 @@ def camelCaseify(s): pass else: raise ValueError( - "Unrecognized value for matchNodePurpose: %r" % match_node_purpose + f"Unrecognized value for matchNodePurpose: {match_node_purpose}" ) # Combine the common tolerations for user pods with singleuser tolerations @@ -349,54 +360,84 @@ def camelCaseify(s): get_config("singleuser.storage.extraVolumeMounts", []) ) -c.JupyterHub.services = [ - { - "name": "users-exporter", - "admin": True, - "api_token": get_secret_value(f"hub.services.users-exporter.apiToken"), - }, - { - "name": "schedulable-notebook", - "admin": True, - "url": "http://schedulable-notebook:8888", - "api_token": get_secret_value(f"hub.services.schedulable-notebook.apiToken"), - }, -] +c.JupyterHub.services = [] + +if get_config("usersExporter.enabled", False): + c.JupyterHub.services.append( + { + "name": "users-exporter", + "admin": True, + "api_token": get_secret_value("hub.services.users-exporter.apiToken"), + } + ) + +if get_config("schedulableNotebook.enabled", False): + c.JupyterHub.services.append( + { + "name": "schedulable-notebook", + "admin": True, + "url": "http://schedulable-notebook:8888", + "api_token": get_secret_value("hub.services.schedulable-notebook.apiToken"), + }, + ) + +c.JupyterHub.load_roles = [] + +# jupyterhub-idle-culler's permissions are scoped to what it needs only, see +# https://github.com/jupyterhub/jupyterhub-idle-culler#permissions. +# if get_config("cull.enabled", False): + jupyterhub_idle_culler_role = { + "name": "jupyterhub-idle-culler", + "scopes": [ + "list:users", + "read:users:activity", + "read:servers", + "delete:servers", + # "admin:users", # dynamically added if --cull-users is passed + ], + # assign the role to a jupyterhub service, so it gains these permissions + "services": ["jupyterhub-idle-culler"], + } + cull_cmd = ["python3", "-m", "jupyterhub_idle_culler"] base_url = c.JupyterHub.get("base_url", "/") cull_cmd.append("--url=http://localhost:8081" + url_path_join(base_url, "hub/api")) cull_timeout = get_config("cull.timeout") if cull_timeout: - cull_cmd.append("--timeout=%s" % cull_timeout) + cull_cmd.append(f"--timeout={cull_timeout}") cull_every = get_config("cull.every") if cull_every: - cull_cmd.append("--cull-every=%s" % cull_every) + cull_cmd.append(f"--cull-every={cull_every}") cull_concurrency = get_config("cull.concurrency") if cull_concurrency: - cull_cmd.append("--concurrency=%s" % cull_concurrency) + cull_cmd.append(f"--concurrency={cull_concurrency}") if get_config("cull.users"): cull_cmd.append("--cull-users") + jupyterhub_idle_culler_role["scopes"].append("admin:users") + + if not get_config("cull.adminUsers"): + cull_cmd.append("--cull-admin-users=false") if get_config("cull.removeNamedServers"): cull_cmd.append("--remove-named-servers") cull_max_age = get_config("cull.maxAge") if cull_max_age: - cull_cmd.append("--max-age=%s" % cull_max_age) + cull_cmd.append(f"--max-age={cull_max_age}") c.JupyterHub.services.append( { - "name": "cull-idle", - "admin": True, + "name": "jupyterhub-idle-culler", "command": cull_cmd, } ) + c.JupyterHub.load_roles.append(jupyterhub_idle_culler_role) for key, service in get_config("hub.services", {}).items(): # c.JupyterHub.services is a list of dicts, but @@ -410,26 +451,44 @@ def camelCaseify(s): c.JupyterHub.services.append(service) +for key, role in get_config("hub.loadRoles", {}).items(): + # c.JupyterHub.load_roles is a list of dicts, but + # hub.loadRoles is a dict of dicts to make the config mergable + role.setdefault("name", key) + + c.JupyterHub.load_roles.append(role) + +# respect explicit null command (distinct from unspecified) +# this avoids relying on KubeSpawner.cmd's default being None +_unspecified = object() +specified_cmd = get_config("singleuser.cmd", _unspecified) +if specified_cmd is not _unspecified: + c.Spawner.cmd = specified_cmd -set_config_if_not_none(c.Spawner, "cmd", "singleuser.cmd") set_config_if_not_none(c.Spawner, "default_url", "singleuser.defaultUrl") -cloud_metadata = get_config("singleuser.cloudMetadata", {}) +cloud_metadata = get_config("singleuser.cloudMetadata") if cloud_metadata.get("blockWithIptables") == True: # Use iptables to block access to cloud metadata by default network_tools_image_name = get_config("singleuser.networkTools.image.name") network_tools_image_tag = get_config("singleuser.networkTools.image.tag") + network_tools_resources = get_config("singleuser.networkTools.resources") + ip = cloud_metadata["ip"] ip_block_container = client.V1Container( name="block-cloud-metadata", image=f"{network_tools_image_name}:{network_tools_image_tag}", command=[ "iptables", - "-A", + "--append", "OUTPUT", - "-d", - cloud_metadata.get("ip", "169.254.169.254"), - "-j", + "--protocol", + "tcp", + "--destination", + ip, + "--destination-port", + "80", + "--jump", "DROP", ], security_context=client.V1SecurityContext( @@ -437,6 +496,7 @@ def camelCaseify(s): run_as_user=0, capabilities=client.V1Capabilities(add=["NET_ADMIN"]), ), + resources=network_tools_resources, ) c.KubeSpawner.init_containers.append(ip_block_container) @@ -446,17 +506,6 @@ def camelCaseify(s): c.JupyterHub.log_level = "DEBUG" c.Spawner.debug = True -# load /usr/local/etc/jupyterhub/jupyterhub_config.d config files -config_dir = "/usr/local/etc/jupyterhub/jupyterhub_config.d" -if os.path.isdir(config_dir): - for file_path in sorted(glob.glob(f"{config_dir}/*.py")): - file_name = os.path.basename(file_path) - print(f"Loading {config_dir} config: {file_name}") - with open(file_path) as f: - file_content = f.read() - # compiling makes debugging easier: https://stackoverflow.com/a/437857 - exec(compile(source=file_content, filename=file_name, mode="exec")) - # load potentially seeded secrets # # NOTE: ConfigurableHTTPProxy.auth_token is set through an environment variable @@ -479,7 +528,18 @@ def camelCaseify(s): cfg.pop("keys", None) c[app].update(cfg) +# load /usr/local/etc/jupyterhub/jupyterhub_config.d config files +config_dir = "/usr/local/etc/jupyterhub/jupyterhub_config.d" +if os.path.isdir(config_dir): + for file_path in sorted(glob.glob(f"{config_dir}/*.py")): + file_name = os.path.basename(file_path) + print(f"Loading {config_dir} config: {file_name}") + with open(file_path) as f: + file_content = f.read() + # compiling makes debugging easier: https://stackoverflow.com/a/437857 + exec(compile(source=file_content, filename=file_name, mode="exec")) + # execute hub.extraConfig entries for key, config_py in sorted(get_config("hub.extraConfig", {}).items()): - print("Loading extra config: %s" % key) + print(f"Loading extra config: {key}") exec(config_py) diff --git a/jupyterhub/files/hub/z2jh.py b/jupyterhub/files/hub/z2jh.py index 85b5e465f3..3735169b2b 100644 --- a/jupyterhub/files/hub/z2jh.py +++ b/jupyterhub/files/hub/z2jh.py @@ -3,14 +3,15 @@ Methods here can be imported by extraConfig in values.yaml """ -from collections import Mapping -from functools import lru_cache import os +from collections.abc import Mapping +from functools import lru_cache import yaml + # memoize so we only load config once -@lru_cache() +@lru_cache def _load_config(): """Load the Helm chart configuration used to render the Helm templates of the chart from a mounted k8s Secret, and merge in values from an optionally @@ -29,7 +30,7 @@ def _load_config(): return cfg -@lru_cache() +@lru_cache def _get_config_value(key): """Load value from the k8s ConfigMap given a key.""" @@ -41,7 +42,7 @@ def _get_config_value(key): raise Exception(f"{path} not found!") -@lru_cache() +@lru_cache def get_secret_value(key, default="never-explicitly-set"): """Load value from the user managed k8s Secret or the default k8s Secret given a key.""" diff --git a/jupyterhub/templates/NOTES.txt b/jupyterhub/templates/NOTES.txt index 81b0c0800d..518ef50de3 100644 --- a/jupyterhub/templates/NOTES.txt +++ b/jupyterhub/templates/NOTES.txt @@ -1,64 +1,101 @@ -Thank you for installing JupyterHub! +{{- $proxy_service := include "jupyterhub.proxy-public.fullname" . -}} -Your release is named "{{ .Release.Name }}" and installed into the namespace "{{ .Release.Namespace }}". +{{- /* Generated with https://patorjk.com/software/taag/#p=display&h=0&f=Slant&t=JupyterHub */}} +. __ __ __ __ __ + / / __ __ ____ __ __ / /_ ___ _____ / / / / __ __ / /_ + __ / / / / / / / __ \ / / / / / __/ / _ \ / ___/ / /_/ / / / / / / __ \ +/ /_/ / / /_/ / / /_/ / / /_/ / / /_ / __/ / / / __ / / /_/ / / /_/ / +\____/ \__,_/ / .___/ \__, / \__/ \___/ /_/ /_/ /_/ \__,_/ /_.___/ + /_/ /____/ -You can check whether the hub and proxy are ready by running: + You have successfully installed the official JupyterHub Helm chart! - kubectl --namespace={{ .Release.Namespace }} get pod +### Installation info -and watching for both those pods to be in status 'Running'.{{ println }} + - Kubernetes namespace: {{ .Release.Namespace }} + - Helm release name: {{ .Release.Name }} + - Helm chart version: {{ .Chart.Version }} + - JupyterHub version: {{ .Chart.AppVersion }} + - Hub pod packages: See https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/{{ include "jupyterhub.chart-version-to-git-ref" .Chart.Version }}/images/hub/requirements.txt -{{- if eq .Values.proxy.service.type "LoadBalancer" }} -You can find the public (load-balancer) IP of JupyterHub by running: +### Followup links - kubectl -n {{ .Release.Namespace }} get svc {{ include "jupyterhub.proxy-public.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[].ip}' + - Documentation: https://z2jh.jupyter.org + - Help forum: https://discourse.jupyter.org + - Social chat: https://gitter.im/jupyterhub/jupyterhub + - Issue tracking: https://github.com/jupyterhub/zero-to-jupyterhub-k8s/issues -It might take a few minutes for it to appear! -{{- end }} -{{- if eq .Values.proxy.service.type "ClusterIP" }} -You can find the internal (cluster) IP of JupyterHub by running: +### Post-installation checklist - kubectl get -n {{ .Release.Namespace }} svc {{ include "jupyterhub.proxy-public.fullname" . }} -o jsonpath='{.spec.clusterIP}' -{{- end }} -{{- if eq .Values.proxy.service.type "NodePort" }} -You can find the NodePorts of JupyterHub by running: + - Verify that created Pods enter a Running state: - kubectl --namespace={{ .Release.Namespace }} get svc {{ include "jupyterhub.proxy-public.fullname" . }} -o jsonpath='{range .spec.ports[*]} {.name}: {.port}{"\n"} {end}' -{{- end }} + kubectl --namespace={{ .Release.Namespace }} get pod -{{- if .Values.ingress.enabled }} + If a pod is stuck with a Pending or ContainerCreating status, diagnose with: -You should be able to access JupyterHub using your configured ingress at: -{{ range $host := .Values.ingress.hosts }} - http://{{ $host }}{{ $.Values.hub.baseUrl | trimSuffix "/" }}/ -{{- end }} -{{- range $tls := .Values.ingress.tls }} - {{- range $host := $tls.hosts }} - https://{{ $host }}{{ $.Values.hub.baseUrl | trimSuffix "/" }}/ - {{- end }} -{{- end }} + kubectl --namespace={{ .Release.Namespace }} describe pod -{{- end }} + If a pod keeps restarting, diagnose with: + + kubectl --namespace={{ .Release.Namespace }} logs --previous + {{- println }} + + {{- if eq .Values.proxy.service.type "LoadBalancer" }} + - Verify an external IP is provided for the k8s Service {{ $proxy_service }}. -To get full information about the JupyterHub proxy service run: + kubectl --namespace={{ .Release.Namespace }} get service {{ $proxy_service }} - kubectl --namespace={{ .Release.Namespace }} get svc {{ include "jupyterhub.proxy-public.fullname" . }} + If the external ip remains , diagnose with: -If you have questions, please: + kubectl --namespace={{ .Release.Namespace }} describe service {{ $proxy_service }} + {{- end }} - 1. Read the guide at https://z2jh.jupyter.org - 2. Ask for help or chat to us on https://discourse.jupyter.org/ - 3. If you find a bug please report it at https://github.com/jupyterhub/zero-to-jupyterhub-k8s/issues + - Verify web based access: + {{- println }} + {{- if .Values.ingress.enabled }} + {{- range $host := .Values.ingress.hosts }} + Try insecure HTTP access: http://{{ $host }}{{ $.Values.hub.baseUrl | trimSuffix "/" }}/ + {{- end }} + + {{- range $tls := .Values.ingress.tls }} + {{- range $host := $tls.hosts }} + Try secure HTTPS access: https://{{ $host }}{{ $.Values.hub.baseUrl | trimSuffix "/" }}/ + {{- end }} + {{- end }} + {{- else }} + You have not configured a k8s Ingress resource so you need to access the k8s + Service {{ $proxy_service }} directly. + {{- println }} + + {{- if eq .Values.proxy.service.type "NodePort" }} + The k8s Service {{ $proxy_service }} is exposed via NodePorts. That means + that all the k8s cluster's nodes are exposing the k8s Service via those + ports. + + Try insecure HTTP access: http://:{{ .Values.proxy.service.nodePorts.http | default "no-http-nodeport-set"}} + Try secure HTTPS access: https://:{{ .Values.proxy.service.nodePorts.https | default "no-https-nodeport-set" }} + + {{- else }} + If your computer is outside the k8s cluster, you can port-forward traffic to + the k8s Service {{ $proxy_service }} with kubectl to access it from your + computer. + + kubectl --namespace={{ .Release.Namespace }} port-forward service/{{ $proxy_service }} 8080:http + + Try insecure HTTP access: http://localhost:8080 + {{- end }} + {{- end }} + {{- println }} {{- /* - Warnings for likely misconfiguration + Warnings for likely misconfigurations */}} -{{- if and (not .Values.scheduling.podPriority.enabled) (and .Values.scheduling.userPlaceholder.enabled .Values.scheduling.userPlaceholder.replicas) }}{{ println }} +{{- if and (not .Values.scheduling.podPriority.enabled) (and .Values.scheduling.userPlaceholder.enabled .Values.scheduling.userPlaceholder.replicas) }} ################################################################################# ###### WARNING: You are using user placeholders without pod priority ##### ###### enabled*, either enable pod priority or stop using the ##### @@ -69,17 +106,7 @@ If you have questions, please: ###### **scheduling.userPlaceholder.enabled ##### ###### **scheduling.userPlaceholder.replicas ##### ################################################################################# -{{- end }} - - -{{- if eq .Values.proxy.https.enabled false }} -{{- if or (not (eq .Values.proxy.https.type "letsencrypt")) (not (eq (.Values.proxy.https.letsencrypt.contactEmail | default "") "")) }}{{ println }} -################################################################################# -###### WARNING: proxy.https.enabled is set to false by default since ##### -###### version 0.10.0. It is now set to false but proxy.https ##### -###### has been modified indicating you may want it enabled. ##### -################################################################################# -{{- end }} +{{- println }} {{- end }} @@ -87,7 +114,7 @@ If you have questions, please: {{- /* - Breaking changes. + Breaking changes and failures for likely misconfigurations. */}} {{- $breaking := "" }} @@ -101,55 +128,31 @@ If you have questions, please: {{- $breaking_title = print $breaking_title "\n#################################################################################" }} -{{- if hasKey .Values.hub "extraConfigMap" }} -{{- $breaking = print $breaking "\n\nRENAMED: hub.extraConfigMap has been renamed to custom" }} -{{- end }} - - -{{- if hasKey .Values "auth" }} -{{- if .Values.auth }} -{{- $breaking = print $breaking (include "jupyterhub.authDep.remapOldToNew" .) }} -{{- else }} -{{- $breaking = print $breaking "\n\nREMOVED: Please remove the empty 'auth' config" }} -{{- end }} -{{- end }} - - -{{- if hasKey .Values.proxy "containerSecurityContext" }} -{{- $breaking = print $breaking "\n\nRENAMED: proxy.containerSecurityContext has been renamed to proxy.chp.containerSecurityContext" }} -{{- end }} - - -{{- if hasKey .Values.proxy "pdb" }} -{{- $breaking = print $breaking "\n\nRENAMED: proxy.pdb has renamed to proxy.chp.pdb" }} -{{- end }} - - -{{- if hasKey .Values.proxy "networkPolicy" }} -{{- $breaking = print $breaking "\n\nRENAMED: proxy.networkPolicy has been renamed to proxy.chp.networkPolicy" }} -{{- end }} - +{{- /* + This is an example (in a helm template comment) on how to detect and + communicate with regards to a breaking chart config change. -{{- if hasKey .Values.hub "uid" }} -{{- $breaking = print $breaking "\n\nRENAMED: hub.uid must as of 1.0.0 be configured using hub.containerSecurityContext.runAsUser" }} -{{- end }} + {{- if hasKey .Values.singleuser.cloudMetadata "enabled" }} + {{- $breaking = print $breaking "\n\nCHANGED: singleuser.cloudMetadata.enabled must as of 1.0.0 be configured using singleuser.cloudMetadata.blockWithIptables with the opposite value." }} + {{- end }} +*/}} -{{- if hasKey .Values.hub "imagePullSecret" }} -{{- $breaking = print $breaking "\n\nREMOVED: hub.imagePullSecret has been removed, but there is now a chart wide wide configuration named imagePullSecret" }} +{{- if hasKey .Values.rbac "enabled" }} +{{- $breaking = print $breaking "\n\nCHANGED: rbac.enabled must as of version 2.0.0 be configured via rbac.create and .serviceAccount.create." }} {{- end }} -{{- if hasKey .Values.singleuser "imagePullSecret" }} -{{- $breaking = print $breaking "\n\nREMOVED: singleuser.imagePullSecret has been removed, but there is now a chart wide wide configuration named imagePullSecret" }} +{{- if hasKey .Values.hub "fsGid" }} +{{- $breaking = print $breaking "\n\nCHANGED: hub.fsGid must as of version 2.0.0 be configured via hub.podSecurityContext.fsGroup." }} {{- end }} -{{- if hasKey .Values.singleuser.cloudMetadata "enabled" }} -{{- $breaking = print $breaking "\n\nCHANGED: singleuser.cloudMetadata.enabled must as of 1.0.0 be configured using singleuser.cloudMetadata.blockWithIptables with the opposite value." }} +{{- if and .Values.singleuser.cloudMetadata.blockWithIptables (and .Values.singleuser.networkPolicy.enabled .Values.singleuser.networkPolicy.egressAllowRules.cloudMetadataServer) }} +{{- $breaking = print $breaking "\n\nCHANGED: singleuser.cloudMetadata.blockWithIptables must as of version 3.0.0 not be configured together with singleuser.networkPolicy.egressAllowRules.cloudMetadataServer as it leads to an ambiguous configuration." }} {{- end }} {{- if $breaking }} -{{- fail (print $breaking_title $breaking) }} +{{- fail (print $breaking_title $breaking "\n\n") }} {{- end }} diff --git a/jupyterhub/templates/_helpers-auth-rework.tpl b/jupyterhub/templates/_helpers-auth-rework.tpl deleted file mode 100644 index 2335398626..0000000000 --- a/jupyterhub/templates/_helpers-auth-rework.tpl +++ /dev/null @@ -1,223 +0,0 @@ -{{- /* - As we found Helm chart configuration of JupyterHub authentication was - too complicated both to maintain and use in its badly maintained state, - we sharply transitioned to a new system in 0.11.0. - - To help users transition, this file was developed. It converts the old - auth configuration under "auth" to the new under "c". We detect if the - old system is used and let the Helm chart's template rendering fail - where we also provide a useful error message including the new config - to use in its place. - - Implementation details: - - Secret content must be censored - - auth.state.cryptoKey needs a new home -*/}} - -{{- define "jupyterhub.authDep.classKeyToLong.map" }} -google: google -github: github -cilogon: cilogon -gitlab: gitlab -azuread: azuread -mediawiki: mediawiki -globus: globus -hmac: hmacauthenticator.HMACAuthenticator -dummy: dummy -tmp: tmpauthenticator.TmpAuthenticator -lti: ltiauthenticator.LTIAuthenticator -ldap: ldapauthenticator.LDAPAuthenticator -{{- end }} - -{{- /* Uses the map above, taking a keys, returning a value. */}} -{{- define "jupyterhub.authDep.classKeyToLong" -}} - {{- $map := include "jupyterhub.authDep.classKeyToLong.map" . | fromYaml }} - {{- index $map . }} -{{- end }} - -{{- define "jupyterhub.authDep.remapOldToNew.map" }} -scopes: OAuthenticator.scope -state.enabled: Authenticator.enable_auth_state -state.cryptoKey: CryptKeeper.keys -admin.access: JupyterHub.admin_access -admin.users: Authenticator.admin_users -whitelist.users: Authenticator.allowed_users -allowedUsers: Authenticator.allowed_users -google.clientId: GoogleOAuthenticator.client_id -google.clientSecret: GoogleOAuthenticator.client_secret -google.callbackUrl: GoogleOAuthenticator.oauth_callback_url -google.hostedDomain: GoogleOAuthenticator.hosted_domain -google.loginService: GoogleOAuthenticator.login_service -github.clientId: GitHubOAuthenticator.client_id -github.clientSecret: GitHubOAuthenticator.client_secret -github.callbackUrl: GitHubOAuthenticator.oauth_callback_url -github.orgWhitelist: GitHubOAuthenticator.allowed_organizations -github.allowedOrganizations: GitHubOAuthenticator.allowed_organizations -cilogon.clientId: CILogonOAuthenticator.client_id -cilogon.clientSecret: CILogonOAuthenticator.client_secret -cilogon.callbackUrl: CILogonOAuthenticator.oauth_callback_url -gitlab.clientId: GitLabOAuthenticator.client_id -gitlab.clientSecret: GitLabOAuthenticator.client_secret -gitlab.callbackUrl: GitLabOAuthenticator.oauth_callback_url -gitlab.gitlabGroupWhitelist: GitLabOAuthenticator.allowed_gitlab_groups -gitlab.allowedGitlabGroups: GitLabOAuthenticator.allowed_gitlab_groups -gitlab.gitlabProjectIdWhitelist: GitLabOAuthenticator.allowed_project_ids -gitlab.allowedProjectIds: GitLabOAuthenticator.allowed_project_ids -gitlab.gitlabUrl: GitLabOAuthenticator.gitlab_url -azuread.clientId: AzureAdOAuthenticator.client_id -azuread.clientSecret: AzureAdOAuthenticator.client_secret -azuread.callbackUrl: AzureAdOAuthenticator.oauth_callback_url -azuread.tenantId: AzureAdOAuthenticator.tenant_id -azuread.usernameClaim: AzureAdOAuthenticator.username_claim -mediawiki.clientId: MWOAuthenticator.client_id -mediawiki.clientSecret: MWOAuthenticator.client_secret -mediawiki.callbackUrl: MWOAuthenticator.oauth_callback_url -mediawiki.indexUrl: MWOAuthenticator.index_url -globus.clientId: GlobusOAuthenticator.client_id -globus.clientSecret: GlobusOAuthenticator.client_secret -globus.callbackUrl: GlobusOAuthenticator.oauth_callback_url -hmac.secretKey: HMACAuthenticator.secret_key -dummy.password: DummyAuthenticator.password -lti.consumers: LTIAuthenticator.consumers -ldap.server.address: LDAPAuthenticator.server_address -ldap.server.port: LDAPAuthenticator.server_port -ldap.server.ssl: LDAPAuthenticator.use_ssl -ldap.allowedGroups: LDAPAuthenticator.allowed_groups -ldap.dn.templates: LDAPAuthenticator.bind_dn_template -ldap.dn.lookup: LDAPAuthenticator.lookup_dn -ldap.dn.search.filter: LDAPAuthenticator.lookup_dn_search_filter -ldap.dn.search.user: LDAPAuthenticator.lookup_dn_search_user -ldap.dn.search.password: LDAPAuthenticator.lookup_dn_search_password -ldap.dn.user.dnAttribute: LDAPAuthenticator.lookup_dn_user_dn_attribute -ldap.dn.user.escape: LDAPAuthenticator.escape_userdn -ldap.dn.user.validRegex: LDAPAuthenticator.valid_username_regex -ldap.dn.user.searchBase: LDAPAuthenticator.user_search_base -ldap.dn.user.attribute: LDAPAuthenticator.user_attribute -ldap.dn.user.useLookupName: LDAPAuthenticator.use_lookup_dn_username -{{- end }} - -{{- /* Uses the map above, taking a keys, returning a value. */}} -{{- define "jupyterhub.authDep.remapOldToNew.single" }} - {{- $map := include "jupyterhub.authDep.remapOldToNew.map" . | fromYaml }} - {{- index $map . }} -{{- end }} - - -{{- /* - Recursively flattens a passed dict structure, outputs the result - in a passed dict which is assumed to be empty. -*/}} -{{- define "jupyterhub.flattenDict" }} - {{- $out := index . 0 }} - {{- $dict := index . 1 }} - - {{- $label := "" }} - {{- if eq (len .) 3 }} - {{- $label = index . 2 }} - {{- end }} - - {{- range $key, $val := $dict }} - {{- $sublabel := list $label $key | join "." | trimPrefix "." }} - {{- if kindOf $val | eq "map" }} - {{- include "jupyterhub.flattenDict" (list $out $val $sublabel) }} - {{- else }} - {{- $_ := set $out $sublabel $val }} - {{- end }} - {{- end }} -{{- end }} - -{{- /* - Remaps Recursively flattens a passed dict structure, outputs the result - in a passed dict which is assumed to be empty. -*/}} -{{- define "jupyterhub.authDep.remapOldToNew.mappable" -}} - {{- $c := index . 0 }} - {{- $safe := index . 1 }} - {{- range $key, $val := $c }} - {{- if not $safe }} - {{- $val = "***" }} - {{- end }} - {{- $_ := unset $c $key }} - {{- $class_dot_new_key := include "jupyterhub.authDep.remapOldToNew.single" $key }} - - {{- /* Manage unrecognized config */}} - {{- if eq $class_dot_new_key "" }} - {{- if not (hasKey $c "WarningUnrecognizedConfig") }} - {{- $_ := set $c "WarningUnrecognizedConfig" dict }} - {{- end }} - {{- $_ := set (index $c "WarningUnrecognizedConfig") $key $val }} - - {{- else }} - {{- /* Config value transformations if needed */}} - {{- if eq $key "state.cryptoKey" }} - {{- $val = list $val }} - {{- end }} - - {{- /* De-flatten the "ClassName.config_name" like strings */}} - {{- $class := splitList "." $class_dot_new_key | first }} - {{- $new_key := splitList "." $class_dot_new_key | last }} - {{- if not (hasKey $c $class) }} - {{- $_ := set $c $class dict }} - {{- end }} - {{- $_ := set (index $c $class) $new_key $val }} - {{- end }} - {{- end }} -{{- end }} - -{{- define "jupyterhub.authDep.remapOldToNew" -}} - {{- $c := dict }} - {{- $result := (dict "hub" (dict "config" $c)) }} - {{- /* - Flattens the config in .Values.auth to a format of - "keyX.keyY...": "value". Writes output to $c. - */}} - {{- include "jupyterhub.flattenDict" (list $c (omit .Values.auth "type" "custom")) }} - - {{- /* - Transform the flattened config using a dictionary - representing the old z2jh config, output the result - in $c. - */}} - {{- include "jupyterhub.authDep.remapOldToNew.mappable" (list $c .Values.global.safeToShowValues) }} - - {{- $class_old_config_key := .Values.auth.type | default "" }} {{- /* ldap - github */}} - {{- $class_new_entrypoint := "" }} {{- /* ldapauthenticator.LDAPAuthenticator - github */}} - {{- $class_new_config_key := "" }} {{- /* LDAPAuthenticator - GitHubOAuthenticator */}} - - {{- /* SET $class_new_entrypoint, $class_new_config_key */}} - {{- if eq $class_old_config_key "custom" }} - {{- $class_new_entrypoint = .Values.auth.custom.className | default "custom.className wasn't configured!" }} - {{- $class_new_config_key = $class_new_entrypoint | splitList "." | last }} - {{- /* UPDATE c dict explicitly with auth.custom.config */}} - {{- if .Values.auth.custom.config }} - {{- $custom_config := merge (dict) .Values.auth.custom.config }} - {{- if not .Values.global.safeToShowValues }} - {{- range $key, $val := $custom_config }} - {{- $_ := set $custom_config $key "***" }} - {{- end }} - {{- end }} - {{- $_ := set $c $class_new_config_key $custom_config }} - {{- end }} - {{- else }} - {{- $class_new_entrypoint = include "jupyterhub.authDep.classKeyToLong" $class_old_config_key }} - {{- end }} - - {{- /* UPDATE c dict authenticator_class */}} - {{- if ne $class_new_entrypoint "" }} - {{- $_ := merge $c (dict "JupyterHub" (dict "authenticator_class" $class_new_entrypoint)) }} - {{- end }} - -{{- /* Output a sensible error message */}} - -The JupyterHub Helm chart's auth config has been reworked and requires changes. - -The new way to configure authentication in chart version 0.11.0+ is printed -below for your convenience. The values are not shown by default to ensure no -secrets are exposed, run helm upgrade with --set global.safeToShowValues=true -to show them. - -{{ $result | toYaml }} - -For more details, please see the updated auth config documentation at: -https://zero-to-jupyterhub.readthedocs.io/en/latest/administrator/authentication.html -{{- end }} diff --git a/jupyterhub/templates/_helpers-names.tpl b/jupyterhub/templates/_helpers-names.tpl index 6ba4b5b2ac..f0fe1a51c7 100644 --- a/jupyterhub/templates/_helpers-names.tpl +++ b/jupyterhub/templates/_helpers-names.tpl @@ -3,8 +3,8 @@ parent charts to reference these dynamic resource names. To avoid duplicating documentation, for more information, please see the the - fullnameOverride entry in schema.yaml or the configuration reference that - schema.yaml renders to. + fullnameOverride entry in values.schema.yaml or the configuration reference + that values.schema.yaml renders to. https://z2jh.jupyter.org/en/latest/resources/reference.html#fullnameOverride */}} @@ -76,12 +76,23 @@ {{- include "jupyterhub.fullname.dash" . }}hub {{- end }} +{{- /* hub-serviceaccount ServiceAccount */}} +{{- define "jupyterhub.hub-serviceaccount.fullname" -}} + {{- if .Values.hub.serviceAccount.create }} + {{- .Values.hub.serviceAccount.name | default (include "jupyterhub.hub.fullname" .) }} + {{- else }} + {{- .Values.hub.serviceAccount.name | default "default" }} + {{- end }} +{{- end }} + {{- /* hub-existing-secret Secret */}} {{- define "jupyterhub.hub-existing-secret.fullname" -}} {{- /* A hack to avoid issues from invoking this from a parent Helm chart. */}} {{- $existing_secret := .Values.hub.existingSecret }} {{- if ne .Chart.Name "jupyterhub" }} - {{- $existing_secret = .Values.jupyterhub.hub.existingSecret }} + {{- if .Values.jupyterhub }} + {{- $existing_secret = .Values.jupyterhub.hub.existingSecret }} + {{- end }} {{- end }} {{- if $existing_secret }} {{- $existing_secret }} @@ -133,11 +144,29 @@ {{- include "jupyterhub.fullname.dash" . }}autohttps {{- end }} +{{- /* autohttps-serviceaccount ServiceAccount */}} +{{- define "jupyterhub.autohttps-serviceaccount.fullname" -}} + {{- if .Values.proxy.traefik.serviceAccount.create }} + {{- .Values.proxy.traefik.serviceAccount.name | default (include "jupyterhub.autohttps.fullname" .) }} + {{- else }} + {{- .Values.proxy.traefik.serviceAccount.name | default "default" }} + {{- end }} +{{- end }} + {{- /* user-scheduler Deployment */}} {{- define "jupyterhub.user-scheduler-deploy.fullname" -}} {{- include "jupyterhub.fullname.dash" . }}user-scheduler {{- end }} +{{- /* user-scheduler-serviceaccount ServiceAccount */}} +{{- define "jupyterhub.user-scheduler-serviceaccount.fullname" -}} + {{- if .Values.scheduling.userScheduler.serviceAccount.create }} + {{- .Values.scheduling.userScheduler.serviceAccount.name | default (include "jupyterhub.user-scheduler-deploy.fullname" .) }} + {{- else }} + {{- .Values.scheduling.userScheduler.serviceAccount.name | default "default" }} + {{- end }} +{{- end }} + {{- /* user-scheduler leader election lock resource */}} {{- define "jupyterhub.user-scheduler-lock.fullname" -}} {{- include "jupyterhub.user-scheduler-deploy.fullname" . }}-lock @@ -153,6 +182,15 @@ {{- include "jupyterhub.fullname.dash" . }}hook-image-awaiter {{- end }} +{{- /* image-awaiter-serviceaccount ServiceAccount */}} +{{- define "jupyterhub.hook-image-awaiter-serviceaccount.fullname" -}} + {{- if .Values.prePuller.hook.serviceAccount.create }} + {{- .Values.prePuller.hook.serviceAccount.name | default (include "jupyterhub.hook-image-awaiter.fullname" .) }} + {{- else }} + {{- .Values.prePuller.hook.serviceAccount.name | default "default" }} + {{- end }} +{{- end }} + {{- /* hook-image-puller DaemonSet */}} {{- define "jupyterhub.hook-image-puller.fullname" -}} {{- include "jupyterhub.fullname.dash" . }}hook-image-puller @@ -210,6 +248,15 @@ {{- end }} {{- end }} +{{- /* image-puller Priority */}} +{{- define "jupyterhub.image-puller-priority.fullname" -}} + {{- if (include "jupyterhub.fullname" .) }} + {{- include "jupyterhub.fullname.dash" . }}image-puller + {{- else }} + {{- .Release.Name }}-image-puller-priority + {{- end }} +{{- end }} + {{- /* user-scheduler's registered name */}} {{- define "jupyterhub.user-scheduler.fullname" -}} {{- if (include "jupyterhub.fullname" .) }} @@ -231,6 +278,7 @@ fullname: {{ include "jupyterhub.fullname" . | quote }} fullname-dash: {{ include "jupyterhub.fullname.dash" . | quote }} hub: {{ include "jupyterhub.hub.fullname" . | quote }} +hub-serviceaccount: {{ include "jupyterhub.hub-serviceaccount.fullname" . | quote }} hub-existing-secret: {{ include "jupyterhub.hub-existing-secret.fullname" . | quote }} hub-existing-secret-or-default: {{ include "jupyterhub.hub-existing-secret-or-default.fullname" . | quote }} hub-pvc: {{ include "jupyterhub.hub-pvc.fullname" . | quote }} @@ -241,10 +289,14 @@ proxy-public: {{ include "jupyterhub.proxy-public.fullname" . | quote }} proxy-public-tls: {{ include "jupyterhub.proxy-public-tls.fullname" . | quote }} proxy-public-manual-tls: {{ include "jupyterhub.proxy-public-manual-tls.fullname" . | quote }} autohttps: {{ include "jupyterhub.autohttps.fullname" . | quote }} +autohttps-serviceaccount: {{ include "jupyterhub.autohttps-serviceaccount.fullname" . | quote }} user-scheduler-deploy: {{ include "jupyterhub.user-scheduler-deploy.fullname" . | quote }} +user-scheduler-serviceaccount: {{ include "jupyterhub.user-scheduler-serviceaccount.fullname" . | quote }} user-scheduler-lock: {{ include "jupyterhub.user-scheduler-lock.fullname" . | quote }} user-placeholder: {{ include "jupyterhub.user-placeholder.fullname" . | quote }} +image-puller-priority: {{ include "jupyterhub.image-puller-priority.fullname" . | quote }} hook-image-awaiter: {{ include "jupyterhub.hook-image-awaiter.fullname" . | quote }} +hook-image-awaiter-serviceaccount: {{ include "jupyterhub.hook-image-awaiter-serviceaccount.fullname" . | quote }} hook-image-puller: {{ include "jupyterhub.hook-image-puller.fullname" . | quote }} continuous-image-puller: {{ include "jupyterhub.continuous-image-puller.fullname" . | quote }} singleuser: {{ include "jupyterhub.singleuser.fullname" . | quote }} diff --git a/jupyterhub/templates/_helpers-netpol.tpl b/jupyterhub/templates/_helpers-netpol.tpl new file mode 100644 index 0000000000..006f633227 --- /dev/null +++ b/jupyterhub/templates/_helpers-netpol.tpl @@ -0,0 +1,101 @@ +{{- /* + This named template renders egress rules for NetworkPolicy resources based on + common configuration. + + It is rendering based on the `egressAllowRules` and `egress` keys of the + passed networkPolicy config object. Each flag set to true under + `egressAllowRules` is rendered to a egress rule that next to any custom user + defined rules from the `egress` config. + + This named template needs to render based on a specific networkPolicy + resource, but also needs access to the root context. Due to that, it + accepts a list as its scope, where the first element is supposed to be the + root context and the second element is supposed to be the networkPolicy + configuration object. + + As an example, this is how you would render this named template from a + NetworkPolicy resource under its egress: + + egress: + # other rules here... + + {{- with (include "jupyterhub.networkPolicy.renderEgressRules" (list . .Values.hub.networkPolicy)) }} + {{- . | nindent 4 }} + {{- end }} + + Note that the reference to privateIPs and nonPrivateIPs relate to + https://en.wikipedia.org/wiki/Private_network#Private_IPv4_addresses. +*/}} + +{{- define "jupyterhub.networkPolicy.renderEgressRules" -}} +{{- $root := index . 0 }} +{{- $netpol := index . 1 }} +{{- if or (or $netpol.egressAllowRules.dnsPortsCloudMetadataServer $netpol.egressAllowRules.dnsPortsKubeSystemNamespace) $netpol.egressAllowRules.dnsPortsPrivateIPs }} +- ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + to: + {{- if $netpol.egressAllowRules.dnsPortsCloudMetadataServer }} + # Allow outbound connections to DNS ports on the cloud metadata server + - ipBlock: + cidr: {{ $root.Values.singleuser.cloudMetadata.ip }}/32 + {{- end }} + {{- if $netpol.egressAllowRules.dnsPortsKubeSystemNamespace }} + # Allow outbound connections to DNS ports on pods in the kube-system + # namespace + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: kube-system + {{- end }} + {{- if $netpol.egressAllowRules.dnsPortsPrivateIPs }} + # Allow outbound connections to DNS ports on destinations in the private IP + # ranges + - ipBlock: + cidr: 10.0.0.0/8 + - ipBlock: + cidr: 172.16.0.0/12 + - ipBlock: + cidr: 192.168.0.0/16 + {{- end }} +{{- end }} + +{{- if $netpol.egressAllowRules.nonPrivateIPs }} +# Allow outbound connections to non-private IP ranges +- to: + - ipBlock: + cidr: 0.0.0.0/0 + except: + # As part of this rule: + # - don't allow outbound connections to private IPs + - 10.0.0.0/8 + - 172.16.0.0/12 + - 192.168.0.0/16 + # - don't allow outbound connections to the cloud metadata server + - {{ $root.Values.singleuser.cloudMetadata.ip }}/32 +{{- end }} + +{{- if $netpol.egressAllowRules.privateIPs }} +# Allow outbound connections to private IP ranges +- to: + - ipBlock: + cidr: 10.0.0.0/8 + - ipBlock: + cidr: 172.16.0.0/12 + - ipBlock: + cidr: 192.168.0.0/16 +{{- end }} + +{{- if $netpol.egressAllowRules.cloudMetadataServer }} +# Allow outbound connections to the cloud metadata server +- to: + - ipBlock: + cidr: {{ $root.Values.singleuser.cloudMetadata.ip }}/32 +{{- end }} + +{{- with $netpol.egress }} +# Allow outbound connections based on user specified rules +{{ . | toYaml }} +{{- end }} +{{- end }} diff --git a/jupyterhub/templates/_helpers.tpl b/jupyterhub/templates/_helpers.tpl index 53bced8f71..5cc5e6dee1 100644 --- a/jupyterhub/templates/_helpers.tpl +++ b/jupyterhub/templates/_helpers.tpl @@ -12,7 +12,7 @@ When you ask a helper to render its content, one often forward the current scope to the helper in order to allow it to access .Release.Name, - .Values.rbac.enabled and similar values. + .Values.rbac.create and similar values. #### Example - Passing the current scope {{ include "jupyterhub.commonLabels" . }} @@ -180,30 +180,51 @@ component: {{ include "jupyterhub.componentLabel" . }} Augments passed .pullSecrets with $.Values.imagePullSecrets */}} {{- define "jupyterhub.imagePullSecrets" -}} -{{- /* Populate $_.list with all relevant entries */}} -{{- $_ := dict "list" (concat .image.pullSecrets .root.Values.imagePullSecrets | uniq) }} -{{- if and .root.Values.imagePullSecret.create .root.Values.imagePullSecret.automaticReferenceInjection }} -{{- $__ := set $_ "list" (append $_.list (include "jupyterhub.image-pull-secret.fullname" .root) | uniq) }} -{{- end }} + {{- /* + We have implemented a trick to allow a parent chart depending on this + chart to call this named templates. + + Caveats and notes: + + 1. While parent charts can reference these, grandparent charts can't. + 2. Parent charts must not use an alias for this chart. + 3. There is no failsafe workaround to above due to + https://github.com/helm/helm/issues/9214. + 4. .Chart is of its own type (*chart.Metadata) and needs to be casted + using "toYaml | fromYaml" in order to be able to use normal helm + template functions on it. + */}} + {{- $jupyterhub_values := .root.Values }} + {{- if ne .root.Chart.Name "jupyterhub" }} + {{- if .root.Values.jupyterhub }} + {{- $jupyterhub_values = .root.Values.jupyterhub }} + {{- end }} + {{- end }} -{{- /* Decide if something should be written */}} -{{- if not (eq ($_.list | toJson) "[]") }} + {{- /* Populate $_.list with all relevant entries */}} + {{- $_ := dict "list" (concat .image.pullSecrets $jupyterhub_values.imagePullSecrets | uniq) }} + {{- if and $jupyterhub_values.imagePullSecret.create $jupyterhub_values.imagePullSecret.automaticReferenceInjection }} + {{- $__ := set $_ "list" (append $_.list (include "jupyterhub.image-pull-secret.fullname" .root) | uniq) }} + {{- end }} -{{- /* Process the $_.list where strings become dicts with a name key and the -strings become the name keys' values into $_.res */}} -{{- $_ := set $_ "res" list }} -{{- range $_.list }} -{{- if eq (typeOf .) "string" }} -{{- $__ := set $_ "res" (append $_.res (dict "name" .)) }} -{{- else }} -{{- $__ := set $_ "res" (append $_.res .) }} -{{- end }} -{{- end }} + {{- /* Decide if something should be written */}} + {{- if not (eq ($_.list | toJson) "[]") }} + + {{- /* Process the $_.list where strings become dicts with a name key and the + strings become the name keys' values into $_.res */}} + {{- $_ := set $_ "res" list }} + {{- range $_.list }} + {{- if eq (typeOf .) "string" }} + {{- $__ := set $_ "res" (append $_.res (dict "name" .)) }} + {{- else }} + {{- $__ := set $_ "res" (append $_.res .) }} + {{- end }} + {{- end }} -{{- /* Write the results */}} -{{- $_.res | toJson }} + {{- /* Write the results */}} + {{- $_.res | toJson }} -{{- end }} + {{- end }} {{- end }} {{- /* @@ -361,3 +382,21 @@ limits: {{- print "\n\nextraFiles entries (" $file_key ") must only contain one of the fields: 'data', 'stringData', and 'binaryData'." | fail }} {{- end }} {{- end }} + +{{- /* + jupyterhub.chart-version-to-git-ref: + Renders a valid git reference from a chartpress generated version string. + In practice, either a git tag or a git commit hash will be returned. + + - The version string will follow a chartpress pattern, see + https://github.com/jupyterhub/chartpress#examples-chart-versions-and-image-tags. + + - The regexReplaceAll function is a sprig library function, see + https://masterminds.github.io/sprig/strings.html. + + - The regular expression is in golang syntax, but \d had to become \\d for + example. +*/}} +{{- define "jupyterhub.chart-version-to-git-ref" -}} +{{- regexReplaceAll ".*[.-]n\\d+[.]h(.*)" . "${1}" }} +{{- end }} diff --git a/jupyterhub/templates/hub/netpol.yaml b/jupyterhub/templates/hub/netpol.yaml index 0ba091963d..904b2c32b0 100644 --- a/jupyterhub/templates/hub/netpol.yaml +++ b/jupyterhub/templates/hub/netpol.yaml @@ -61,31 +61,24 @@ spec: egress: # hub --> proxy - - ports: - - port: 8001 - to: + - to: - podSelector: matchLabels: {{- $_ := merge (dict "componentLabel" "proxy") . }} {{- include "jupyterhub.matchLabels" $_ | nindent 14 }} + ports: + - port: 8001 + # hub --> singleuser-server - - ports: - - port: 8888 - to: + - to: - podSelector: matchLabels: {{- $_ := merge (dict "componentLabel" "singleuser-server") . }} {{- include "jupyterhub.matchLabels" $_ | nindent 14 }} + ports: + - port: 8888 - # hub --> Kubernetes internal DNS - - ports: - - protocol: UDP - port: 53 - - protocol: TCP - port: 53 - - {{- with .Values.hub.networkPolicy.egress }} - # hub --> depends, but the default is everything - {{- . | toYaml | nindent 4 }} + {{- with (include "jupyterhub.networkPolicy.renderEgressRules" (list . .Values.hub.networkPolicy)) }} + {{- . | nindent 4 }} {{- end }} {{- end }} diff --git a/jupyterhub/templates/hub/pdb.yaml b/jupyterhub/templates/hub/pdb.yaml index 00816d78fe..5b69eb4311 100644 --- a/jupyterhub/templates/hub/pdb.yaml +++ b/jupyterhub/templates/hub/pdb.yaml @@ -1,9 +1,5 @@ {{- if .Values.hub.pdb.enabled -}} -{{- if .Capabilities.APIVersions.Has "policy/v1" }} apiVersion: policy/v1 -{{- else }} -apiVersion: policy/v1beta1 -{{- end }} kind: PodDisruptionBudget metadata: name: {{ include "jupyterhub.hub.fullname" . }} diff --git a/jupyterhub/templates/hub/rbac.yaml b/jupyterhub/templates/hub/rbac.yaml index 81a78fbe8f..3abf00eb5e 100644 --- a/jupyterhub/templates/hub/rbac.yaml +++ b/jupyterhub/templates/hub/rbac.yaml @@ -1,15 +1,4 @@ -{{- if .Values.rbac.enabled -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "jupyterhub.hub.fullname" . }} - {{- with .Values.hub.serviceAccount.annotations }} - annotations: - {{- . | toYaml | nindent 4 }} - {{- end }} - labels: - {{- include "jupyterhub.labels" . | nindent 4 }} ---- +{{- if .Values.rbac.create -}} kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: @@ -32,7 +21,7 @@ metadata: {{- include "jupyterhub.labels" . | nindent 4 }} subjects: - kind: ServiceAccount - name: {{ include "jupyterhub.hub.fullname" . }} + name: {{ include "jupyterhub.hub-serviceaccount.fullname" . }} namespace: "{{ .Release.Namespace }}" roleRef: kind: Role diff --git a/jupyterhub/templates/hub/rollout.yaml b/jupyterhub/templates/hub/rollout.yaml index 826e5aeedb..07d42345aa 100644 --- a/jupyterhub/templates/hub/rollout.yaml +++ b/jupyterhub/templates/hub/rollout.yaml @@ -5,6 +5,9 @@ metadata: labels: {{- include "jupyterhub.labels" . | nindent 4 }} spec: + {{- if typeIs "int" .Values.hub.revisionHistoryLimit }} + revisionHistoryLimit: {{ .Values.hub.revisionHistoryLimit }} + {{- end }} replicas: 1 selector: matchLabels: @@ -14,7 +17,7 @@ spec: blueGreen: previewService: {{ include "jupyterhub.hub.fullname" . }}-preview activeService: {{ include "jupyterhub.hub.fullname" . }} - autoPromotionEnabled: false + autoPromotionEnabled: {{ .Values.hub.rollout.autoPromotionEnabled }} template: metadata: labels: @@ -40,7 +43,10 @@ spec: {{- if .Values.scheduling.podPriority.enabled }} priorityClassName: {{ include "jupyterhub.priority.fullname" . }} {{- end }} - nodeSelector: {{ toJson .Values.hub.nodeSelector }} + {{- with .Values.hub.nodeSelector }} + nodeSelector: + {{- . | toYaml | nindent 8 }} + {{- end }} {{- with concat .Values.scheduling.corePods.tolerations .Values.hub.tolerations }} tolerations: {{- . | toYaml | nindent 8 }} @@ -79,11 +85,13 @@ spec: persistentVolumeClaim: claimName: {{ include "jupyterhub.hub-pvc.fullname" . }} {{- end }} - {{- if .Values.rbac.enabled }} - serviceAccountName: {{ include "jupyterhub.hub.fullname" . }} + {{- with include "jupyterhub.hub-serviceaccount.fullname" . }} + serviceAccountName: {{ . }} {{- end }} + {{- with .Values.hub.podSecurityContext }} securityContext: - fsGroup: {{ .Values.hub.fsGid }} + {{- . | toYaml | nindent 8 }} + {{- end }} {{- with include "jupyterhub.imagePullSecrets" (dict "root" . "image" .Values.hub.image) }} imagePullSecrets: {{ . }} {{- end }} diff --git a/jupyterhub/templates/hub/secret.yaml b/jupyterhub/templates/hub/secret.yaml index 5e5885f834..b169be6eb8 100644 --- a/jupyterhub/templates/hub/secret.yaml +++ b/jupyterhub/templates/hub/secret.yaml @@ -11,12 +11,16 @@ data: {{- $_ := set $values "Chart" (dict "Name" .Chart.Name "Version" .Chart.Version) }} {{- $_ := set $values "Release" (pick .Release "Name" "Namespace" "Service") }} values.yaml: {{ $values | toYaml | b64enc | quote }} + {{- if .Values.schedulableNotebook.enabled }} {{- $schedulableNotebookToken := (required "Schedulable notebook token must be a 32 byte random string generated with `openssl rand -hex 32`!" .Values.schedulableNotebook.secretToken) | b64enc | quote }} schedulable-notebook.token: {{ $schedulableNotebookToken }} hub.services.schedulable-notebook.apiToken: {{ $schedulableNotebookToken }} + {{- end }} + {{- if .Values.usersExporter.enabled }} {{- $usersExporterToken := (required "Users exporter token must be a 32 byte random string generated with `openssl rand -hex 32`!" .Values.usersExporter.secretToken) | b64enc | quote }} users-exporter.token: {{ $usersExporterToken }} hub.services.users-exporter.apiToken: {{ $usersExporterToken }} + {{- end }} gcs.bucketName: {{ .Values.googleCloudStorage.bucket | b64enc | quote }} googleCloudServiceAccount.json: {{ .Values.googleCloudServiceAccount.json | b64enc | quote }} grafana.apiKey: {{ .Values.grafana.apiKey | b64enc | quote }} diff --git a/jupyterhub/templates/hub/serviceaccount.yaml b/jupyterhub/templates/hub/serviceaccount.yaml new file mode 100644 index 0000000000..06a50692a6 --- /dev/null +++ b/jupyterhub/templates/hub/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.hub.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "jupyterhub.hub-serviceaccount.fullname" . }} + {{- with .Values.hub.serviceAccount.annotations }} + annotations: + {{- . | toYaml | nindent 4 }} + {{- end }} + labels: + {{- include "jupyterhub.labels" . | nindent 4 }} +{{- end }} diff --git a/jupyterhub/templates/image-puller/_helpers-daemonset.tpl b/jupyterhub/templates/image-puller/_helpers-daemonset.tpl index 6de33b85bc..610f8bde92 100644 --- a/jupyterhub/templates/image-puller/_helpers-daemonset.tpl +++ b/jupyterhub/templates/image-puller/_helpers-daemonset.tpl @@ -34,6 +34,9 @@ spec: type: RollingUpdate rollingUpdate: maxUnavailable: 100% + {{- if typeIs "int" .Values.prePuller.revisionHistoryLimit }} + revisionHistoryLimit: {{ .Values.prePuller.revisionHistoryLimit }} + {{- end }} template: metadata: labels: @@ -44,13 +47,17 @@ spec: {{- end }} spec: {{- /* - continuous-image-puller pods are made evictable to save on the k8s pods - per node limit all k8s clusters have. + image-puller pods are made evictable to save on the k8s pods + per node limit all k8s clusters have and have a higher priority + than user-placeholder pods that could block an entire node. */}} - {{- if and (not .hook) .Values.scheduling.podPriority.enabled }} - priorityClassName: {{ include "jupyterhub.user-placeholder-priority.fullname" . }} + {{- if .Values.scheduling.podPriority.enabled }} + priorityClassName: {{ include "jupyterhub.image-puller-priority.fullname" . }} + {{- end }} + {{- with .Values.singleuser.nodeSelector }} + nodeSelector: + {{- . | toYaml | nindent 8 }} {{- end }} - nodeSelector: {{ toJson .Values.singleuser.nodeSelector }} {{- with concat .Values.scheduling.userPods.tolerations .Values.singleuser.extraTolerations .Values.prePuller.extraTolerations }} tolerations: {{- . | toYaml | nindent 8 }} @@ -127,6 +134,7 @@ spec: {{- /* --- Conditionally pull profileList images --- */}} {{- if .Values.prePuller.pullProfileListImages }} {{- range $k, $container := .Values.singleuser.profileList }} + {{- /* profile's kubespawner_override */}} {{- if $container.kubespawner_override }} {{- if $container.kubespawner_override.image }} - name: image-pull-singleuser-profilelist-{{ $k }} @@ -145,6 +153,33 @@ spec: {{- end }} {{- end }} {{- end }} + {{- /* kubespawner_override in profile's profile_options */}} + {{- if $container.profile_options }} + {{- range $option, $option_spec := $container.profile_options }} + {{- if $option_spec.choices }} + {{- range $choice, $choice_spec := $option_spec.choices }} + {{- if $choice_spec.kubespawner_override }} + {{- if $choice_spec.kubespawner_override.image }} + - name: image-pull-profile-{{ $k }}-option-{{ $option }}-{{ $choice }} + image: {{ $choice_spec.kubespawner_override.image }} + command: + - /bin/sh + - -c + - echo "Pulling complete" + {{- with $.Values.prePuller.resources }} + resources: + {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with $.Values.prePuller.containerSecurityContext }} + securityContext: + {{- . | toYaml | nindent 12 }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} {{- end }} {{- end }} diff --git a/jupyterhub/templates/image-puller/job.yaml b/jupyterhub/templates/image-puller/job.yaml index a6a2bf0487..5509f13e50 100644 --- a/jupyterhub/templates/image-puller/job.yaml +++ b/jupyterhub/templates/image-puller/job.yaml @@ -28,16 +28,22 @@ spec: labels: {{- /* Changes here will cause the Job to restart the pods. */}} {{- include "jupyterhub.matchLabels" . | nindent 8 }} + {{- with .Values.prePuller.labels }} + {{- . | toYaml | nindent 8 }} + {{- end }} {{- with .Values.prePuller.annotations }} annotations: {{- . | toYaml | nindent 8 }} {{- end }} spec: restartPolicy: Never - {{- if .Values.rbac.enabled }} - serviceAccountName: {{ include "jupyterhub.hook-image-awaiter.fullname" . }} + {{- with include "jupyterhub.hook-image-awaiter-serviceaccount.fullname" . }} + serviceAccountName: {{ . }} + {{- end }} + {{- with .Values.prePuller.hook.nodeSelector }} + nodeSelector: + {{- . | toYaml | nindent 8 }} {{- end }} - nodeSelector: {{ toJson .Values.prePuller.hook.nodeSelector }} {{- with concat .Values.scheduling.corePods.tolerations .Values.prePuller.hook.tolerations }} tolerations: {{- . | toYaml | nindent 8 }} diff --git a/jupyterhub/templates/image-puller/priorityclass.yaml b/jupyterhub/templates/image-puller/priorityclass.yaml new file mode 100644 index 0000000000..b2dbae0735 --- /dev/null +++ b/jupyterhub/templates/image-puller/priorityclass.yaml @@ -0,0 +1,18 @@ +{{- if .Values.scheduling.podPriority.enabled }} +{{- if or .Values.prePuller.hook.enabled .Values.prePuller.continuous.enabled -}} +apiVersion: scheduling.k8s.io/v1 +kind: PriorityClass +metadata: + name: {{ include "jupyterhub.image-puller-priority.fullname" . }} + annotations: + meta.helm.sh/release-name: "{{ .Release.Name }}" + meta.helm.sh/release-namespace: "{{ .Release.Namespace }}" + labels: + {{- include "jupyterhub.labels" . | nindent 4 }} +value: {{ .Values.scheduling.podPriority.imagePullerPriority }} +globalDefault: false +description: >- + Enables [hook|continuous]-image-puller pods to fit on nodes even though they + are clogged by user-placeholder pods, while not evicting normal user pods. +{{- end }} +{{- end }} diff --git a/jupyterhub/templates/image-puller/rbac.yaml b/jupyterhub/templates/image-puller/rbac.yaml index 572524a836..996a59a4a3 100644 --- a/jupyterhub/templates/image-puller/rbac.yaml +++ b/jupyterhub/templates/image-puller/rbac.yaml @@ -1,29 +1,8 @@ {{- /* Permissions to be used by the hook-image-awaiter job */}} -{{- if .Values.rbac.enabled }} -{{- if (include "jupyterhub.imagePuller.daemonset.hook.install" .) }} -{{- /* -This service account... -*/ -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "jupyterhub.hook-image-awaiter.fullname" . }} - labels: - {{- include "jupyterhub.labels" . | nindent 4 }} - hub.jupyter.org/deletable: "true" - annotations: - "helm.sh/hook": pre-install,pre-upgrade - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded - "helm.sh/hook-weight": "0" - {{- with .Values.prePuller.hook.serviceAccount.annotations }} - {{- . | toYaml | nindent 4 }} - {{- end }} ---- -{{- /* -... will be used by this role... -*/}} +{{- if .Values.rbac.create -}} +{{- if (include "jupyterhub.imagePuller.daemonset.hook.install" .) -}} kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: @@ -56,7 +35,7 @@ metadata: "helm.sh/hook-weight": "0" subjects: - kind: ServiceAccount - name: {{ include "jupyterhub.hook-image-awaiter.fullname" . }} + name: {{ include "jupyterhub.hook-image-awaiter-serviceaccount.fullname" . }} namespace: "{{ .Release.Namespace }}" roleRef: kind: Role diff --git a/jupyterhub/templates/image-puller/serviceaccount.yaml b/jupyterhub/templates/image-puller/serviceaccount.yaml new file mode 100644 index 0000000000..8161101885 --- /dev/null +++ b/jupyterhub/templates/image-puller/serviceaccount.yaml @@ -0,0 +1,21 @@ +{{- /* +ServiceAccount for the pre-puller hook's image-awaiter-job +*/}} +{{- if .Values.prePuller.hook.serviceAccount.create -}} +{{- if (include "jupyterhub.imagePuller.daemonset.hook.install" .) -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "jupyterhub.hook-image-awaiter-serviceaccount.fullname" . }} + labels: + {{- include "jupyterhub.labels" . | nindent 4 }} + hub.jupyter.org/deletable: "true" + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + "helm.sh/hook-weight": "0" + {{- with .Values.prePuller.hook.serviceAccount.annotations }} + {{- . | toYaml | nindent 4 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/jupyterhub/templates/ingress.yaml b/jupyterhub/templates/ingress.yaml index cc4f9ee119..91f96f4bf6 100644 --- a/jupyterhub/templates/ingress.yaml +++ b/jupyterhub/templates/ingress.yaml @@ -1,9 +1,5 @@ {{- if .Values.ingress.enabled -}} -{{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress" }} apiVersion: networking.k8s.io/v1 -{{- else }} -apiVersion: networking.k8s.io/v1beta1 -{{- end }} kind: Ingress metadata: name: {{ include "jupyterhub.ingress.fullname" . }} @@ -14,23 +10,20 @@ metadata: {{- . | toYaml | nindent 4 }} {{- end }} spec: + {{- with .Values.ingress.ingressClassName }} + ingressClassName: "{{ . }}" + {{- end }} rules: {{- range $host := .Values.ingress.hosts | default (list "") }} - http: paths: - path: {{ $.Values.hub.baseUrl | trimSuffix "/" }}/{{ $.Values.ingress.pathSuffix }} - {{- if $.Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress" }} pathType: {{ $.Values.ingress.pathType }} backend: service: name: {{ include "jupyterhub.proxy-public.fullname" $ }} port: name: http - {{- else }} - backend: - serviceName: {{ include "jupyterhub.proxy-public.fullname" $ }} - servicePort: 80 - {{- end }} {{- if $host }} host: {{ $host | quote }} {{- end }} diff --git a/jupyterhub/templates/proxy/autohttps/deployment.yaml b/jupyterhub/templates/proxy/autohttps/deployment.yaml index f6b7a6af97..f76f3efbfa 100644 --- a/jupyterhub/templates/proxy/autohttps/deployment.yaml +++ b/jupyterhub/templates/proxy/autohttps/deployment.yaml @@ -8,6 +8,9 @@ metadata: labels: {{- include "jupyterhub.labels" . | nindent 4 }} spec: + {{- if typeIs "int" .Values.proxy.traefik.revisionHistoryLimit }} + revisionHistoryLimit: {{ .Values.proxy.traefik.revisionHistoryLimit }} + {{- end }} replicas: 1 selector: matchLabels: @@ -27,13 +30,16 @@ spec: # entrypoint of all network traffic. checksum/static-config: {{ include "jupyterhub.traefik.yaml" . | fromYaml | merge .Values.proxy.traefik.extraStaticConfig | toYaml | sha256sum }} spec: - {{- if .Values.rbac.enabled }} - serviceAccountName: {{ include "jupyterhub.autohttps.fullname" . }} + {{- with include "jupyterhub.autohttps-serviceaccount.fullname" . }} + serviceAccountName: {{ . }} {{- end }} {{- if .Values.scheduling.podPriority.enabled }} priorityClassName: {{ include "jupyterhub.priority.fullname" . }} {{- end }} - nodeSelector: {{ toJson .Values.proxy.traefik.nodeSelector }} + {{- with .Values.proxy.traefik.nodeSelector }} + nodeSelector: + {{- . | toYaml | nindent 8 }} + {{- end }} {{- with concat .Values.scheduling.corePods.tolerations .Values.proxy.traefik.tolerations }} tolerations: {{- . | toYaml | nindent 8 }} @@ -76,6 +82,9 @@ spec: securityContext: {{- . | toYaml | nindent 12 }} {{- end }} + {{- with .Values.proxy.traefik.extraInitContainers }} + {{- . | toYaml | nindent 8 }} + {{- end }} containers: - name: traefik image: "{{ .Values.proxy.traefik.image.name }}:{{ .Values.proxy.traefik.image.tag }}" @@ -115,6 +124,10 @@ spec: {{- with .Values.proxy.secretSync.image.pullPolicy }} imagePullPolicy: {{ . }} {{- end }} + {{- with .Values.proxy.secretSync.resources }} + resources: + {{- . | toYaml | nindent 12 }} + {{- end }} args: - watch-save - --label=app={{ include "jupyterhub.appLabel" . }} diff --git a/jupyterhub/templates/proxy/autohttps/netpol.yaml b/jupyterhub/templates/proxy/autohttps/netpol.yaml index 50b7fe2eb5..78270b696d 100644 --- a/jupyterhub/templates/proxy/autohttps/netpol.yaml +++ b/jupyterhub/templates/proxy/autohttps/netpol.yaml @@ -64,23 +64,15 @@ spec: egress: # autohttps --> proxy (http port) - - ports: - - port: 8000 - to: + - to: - podSelector: matchLabels: {{- $_ := merge (dict "componentLabel" "proxy") . }} {{- include "jupyterhub.matchLabels" $_ | nindent 14 }} + ports: + - port: 8000 - # autohttps --> Kubernetes internal DNS - - ports: - - protocol: UDP - port: 53 - - protocol: TCP - port: 53 - - {{- with .Values.proxy.traefik.networkPolicy.egress }} - # autohttps --> depends, but the default is everything - {{- . | toYaml | nindent 4 }} + {{- with (include "jupyterhub.networkPolicy.renderEgressRules" (list . .Values.proxy.traefik.networkPolicy)) }} + {{- . | nindent 4 }} {{- end }} {{- end }} diff --git a/jupyterhub/templates/proxy/autohttps/pdb.yaml b/jupyterhub/templates/proxy/autohttps/pdb.yaml index 57fc181b6c..fe6c692134 100644 --- a/jupyterhub/templates/proxy/autohttps/pdb.yaml +++ b/jupyterhub/templates/proxy/autohttps/pdb.yaml @@ -1,9 +1,5 @@ {{- if .Values.proxy.traefik.pdb.enabled -}} -{{- if .Capabilities.APIVersions.Has "policy/v1" }} apiVersion: policy/v1 -{{- else }} -apiVersion: policy/v1beta1 -{{- end }} kind: PodDisruptionBudget metadata: name: proxy diff --git a/jupyterhub/templates/proxy/autohttps/rbac.yaml b/jupyterhub/templates/proxy/autohttps/rbac.yaml index 9cdb62c962..a0fd41aefa 100644 --- a/jupyterhub/templates/proxy/autohttps/rbac.yaml +++ b/jupyterhub/templates/proxy/autohttps/rbac.yaml @@ -1,6 +1,7 @@ -{{- $HTTPS := (and .Values.proxy.https.hosts .Values.proxy.https.enabled) }} -{{- $autoHTTPS := (and $HTTPS (eq .Values.proxy.https.type "letsencrypt")) }} -{{- if (and $autoHTTPS .Values.rbac.enabled) -}} +{{- $HTTPS := (and .Values.proxy.https.hosts .Values.proxy.https.enabled) -}} +{{- $autoHTTPS := (and $HTTPS (eq .Values.proxy.https.type "letsencrypt")) -}} +{{- if $autoHTTPS -}} +{{- if .Values.rbac.create -}} apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: @@ -24,17 +25,11 @@ metadata: {{- include "jupyterhub.labels" . | nindent 4 }} subjects: - kind: ServiceAccount - name: {{ include "jupyterhub.autohttps.fullname" . }} + name: {{ include "jupyterhub.autohttps-serviceaccount.fullname" . }} apiGroup: roleRef: kind: Role name: {{ include "jupyterhub.autohttps.fullname" . }} apiGroup: rbac.authorization.k8s.io ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "jupyterhub.autohttps.fullname" . }} - labels: - {{- include "jupyterhub.labels" . | nindent 4 }} +{{- end }} {{- end }} diff --git a/jupyterhub/templates/proxy/autohttps/serviceaccount.yaml b/jupyterhub/templates/proxy/autohttps/serviceaccount.yaml new file mode 100644 index 0000000000..5b340bbbcd --- /dev/null +++ b/jupyterhub/templates/proxy/autohttps/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- $HTTPS := (and .Values.proxy.https.hosts .Values.proxy.https.enabled) -}} +{{- $autoHTTPS := (and $HTTPS (eq .Values.proxy.https.type "letsencrypt")) -}} +{{- if $autoHTTPS -}} +{{- if .Values.proxy.traefik.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "jupyterhub.autohttps-serviceaccount.fullname" . }} + labels: + {{- include "jupyterhub.labels" . | nindent 4 }} +{{- end }} +{{- end }} diff --git a/jupyterhub/templates/proxy/deployment.yaml b/jupyterhub/templates/proxy/deployment.yaml index b852729e93..b3596c1ed6 100644 --- a/jupyterhub/templates/proxy/deployment.yaml +++ b/jupyterhub/templates/proxy/deployment.yaml @@ -7,6 +7,9 @@ metadata: labels: {{- include "jupyterhub.labels" . | nindent 4 }} spec: + {{- if typeIs "int" .Values.proxy.chp.revisionHistoryLimit }} + revisionHistoryLimit: {{ .Values.proxy.chp.revisionHistoryLimit }} + {{- end }} replicas: 1 selector: matchLabels: @@ -44,7 +47,10 @@ spec: {{- if .Values.scheduling.podPriority.enabled }} priorityClassName: {{ include "jupyterhub.priority.fullname" . }} {{- end }} - nodeSelector: {{ toJson .Values.proxy.chp.nodeSelector }} + {{- with .Values.proxy.chp.nodeSelector }} + nodeSelector: + {{- . | toYaml | nindent 8 }} + {{- end }} {{- with concat .Values.scheduling.corePods.tolerations .Values.proxy.chp.tolerations }} tolerations: {{- . | toYaml | nindent 8 }} @@ -137,6 +143,8 @@ spec: livenessProbe: initialDelaySeconds: {{ .Values.proxy.chp.livenessProbe.initialDelaySeconds }} periodSeconds: {{ .Values.proxy.chp.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.proxy.chp.livenessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.proxy.chp.livenessProbe.failureThreshold }} httpGet: path: /_chp_healthz {{- if or $manualHTTPS $manualHTTPSwithsecret }} @@ -151,6 +159,8 @@ spec: readinessProbe: initialDelaySeconds: {{ .Values.proxy.chp.readinessProbe.initialDelaySeconds }} periodSeconds: {{ .Values.proxy.chp.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.proxy.chp.readinessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.proxy.chp.readinessProbe.failureThreshold }} httpGet: path: /_chp_healthz {{- if or $manualHTTPS $manualHTTPSwithsecret }} diff --git a/jupyterhub/templates/proxy/netpol.yaml b/jupyterhub/templates/proxy/netpol.yaml index 69e0412271..8b9cc183f9 100644 --- a/jupyterhub/templates/proxy/netpol.yaml +++ b/jupyterhub/templates/proxy/netpol.yaml @@ -89,32 +89,24 @@ spec: egress: # proxy --> hub - - ports: - - port: 8081 - to: + - to: - podSelector: matchLabels: {{- $_ := merge (dict "componentLabel" "hub") . }} {{- include "jupyterhub.matchLabels" $_ | nindent 14 }} + ports: + - port: 8081 # proxy --> singleuser-server - - ports: - - port: 8888 - to: + - to: - podSelector: matchLabels: {{- $_ := merge (dict "componentLabel" "singleuser-server") . }} {{- include "jupyterhub.matchLabels" $_ | nindent 14 }} + ports: + - port: 8888 - # proxy --> Kubernetes internal DNS - - ports: - - protocol: UDP - port: 53 - - protocol: TCP - port: 53 - - {{- with .Values.proxy.chp.networkPolicy.egress }} - # proxy --> depends, but the default is everything - {{- . | toYaml | nindent 4 }} + {{- with (include "jupyterhub.networkPolicy.renderEgressRules" (list . .Values.proxy.chp.networkPolicy)) }} + {{- . | nindent 4 }} {{- end }} {{- end }} diff --git a/jupyterhub/templates/proxy/pdb.yaml b/jupyterhub/templates/proxy/pdb.yaml index c59d53279d..6262f8e4de 100644 --- a/jupyterhub/templates/proxy/pdb.yaml +++ b/jupyterhub/templates/proxy/pdb.yaml @@ -1,9 +1,5 @@ {{- if .Values.proxy.chp.pdb.enabled -}} -{{- if .Capabilities.APIVersions.Has "policy/v1" }} apiVersion: policy/v1 -{{- else }} -apiVersion: policy/v1beta1 -{{- end }} kind: PodDisruptionBudget metadata: name: {{ include "jupyterhub.proxy.fullname" . }} diff --git a/jupyterhub/templates/proxy/service.yaml b/jupyterhub/templates/proxy/service.yaml index bba8df24d1..1a3f6bb531 100644 --- a/jupyterhub/templates/proxy/service.yaml +++ b/jupyterhub/templates/proxy/service.yaml @@ -39,12 +39,15 @@ metadata: {{- end }} spec: selector: + # This service will target the autohttps pod if autohttps is configured, and + # the proxy pod if not. When autohttps is configured, the service proxy-http + # will be around to target the proxy pod directly. {{- if $autoHTTPS }} - component: autohttps + {{- $_ := merge (dict "componentLabel" "autohttps") . -}} + {{- include "jupyterhub.matchLabels" $_ | nindent 4 }} {{- else }} - component: proxy + {{- include "jupyterhub.matchLabels" . | nindent 4 }} {{- end }} - release: {{ .Release.Name }} ports: {{- if $HTTPS }} - name: https diff --git a/jupyterhub/templates/schedulable-notebook/deployment.yaml b/jupyterhub/templates/schedulable-notebook/deployment.yaml index dcf6ff6dd1..1ac1aec661 100644 --- a/jupyterhub/templates/schedulable-notebook/deployment.yaml +++ b/jupyterhub/templates/schedulable-notebook/deployment.yaml @@ -32,6 +32,7 @@ spec: claimName: schedulable-notebook-home securityContext: fsGroup: {{ .Values.hub.fsGid }} + fsGroupChangePolicy: "OnRootMismatch" containers: - command: - jupyterhub-singleuser diff --git a/jupyterhub/templates/scheduling/priorityclass.yaml b/jupyterhub/templates/scheduling/priorityclass.yaml index 3f7d8b84a9..77c84cbffc 100644 --- a/jupyterhub/templates/scheduling/priorityclass.yaml +++ b/jupyterhub/templates/scheduling/priorityclass.yaml @@ -4,22 +4,9 @@ kind: PriorityClass metadata: name: {{ include "jupyterhub.priority.fullname" . }} annotations: - # FIXME: PriorityClasses must be added before the other resources reference - # them, and in the past a workaround was needed to accomplish this: - # to make the resource a Helm hook. - # - # To transition this resource to no longer be a Helm hook resource, - # we explicitly add ownership annotations/labels (in 1.0.0) which - # will allow a future upgrade (in 2.0.0) to remove all hook and - # ownership annotations/labels. - # - helm.sh/hook: pre-install,pre-upgrade - helm.sh/hook-delete-policy: before-hook-creation - helm.sh/hook-weight: "-100" meta.helm.sh/release-name: "{{ .Release.Name }}" meta.helm.sh/release-namespace: "{{ .Release.Namespace }}" labels: - app.kubernetes.io/managed-by: Helm {{- $_ := merge (dict "componentLabel" "default-priority") . }} {{- include "jupyterhub.labels" $_ | nindent 4 }} value: {{ .Values.scheduling.podPriority.defaultPriority }} diff --git a/jupyterhub/templates/scheduling/user-placeholder/pdb.yaml b/jupyterhub/templates/scheduling/user-placeholder/pdb.yaml index 08dcf06389..85e64c968b 100644 --- a/jupyterhub/templates/scheduling/user-placeholder/pdb.yaml +++ b/jupyterhub/templates/scheduling/user-placeholder/pdb.yaml @@ -3,11 +3,7 @@ The cluster autoscaler should be allowed to evict and reschedule these pods if it would help in order to scale down a node. */}} {{- if .Values.scheduling.userPlaceholder.enabled -}} -{{- if .Capabilities.APIVersions.Has "policy/v1" }} apiVersion: policy/v1 -{{- else }} -apiVersion: policy/v1beta1 -{{- end }} kind: PodDisruptionBudget metadata: name: {{ include "jupyterhub.user-placeholder.fullname" . }} diff --git a/jupyterhub/templates/scheduling/user-placeholder/priorityclass.yaml b/jupyterhub/templates/scheduling/user-placeholder/priorityclass.yaml index 4466e339f1..bdedbddadc 100644 --- a/jupyterhub/templates/scheduling/user-placeholder/priorityclass.yaml +++ b/jupyterhub/templates/scheduling/user-placeholder/priorityclass.yaml @@ -5,22 +5,9 @@ kind: PriorityClass metadata: name: {{ include "jupyterhub.user-placeholder-priority.fullname" . }} annotations: - # FIXME: PriorityClasses must be added before the other resources reference - # them, and in the past a workaround was needed to accomplish this: - # to make the resource a Helm hook. - # - # To transition this resource to no longer be a Helm hook resource, - # we explicitly add ownership annotations/labels (in 1.0.0) which - # will allow a future upgrade (in 2.0.0) to remove all hook and - # ownership annotations/labels. - # - helm.sh/hook: pre-install,pre-upgrade - helm.sh/hook-delete-policy: before-hook-creation - helm.sh/hook-weight: "-100" meta.helm.sh/release-name: "{{ .Release.Name }}" meta.helm.sh/release-namespace: "{{ .Release.Namespace }}" labels: - app.kubernetes.io/managed-by: Helm {{- include "jupyterhub.labels" . | nindent 4 }} value: {{ .Values.scheduling.podPriority.userPlaceholderPriority }} globalDefault: false diff --git a/jupyterhub/templates/scheduling/user-placeholder/statefulset.yaml b/jupyterhub/templates/scheduling/user-placeholder/statefulset.yaml index d92bb05c6e..e0f6f5958c 100644 --- a/jupyterhub/templates/scheduling/user-placeholder/statefulset.yaml +++ b/jupyterhub/templates/scheduling/user-placeholder/statefulset.yaml @@ -16,6 +16,9 @@ metadata: {{- include "jupyterhub.labels" . | nindent 4 }} spec: podManagementPolicy: Parallel + {{- if typeIs "int" .Values.scheduling.userPlaceholder.revisionHistoryLimit }} + revisionHistoryLimit: {{ .Values.scheduling.userPlaceholder.revisionHistoryLimit }} + {{- end }} replicas: {{ .Values.scheduling.userPlaceholder.replicas }} selector: matchLabels: @@ -23,9 +26,16 @@ spec: serviceName: {{ include "jupyterhub.user-placeholder.fullname" . }} template: metadata: + {{- with .Values.scheduling.userPlaceholder.annotations }} + annotations: + {{- . | toYaml | nindent 8 }} + {{- end }} labels: {{- /* Changes here will cause the Deployment to restart the pods. */}} {{- include "jupyterhub.matchLabels" . | nindent 8 }} + {{- with .Values.scheduling.userPlaceholder.labels }} + {{- . | toYaml | nindent 8 }} + {{- end }} spec: {{- if .Values.scheduling.podPriority.enabled }} priorityClassName: {{ include "jupyterhub.user-placeholder-priority.fullname" . }} @@ -33,7 +43,10 @@ spec: {{- if .Values.scheduling.userScheduler.enabled }} schedulerName: {{ include "jupyterhub.user-scheduler.fullname" . }} {{- end }} - nodeSelector: {{ toJson .Values.singleuser.nodeSelector }} + {{- with .Values.singleuser.nodeSelector }} + nodeSelector: + {{- . | toYaml | nindent 8 }} + {{- end }} {{- with concat .Values.scheduling.userPods.tolerations .Values.singleuser.extraTolerations }} tolerations: {{- . | toYaml | nindent 8 }} diff --git a/jupyterhub/templates/scheduling/user-scheduler/configmap.yaml b/jupyterhub/templates/scheduling/user-scheduler/configmap.yaml index 60d533967b..0f142b01ff 100644 --- a/jupyterhub/templates/scheduling/user-scheduler/configmap.yaml +++ b/jupyterhub/templates/scheduling/user-scheduler/configmap.yaml @@ -6,16 +6,40 @@ metadata: labels: {{- include "jupyterhub.labels" . | nindent 4 }} data: - # ref: https://kubernetes.io/docs/reference/scheduling/config/ + {{- /* + This is configuration of a k8s official kube-scheduler binary running in the + user-scheduler. + + The config version and kube-scheduler binary version has a fallback for k8s + clusters versioned v1.23 or lower because: + + - v1 / v1beta3 config requires kube-scheduler binary >=1.25 / >=1.23 + - kube-scheduler binary >=1.25 requires storage.k8s.io/v1/CSIStorageCapacity + available first in k8s >=1.24 + + ref: https://kubernetes.io/docs/reference/scheduling/config/ + ref: https://kubernetes.io/docs/reference/config-api/kube-scheduler-config.v1/ + ref: https://kubernetes.io/docs/reference/config-api/kube-scheduler-config.v1beta3/ + */}} config.yaml: | - apiVersion: kubescheduler.config.k8s.io/v1beta1 + {{- if semverCompare ">=1.24.0-0" .Capabilities.KubeVersion.Version }} + apiVersion: kubescheduler.config.k8s.io/v1 + {{- else }} + apiVersion: kubescheduler.config.k8s.io/v1beta3 + {{- end }} kind: KubeSchedulerConfiguration leaderElection: - resourceLock: endpoints + resourceLock: endpointsleases resourceName: {{ include "jupyterhub.user-scheduler-lock.fullname" . }} resourceNamespace: "{{ .Release.Namespace }}" profiles: - schedulerName: {{ include "jupyterhub.user-scheduler.fullname" . }} + {{- with .Values.scheduling.userScheduler.plugins }} plugins: - {{- .Values.scheduling.userScheduler.plugins | toYaml | nindent 10 }} + {{- . | toYaml | nindent 10 }} + {{- end }} + {{- with .Values.scheduling.userScheduler.pluginConfig }} + pluginConfig: + {{- . | toYaml | nindent 10 }} + {{- end }} {{- end }} diff --git a/jupyterhub/templates/scheduling/user-scheduler/deployment.yaml b/jupyterhub/templates/scheduling/user-scheduler/deployment.yaml index e8da8b5991..5baf4f4e8d 100644 --- a/jupyterhub/templates/scheduling/user-scheduler/deployment.yaml +++ b/jupyterhub/templates/scheduling/user-scheduler/deployment.yaml @@ -6,6 +6,9 @@ metadata: labels: {{- include "jupyterhub.labels" . | nindent 4 }} spec: + {{- if typeIs "int" .Values.scheduling.userScheduler.revisionHistoryLimit }} + revisionHistoryLimit: {{ .Values.scheduling.userScheduler.revisionHistoryLimit }} + {{- end }} replicas: {{ .Values.scheduling.userScheduler.replicas }} selector: matchLabels: @@ -14,16 +17,25 @@ spec: metadata: labels: {{- include "jupyterhub.matchLabels" . | nindent 8 }} + {{- with .Values.scheduling.userScheduler.labels }} + {{- . | toYaml | nindent 8 }} + {{- end }} annotations: checksum/config-map: {{ include (print $.Template.BasePath "/scheduling/user-scheduler/configmap.yaml") . | sha256sum }} + {{- with .Values.scheduling.userScheduler.annotations }} + {{- . | toYaml | nindent 8 }} + {{- end }} spec: - {{- if .Values.rbac.enabled }} - serviceAccountName: {{ include "jupyterhub.user-scheduler-deploy.fullname" . }} + {{ with include "jupyterhub.user-scheduler-serviceaccount.fullname" . }} + serviceAccountName: {{ . }} {{- end }} {{- if .Values.scheduling.podPriority.enabled }} priorityClassName: {{ include "jupyterhub.priority.fullname" . }} {{- end }} - nodeSelector: {{ toJson .Values.scheduling.userScheduler.nodeSelector }} + {{- with .Values.scheduling.userScheduler.nodeSelector }} + nodeSelector: + {{- . | toYaml | nindent 8 }} + {{- end }} {{- with concat .Values.scheduling.corePods.tolerations .Values.scheduling.userScheduler.tolerations }} tolerations: {{- . | toYaml | nindent 8 }} @@ -38,19 +50,22 @@ spec: {{- end }} containers: - name: kube-scheduler + {{- if semverCompare ">=1.24.0-0" .Capabilities.KubeVersion.Version }} image: {{ .Values.scheduling.userScheduler.image.name }}:{{ .Values.scheduling.userScheduler.image.tag }} + {{- else }} + # WARNING: The tag of this image is hardcoded, and the + # "scheduling.userScheduler.image.tag" configuration of the + # Helm chart that generated this resource manifest isn't + # respected. If you install the Helm chart in a k8s cluster + # versioned 1.24 or higher, your configuration will be + # respected. + image: {{ .Values.scheduling.userScheduler.image.name }}:v1.23.14 + {{- end }} {{- with .Values.scheduling.userScheduler.image.pullPolicy }} imagePullPolicy: {{ . }} {{- end }} command: - /usr/local/bin/kube-scheduler - # NOTE: --leader-elect-... (new) and --lock-object-... (deprecated) - # flags are silently ignored in favor of whats defined in the - # passed KubeSchedulerConfiguration whenever --config is - # passed. - # - # ref: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-scheduler/ - # # NOTE: --authentication-skip-lookup=true is used to avoid a # seemingly harmless error, if we need to not skip # "authentication lookup" in the future, see the linked issue. @@ -65,12 +80,14 @@ spec: livenessProbe: httpGet: path: /healthz - port: 10251 + scheme: HTTPS + port: 10259 initialDelaySeconds: 15 readinessProbe: httpGet: path: /healthz - port: 10251 + scheme: HTTPS + port: 10259 {{- with .Values.scheduling.userScheduler.resources }} resources: {{- . | toYaml | nindent 12 }} diff --git a/jupyterhub/templates/scheduling/user-scheduler/pdb.yaml b/jupyterhub/templates/scheduling/user-scheduler/pdb.yaml index c7831e2fb1..d12e99b869 100644 --- a/jupyterhub/templates/scheduling/user-scheduler/pdb.yaml +++ b/jupyterhub/templates/scheduling/user-scheduler/pdb.yaml @@ -1,9 +1,5 @@ {{- if and .Values.scheduling.userScheduler.enabled .Values.scheduling.userScheduler.pdb.enabled -}} -{{- if .Capabilities.APIVersions.Has "policy/v1" }} apiVersion: policy/v1 -{{- else }} -apiVersion: policy/v1beta1 -{{- end }} kind: PodDisruptionBudget metadata: name: {{ include "jupyterhub.user-scheduler-deploy.fullname" . }} diff --git a/jupyterhub/templates/scheduling/user-scheduler/rbac.yaml b/jupyterhub/templates/scheduling/user-scheduler/rbac.yaml index 0056f3525c..7e188c742d 100644 --- a/jupyterhub/templates/scheduling/user-scheduler/rbac.yaml +++ b/jupyterhub/templates/scheduling/user-scheduler/rbac.yaml @@ -1,16 +1,5 @@ {{- if .Values.scheduling.userScheduler.enabled -}} -{{- if .Values.rbac.enabled }} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "jupyterhub.user-scheduler-deploy.fullname" . }} - labels: - {{- include "jupyterhub.labels" . | nindent 4 }} - {{- with .Values.scheduling.userScheduler.serviceAccount.annotations }} - annotations: - {{- . | toYaml | nindent 4 }} - {{- end }} ---- +{{- if .Values.rbac.create -}} kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: @@ -19,13 +8,20 @@ metadata: {{- include "jupyterhub.labels" . | nindent 4 }} rules: # Copied from the system:kube-scheduler ClusterRole of the k8s version - # matching the kube-scheduler binary we use. A modification of two resource - # name references from kube-scheduler to user-scheduler-lock was made. + # matching the kube-scheduler binary we use. A modification has been made to + # resourceName fields to remain relevant for how we have named our resources + # in this Helm chart. # - # NOTE: These rules have been unchanged between 1.12 and 1.15, then changed in - # 1.16 and in 1.17, but unchanged in 1.18 and 1.19. + # NOTE: These rules have been: + # - unchanged between 1.12 and 1.15 + # - changed in 1.16 + # - changed in 1.17 + # - unchanged between 1.18 and 1.20 + # - changed in 1.21: get/list/watch permission for namespace, + # csidrivers, csistoragecapacities was added. + # - unchanged between 1.22 and 1.27 # - # ref: https://github.com/kubernetes/kubernetes/blob/v1.19.0/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml#L696-L829 + # ref: https://github.com/kubernetes/kubernetes/blob/v1.27.0/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml#L736-L892 - apiGroups: - "" - events.k8s.io @@ -159,13 +155,37 @@ rules: - get - list - watch + - apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - list + - watch + - apiGroups: + - storage.k8s.io + resources: + - csidrivers + verbs: + - get + - list + - watch + - apiGroups: + - storage.k8s.io + resources: + - csistoragecapacities + verbs: + - get + - list + - watch # Copied from the system:volume-scheduler ClusterRole of the k8s version # matching the kube-scheduler binary we use. # - # NOTE: These rules have not changed between 1.12 and 1.19. + # NOTE: These rules have not changed between 1.12 and 1.27. # - # ref: https://github.com/kubernetes/kubernetes/blob/v1.19.0/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml#L1213-L1240 + # ref: https://github.com/kubernetes/kubernetes/blob/v1.27.0/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml#L1311-L1338 - apiGroups: - "" resources: @@ -203,7 +223,7 @@ metadata: {{- include "jupyterhub.labels" . | nindent 4 }} subjects: - kind: ServiceAccount - name: {{ include "jupyterhub.user-scheduler-deploy.fullname" . }} + name: {{ include "jupyterhub.user-scheduler-serviceaccount.fullname" . }} namespace: "{{ .Release.Namespace }}" roleRef: kind: ClusterRole diff --git a/jupyterhub/templates/scheduling/user-scheduler/serviceaccount.yaml b/jupyterhub/templates/scheduling/user-scheduler/serviceaccount.yaml new file mode 100644 index 0000000000..f84ffc1c81 --- /dev/null +++ b/jupyterhub/templates/scheduling/user-scheduler/serviceaccount.yaml @@ -0,0 +1,14 @@ +{{- if .Values.scheduling.userScheduler.enabled -}} +{{- if .Values.scheduling.userScheduler.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "jupyterhub.user-scheduler-serviceaccount.fullname" . }} + labels: + {{- include "jupyterhub.labels" . | nindent 4 }} + {{- with .Values.scheduling.userScheduler.serviceAccount.annotations }} + annotations: + {{- . | toYaml | nindent 4 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/jupyterhub/templates/singleuser/netpol.yaml b/jupyterhub/templates/singleuser/netpol.yaml index 6f3d44debb..f388b81d3e 100644 --- a/jupyterhub/templates/singleuser/netpol.yaml +++ b/jupyterhub/templates/singleuser/netpol.yaml @@ -62,23 +62,38 @@ spec: egress: # singleuser-server --> hub - - ports: - - port: 8081 - to: + - to: - podSelector: matchLabels: {{- $_ := merge (dict "componentLabel" "hub") . }} {{- include "jupyterhub.matchLabels" $_ | nindent 14 }} + ports: + - port: 8081 - # singleuser-server --> Kubernetes internal DNS - - ports: - - protocol: UDP - port: 53 - - protocol: TCP - port: 53 + # singleuser-server --> proxy + # singleuser-server --> autohttps + # + # While not critical for core functionality, a user or library code may rely + # on communicating with the proxy or autohttps pods via a k8s Service it can + # detected from well known environment variables. + # + - to: + - podSelector: + matchLabels: + {{- $_ := merge (dict "componentLabel" "proxy") . }} + {{- include "jupyterhub.matchLabels" $_ | nindent 14 }} + ports: + - port: 8000 + - to: + - podSelector: + matchLabels: + {{- $_ := merge (dict "componentLabel" "autohttps") . }} + {{- include "jupyterhub.matchLabels" $_ | nindent 14 }} + ports: + - port: 8080 + - port: 8443 - {{- with .Values.singleuser.networkPolicy.egress }} - # singleuser-server --> depends, but the default is everything - {{- . | toYaml | nindent 4 }} + {{- with (include "jupyterhub.networkPolicy.renderEgressRules" (list . .Values.singleuser.networkPolicy)) }} + {{- . | nindent 4 }} {{- end }} {{- end }} diff --git a/jupyterhub/schema.yaml b/jupyterhub/values.schema.yaml similarity index 81% rename from jupyterhub/schema.yaml rename to jupyterhub/values.schema.yaml index 6eca4b6ab3..cccc9b70a9 100644 --- a/jupyterhub/schema.yaml +++ b/jupyterhub/values.schema.yaml @@ -1,17 +1,17 @@ # This schema (a jsonschema in YAML format) is used to generate # values.schema.json which is packaged with the Helm chart for client side -# validation by Helm of values before template rendering. +# validation by helm of values before template rendering. # # This schema is also used by our documentation system to build the # configuration reference section based on the description fields. See -# doc/source/conf.py for that logic! +# docs/source/conf.py for that logic! # # We look to document everything we have default values for in values.yaml, but # we don't look to enforce the perfect validation logic within this file. # # ref: https://json-schema.org/learn/getting-started-step-by-step.html # -$schema": http://json-schema.org/draft-07/schema# +$schema: http://json-schema.org/draft-07/schema# type: object additionalProperties: false required: @@ -26,7 +26,15 @@ required: - debug - rbac - global + - usersExporter + - schedulableNotebook properties: + enabled: + type: [boolean, "null"] + description: | + `enabled` is ignored by the jupyterhub chart itself, but a chart depending + on the jupyterhub chart conditionally can make use this config option as + the condition. fullnameOverride: type: [string, "null"] description: | @@ -111,13 +119,7 @@ properties: ``` If you just want to let all Pods reference an existing secret, use the - `imagePullSecrets` configuration instead. - - To learn the username and password fields to access a gcr.io registry from - a Kubernetes cluster not associated with the same google cloud - credentials, look into [this - guide](http://docs.heptio.com/content/private-registries/pr-gcr.html) and - read the notes about the password. + [`imagePullSecrets`](schema_imagePullSecrets) configuration instead. properties: create: type: boolean @@ -172,9 +174,6 @@ properties: ... } ``` - - Learn more in [this - guide](http://docs.heptio.com/content/private-registries/pr-gcr.html). email: type: [string, "null"] description: | @@ -199,6 +198,22 @@ properties: additionalProperties: false required: [baseUrl] properties: + rollout: + type: object + properties: + autoPromotionEnabled: + type: boolean + description: | + Whether automatic promotion is enabled or not. + revisionHistoryLimit: &revisionHistoryLimit + type: [integer, "null"] + minimum: 0 + description: | + Configures the resource's `spec.revisionHistoryLimit`. This is + available for Deployment, StatefulSet, and DaemonSet resources. + + See the [Kubernetes docs](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#revision-history-limit) + for more info. config: type: object additionalProperties: true @@ -233,6 +248,8 @@ properties: ```python c.JupyterHub.admin_access = true c.JupyterHub.admin_users = ["jovyan1", "jovyan2"] + c.KubeSpawner.k8s_api_request_timeout = 10 + c.GitHubOAuthenticator.allowed_organizations = ["jupyterhub"] ``` Then, you would be able to represent it with this configuration like: @@ -245,6 +262,11 @@ properties: admin_users: - jovyan1 - jovyan2 + KubeSpawner: + k8s_api_request_timeout: 10 + GitHubOAuthenticator: + allowed_organizations: + - jupyterhub ``` ```{admonition} YAML limitations @@ -429,7 +451,7 @@ properties: some custom way. For more details, see the [Kubernetes - documentation](https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#notes). + documentation](https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/). args: type: array description: | @@ -472,7 +494,7 @@ properties: ``` For more details, see the [Kubernetes - documentation](https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#notes). + documentation](https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/). cookieSecret: type: [string, "null"] description: | @@ -575,19 +597,208 @@ properties: enabled: type: boolean description: | - Toggle the creation of the NetworkPolicy resource for this pod. + Toggle the creation of the NetworkPolicy resource targeting this + pod, and by doing so, restricting its communication to only what + is explicitly allowed in the NetworkPolicy. ingress: type: array description: | - Additional ingress rules to add except those that is known to be needed by the respective pods in the Helm chart. + Additional ingress rules to add besides those that are required + for core functionality. egress: type: array description: | - Additional egress rules to add except those that is known to be needed by the respective pods in the Helm chart. + Additional egress rules to add besides those that are required for + core functionality and those added via + [`.egressAllowRules`](schema_hub.networkPolicy.egressAllowRules). + + ```{versionchanged} 2.0.0 + The default value changed from providing one very permissive rule + allowing all egress to providing no rule. The permissive rule is + still provided via + [`.egressAllowRules`](schema_hub.networkPolicy.egressAllowRules) + set to true though. + ``` + + As an example, below is a configuration that disables the more + broadly permissive `.privateIPs` egress allow rule for the hub + pod, and instead provides tightly scoped permissions to access a + specific k8s local service as identified by pod labels. + + ```yaml + hub: + networkPolicy: + egressAllowRules: + privateIPs: false + egress: + - to: + - podSelector: + matchLabels: + app: my-k8s-local-service + ports: + - protocol: TCP + port: 5978 + ``` + egressAllowRules: + type: object + additionalProperties: false + description: | + This is a set of predefined rules that when enabled will be added + to the NetworkPolicy list of egress rules. + + The resulting egress rules will be a composition of: + - rules specific for the respective pod(s) function within the + Helm chart + - rules based on enabled `egressAllowRules` flags + - rules explicitly specified by the user + + ```{note} + Each flag under this configuration will not render into a + dedicated rule in the NetworkPolicy resource, but instead combine + with the other flags to a reduced set of rules to avoid a + performance penalty. + ``` + + ```{versionadded} 2.0.0 + ``` + properties: + cloudMetadataServer: + type: boolean + description: | + Defaults to `false` for singleuser servers, but to `true` for + all other network policies. + + When enabled this rule allows the respective pod(s) to + establish outbound connections to the cloud metadata server. + + Note that the `nonPrivateIPs` rule is allowing all non Private + IP ranges but makes an exception for the cloud metadata + server, leaving this as the definitive configuration to allow + access to the cloud metadata server. + + ```{versionchanged} 3.0.0 + This configuration is not allowed to be configured true at the + same time as + [`singleuser.cloudMetadata.blockWithIptables`](schema_singleuser.cloudMetadata.blockWithIptables) + to avoid an ambiguous configuration. + ``` + dnsPortsCloudMetadataServer: + type: boolean + description: | + Defaults to `true` for all network policies. + + When enabled this rule allows the respective pod(s) to + establish outbound connections to the cloud metadata server + via port 53. + + Relying on this rule for the singleuser config should go hand + in hand with disabling + [`singleuser.cloudMetadata.blockWithIptables`](schema_singleuser.cloudMetadata.blockWithIptables) + to avoid an ambiguous configuration. + + Known situations when this rule can be relevant: + + - In GKE clusters with Cloud DNS that is reached at the + cloud metadata server's non-private IP. + + ```{note} + This chart doesn't know how to identify the DNS server that + pods will rely on due to variations between how k8s clusters + have been setup. Due to that, multiple rules are enabled by + default to ensure DNS connectivity. + ``` + + ```{versionadded} 3.0.0 + ``` + dnsPortsKubeSystemNamespace: + type: boolean + description: | + Defaults to `true` for all network policies. - The default value of this egress is to allow all traffic, except for the `singleuser.networkPolicy.egress`, which is also limiting access to a metadata server that can be exploited. + When enabled this rule allows the respective pod(s) to + establish outbound connections to pods in the kube-system + namespace via port 53. - If you want to restrict egress, you can override this permissive default to be an empty list. + Known situations when this rule can be relevant: + + - GKE, EKS, AKS, and other clusters relying directly on + `kube-dns` or `coredns` pods in the `kube-system` namespace. + + ```{note} + This chart doesn't know how to identify the DNS server that + pods will rely on due to variations between how k8s clusters + have been setup. Due to that, multiple rules are enabled by + default to ensure DNS connectivity. + ``` + + ```{versionadded} 3.0.0 + ``` + dnsPortsPrivateIPs: + type: boolean + description: | + Defaults to `true` for all network policies. + + When enabled this rule allows the respective pod(s) to + establish outbound connections to private IPs via port 53. + + Known situations when this rule can be relevant: + + - GKE clusters relying on a DNS server indirectly via a a node + local DNS cache at an unknown private IP. + + ```{note} + This chart doesn't know how to identify the DNS server that + pods will rely on due to variations between how k8s clusters + have been setup. Due to that, multiple rules are enabled by + default to ensure DNS connectivity. + + ```{warning} + This rule is not expected to work in clusters relying on + Cilium to enforce the NetworkPolicy rules (includes GKE + clusters with Dataplane v2), this is due to a [known + limitation](https://github.com/cilium/cilium/issues/9209). + ``` + nonPrivateIPs: + type: boolean + description: | + Defaults to `true` for all network policies. + + When enabled this rule allows the respective pod(s) to + establish outbound connections to the non-private IP ranges + with the exception of the cloud metadata server. This means + respective pod(s) can establish connections to the internet + but not (say) an unsecured prometheus server running in the + same cluster. + privateIPs: + type: boolean + description: | + Defaults to `false` for singleuser servers, but to `true` for + all other network policies. + + Private IPs refer to the IP ranges `10.0.0.0/8`, + `172.16.0.0/12`, `192.168.0.0/16`. + + When enabled this rule allows the respective pod(s) to + establish outbound connections to the internal k8s cluster. + This means users can access the internet but not (say) an + unsecured prometheus server running in the same cluster. + + Since not all workloads in the k8s cluster may have + NetworkPolicies setup to restrict their incoming connections, + having this set to false can be a good defense against + malicious intent from someone in control of software in these + pods. + + If possible, try to avoid setting this to true as it gives + broad permissions that could be specified more directly via + the [`.egress`](schema_singleuser.networkPolicy.egress). + + ```{warning} + This rule is not expected to work in clusters relying on + Cilium to enforce the NetworkPolicy rules (includes GKE + clusters with Dataplane v2), this is due to a [known + limitation](https://github.com/cilium/cilium/issues/9209). + ``` interNamespaceAccessLabels: enum: [accept, ignore] description: | @@ -824,7 +1035,7 @@ properties: ``` For more information, see the [Kubernetes EnvVar - specification](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvar-v1-core). + specification](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#envvar-v1-core). extraConfig: type: object additionalProperties: true @@ -845,7 +1056,7 @@ properties: - Anything else you can think of! Since this is usually a multi-line string, you want to format it using YAML's - [| operator](https://yaml.org/spec/1.2/spec.html#id2795688). + [| operator](https://yaml.org/spec/1.2.2/#23-scalars). For example: @@ -870,33 +1081,18 @@ properties: extra configuration logic. ``` - uid: - type: [integer, "null"] - minimum: 0 - deprecated: true - description: | - Deprecated since chart version 0.11.0. Use - [`hub.containerSecurityContext`](schema_hub.containerSecurityContext) - instead. - - The UID the hub process should be running as. - - Use this only if you are building your own image & know that a user with this uid - exists inside the hub container! Advanced feature, handle with care! - - Defaults to 1000, which is the uid of the `jovyan` user that is present in the - default hub image. fsGid: type: [integer, "null"] minimum: 0 - description: - The gid the hub process should be using when touching any volumes mounted. - - Use this only if you are building your own image & know that a group with this gid - exists inside the hub container! Advanced feature, handle with care! - - Defaults to 1000, which is the gid of the `jovyan` user that is present in the - default hub image. + # This schema entry is needed to help us print a more helpful error + # message in NOTES.txt if hub.fsGid is set. + # + description: | + ```{note} + Removed in version 2.0.0. Use + [`hub.podSecurityContext`](schema_hub.podSecurityContext) and specify + `fsGroup` instead. + ``` service: type: object additionalProperties: false @@ -931,7 +1127,7 @@ properties: extraPorts: type: array description: | - Extra ports to add to the Hub Service object besides `hub` / `8081`. + Extra ports to add to the Hub Service object besides `hub` / `8081`. This should be an array that includes `name`, `port`, and `targetPort`. See [Multi-port Services](https://kubernetes.io/docs/concepts/services-networking/service/#multi-port-services) for more details. loadBalancerIP: @@ -1021,7 +1217,7 @@ properties: [scheduling.userPods.tolerations](schema_scheduling.userPods.tolerations)). Pass this field an array of - [`Toleration`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#toleration-v1-core) + [`Toleration`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#toleration-v1-core) objects. See the [Kubernetes @@ -1031,7 +1227,7 @@ properties: type: [integer, "null"] description: &jupyterhub-native-config-description | JupyterHub native configuration, see the [JupyterHub - documentation](https://jupyterhub.readthedocs.io/en/stable/api/app.html) + documentation](https://jupyterhub.readthedocs.io/en/stable/reference/api/app.html) for more information. allowNamedServers: type: [boolean, "null"] @@ -1051,20 +1247,30 @@ properties: consecutiveFailureLimit: type: [integer, "null"] description: *jupyterhub-native-config-description + podSecurityContext: &podSecurityContext-spec + additionalProperties: true + description: | + A k8s native specification of the pod's security context, see [the + documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core) + for details. containerSecurityContext: &containerSecurityContext-spec type: object additionalProperties: true description: | A k8s native specification of the container's security context, see [the - documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#securitycontext-v1-core) + documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core) for details. - extraConfigMap: + deploymentStrategy: type: object - additionalProperties: true - deprecated: true - description: | - Deprecated since chart version 0.8. Use [`custom`](schema_custom) - instead. + additionalProperties: false + properties: + rollingUpdate: + type: [string, "null"] + type: + type: [string, "null"] + description: | + JupyterHub does not support running in parallel, due to this we + default to using a deployment strategy of Recreate. extraContainers: &extraContainers-spec type: array description: | @@ -1087,12 +1293,12 @@ properties: const: true then: description: | - This config option is exactly like the k8s native specification of a + This config option is like the k8s native specification of a container probe, except that it also supports an `enabled` boolean flag. See [the k8s - documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#probe-v1-core) + documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#probe-v1-core) for more details. readinessProbe: *probe-spec namedServerLimitPerUser: @@ -1106,13 +1312,13 @@ properties: additionalProperties: true description: | A k8s native specification of resources, see [the - documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#resourcerequirements-v1-core). + documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#resourcerequirements-v1-core). lifecycle: &lifecycle-spec type: object additionalProperties: false description: | A k8s native specification of lifecycle hooks on the container, see [the - documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#lifecycle-v1-core). + documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#lifecycle-v1-core). properties: postStart: type: object @@ -1127,7 +1333,7 @@ properties: This is where you register JupyterHub services. For details on how to configure these services in this Helm chart just keep reading but for details on services themselves instead read [JupyterHub's - documentation](https://jupyterhub.readthedocs.io/en/stable/api/service.html). + documentation](https://jupyterhub.readthedocs.io/en/stable/reference/api/service.html). ```{note} Only a selection of JupyterHub's configuration options that can be @@ -1213,6 +1419,40 @@ properties: An alias for api_token provided for backward compatibility by the JupyterHub Helm chart that will be transformed to api_token. + loadRoles: + type: object + additionalProperties: true + description: | + This is where you should define JupyterHub roles and apply them to + JupyterHub users, groups, and services to grant them additional + permissions as defined in JupyterHub's RBAC system. + + Complement this documentation with [JupyterHub's + documentation](https://jupyterhub.readthedocs.io/en/stable/rbac/roles.html#defining-roles) + about `load_roles`. + + Note that while JupyterHub's native configuration `load_roles` accepts + a list of role objects, this Helm chart only accepts a dictionary where + each key represents the name of a role and the value is the actual + role object. + + ```yaml + hub: + loadRoles: + teacher: + description: Access to users' information and group membership + + # this role provides permissions to... + scopes: [users, groups] + + # this role will be assigned to... + users: [erik] + services: [grading-service] + groups: [teachers] + ``` + + When configuring JupyterHub roles via this Helm chart, the `name` + field can be omitted as it can be implied by the dictionary key. shutdownOnLogout: type: [boolean, "null"] description: *jupyterhub-native-config-description @@ -1223,19 +1463,28 @@ properties: type: object additionalProperties: true description: *jupyterhub-native-config-description - imagePullSecret: &deprecated-imagePullSecret - type: object - additionalProperties: true - deprecated: true - description: | - DEPRECATED: Use [`imagePullSecret`](schema_imagePullSecret) instead. serviceAccount: &serviceAccount type: object + required: [create] additionalProperties: false description: | Configuration for a k8s ServiceAccount dedicated for use by the specific pod which this configuration is nested under. properties: + create: + type: boolean + description: | + Whether or not to create the `ServiceAccount` resource. + name: + type: ["string", "null"] + description: | + This configuration serves multiple purposes: + + - It will be the `serviceAccountName` referenced by related Pods. + - If `create` is set, the created ServiceAccount resource will be named like this. + - If [`rbac.create`](schema_rbac.create) is set, the associated (Cluster)RoleBindings will bind to this name. + + If not explicitly provided, a default name will be used. annotations: type: object additionalProperties: false @@ -1303,6 +1552,7 @@ properties: Configure the configurable-http-proxy (chp) pod managed by jupyterhub to route traffic both to itself and to user pods. properties: + revisionHistoryLimit: *revisionHistoryLimit networkPolicy: *networkPolicy-spec extraCommandLineFlags: type: array @@ -1362,7 +1612,7 @@ properties: ``` For more information, see the [Kubernetes EnvVar - specification](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvar-v1-core). + specification](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#envvar-v1-core). pdb: *pdb-spec nodeSelector: *nodeSelector-spec tolerations: *tolerations-spec @@ -1430,7 +1680,9 @@ properties: type: enum: [ClusterIP, NodePort, LoadBalancer, ExternalName] description: | - Default `LoadBalancer`. See `hub.service.type` for supported values. + Default `LoadBalancer`. + See the [Kubernetes docs](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) + to learn more about service types. labels: type: object additionalProperties: false @@ -1457,7 +1709,7 @@ properties: Object to set NodePorts to expose the service on for http and https. See [the Kubernetes - documentation](https://kubernetes.io/docs/concepts/services-networking/service/#nodeport) + documentation](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport) for more details about NodePorts. properties: http: @@ -1482,7 +1734,7 @@ properties: or the `proxy` pod (chp). See [the Kubernetes - documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#serviceport-v1-core) + documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#serviceport-v1-core) for the structure of the items in this list. loadBalancerIP: type: [string, "null"] @@ -1602,6 +1854,7 @@ properties: description: | Configure the traefik proxy used to terminate TLS when 'autohttps' is enabled properties: + revisionHistoryLimit: *revisionHistoryLimit labels: type: object additionalProperties: false @@ -1612,6 +1865,22 @@ properties: See the [Kubernetes docs](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) to learn more about labels. networkPolicy: *networkPolicy-spec + extraInitContainers: + type: array + description: | + list of extraInitContainers to be run with traefik pod, after the containers set in the chart. See [Kubernetes Docs](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/) + + ```yaml + proxy: + traefik: + extraInitContainers: + - name: init-myservice + image: busybox:1.28 + command: ['sh', '-c', 'command1'] + - name: init-mydb + image: busybox:1.28 + command: ['sh', '-c', 'command2'] + ``` extraEnv: type: [object, array] additionalProperties: true @@ -1648,7 +1917,7 @@ properties: ``` For more information, see the [Kubernetes EnvVar - specification](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvar-v1-core). + specification](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#envvar-v1-core). pdb: *pdb-spec nodeSelector: *nodeSelector-spec tolerations: *tolerations-spec @@ -1746,21 +2015,6 @@ properties: both receive updates from JupyterHub regarding how it should route traffic. Due to this we default to using a deployment strategy of Recreate instead of RollingUpdate. - containerSecurityContext: - type: object - additionalProperties: true - deprecated: true - description: | - Deprecated since chart version 0.11.0. Use - [`proxy.chp.containerSecurityContext`](schema_proxy.chp.containerSecurityContext) - instead. - networkPolicy: - type: object - additionalProperties: true - deprecated: true - description: | - Deprecated since chart version 0.11.0. Use - [`proxy.chp.networkPolicy`](schema_proxy.chp.networkPolicy) instead. secretSync: type: object additionalProperties: false @@ -1777,12 +2031,6 @@ properties: containerSecurityContext: *containerSecurityContext-spec image: *image-spec resources: *resources-spec - pdb: - type: object - additionalProperties: true - deprecated: true - description: | - DEPRECATED: Use [`proxy.chp.pdb`](schema_proxy.chp.pdb) instead. singleuser: type: object @@ -1793,10 +2041,9 @@ properties: networkPolicy: *networkPolicy-spec podNameTemplate: type: [string, "null"] - description: &kubespawner-native-config-description | - KubeSpawner native configuration, see the [KubeSpawner - documentation](https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html) - for more information. + description: | + Passthrough configuration for + [KubeSpawner.pod_name_template](https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html#kubespawner.KubeSpawner.pod_name_template). cpu: type: object additionalProperties: false @@ -1904,7 +2151,7 @@ properties: ``` For more information, see the [Kubernetes EnvVar - specification](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvar-v1-core). + specification](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#envvar-v1-core). nodeSelector: *nodeSelector-spec extraTolerations: *tolerations-spec extraNodeAffinity: @@ -1925,13 +2172,13 @@ properties: type: array description: | Pass this field an array of - [`NodeSelectorTerm`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#nodeselectorterm-v1-core) + [`NodeSelectorTerm`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#nodeselectorterm-v1-core) objects. preferred: type: array description: | Pass this field an array of - [`PreferredSchedulingTerm`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#preferredschedulingterm-v1-core) + [`PreferredSchedulingTerm`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#preferredschedulingterm-v1-core) objects. extraPodAffinity: type: object @@ -1943,13 +2190,13 @@ properties: type: array description: | Pass this field an array of - [`PodAffinityTerm`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#podaffinityterm-v1-core) + [`PodAffinityTerm`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podaffinityterm-v1-core) objects. preferred: type: array description: | Pass this field an array of - [`WeightedPodAffinityTerm`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#weightedpodaffinityterm-v1-core) + [`WeightedPodAffinityTerm`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#weightedpodaffinityterm-v1-core) objects. extraPodAntiAffinity: type: object @@ -1961,17 +2208,18 @@ properties: type: array description: | Pass this field an array of - [`PodAffinityTerm`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#podaffinityterm-v1-core) + [`PodAffinityTerm`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podaffinityterm-v1-core) objects. preferred: type: array description: | Pass this field an array of - [`WeightedPodAffinityTerm`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#weightedpodaffinityterm-v1-core) + [`WeightedPodAffinityTerm`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#weightedpodaffinityterm-v1-core) objects. cloudMetadata: type: object additionalProperties: false + required: [blockWithIptables, ip] description: | Please refer to dedicated section in [the Helm chart documentation](block-metadata-iptables) for more information about @@ -1981,41 +2229,52 @@ properties: type: boolean ip: type: string - enabled: - type: boolean - deprecated: true - description: | - Deprecated since chart version 0.11.0. Use - [`singleuser.cloudMetadata.blockWithIptables`](schema_singleuser.cloudMetadata.blockWithIptables) - instead. cmd: type: [array, string, "null"] - description: *kubespawner-native-config-description + description: | + Passthrough configuration for + [KubeSpawner.cmd](https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html#kubespawner.KubeSpawner.cmd). + The default is "jupyterhub-singleuser". + Use `cmd: null` to launch a custom CMD from the image, + which must launch jupyterhub-singleuser or an equivalent process eventually. + For example: Jupyter's docker-stacks images. defaultUrl: type: [string, "null"] - description: *kubespawner-native-config-description + description: | + Passthrough configuration for + [KubeSpawner.default_url](https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html#kubespawner.KubeSpawner.default_url). # FIXME: name mismatch, named events_enabled in kubespawner events: type: [boolean, "null"] - description: *kubespawner-native-config-description + description: | + Passthrough configuration for + [KubeSpawner.events_enabled](https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html#kubespawner.KubeSpawner.events_enabled). extraAnnotations: type: object additionalProperties: false patternProperties: *labels-and-annotations-patternProperties - description: *kubespawner-native-config-description + description: | + Passthrough configuration for + [KubeSpawner.extra_annotations](https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html#kubespawner.KubeSpawner.extra_annotations). extraContainers: type: array - description: *kubespawner-native-config-description + description: | + Passthrough configuration for + [KubeSpawner.extra_containers](https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html#kubespawner.KubeSpawner.extra_containers). extraLabels: type: object additionalProperties: false patternProperties: *labels-and-annotations-patternProperties - description: *kubespawner-native-config-description + description: | + Passthrough configuration for + [KubeSpawner.extra_labels](https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html#kubespawner.KubeSpawner.extra_labels). extraPodConfig: type: object additionalProperties: true - description: *kubespawner-native-config-description + description: | + Passthrough configuration for + [KubeSpawner.extra_pod_config](https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html#kubespawner.KubeSpawner.extra_pod_config). extraResource: type: object additionalProperties: false @@ -2024,19 +2283,27 @@ properties: guarantees: type: object additionalProperties: true - description: *kubespawner-native-config-description + description: | + Passthrough configuration for + [KubeSpawner.extra_resource_guarantees](https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html#kubespawner.KubeSpawner.extra_resource_guarantees). # FIXME: name mismatch, named extra_resource_limits in kubespawner limits: type: object additionalProperties: true - description: *kubespawner-native-config-description + description: | + Passthrough configuration for + [KubeSpawner.extra_resource_limits](https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html#kubespawner.KubeSpawner.extra_resource_limits). fsGid: type: [integer, "null"] - description: *kubespawner-native-config-description + description: | + Passthrough configuration for + [KubeSpawner.fs_gid](https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html#kubespawner.KubeSpawner.fs_gid). lifecycleHooks: type: object additionalProperties: false - description: *kubespawner-native-config-description + description: | + Passthrough configuration for + [KubeSpawner.lifecycle_hooks](https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html#kubespawner.KubeSpawner.lifecycle_hooks). properties: postStart: type: object @@ -2057,13 +2324,18 @@ properties: is set to true. properties: image: *image-spec + resources: *resources-spec # FIXME: name mismatch, named service_account in kubespawner serviceAccountName: type: [string, "null"] - description: *kubespawner-native-config-description + description: | + Passthrough configuration for + [KubeSpawner.service_account](https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html#kubespawner.KubeSpawner.service_account). startTimeout: type: [integer, "null"] - description: *kubespawner-native-config-description + description: | + Passthrough configuration for + [KubeSpawner.start_timeout](https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html#kubespawner.KubeSpawner.start_timeout). storage: type: object additionalProperties: false @@ -2153,16 +2425,25 @@ properties: Decide if you want storage to be provisioned dynamically (dynamic), or if you want to attach existing storage (static), or don't want any storage to be attached (none). + allowPrivilegeEscalation: + type: [boolean, "null"] + description: | + Passthrough configuration for + [KubeSpawner.allow_privilege_escalation](https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html#kubespawner.KubeSpawner.allow_privilege_escalation). uid: type: [integer, "null"] description: | + Passthrough configuration for + [KubeSpawner.uid](https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html#kubespawner.KubeSpawner.uid). + This dictates as what user the main container will start up as. As an example of when this is needed, consider if you want to enable sudo rights for some of your users. This can be done by starting up as root, enabling it from the container in a startup script, and then transitioning to the normal user. - imagePullSecret: *deprecated-imagePullSecret + + Default is 1000, set to null to use the container's default. scheduling: type: object @@ -2174,7 +2455,7 @@ properties: userScheduler: type: object additionalProperties: false - required: [enabled, plugins, logLevel] + required: [enabled, plugins, pluginConfig, logLevel] description: | The user scheduler is making sure that user pods are scheduled tight on nodes, this is useful for autoscaling of user node pools. @@ -2183,6 +2464,7 @@ properties: type: boolean description: | Enables the user scheduler. + revisionHistoryLimit: *revisionHistoryLimit replicas: type: integer description: | @@ -2192,6 +2474,21 @@ properties: pdb: *pdb-spec nodeSelector: *nodeSelector-spec tolerations: *tolerations-spec + labels: + type: object + additionalProperties: false + patternProperties: *labels-and-annotations-patternProperties + description: | + Extra labels to add to the userScheduler pods. + + See the [Kubernetes docs](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) + to learn more about labels. + annotations: + type: object + additionalProperties: false + patternProperties: *labels-and-annotations-patternProperties + description: | + Extra annotations to add to the user-scheduler pods. containerSecurityContext: *containerSecurityContext-spec logLevel: type: integer @@ -2200,7 +2497,7 @@ properties: kube-scheduler binary running within the user-scheduler pod. plugins: type: object - additionalProperties: false + additionalProperties: true description: | These plugins refers to kube-scheduler plugins as documented [here](https://kubernetes.io/docs/reference/scheduling/config/). @@ -2208,29 +2505,10 @@ properties: The user-scheduler is really just a kube-scheduler configured in a way to pack users tight on nodes using these plugins. See values.yaml for information about the default plugins. - properties: - score: - type: object - additionalProperties: false - properties: - disabled: - type: array - items: - type: object - additionalProperties: false - properties: - name: - type: string - enabled: - type: array - items: - type: object - additionalProperties: false - properties: - name: - type: string - weight: - type: integer + pluginConfig: + type: array + description: | + Individually activated plugins can be configured further. resources: *resources-spec serviceAccount: *serviceAccount extraPodSpec: *extraPodSpec-spec @@ -2238,16 +2516,22 @@ properties: type: object additionalProperties: false description: | - Pod Priority is used to allow real users evict placeholder pods that - in turn triggers a scale up by a cluster autoscaler. So, enabling this - option will only make sense if the following conditions are met: + Pod Priority is used to allow real users evict user placeholder pods + that in turn by entering a Pending state can trigger a scale up by a + cluster autoscaler. - 1. Your Kubernetes cluster has at least version 1.11 - 2. A cluster autoscaler is installed - 3. user-placeholer pods is configured to get a priority equal or - higher than the cluster autoscaler's priority cutoff - 4. Normal user pods have a higher priority than the user-placeholder - pods + Having this option enabled only make sense if the following conditions + are met: + + 1. A cluster autoscaler is installed. + 2. user-placeholer pods are configured to have a priority equal or + higher than the cluster autoscaler's "priority cutoff" so that the + cluster autoscaler scales up a node in advance for a pending user + placeholder pod. + 3. Normal user pods have a higher priority than the user-placeholder + pods. + 4. Image puller pods have a priority between normal user pods and + user-placeholder pods. Note that if the default priority cutoff if not configured on cluster autoscaler, it will currently default to 0, and that in the future @@ -2263,6 +2547,7 @@ properties: enabled: true globalDefault: false defaultPriority: 0 + imagePullerPriority: -5 userPlaceholderPriority: -10 ``` @@ -2273,6 +2558,7 @@ properties: enabled: true globalDefault: true defaultPriority: 10 + imagePullerPriority: 5 userPlaceholderPriority: 0 ``` properties: @@ -2291,6 +2577,10 @@ properties: type: integer description: | The actual value for the default pod priority. + imagePullerPriority: + type: integer + description: | + The actual value for the [hook|continuous]-image-puller pods' priority. userPlaceholderPriority: type: integer description: | @@ -2316,10 +2606,26 @@ properties: enabled: type: boolean image: *image-spec + revisionHistoryLimit: *revisionHistoryLimit replicas: type: integer description: | How many placeholder pods would you like to have? + labels: + type: object + additionalProperties: false + patternProperties: *labels-and-annotations-patternProperties + description: | + Extra labels to add to the userPlaceholder pods. + + See the [Kubernetes docs](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) + to learn more about labels. + annotations: + type: object + additionalProperties: false + patternProperties: *labels-and-annotations-patternProperties + description: | + Extra annotations to add to the placeholder pods. resources: type: object additionalProperties: true @@ -2424,6 +2730,10 @@ properties: usersExporter: type: object properties: + enabled: + type: boolean + description: | + Whether usersExporter is enabled or not. secretToken: type: [string, "null"] description: | @@ -2469,6 +2779,10 @@ properties: schedulableNotebook: type: object properties: + enabled: + type: boolean + description: | + Whether schedulableNotebook is enabled or not. secretToken: type: [string, "null"] description: | @@ -2581,6 +2895,14 @@ properties: See [the Kubernetes documentation](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) for more details about annotations. + ingressClassName: + type: [string, "null"] + description: | + Maps directly to the Ingress resource's `spec.ingressClassName``. + + See [the Kubernetes + documentation](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class) + for more details. hosts: type: array description: | @@ -2594,9 +2916,9 @@ properties: pathType: enum: [Prefix, Exact, ImplementationSpecific] description: | - The path type to use. The default value is 'Prefix'. Only applies on Kubernetes v1.18+. + The path type to use. The default value is 'Prefix'. - See [the Kubernetes documentation](https://kubernetes.io/docs/concepts/services-networking/ingress/#path-types) + See [the Kubernetes documentation](https://kubernetes.io/docs/concepts/services-networking/ingress/#path-types) for more details about path types. tls: type: array @@ -2612,6 +2934,16 @@ properties: additionalProperties: false required: [hook, continuous] properties: + revisionHistoryLimit: *revisionHistoryLimit + labels: + type: object + additionalProperties: false + patternProperties: *labels-and-annotations-patternProperties + description: | + Extra labels to add to the pre puller job pods. + + See the [Kubernetes docs](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) + to learn more about labels. annotations: type: object additionalProperties: false @@ -2690,9 +3022,12 @@ properties: pullProfileListImages: type: boolean description: | - The singleuser.profileList configuration can let the user choose an - image through the selection of a profile. This option determines if - those images will be pulled, both by the hook and continuous pullers. + The singleuser.profileList configuration can provide a selection of + images. This option determines if all images identified there should + be pulled, both by the hook and continuous pullers. + + Images are looked for under `kubespawner_override`, and also + `profile_options.choices.kubespawner_override` since version 3.2.0. The reason to disable this, is that if you have for example 10 images which start pulling in order from 1 to 10, a user that arrives and @@ -2709,7 +3044,7 @@ properties: ```yaml prePuller: extraImages: - myExtraImageIWantPulled: + my-extra-image-i-want-pulled: name: jupyter/all-spark-notebook tag: 2343e33dec46 ``` @@ -2769,6 +3104,9 @@ properties: users: type: [boolean, "null"] description: See the `--cull-users` flag. + adminUsers: + type: [boolean, "null"] + description: See the `--cull-admin-users` flag. removeNamedServers: type: [boolean, "null"] description: See the `--remove-named-servers` flag. @@ -2798,13 +3136,43 @@ properties: rbac: type: object additionalProperties: false - required: [enabled] + required: [create] properties: enabled: type: boolean + # This schema entry is needed to help us print a more helpful error + # message in NOTES.txt if hub.fsGid is set. + # description: | - Decides if RBAC resources are to be created and referenced by the the - Helm chart's workloads. + ````{note} + Removed in version 2.0.0. If you have been using `rbac.enable=false` + (strongly discouraged), then the equivalent configuration would be: + + ```yaml + rbac: + create: false + hub: + serviceAccount: + create: false + proxy: + traefik: + serviceAccount: + create: false + scheduling: + userScheduler: + serviceAccount: + create: false + prePuller: + hook: + serviceAccount: + create: false + ``` + ```` + create: + type: boolean + description: | + Decides if (Cluster)Role and (Cluster)RoleBinding resources are + created and bound to the configured serviceAccounts. global: type: object @@ -2816,10 +3184,3 @@ properties: A flag that should only be set to true temporarily when experiencing a deprecation message that contain censored content that you wish to reveal. - - auth: - type: object - additionalProperties: true - deprecated: true - description: | - DEPRECATED: The Authenticator should be configured using [`hub.config`](schema_hub.config) instead. diff --git a/jupyterhub/values.yaml b/jupyterhub/values.yaml index e724f5eea9..c6da74b25c 100644 --- a/jupyterhub/values.yaml +++ b/jupyterhub/values.yaml @@ -3,6 +3,11 @@ fullnameOverride: "" nameOverride: +# enabled is ignored by the jupyterhub chart itself, but a chart depending on +# the jupyterhub chart conditionally can make use this config option as the +# condition. +enabled: + # custom can contain anything you want to pass to the hub pod, as all passed # Helm template values will be made available there. custom: {} @@ -26,6 +31,9 @@ imagePullSecrets: [] # ConfigurableHTTPProxy speaks with the actual ConfigurableHTTPProxy server in # the proxy pod. hub: + revisionHistoryLimit: + rollout: + autoPromotionEnabled: true config: JupyterHub: admin_access: true @@ -40,7 +48,6 @@ hub: baseUrl: / cookieSecret: initContainers: [] - fsGid: 1000 nodeSelector: {} tolerations: [] concurrentSpawnLimit: 64 @@ -70,16 +77,19 @@ hub: extraVolumes: [] extraVolumeMounts: [] image: - name: jupyterhub/k8s-hub + name: gcr.io/nii-ap-ops/k8s-hub tag: "set-by-chartpress" pullPolicy: pullSecrets: [] resources: {} + podSecurityContext: + fsGroup: 1000 containerSecurityContext: runAsUser: 1000 runAsGroup: 1000 allowPrivilegeEscalation: false lifecycle: {} + loadRoles: {} services: {} pdb: enabled: false @@ -88,16 +98,14 @@ hub: networkPolicy: enabled: true ingress: [] - ## egress for JupyterHub already includes Kubernetes internal DNS and - ## access to the proxy, but can be restricted further, but ensure to allow - ## access to the Kubernetes API server that couldn't be pinned ahead of - ## time. - ## - ## ref: https://stackoverflow.com/a/59016417/2220152 - egress: - - to: - - ipBlock: - cidr: 0.0.0.0/0 + egress: [] + egressAllowRules: + cloudMetadataServer: true + dnsPortsCloudMetadataServer: true + dnsPortsKubeSystemNamespace: true + dnsPortsPrivateIPs: true + nonPrivateIPs: true + privateIPs: true interNamespaceAccessLabels: ignore allowedIngressPorts: [] allowNamedServers: false @@ -127,11 +135,13 @@ hub: timeoutSeconds: 1 existingSecret: serviceAccount: + create: true + name: annotations: {} extraPodSpec: {} rbac: - enabled: true + create: true grafana: apiKey: "" @@ -224,13 +234,17 @@ proxy: # chp relates to the proxy pod, which is responsible for routing traffic based # on dynamic configuration sent from JupyterHub to CHP's REST API. chp: + revisionHistoryLimit: containerSecurityContext: runAsUser: 65534 # nobody user runAsGroup: 65534 # nobody group allowPrivilegeEscalation: false image: - name: jupyterhub/configurable-http-proxy - tag: 4.5.0 # https://github.com/jupyterhub/configurable-http-proxy/releases + name: quay.io/jupyterhub/configurable-http-proxy + # tag is automatically bumped to new patch versions by the + # watch-dependencies.yaml workflow. + # + tag: "4.6.1" # https://github.com/jupyterhub/configurable-http-proxy/tags pullPolicy: pullSecrets: [] extraCommandLineFlags: [] @@ -238,11 +252,14 @@ proxy: enabled: true initialDelaySeconds: 60 periodSeconds: 10 + failureThreshold: 30 + timeoutSeconds: 3 readinessProbe: enabled: true initialDelaySeconds: 0 periodSeconds: 2 failureThreshold: 1000 + timeoutSeconds: 1 resources: {} defaultTarget: errorTarget: @@ -252,10 +269,14 @@ proxy: networkPolicy: enabled: true ingress: [] - egress: - - to: - - ipBlock: - cidr: 0.0.0.0/0 + egress: [] + egressAllowRules: + cloudMetadataServer: true + dnsPortsCloudMetadataServer: true + dnsPortsKubeSystemNamespace: true + dnsPortsPrivateIPs: true + nonPrivateIPs: true + privateIPs: true interNamespaceAccessLabels: ignore allowedIngressPorts: [http, https] pdb: @@ -266,13 +287,17 @@ proxy: # traefik relates to the autohttps pod, which is responsible for TLS # termination when proxy.https.type=letsencrypt. traefik: + revisionHistoryLimit: containerSecurityContext: runAsUser: 65534 # nobody user runAsGroup: 65534 # nobody group allowPrivilegeEscalation: false image: name: traefik - tag: v2.4.11 # ref: https://hub.docker.com/_/traefik?tab=tags + # tag is automatically bumped to new patch versions by the + # watch-dependencies.yaml workflow. + # + tag: "v2.10.5" # ref: https://hub.docker.com/_/traefik?tab=tags pullPolicy: pullSecrets: [] hsts: @@ -281,6 +306,7 @@ proxy: maxAge: 15724800 # About 6 months resources: {} labels: {} + extraInitContainers: [] extraEnv: {} extraVolumes: [] extraVolumeMounts: [] @@ -292,10 +318,14 @@ proxy: networkPolicy: enabled: true ingress: [] - egress: - - to: - - ipBlock: - cidr: 0.0.0.0/0 + egress: [] + egressAllowRules: + cloudMetadataServer: true + dnsPortsCloudMetadataServer: true + dnsPortsKubeSystemNamespace: true + dnsPortsPrivateIPs: true + nonPrivateIPs: true + privateIPs: true interNamespaceAccessLabels: ignore allowedIngressPorts: [http, https] pdb: @@ -303,6 +333,8 @@ proxy: maxUnavailable: minAvailable: 1 serviceAccount: + create: true + name: annotations: {} extraPodSpec: {} secretSync: @@ -311,7 +343,7 @@ proxy: runAsGroup: 65534 # nobody group allowPrivilegeEscalation: false image: - name: jupyterhub/k8s-secret-sync + name: gcr.io/nii-ap-ops/k8s-secret-sync tag: "set-by-chartpress" pullPolicy: pullSecrets: [] @@ -351,10 +383,11 @@ singleuser: preferred: [] networkTools: image: - name: jupyterhub/k8s-network-tools + name: gcr.io/nii-ap-ops/k8s-network-tools tag: "set-by-chartpress" pullPolicy: pullSecrets: [] + resources: {} cloudMetadata: # block set to true will append a privileged initContainer using the # iptables to block the sensitive metadata server at the provided ip. @@ -363,18 +396,14 @@ singleuser: networkPolicy: enabled: true ingress: [] - egress: - # Required egress to communicate with the hub and DNS servers will be - # augmented to these egress rules. - # - # This default rule explicitly allows all outbound traffic from singleuser - # pods, except to a typical IP used to return metadata that can be used by - # someone with malicious intent. - - to: - - ipBlock: - cidr: 0.0.0.0/0 - except: - - 169.254.169.254/32 + egress: [] + egressAllowRules: + cloudMetadataServer: false + dnsPortsCloudMetadataServer: true + dnsPortsKubeSystemNamespace: true + dnsPortsPrivateIPs: true + nonPrivateIPs: true + privateIPs: false interNamespaceAccessLabels: ignore allowedIngressPorts: [] events: true @@ -386,6 +415,7 @@ singleuser: lifecycleHooks: {} initContainers: [] extraContainers: [] + allowPrivilegeEscalation: false uid: 1000 fsGid: 100 serviceAccountName: @@ -405,7 +435,7 @@ singleuser: volumeNameTemplate: volume-{username}{servername} storageAccessModes: [ReadWriteOnce] image: - name: jupyterhub/k8s-singleuser-sample + name: gcr.io/nii-ap-ops/k8s-singleuser-sample tag: "set-by-chartpress" pullPolicy: pullSecrets: [] @@ -428,34 +458,66 @@ singleuser: scheduling: userScheduler: enabled: true + revisionHistoryLimit: replicas: 2 logLevel: 4 + # plugins are configured on the user-scheduler to make us score how we + # schedule user pods in a way to help us schedule on the most busy node. By + # doing this, we help scale down more effectively. It isn't obvious how to + # enable/disable scoring plugins, and configure them, to accomplish this. + # # plugins ref: https://kubernetes.io/docs/reference/scheduling/config/#scheduling-plugins-1 + # migration ref: https://kubernetes.io/docs/reference/scheduling/config/#scheduler-configuration-migrations + # plugins: score: + # These scoring plugins are enabled by default according to + # https://kubernetes.io/docs/reference/scheduling/config/#scheduling-plugins + # 2022-02-22. + # + # Enabled with high priority: + # - NodeAffinity + # - InterPodAffinity + # - NodeResourcesFit + # - ImageLocality + # Remains enabled with low default priority: + # - TaintToleration + # - PodTopologySpread + # - VolumeBinding + # Disabled for scoring: + # - NodeResourcesBalancedAllocation + # disabled: - - name: SelectorSpread - - name: TaintToleration - - name: PodTopologySpread + # We disable these plugins (with regards to scoring) to not interfere + # or complicate our use of NodeResourcesFit. - name: NodeResourcesBalancedAllocation - - name: NodeResourcesLeastAllocated # Disable plugins to be allowed to enable them again with a different # weight and avoid an error. - - name: NodePreferAvoidPods - name: NodeAffinity - name: InterPodAffinity + - name: NodeResourcesFit - name: ImageLocality enabled: - - name: NodePreferAvoidPods - weight: 161051 - name: NodeAffinity weight: 14631 - name: InterPodAffinity weight: 1331 - - name: NodeResourcesMostAllocated + - name: NodeResourcesFit weight: 121 - name: ImageLocality weight: 11 + pluginConfig: + # Here we declare that we should optimize pods to fit based on a + # MostAllocated strategy instead of the default LeastAllocated. + - name: NodeResourcesFit + args: + scoringStrategy: + resources: + - name: cpu + weight: 1 + - name: memory + weight: 1 + type: MostAllocated containerSecurityContext: runAsUser: 65534 # nobody user runAsGroup: 65534 # nobody group @@ -463,38 +525,78 @@ scheduling: image: # IMPORTANT: Bumping the minor version of this binary should go hand in # hand with an inspection of the user-scheduelrs RBAC resources - # that we have forked. - name: k8s.gcr.io/kube-scheduler - tag: v1.19.13 # ref: https://github.com/kubernetes/website/blob/main/content/en/releases/patch-releases.md + # that we have forked in + # templates/scheduling/user-scheduler/rbac.yaml. + # + # Debugging advice: + # + # - Is configuration of kube-scheduler broken in + # templates/scheduling/user-scheduler/configmap.yaml? + # + # - Is the kube-scheduler binary's compatibility to work + # against a k8s api-server that is too new or too old? + # + # - You can update the GitHub workflow that runs tests to + # include "deploy/user-scheduler" in the k8s namespace report + # and reduce the user-scheduler deployments replicas to 1 in + # dev-config.yaml to get relevant logs from the user-scheduler + # pods. Inspect the "Kubernetes namespace report" action! + # + # - Typical failures are that kube-scheduler fails to search for + # resources via its "informers", and won't start trying to + # schedule pods before they succeed which may require + # additional RBAC permissions or that the k8s api-server is + # aware of the resources. + # + # - If "successfully acquired lease" can be seen in the logs, it + # is a good sign kube-scheduler is ready to schedule pods. + # + name: registry.k8s.io/kube-scheduler + # tag is automatically bumped to new patch versions by the + # watch-dependencies.yaml workflow. The minor version is pinned in the + # workflow, and should be updated there if a minor version bump is done + # here. We aim to stay around 1 minor version behind the latest k8s + # version. + # + tag: "v1.26.11" # ref: https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG pullPolicy: pullSecrets: [] nodeSelector: {} tolerations: [] + labels: {} + annotations: {} pdb: enabled: true maxUnavailable: 1 minAvailable: resources: {} serviceAccount: + create: true + name: annotations: {} extraPodSpec: {} podPriority: enabled: false globalDefault: false defaultPriority: 0 + imagePullerPriority: -5 userPlaceholderPriority: -10 userPlaceholder: enabled: true image: - name: k8s.gcr.io/pause - # tag's can be updated by inspecting the output of the command: - # gcloud container images list-tags k8s.gcr.io/pause --sort-by=~tags + name: registry.k8s.io/pause + # tag is automatically bumped to new patch versions by the + # watch-dependencies.yaml workflow. # # If you update this, also update prePuller.pause.image.tag - tag: "3.5" + # + tag: "3.9" pullPolicy: pullSecrets: [] + revisionHistoryLimit: replicas: 0 + labels: {} + annotations: {} containerSecurityContext: runAsUser: 65534 # nobody user runAsGroup: 65534 # nobody group @@ -527,6 +629,8 @@ scheduling: # prePuller relates to the hook|continuous-image-puller DaemonsSets prePuller: + revisionHistoryLimit: + labels: {} annotations: {} resources: {} containerSecurityContext: @@ -540,7 +644,7 @@ prePuller: pullOnlyOnChanges: true # image and the configuration below relates to the hook-image-awaiter Job image: - name: jupyterhub/k8s-image-awaiter + name: gcr.io/nii-ap-ops/k8s-image-awaiter tag: "set-by-chartpress" pullPolicy: pullSecrets: [] @@ -553,6 +657,8 @@ prePuller: tolerations: [] resources: {} serviceAccount: + create: true + name: annotations: {} continuous: enabled: true @@ -564,18 +670,20 @@ prePuller: runAsGroup: 65534 # nobody group allowPrivilegeEscalation: false image: - name: k8s.gcr.io/pause - # tag's can be updated by inspecting the output of the command: - # gcloud container images list-tags k8s.gcr.io/pause --sort-by=~tags + name: registry.k8s.io/pause + # tag is automatically bumped to new patch versions by the + # watch-dependencies.yaml workflow. # # If you update this, also update scheduling.userPlaceholder.image.tag - tag: "3.5" + # + tag: "3.9" pullPolicy: pullSecrets: [] ingress: enabled: false annotations: {} + ingressClassName: hosts: [] pathSuffix: pathType: Prefix @@ -591,6 +699,7 @@ ingress: cull: enabled: true users: false # --cull-users + adminUsers: true # --cull-admin-users removeNamedServers: false # --remove-named-servers timeout: 3600 # --timeout every: 600 # --cull-every diff --git a/tbump.toml b/tbump.toml new file mode 100644 index 0000000000..560f5d28af --- /dev/null +++ b/tbump.toml @@ -0,0 +1,40 @@ +# tbump is a tool to update version fields that we use +# to update baseVersion in chartpress.yaml as documented +# in RELEASE.md +# +# Config reference: https://github.com/your-tools/tbump#readme +# +[version] +current = "3.2.1" + +# match our prerelease prefixes +# -alpha.1 +# -beta.2 +# -0.dev + +regex = ''' + (?P\d+) + \. + (?P\d+) + \. + (?P\d+) + (\- + (?P + ( + (alpha|beta|rc)\.\d+| + 0\.dev + ) + ) + )? + ''' + +[git] +message_template = "Bump to {new_version}" +tag_template = "{new_version}" + +# For each file to patch, add a [[file]] config +# section containing the path of the file, relative to the +# tbump.toml location. +[[file]] +src = "chartpress.yaml" +search = 'baseVersion: "{current_version}"' diff --git a/tests/conftest.py b/tests/conftest.py index c9d4fb8778..e855cf1f40 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,13 +4,11 @@ """ import os -import requests import textwrap import uuid -from urllib.parse import urlparse - import pytest +import requests import yaml @@ -28,16 +26,31 @@ def pytest_configure(config): @pytest.fixture(scope="module") -def request_data(): +def admin_api_token(): base_dir = os.path.dirname(os.path.dirname(__file__)) with open(os.path.join(base_dir, "dev-config.yaml")) as f: y = yaml.safe_load(f) token = y["hub"]["services"]["test"]["apiToken"] + return token + + +@pytest.fixture(scope="module") +def scoped_api_token(): + """This token is granted a limited scope""" + base_dir = os.path.dirname(os.path.dirname(__file__)) + with open(os.path.join(base_dir, "dev-config.yaml")) as f: + y = yaml.safe_load(f) + token = y["hub"]["services"]["test-with-scoped-access"]["apiToken"] + return token + + +@pytest.fixture(scope="module") +def request_data(admin_api_token): hub_url = os.environ.get("HUB_URL", "https://local.jovyan.org:30443") return { - "token": token, + "token": admin_api_token, "hub_url": f'{hub_url.rstrip("/")}/hub/api', - "headers": {"Authorization": f"token {token}"}, + "headers": {"Authorization": f"token {admin_api_token}"}, "test_timeout": 60, "request_timeout": 25, } @@ -70,7 +83,7 @@ def pebble_acme_ca_cert(): return cert_path -class JupyterRequest(object): +class JupyterRequest: def __init__(self, request_data, pebble_acme_ca_cert): self.request_data = request_data self.pebble_acme_ca_cert = pebble_acme_ca_cert diff --git a/tests/test_hub.py b/tests/test_hub.py index bca57e1891..26434ed849 100644 --- a/tests/test_hub.py +++ b/tests/test_hub.py @@ -1,6 +1,6 @@ """ -These tests commonl use JupyterHub's REST API: -http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyterhub/jupyterhub/HEAD/docs/rest-api.yml +These tests common use JupyterHub's REST API: +https://jupyterhub.readthedocs.io/en/stable/reference/rest-api.html """ import os @@ -53,6 +53,22 @@ def test_api_info(api_request): assert result["spawner"]["class"] == "kubespawner.spawner.KubeSpawner" +def test_api_info_with_scoped_token(api_request, scoped_api_token): + """ + Test access to the hub api's /info endpoint with an hub api token defined + via hub.services and that is granted the permissions of a role via + hub.loadRoles chart configuration. + + A typical jupyterhub logging response to this test: + + [I 2019-09-25 12:03:12.086 JupyterHub log:174] 200 GET /hub/api/info (test@127.0.0.1) 10.21ms + """ + + print("asking for the hub information using a dedicated token with read:hub scope") + r = api_request.get("/info", headers={"Authorization": f"token {scoped_api_token}"}) + assert r.status_code == 200 + + def test_api_create_and_get_user(api_request, jupyter_user): """ Tests the hub api's /users/:user endpoint, both POST and GET. @@ -140,7 +156,7 @@ def test_extra_files(extra_files_test_command): ) assert ( c.returncode == 0 - ), f"The hub.extraFiles configuration doesn't seem to have been honored!" + ), "The hub.extraFiles configuration doesn't seem to have been honored!" def test_load_etc_jupyterhub_d(): @@ -162,7 +178,7 @@ def test_load_etc_jupyterhub_d(): ) assert ( c.returncode == 0 - ), f"The hub.extraFiles configuration should have mounted a config file to /usr/local/etc/jupyterhub/jupyterhub_config.d which should have been loaded to write a dummy file for us!" + ), "The hub.extraFiles configuration should have mounted a config file to /usr/local/etc/jupyterhub/jupyterhub_config.d which should have been loaded to write a dummy file for us!" def test_load_existing_secret(): @@ -215,7 +231,6 @@ def test_load_existing_secret(): if "hub.existingSecret=None" in hub_logs: pytest.skip("hub.existingSecret is None") else: - k8s_secret_exist = False match = re.compile(r".*hub.existingSecret=(?P[\S]*).*", re.DOTALL).match( hub_logs ) diff --git a/tests/test_spawn.py b/tests/test_spawn.py index 525b823bff..bd3f7ccdda 100644 --- a/tests/test_spawn.py +++ b/tests/test_spawn.py @@ -51,7 +51,7 @@ def test_spawn_basic( ) assert ( c.returncode == 0 - ), f"singleuser.extraEnv didn't lead to a mounted environment variable!" + ), "singleuser.extraEnv didn't lead to a mounted environment variable!" # check user pod's extra files c = subprocess.run( @@ -67,7 +67,7 @@ def test_spawn_basic( ) assert ( c.returncode == 0 - ), f"The singleuser.extraFiles configuration doesn't seem to have been honored!" + ), "The singleuser.extraFiles configuration doesn't seem to have been honored!" finally: _delete_server(api_request, jupyter_user, request_data["test_timeout"]) diff --git a/tools/compare-values-schema-content.py b/tools/compare-values-schema-content.py index d66ec505f7..57ba41a721 100755 --- a/tools/compare-values-schema-content.py +++ b/tools/compare-values-schema-content.py @@ -1,49 +1,50 @@ #!/usr/bin/env python3 """ -This script is meant to assist in a manual validation that the content of -schema.yaml covers values.yaml, and vice versa. +This script is meant to help compare the entries in values.schema.yaml with the +entries in values.yaml and lint-and-validate-values.yaml. -FIXME: It would be nice to run this as part of our CI pipeline to report if - schema.yaml and values.yaml gets out of sync, but first we need to - address what it means to be out of sync. +Running this script can result in output like: - Consider if schema.yaml describes extraLabels, and we in this helm chart - have an extra label set in values, how should our comparison realize that - its nothing to bother about? - - That kind of complexity is currently an issue for labels, resources, - containerSecurityContext, readiness- and livenessProbe's, and hub.config. + values.schema.yaml entries not found in values.yaml: + - hub.deploymentStrategy.rollingUpdate + - hub.fsGid + - rbac.enabled """ -import jsonschema import os -import sys - from collections.abc import MutableMapping import yaml here_dir = os.path.abspath(os.path.dirname(__file__)) -schema_yaml = os.path.join(here_dir, os.pardir, "jupyterhub", "schema.yaml") +schema_yaml = os.path.join(here_dir, os.pardir, "jupyterhub", "values.schema.yaml") values_yaml = os.path.join(here_dir, os.pardir, "jupyterhub", "values.yaml") -lint_and_validate_values_yaml = os.path.join( - here_dir, "templates", "lint-and-validate-values.yaml" -) +lint_values_yaml = os.path.join(here_dir, "templates", "lint-and-validate-values.yaml") def reduce_schema(d): """ Takes a jsonschema loaded as a dictionary and return a reduced structure ignoring everything apart from the structure it describes. + + If additionalProperties or patternProperties is set, a "*" key will be added + instead of whats listed under "properties". """ r = {} - CONTAINS_KEYS = "properties" - if CONTAINS_KEYS in d: - for k, v in d[CONTAINS_KEYS].items(): - if isinstance(v, MutableMapping) and v.get(CONTAINS_KEYS): - r[k] = reduce_schema(v) - else: - r[k] = None + if "properties" in d: + for k, v in d["properties"].items(): + r[k] = None + if isinstance(v, MutableMapping): + if v.get("additionalProperties") or v.get("patternProperties"): + r[k] = {"*": None} + # Exception: The schema describes conditional properties based + # on a condition in an "if" key. Then assume we want + # the properties found in the "then" key. + # + elif v.get("then", {}).get("properties"): + r[k] = reduce_schema(v["then"]) + elif v.get("properties"): + r[k] = reduce_schema(v) return r @@ -57,42 +58,55 @@ def flatten(d, parent_key="", sep="."): new_key = parent_key + sep + k if parent_key else k if isinstance(v, MutableMapping): if v: + items.append(new_key) items.extend(flatten(v, parent_key=new_key, sep=sep)) else: items.append(new_key) else: items.append(new_key) if not parent_key: - return set(items) - else: - return items + items = set(items) + return items + + +def startswith_any_element_in_list(string, in_list): + for s in in_list: + if string.startswith(s): + return True + return False + + +def get_schema_values_diff(values_file, schema, schema_wildcards): + with open(values_file) as f: + values = yaml.safe_load(f) + values = flatten(values) + return { + v + for v in schema - values + if not startswith_any_element_in_list(v, schema_wildcards) + } def run(): - # Using these sets, we can validate further manually by printing the results - # of set operations. with open(schema_yaml) as f: schema = yaml.safe_load(f) - with open(values_yaml) as f: - values = yaml.safe_load(f) - # with open(lint_and_validate_values_yaml) as f: - # lint_and_validate_values = yaml.safe_load(f) schema = flatten(reduce_schema(schema)) - values = flatten(values) - # lint_and_validate_values = flatten(lint_and_validate_values) + schema_wildcards = {l[:-2] for l in schema if l.endswith(".*")} + schema = {l for l in schema if not l.endswith(".*")} - print( - "The keys from values.yaml minus those from schema.yaml:\n", - "\n".join(sorted(values - schema)), - "\n\n", - sep="\n", - ) - print( - "The keys from schema.yaml minus those from values.yaml:\n", - "\n".join(sorted(schema - values)), - "\n\n", - sep="\n", + schema_values_diff = get_schema_values_diff(values_yaml, schema, schema_wildcards) + if schema_values_diff: + print("values.schema.yaml entries not found in values.yaml:") + for l in sorted(schema_values_diff): + print(f"- {l}") + + lint_schema_values_diff = get_schema_values_diff( + lint_values_yaml, schema, schema_wildcards ) + if lint_schema_values_diff: + print("values.schema.yaml entries not found in lint-and-validate-values.yaml:"), + for l in sorted(lint_schema_values_diff): + print(f"- {l}") run() diff --git a/tools/generate-json-schema.py b/tools/generate-json-schema.py index 0b8bf74c69..5fe87461a1 100755 --- a/tools/generate-json-schema.py +++ b/tools/generate-json-schema.py @@ -1,9 +1,9 @@ #!/usr/bin/env python3 """ -This script reads schema.yaml and generates a values.schema.json that we can -package with the Helm chart, allowing helm the CLI perform validation. +This script reads values.schema.yaml and generates a values.schema.json that we +can package with the Helm chart, allowing helm the CLI perform validation. -While we can directly generate a values.schema.json from schema.yaml, it +While we can directly generate a values.schema.json from values.schema.yaml, it contains a lot of description text we use to generate our configuration reference that isn't helpful to ship along the validation schema. Due to that, we trim away everything that isn't needed. @@ -11,14 +11,12 @@ import json import os -import sys - from collections.abc import MutableMapping import yaml here_dir = os.path.abspath(os.path.dirname(__file__)) -schema_yaml = os.path.join(here_dir, os.pardir, "jupyterhub", "schema.yaml") +schema_yaml = os.path.join(here_dir, os.pardir, "jupyterhub", "values.schema.yaml") values_schema_json = os.path.join( here_dir, os.pardir, "jupyterhub", "values.schema.json" ) diff --git a/tools/set-chart-yaml-annotations.py b/tools/set-chart-yaml-annotations.py index 8b02a968fe..6dfd034803 100755 --- a/tools/set-chart-yaml-annotations.py +++ b/tools/set-chart-yaml-annotations.py @@ -12,7 +12,6 @@ import os import textwrap - from collections.abc import MutableMapping import yaml diff --git a/tools/templates/lint-and-validate-values.yaml b/tools/templates/lint-and-validate-values.yaml index b04f919f4a..8f924da92a 100644 --- a/tools/templates/lint-and-validate-values.yaml +++ b/tools/templates/lint-and-validate-values.yaml @@ -8,6 +8,7 @@ imagePullSecret: imagePullSecrets: [a, b] hub: + revisionHistoryLimit: 1 config: # We pin these to avoid generating changes which cause diffs ConfigurableHTTPProxy: @@ -157,16 +158,35 @@ hub: oauth_roles: [dummy] info: key1: value1 + loadRoles: + test-role-1: + name: test-role-1 + description: Access to users' information and group membership + scopes: [users, groups] + users: [cyclops, gandalf] + services: [test-service-1] + groups: [test-group-1] pdb: enabled: true maxUnavailable: 1 minAvailable: null networkPolicy: enabled: true + egressAllowRules: + cloudMetadataServer: true + dnsPortsCloudMetadataServer: true + dnsPortsKubeSystemNamespace: true + dnsPortsPrivateIPs: true + nonPrivateIPs: true + privateIPs: false egress: - to: - - ipBlock: - cidr: 0.0.0.0/0 + - podSelector: + matchLabels: + app: my-k8s-local-service + ports: + - protocol: TCP + port: 5978 interNamespaceAccessLabels: ignore allowedIngressPorts: [] allowNamedServers: true @@ -178,13 +198,15 @@ hub: value: mock-taint-value-hub effect: NoSchedule serviceAccount: &serviceAccount + create: true + name: mock-serviceaccount-name annotations: *annotations extraPodSpec: &extraPodSpec hostNetwork: true dnsPolicy: ClusterFirstWithHostNet rbac: - enabled: true + create: true proxy: service: @@ -199,6 +221,7 @@ proxy: http: https: chp: + revisionHistoryLimit: 1 extraCommandLineFlags: - "--auto-rewrite" - "--mock-flag {{ .Values.proxy.chp.resources.requests.memory }}" @@ -222,6 +245,11 @@ proxy: effect: NoSchedule networkPolicy: enabled: true + egressAllowRules: + cloudMetadataServer: false + dnsPortsPrivateIPs: false + nonPrivateIPs: false + privateIPs: true egress: - to: - ipBlock: @@ -234,6 +262,7 @@ proxy: minAvailable: 1 extraPodSpec: *extraPodSpec traefik: + revisionHistoryLimit: 1 labels: *labels resources: *resources extraEnv: *extraEnv @@ -246,6 +275,11 @@ proxy: effect: NoSchedule networkPolicy: enabled: true + egressAllowRules: + cloudMetadataServer: false + dnsPortsPrivateIPs: false + nonPrivateIPs: true + privateIPs: true egress: - to: - ipBlock: @@ -313,6 +347,26 @@ singleuser: mock description 2 kubespawner_override: image: XYZ:XYZ + - display_name: "mock display name 3" + description: | + mock description 3 + profile_options: + image: + display_name: Image + choices: + image1: + display_name: "image 1" + kubespawner_override: + image: XXX:XXX + image2: + display_name: "image 2" + kubespawner_override: + image: YYY:YYY + unlisted_choice: + enabled: true + display_name: "image ZZZ tag" + kubespawner_override: + image: "ZZZ:{value}" nodeSelector: mock-node-selector: mock extraTolerations: @@ -372,6 +426,11 @@ singleuser: ip: 169.254.169.254 networkPolicy: enabled: true + egressAllowRules: + cloudMetadataServer: false + dnsPortsPrivateIPs: true + nonPrivateIPs: false + privateIPs: false egress: - to: - ipBlock: @@ -392,6 +451,7 @@ singleuser: - name: mock-extra-container-name image: mock-extra-container-image imagePullPolicy: IfNotPresent + allowPrivilegeEscalation: false uid: 1000 fsGid: 100 serviceAccountName: @@ -428,6 +488,7 @@ singleuser: scheduling: userScheduler: enabled: true + revisionHistoryLimit: 1 replicas: 1 logLevel: 10 image: *image @@ -441,17 +502,26 @@ scheduling: plugins: score: disabled: - - name: SelectorSpread + - name: PodTopologySpread enabled: - name: NodePreferAvoidPods weight: 161051 - name: NodeAffinity + pluginConfig: + - name: NodeResourcesFit + args: + scoringStrategy: + resources: + - name: cpu + weight: 1 + type: MostAllocated serviceAccount: *serviceAccount extraPodSpec: *extraPodSpec podPriority: enabled: true userPlaceholder: enabled: true + revisionHistoryLimit: 1 replicas: 1 resources: *resources corePods: @@ -472,6 +542,7 @@ scheduling: matchNodePurpose: require prePuller: + revisionHistoryLimit: 1 extraTolerations: - key: mock-taint-key-prePuller operator: Equal @@ -500,6 +571,7 @@ prePuller: ingress: enabled: true annotations: *annotations + ingressClassName: mock-ingress-class-name hosts: - mocked1.domain.name - mocked2.domain.name diff --git a/tools/templates/lint-and-validate.py b/tools/templates/lint-and-validate.py index 07b266bccd..05b1b2fbb9 100755 --- a/tools/templates/lint-and-validate.py +++ b/tools/templates/lint-and-validate.py @@ -14,12 +14,11 @@ pip install yamllint """ -import os -import sys import argparse -import glob +import os import pipes import subprocess +import sys os.chdir(os.path.dirname(sys.argv[0])) @@ -43,30 +42,12 @@ def lint(yamllint_config, values, output_dir, strict, debug): """Calls `helm lint`, `helm template`, and `yamllint`.""" print("### Clearing output directory") - check_call( - [ - "mkdir", - "-p", - output_dir, - ] - ) - check_call( - [ - "rm", - "-rf", - output_dir + "/*", - ] - ) + check_call(["mkdir", "-p", output_dir]) + check_call(["rm", "-rf", f"{output_dir}/*"]) print("### Linting started") print("### 1/3 - helm lint: lint helm templates") - helm_lint_cmd = [ - "helm", - "lint", - "../../jupyterhub", - "--values", - values, - ] + helm_lint_cmd = ["helm", "lint", "../../jupyterhub", f"--values={values}"] if strict: helm_lint_cmd.append("--strict") if debug: @@ -78,10 +59,8 @@ def lint(yamllint_config, values, output_dir, strict, debug): "helm", "template", "../../jupyterhub", - "--values", - values, - "--output-dir", - output_dir, + f"--values={values}", + f"--output-dir={output_dir}", ] if debug: helm_template_cmd.append("--debug") diff --git a/tools/templates/watch-diff.sh b/tools/templates/watch-diff.sh index b2ee45d37c..358eae1de9 100755 --- a/tools/templates/watch-diff.sh +++ b/tools/templates/watch-diff.sh @@ -17,10 +17,10 @@ rm -rf $TMP_DIFF_DIR mkdir $TMP_DIFF_DIR git init $TMP_DIFF_DIR -helm template jupyterhub --values $HERE_DIR/lint-and-validate-values.yaml --output-dir $TMP_DIFF_DIR +helm template jupyterhub --values "$HERE_DIR/lint-and-validate-values.yaml" --output-dir $TMP_DIFF_DIR # create a point of comparison (cd $TMP_DIFF_DIR && git add . && git commit -m "Comparision point") # watch "git diff" every second (-n1), in color (-c), without watch header (-t) -watch -n1 -ct "helm template jupyterhub --values $HERE_DIR/lint-and-validate-values.yaml --output-dir $TMP_DIFF_DIR > /dev/null && (cd $TMP_DIFF_DIR && git diff --unified=1 --color=always)" +watch -n1 -ct "helm template jupyterhub --values \"$HERE_DIR/lint-and-validate-values.yaml\" --output-dir $TMP_DIFF_DIR > /dev/null && (cd $TMP_DIFF_DIR && git diff --unified=1 --color=always)" diff --git a/tools/templates/yamllint-config.yaml b/tools/templates/yamllint-config.yaml index 82b2ae45cf..ade69db121 100644 --- a/tools/templates/yamllint-config.yaml +++ b/tools/templates/yamllint-config.yaml @@ -1,67 +1,8 @@ rules: - braces: - min-spaces-inside: 0 - max-spaces-inside: 0 - min-spaces-inside-empty: -1 - max-spaces-inside-empty: -1 - brackets: - min-spaces-inside: 0 - max-spaces-inside: 0 - min-spaces-inside-empty: -1 - max-spaces-inside-empty: -1 - colons: - max-spaces-before: 0 - max-spaces-after: 1 - commas: - max-spaces-before: 0 - min-spaces-after: 0 - max-spaces-after: 1 - comments: - require-starting-space: false # Default: true (*) - min-spaces-from-content: 2 - comments-indentation: {} - document-end: disable - document-start: disable # Default: { present: true } - empty-lines: - max: 2 - max-start: 0 - max-end: 0 - empty-values: - forbid-in-block-mappings: false - forbid-in-flow-mappings: false - hyphens: - max-spaces-after: 1 indentation: spaces: 2 # Default: consistent - indent-sequences: whatever # Default true (**) - check-multi-line-strings: false - key-duplicates: enable - key-ordering: disable + indent-sequences: whatever # Default true (*) line-length: disable # Default: { max: 80, ... } - new-line-at-end-of-file: enable - new-lines: - type: unix - octal-values: - forbid-implicit-octal: false - forbid-explicit-octal: false - trailing-spaces: disable - truthy: - level: warning -# (*) Until we can use PR: https://github.com/kubernetes/helm/pull/3811 -# (**) toYaml forces us to use false and be indent different amounts of spaced -# depending on importing lists or dicts. For all fields, where we support both -# lists and dicts, this would be a hassle. -# Consider this case... - -# # values.yaml -# list: -# - key1: value1 -# dict: -# key1: value1 -# -# # template.yaml -# myList: -# {{- .Values.list | toYaml | nindent 0 }} -# myDict: -# {{- .Values.dict | toYaml | nindent 2 }} +# (*) toYaml's emitted sequences/lists will have no indentation and we have no +# control over it, so we compromise by setting "whatever". diff --git a/tools/validate-against-schema.py b/tools/validate-against-schema.py index d9e9cae10e..83e5918025 100755 --- a/tools/validate-against-schema.py +++ b/tools/validate-against-schema.py @@ -1,11 +1,11 @@ #!/usr/bin/env python3 -import jsonschema import os -import sys + +import jsonschema import yaml here_dir = os.path.abspath(os.path.dirname(__file__)) -schema_yaml = os.path.join(here_dir, os.pardir, "jupyterhub", "schema.yaml") +schema_yaml = os.path.join(here_dir, os.pardir, "jupyterhub", "values.schema.yaml") values_yaml = os.path.join(here_dir, os.pardir, "jupyterhub", "values.yaml") lint_and_validate_values_yaml = os.path.join( here_dir, "templates", "lint-and-validate-values.yaml" @@ -19,12 +19,12 @@ lint_and_validate_values = yaml.safe_load(f) # Validate values.yaml against schema -print("Validating values.yaml against schema.yaml...") +print("Validating values.yaml against values.schema.yaml...") jsonschema.validate(values, schema) print("OK!") print() # Validate lint-and-validate-values.yaml against schema -print("Validating lint-and-validate-values.yaml against schema.yaml...") +print("Validating lint-and-validate-values.yaml against values.schema.yaml...") jsonschema.validate(lint_and_validate_values, schema) print("OK!")