diff --git a/.circleci/config.yml b/.circleci/config.yml index 4d91a6a84..0a4582583 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -325,6 +325,12 @@ jobs: hubploy deploy --timeout 30m stat20 hub ${CIRCLE_BRANCH} no_output_timeout: 30m + - run: + name: Deploy ugr01 + command: | + hubploy deploy --timeout 30m ugr01 hub ${CIRCLE_BRANCH} + no_output_timeout: 30m + - run: name: Deploy workshop command: | @@ -626,6 +632,15 @@ workflows: ignore: - staging - prod + - hubploy/build-image: + deployment: ugr01 + name: ugr01 image build + # Filters can only be per-job? wtf + filters: + branches: + ignore: + - staging + - prod deploy: jobs: @@ -799,6 +814,14 @@ workflows: branches: only: - staging + - hubploy/build-image: + deployment: ugr01 + name: ugr01 image build + push: true + filters: + branches: + only: + - staging # Build images only during the staging deploy. All merges # to prod need to go via staging, so prod should *never* # use images not built for staging. By enforcing this at the diff --git a/deployments/ugr01/config/common.yaml b/deployments/ugr01/config/common.yaml new file mode 100644 index 000000000..851b5c2a9 --- /dev/null +++ b/deployments/ugr01/config/common.yaml @@ -0,0 +1,94 @@ +nfsPVC: + enabled: true + nfs: + serverIP: 10.49.181.18 + +jupyterhub: + scheduling: + userScheduler: + nodeSelector: + hub.jupyter.org/pool-name: core-pool-2024-07-07 + proxy: + chp: + nodeSelector: + hub.jupyter.org/pool-name: core-pool-2024-07-07 + + hub: + nodeSelector: + hub.jupyter.org/pool-name: core-pool-2024-07-07 + config: + loadRoles: + # datahub staff + datahub-staff: + description: Enable admin for datahub staff + # this role provides permissions to... + scopes: + - admin-ui + - admin:groups + - admin:users + - admin:servers + - read:roles + - read:hub + - access:servers + # this role will be assigned to... + groups: + - course::1524699::group::all-admins + singleuser: + extraFiles: + # DH-216 + remove-exporters: + mountPath: /etc/jupyter/jupyter_notebook_config.py + stringData: | + c.QtPDFExporter.enabled = False + c.QtPNGExporter.enabled = False + c.WebPDFExporter.enabled = False + extraEnv: + # Unset NotebookApp from hub/values. Necessary for recent lab versions. + JUPYTERHUB_SINGLEUSER_APP: "jupyter_server.serverapp.ServerApp" + nodeSelector: + hub.jupyter.org/pool-name: user-ugr01 + storage: + type: static + static: + pvcName: home-nfs-v3 + subPath: "{username}" + memory: + guarantee: 512M + limit: 1G + + #custom: + # group_profiles: + # + # # Example: increase memory for everyone affiliated with a course. + # + # # Name of Class 100, Fall '22; requested in #98765 + # course::123456: + # mem_limit: 4096M + # mem_guarantee: 2048M + # + # # Example: grant admin rights to course staff. + # # Enrollment types returned by the Canvas API are `teacher`, + # # `student`, `ta`, `observer`, and `designer`. + # # https://canvas.instructure.com/doc/api/enrollments.html + # + # # Some other class 200, Spring '23; requested in #98776 + # course::234567::enrollment_type::teacher: + # mem_limit: 2096M + # mem_guarantee: 2048M + # course::234567::enrollment_type::ta: + # mem_limit: 2096M + # mem_guarantee: 2048M + # + # + # # Example: a fully specified CanvasOAuthenticator group name. + # # This could be useful for temporary resource bumps where the + # # instructor could add people to groups in the bCourses UI. This + # # would benefit from the ability to read resource bumps from + # # jupyterhub's properties. (attributes in the ORM) + # + # # Name of Class 100, Fall '22; requested in #98770 + # course::123456::group::lab4-bigdata: + # - mountPath: /home/rstudio/.ssh + # name: home + # subPath: _some_directory/_ssh + # readOnly: true diff --git a/deployments/ugr01/config/filestore/squash-flags.json b/deployments/ugr01/config/filestore/squash-flags.json new file mode 100644 index 000000000..d5d1e38e7 --- /dev/null +++ b/deployments/ugr01/config/filestore/squash-flags.json @@ -0,0 +1,16 @@ +{ +"--file-share": + { + "name": "shares", + "capacity": "desired-capacity", + "nfs-export-options": [ + { + "access-mode": "READ_WRITE", + "ip-ranges": ["10.0.0.0/8"], + "squash-mode": "ROOT_SQUASH", + "anon_uid": 1000, + "anon_gid": 1000 + } + ], + } +} diff --git a/deployments/ugr01/config/prod.yaml b/deployments/ugr01/config/prod.yaml new file mode 100644 index 000000000..9268ff061 --- /dev/null +++ b/deployments/ugr01/config/prod.yaml @@ -0,0 +1,18 @@ +nfsPVC: + nfs: + shareName: shares/ugr01/prod + +jupyterhub: + ingress: + enabled: true + hosts: + - ugr01.datahub.berkeley.edu + tls: + - secretName: tls-cert + hosts: + - ugr01.datahub.berkeley.edu + hub: + db: + pvc: + # This also holds logs + storage: 4Gi diff --git a/deployments/ugr01/config/staging.yaml b/deployments/ugr01/config/staging.yaml new file mode 100644 index 000000000..66224c5a3 --- /dev/null +++ b/deployments/ugr01/config/staging.yaml @@ -0,0 +1,19 @@ +nfsPVC: + nfs: + shareName: shares/ugr01/staging + +jupyterhub: + scheduling: + userScheduler: + replicas: 1 + prePuller: + continuous: + enabled: false + ingress: + enabled: true + hosts: + - ugr01-staging.datahub.berkeley.edu + tls: + - secretName: tls-cert + hosts: + - ugr01-staging.datahub.berkeley.edu diff --git a/deployments/ugr01/hubploy.yaml b/deployments/ugr01/hubploy.yaml new file mode 100644 index 000000000..2ff8daaea --- /dev/null +++ b/deployments/ugr01/hubploy.yaml @@ -0,0 +1,19 @@ +images: + images: + - name: us-central1-docker.pkg.dev/ucb-datahub-2018/user-images/ugr01-user-image + path: image/ + repo2docker: + base_image: docker.io/library/buildpack-deps:jammy + registry: + provider: gcloud + gcloud: + project: ucb-datahub-2018 + service_key: gcr-key.json + +cluster: + provider: gcloud + gcloud: + project: ucb-datahub-2018 + service_key: gke-key.json + cluster: ugresearch-cluster + zone: us-central1 diff --git a/deployments/ugr01/image/apt.txt b/deployments/ugr01/image/apt.txt new file mode 100644 index 000000000..10e53b036 --- /dev/null +++ b/deployments/ugr01/image/apt.txt @@ -0,0 +1,97 @@ +# Some linux packages for basic terminal work, particularly +# oriented at users new to Unix/cmd line environments. + +# installing less as more just isn't enough +less + +# Basic unix tools +man +man-db +manpages-posix +manpages-dev +manpages-posix-dev + +# Download tools +curl +wget + +# Core text editors on a *nix box: vim +vim + +# A couple of CLI editors that are easier than vim +# micro # currently not working on 18.04 +nano +jed +jed-extra + +# powerful terminal-based file manager, better than the one in JLab +mc + +# for easily managing multiple repositories with one command (perl-doc +# is needed for its help pages to work) +mr +perl-doc + +# Regular build tools for compiling common stuff +build-essential +gfortran + +# Dependencies for nbconvert +texlive-xetex +texlive-fonts-recommended +texlive-plain-generic +# https://github.com/berkeley-dsep-infra/datahub/issues/3719 +texlive-lang-chinese +lmodern + +# Other useful document-related tools +pandoc +latexdiff + +# Some useful git utilities use basic Ruby +ruby + +# Other niceties for command-line work and life +ack # powerful grep-like tool +pydf # colorized disk usage +tmux +screen +htop +nnn # cmd line file manager +zsh +rsync +tig # console UI for git +multitail + +# For later, these are not available in 18.04 +#browsh # text-based web browser, occasionally handy +#dasel # json/yml/csv/etc data wrangling at the terminal +#fzf # fuzzy file finder + +## This section adds tools for desktop environment usage +dbus-x11 +xorg +xubuntu-icon-theme +xfce4 +xfce4-goodies +xclip +xsel +firefox +chromium-browser + +# GUI text editors +vim-gtk3 +gedit + +# Git clients and tools +git-gui +gitg +qgit +meld + +# For jupyter-tree-download. Ref: https://github.com/berkeley-dsep-infra/datahub/issues/3979 +zip + +# playwright deps https://jira-secure.berkeley.edu/browse/DH-305 +libnss3 +libnspr4 diff --git a/deployments/ugr01/image/environment.yml b/deployments/ugr01/image/environment.yml new file mode 100644 index 000000000..9ee6fc0fa --- /dev/null +++ b/deployments/ugr01/image/environment.yml @@ -0,0 +1,63 @@ +name: ugr01-FA24 + +channels: +- conda-forge +- pytorch + +dependencies: +- python==3.11.* +- git==2.39.1 +- jupyter-resource-usage==1.0.0 +- jupyterlab==4.0.11 +- jupyterlab-favorites==3.0.0 +- jupyterlab_server==2.23.0 +- jupyterlab_widgets==3.0.8 +- jupyter_server==2.7.0 +- nbgitpuller==1.2.1 +- notebook==7.0.7 +- folium==0.14.0 +- h5netcdf==1.0.2 +- ipywidgets==8.0.7 +- jupysql==0.8.0 +- jupyter-archive==3.4.0 +- matplotlib==3.7.1 +- mdit-py-plugins==0.4.0 +- numpy==1.24.2 +- pandas==2.0.2 +- plotly==5.13.1 +- requests==2.28.2 +- scikit-image==0.19.3 +- scikit-learn==1.2.2 +- scipy==1.10.1 +- seaborn==0.12.2 +- statsmodels==0.14.0 +- tensorflow-cpu==2.12.1 +- sqlalchemy==2.0.16 +- mlxtend==0.23.0 +# Spring 2024 data 100 +- pytorch==2.1.2 +- cpuonly==2.0 +- transformers==4.37.1 +# Spring 2024 table demos +- lxml==5.1.0 +# Spring 2024 Econ 148 Packages +- geopandas==0.14.2 +- geopy==2.4.1 +- lifelines==0.27.8 +- pycountry==22.3.5 +- pip +- pip: + # - -r infra-requirements.txt + - ipywidgets==8.0.7 + # disable until fixed (probably this: https://github.com/jupyterlab/jupyter-collaboration/issues/162) + # - jupyter_collaboration==1.0.1 + - jupyterhub==4.1.5 + - nbconvert[webpdf] + # - pyppeteer==2.0.0 + - pytest-notebook==0.8.1 + - gh-scoped-creds==4.1 + - git+https://github.com/shaneknapp/python-popularity-contest.git@add-error-handling + - ydata-profiling==4.6.4 + - otter-grader==5.4.0 + - duckdb==0.10.1 + - duckdb_engine==0.11.2 diff --git a/deployments/ugr01/image/infra-requirements.txt b/deployments/ugr01/image/infra-requirements.txt new file mode 100644 index 000000000..b01c9d80d --- /dev/null +++ b/deployments/ugr01/image/infra-requirements.txt @@ -0,0 +1,29 @@ +# WARNING: Original source at scripts/infra-packages/requirements.txt +# PLEASE DO NOT EDIT ELSEWHERE +# After editing scripts/infra-packages/requirements.txt, please run +# scripts/infra-packages/sync.bash. + +# This file pins versions of notebook related python packages we want +# across all hubs. This makes sure we don't need to upgrade them +# everwhere one by one. + +# FIXME: Freeze this to get exact versions of all dependencies +notebook==7.0.7 +jupyterlab==4.0.11 +nbgitpuller==1.2.1 +jupyter-resource-usage==1.0.1 +# Matches version in images/hub/Dockerfile +jupyterhub==4.1.5 +appmode==0.8.0 +ipywidgets==8.0.7 +jupyter-tree-download==1.0.1 +git-credential-helpers==0.2 +# Measure popularity of different packages in our hubs +# https://discourse.jupyter.org/t/request-for-implementation-instrument-libraries-actively-used-by-users-on-a-jupyterhub/7994?u=yuvipanda +git+https://github.com/shaneknapp/python-popularity-contest.git@add-error-handling +# RISE is useful for presentations - see https://github.com/berkeley-dsep-infra/datahub/issues/2527 +RISE==5.7.1 +# syncthing for dropbox-like functionality +jupyter-syncthing-proxy==1.0.3 +# jupyter archival tool for easy user downloads +jupyter-archive==3.4.0 diff --git a/deployments/ugr01/image/postBuild b/deployments/ugr01/image/postBuild new file mode 100644 index 000000000..1b6bcc9d1 --- /dev/null +++ b/deployments/ugr01/image/postBuild @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +# installing chromium browser to enable webpdf conversion using nbconvert +export PLAYWRIGHT_BROWSERS_PATH=${CONDA_DIR} +playwright install chromium diff --git a/deployments/ugr01/image/start b/deployments/ugr01/image/start new file mode 100644 index 000000000..c3a978b7f --- /dev/null +++ b/deployments/ugr01/image/start @@ -0,0 +1,5 @@ +#!/bin/bash + +# See https://jira-secure.berkeley.edu/browse/DH-305 +export PLAYWRIGHT_BROWSERS_PATH=${CONDA_DIR} +exec "$@" diff --git a/deployments/ugr01/secrets/prod.yaml b/deployments/ugr01/secrets/prod.yaml new file mode 100644 index 000000000..422104f73 --- /dev/null +++ b/deployments/ugr01/secrets/prod.yaml @@ -0,0 +1,21 @@ +jupyterhub: + hub: + config: + CanvasOAuthenticator: + client_id: ENC[AES256_GCM,data:/VedfPLyL+Rj3gciMxQ5H84=,iv:WZsC/06SEfEEeH4/NY+txGypgP/lShrJLc8DVXS7tco=,tag:kdZCzktRscuCYz4nRlkxTA==,type:str] + client_secret: ENC[AES256_GCM,data:EqzXDvAIMyGeTnGjUDOg6X6XqSwDmogtz/HXhc2LNYMhoSgg8PSUqvEFNUNG6w59tkRXPerBR6PyOuG31ftYXQ==,iv:D/rf3aWams6O2NcmdjFYxEVV5dQoWv3ubZ1kTN5KMO8=,tag:/LLaEHP/RB17Td0UW1I2bQ==,type:str] + oauth_callback_url: ENC[AES256_GCM,data:RU1IE0Q0bHIXfuVwptLkVgRyj+7z9ps4V30cvQozIL1XcprM3PSp5cJ7Mdyk9MwWQKUHe3o=,iv:QfiqlA0VAJIigpKfhbmvsg74VA/f8l0/+E7n587DZSI=,tag:i5OLqjG4BdJm+cVE3nBgIQ==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/ucb-datahub-2018/locations/global/keyRings/datahub/cryptoKeys/sops + created_at: "2021-05-05T10:57:58Z" + enc: CiQA67O9AK2027WGYGTzywa01Cz+Ez7sOTk/d9payovyK5pg8g4SSADmhpq89bbIWFjlGg79o/iupJ4anLU5Ab9VL+qNzhu6e83JtJ7wSv6sK+cDiEfVSaKQ1YIcadDXFt4WUKRt7MFvAa1sLqp2LA== + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2024-07-16T21:32:11Z" + mac: ENC[AES256_GCM,data:NC/cFuqBfuRWCKKuIWBIyejGcOme6lOD84trvY/QQWVWd9dJVHfCDKwDEVU2EOYn4bFjXR1z4Hi//hlWqoH47LIfS87KprPoVSGN+0DoG6tdN0SzP44hKi37rGwKotrvL6+qnwHnH45M6yk12efs2bU5iFbiOlFhuWMYOxqNEo8=,iv:GqPajLKVLr+R8kUQgWwFkjd+duKnpKFMmPPYBBrssq8=,tag:yYsWY3wuIsNXZRmN33rG9Q==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.9.0 diff --git a/deployments/ugr01/secrets/staging.yaml b/deployments/ugr01/secrets/staging.yaml new file mode 100644 index 000000000..0a45fb78f --- /dev/null +++ b/deployments/ugr01/secrets/staging.yaml @@ -0,0 +1,21 @@ +jupyterhub: + hub: + config: + CanvasOAuthenticator: + client_id: ENC[AES256_GCM,data:G0+pIvyOsh+Zj4ZxddKbON4=,iv:iX8jMrXcJvjBi0GKRtuN886bXWFwBfCsaUoH+HRMn6U=,tag:BsyGAveKrd8TvWMuUlw3kw==,type:str] + client_secret: ENC[AES256_GCM,data:6mR3zs4jvkVuVwjut56tuW3HIOHcYWRSIJJZiOeC+H82tqgZeuVEe7+/zMxq6J0ba5RMas9npep4svuL+TppcA==,iv:K6/MFusdxnLkrEA5LaXLO8mFm1Xa4U2OmxUBOLqdpJk=,tag:xweE4+/ZCIcXj9CtbFpUSw==,type:str] + oauth_callback_url: ENC[AES256_GCM,data:ycdZfwiP7ouq/0pGarj89xGze4aXoVAJiA+k0U+9GHtt1yqiqcw4cndcO67q+0LfrtNOB/ugHPaWu+gkig==,iv:Y9k4n0NyHKX2B8cO1Bo4cRIUZBtYD8si9GszXd4aGKc=,tag:h0Bff7yQPxc57GBk1e44wQ==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/ucb-datahub-2018/locations/global/keyRings/datahub/cryptoKeys/sops + created_at: "2021-05-05T10:57:58Z" + enc: CiQA67O9ALEiz+lgnWQQgjT08Fx2+SUNdWEA2MqdIoEl0Ett3zASSQDmhpq85T+08Rtt/sqeMktjA6t8rCVH8soCR/sNJwDHgXabOipn/od+64D/L+aggCaXqJ433twByk0+YUJAe5z733oW/3J53eU= + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2024-07-16T21:32:30Z" + mac: ENC[AES256_GCM,data:V+KX6npLuuvAGl3+PgZ2EmdEk8glFRxNOjNvm0A5e20/gJIABFucy0yo7xnel/NfLfyGPnMwKHWJ/5CPLJYNRZ2x/gBYY15L+QvPN1ktwtLWa15rr9o1bQP5grv8WVt78iverz39l9HUgaLODjgPNKrsHFmvpAkUruH1uSD5T1M=,iv:elQE5tpiQ5spWOw/3GpdsUDnKxiavBruMA8bvAoSP0g=,tag:hSFukL/hx7SgkDne7ctH+w==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.9.0 diff --git a/docs/admins/cluster-config.rst b/docs/admins/cluster-config.rst index c9973e93b..0c06b57d5 100644 --- a/docs/admins/cluster-config.rst +++ b/docs/admins/cluster-config.rst @@ -25,6 +25,8 @@ A ``gcloud container clusters create`` command can succintly express the configuration of our kubernetes cluster. The following command represents the currently favored configuration. +This creates the GKE cluster. It may host one or more node pools: + .. code:: bash gcloud container clusters create \ @@ -42,6 +44,8 @@ the currently favored configuration. --tags=hub-cluster \ +Here's how we add a node pool to the cluster, beyond the default pool: + .. code:: bash gcloud container node-pools create \ @@ -56,7 +60,7 @@ the currently favored configuration. --disk-size=200 --disk-type=pd-balanced \ --no-enable-autoupgrade \ --tags=hub-cluster \ - --cluster=spring-2024 \ + --cluster= \ user----
diff --git a/vendor/google/ugr/README.md b/vendor/google/ugr/README.md new file mode 100644 index 000000000..4ca1367d6 --- /dev/null +++ b/vendor/google/ugr/README.md @@ -0,0 +1,88 @@ +# UGR Cluster & Hub Deployment + +This set of templates, configuration files and scripts use the [GCP Cloud Deployment Manager](https://cloud.google.com/deployment-manager/docs) service to deploy and update the undergraduate research GKE cluster and node pools. + +The documentation below starts from the highest level -- the Deployment Scripts -- and drills down into the two supporting layers beneath (Configurations, Templates). + + +## Deployment Scripts (gcloud wrapped in shell) + +The deployment shell scripts are wrapped around gcloud commands to add a bit of convenience. This convenience boils down to the following: + +``` +gcloud deployment-manager deployments create ... || \ +gcloud deployment-manager deployments update ... +``` + +That is, the script will run the create version; if this fails (due to the deployement already existing), then it will update the deployment, only taking actions to effect changes in the "deltas" between the live deployment and the new local configuration. + +Deployments may be destroyed wholesale with "one click" in the web console, or with gcloud as described in the shell script comments: + +``` +gcloud deployment-manager deployments delete "$DEPLOYMENT_NAME" +``` +## Configurations (yaml) + +Each deployment shell script (above) "knows" its config, e.g. + +``` +CONFIG_PATH="./configs/gke_ugresearch.yaml" +``` + +[The yaml file for a templated config](https://cloud.google.com/deployment-manager/docs/configuration/templates/define-template-properties) contains all of the configuration variable values, such as resource names, numbers, sizes, and other parameters; for example, + +``` + initialNodeCount: 1 + diskSizeGb: 100 + machineType: n2-standard-2 +``` + +## Custom Templates (python) + +The yaml config files (above) work with [templates](https://cloud.google.com/deployment-manager/docs/configuration/templates/create-basic-template) to feed the full deployment specifications to the shell script's gcloud command. The yaml specifies the template(s) that the deployment manager should use for the deployment: + +``` +imports: + - path: ../templates/gke_template.py +``` + +When choosing python for the template language, the following function is expected: + +``` +def GenerateConfig(context): +``` + +At deployment, the template has access to the properties set in the associated yaml, and this function's one job is to return a dictionary that descries the deployment: + +``` + return {'resources': resources} +``` + +Note that this python is run "in the cloud" by the deployment manager service, not locally in the gcloud context. + +## Adding a Node Pool + +To add a node pool, such as ugr02, create these two files (based on the ugr01 example): + +``` +.//configs/node_pool_ugr02.yaml +.//deploy_node_pool_ugr02.sh +``` + +Edit the yaml config to have the names and properties of your new node pool, and edit the shell script's CONFIG_PATH to reference the new yaml config. + +The associated template is meant to be unchanged; it contains the structure, not the configuration: + +``` +templates/node_pool_template.py +``` + +Run the shell script to deploy: + +``` +./deploy_node_pool_ugr02.sh +``` + +## Change a deployment + +To change an existing deployment, edit the parameters to be changed in the deployment's yaml config and run its associated shell script. \ No newline at end of file diff --git a/vendor/google/ugr/gke/configs/gke_ugresearch.yaml b/vendor/google/ugr/gke/configs/gke_ugresearch.yaml new file mode 100644 index 000000000..fe23b0362 --- /dev/null +++ b/vendor/google/ugr/gke/configs/gke_ugresearch.yaml @@ -0,0 +1,17 @@ +imports: + - path: ../templates/gke_template.py + +resources: + - name: ugresearch-cluster + type: ../templates/gke_template.py + properties: + clusterName: ugresearch-cluster + region: us-central1 + poolName: core + dateSuffix: '2024-07-07' + nodeLocation: us-central1-b + initialNodeCount: 1 + diskSizeGb: 100 + machineType: n2-standard-2 + minNodeCount: 1 + maxNodeCount: 20 diff --git a/vendor/google/ugr/gke/configs/node_pool_ugr01.yaml b/vendor/google/ugr/gke/configs/node_pool_ugr01.yaml new file mode 100644 index 000000000..5979cc1af --- /dev/null +++ b/vendor/google/ugr/gke/configs/node_pool_ugr01.yaml @@ -0,0 +1,16 @@ +imports: + - path: ../templates/node_pool_template.py + +resources: + - name: ugr01-node-pool + type: ../templates/node_pool_template.py + properties: + poolName: ugr01 + clusterName: ugresearch-cluster + region: us-central1 + dateSuffix: '2024-07-07' + initialNodeCount: 1 + diskSizeGb: 100 + machineType: n2-standard-2 + minNodeCount: 1 + maxNodeCount: 20 diff --git a/vendor/google/ugr/gke/deploy_gke_ugr.sh b/vendor/google/ugr/gke/deploy_gke_ugr.sh new file mode 100755 index 000000000..7ca45f98a --- /dev/null +++ b/vendor/google/ugr/gke/deploy_gke_ugr.sh @@ -0,0 +1,22 @@ +#!/bin/bash +set -euo pipefail + +# Define variables +PROJECT_ID="ucb-datahub-2018" # Replace this with your actual GCP project ID +DEPLOYMENT_NAME="ugr-gke-deployment" +CONFIG_PATH="./configs/gke_ugresearch.yaml" + +# Set the GCP project context +gcloud config set project "$PROJECT_ID" + +# Navigate to the directory where the deploy.sh script is located +cd "$(dirname "$0")" + +# Deploy the configuration +gcloud deployment-manager deployments create "$DEPLOYMENT_NAME" --config "$CONFIG_PATH" || \ +gcloud deployment-manager deployments update "$DEPLOYMENT_NAME" --config "$CONFIG_PATH" + +# To manually delete the deployment, run the following command: +# gcloud deployment-manager deployments delete "$DEPLOYMENT_NAME" + +echo "Deployment process completed." diff --git a/vendor/google/ugr/gke/deploy_node_pool_ugr01.sh b/vendor/google/ugr/gke/deploy_node_pool_ugr01.sh new file mode 100755 index 000000000..8f95fc211 --- /dev/null +++ b/vendor/google/ugr/gke/deploy_node_pool_ugr01.sh @@ -0,0 +1,22 @@ +#!/bin/bash +set -euo pipefail + +# Define variables +PROJECT_ID="ucb-datahub-2018" # Replace this with your actual GCP project ID +DEPLOYMENT_NAME="ugr-ugr01-node-pool-deployment" +CONFIG_PATH="./configs/node_pool_ugr01.yaml" + +# Set the GCP project context +gcloud config set project "$PROJECT_ID" + +# Navigate to the directory where the script is located +cd "$(dirname "$0")" + +# Deploy the node pool configuration +gcloud deployment-manager deployments create "$DEPLOYMENT_NAME" --config "$CONFIG_PATH" || \ +gcloud deployment-manager deployments update "$DEPLOYMENT_NAME" --config "$CONFIG_PATH" + +# To manually delete the deployment, run the following command: +# gcloud deployment-manager deployments delete "$DEPLOYMENT_NAME" + +echo "Node pool deployment process completed." diff --git a/vendor/google/ugr/gke/templates/gke_template.py b/vendor/google/ugr/gke/templates/gke_template.py new file mode 100644 index 000000000..4f8e96b84 --- /dev/null +++ b/vendor/google/ugr/gke/templates/gke_template.py @@ -0,0 +1,78 @@ +"""Creates a GKE cluster with specific configurations.""" + + +def GenerateConfig(context): + """Generates the YAML resource configuration.""" + + project = context.env['project'] + cluster_name = context.properties['clusterName'] + region = context.properties['region'] + pool_name = context.properties['poolName'] + date_suffix = context.properties['dateSuffix'] # Format: yyyy-mm-dd + node_location = context.properties['nodeLocation'] + initial_node_count = context.properties['initialNodeCount'] + disk_size_gb = context.properties['diskSizeGb'] + machine_type = context.properties['machineType'] + min_node_count = context.properties['minNodeCount'] + max_node_count = context.properties['maxNodeCount'] + + resources = [{ + 'name': cluster_name, + 'type': 'gcp-types/container-v1:projects.locations.clusters', + 'properties': { + 'parent': f'projects/{project}/locations/{region}', + 'cluster': { + 'name': cluster_name, + 'initialClusterVersion': 'latest', + 'location': region, + 'locations': [node_location], + 'ipAllocationPolicy': { + 'useIpAliases': True + }, + 'addonsConfig': { + 'httpLoadBalancing': { + 'disabled': True + } + }, + 'nodePools': [{ + 'name': f'{pool_name}-{date_suffix}', + 'initialNodeCount': initial_node_count, + 'config': { + 'diskSizeGb': disk_size_gb, + 'diskType': 'pd-balanced', + 'machineType': machine_type, + 'imageType': 'COS_CONTAINERD', + 'labels': { + 'hub.jupyter.org/pool-name': f'{pool_name}-pool-{date_suffix}' + }, + 'oauthScopes': [ + 'https://www.googleapis.com/auth/compute', + 'https://www.googleapis.com/auth/devstorage.read_only', + 'https://www.googleapis.com/auth/logging.write', + 'https://www.googleapis.com/auth/monitoring', + 'https://www.googleapis.com/auth/servicecontrol', + 'https://www.googleapis.com/auth/service.management.readonly', + 'https://www.googleapis.com/auth/trace.append' + ], + }, + 'autoscaling': { + 'enabled': True, + 'maxNodeCount': max_node_count, + 'minNodeCount': min_node_count + }, + 'management': { + 'autoUpgrade': False, + 'autoRepair': True + }, + 'locations': [ + node_location + ] + }], + 'networkPolicy': { + 'enabled': True + } + } + } + }] + + return {'resources': resources} diff --git a/vendor/google/ugr/gke/templates/node_pool_template.py b/vendor/google/ugr/gke/templates/node_pool_template.py new file mode 100644 index 000000000..19a9806a2 --- /dev/null +++ b/vendor/google/ugr/gke/templates/node_pool_template.py @@ -0,0 +1,53 @@ +"""Creates a GKE node pool with specific configurations.""" + + +def GenerateConfig(context): + """Generates the YAML resource configuration for a node pool.""" + + pool_name = context.properties['poolName'] + cluster_name = context.properties['clusterName'] + region = context.properties['region'] + date_suffix = context.properties['dateSuffix'] # Format: yyyy-mm-dd + initial_node_count = context.properties['initialNodeCount'] + disk_size_gb = context.properties['diskSizeGb'] + machine_type = context.properties['machineType'] + min_node_count = context.properties['minNodeCount'] + max_node_count = context.properties['maxNodeCount'] + + resources = [{ + 'name': f'user-{pool_name}-{date_suffix}', + 'type': 'gcp-types/container-v1:projects.locations.clusters.nodePools', + 'properties': { + 'parent': f'projects/{context.env["project"]}/locations/{region}/clusters/{cluster_name}', + 'nodePool': { + 'name': f'{pool_name}-pool', + 'initialNodeCount': initial_node_count, + 'config': { + 'machineType': machine_type, + 'diskSizeGb': disk_size_gb, + 'diskType': 'pd-balanced', + 'imageType': 'COS_CONTAINERD', + 'labels': { + 'hub.jupyter.org/pool-name': f'{pool_name}-pool' + }, + 'taints': [{ + 'key': 'hub.jupyter.org_dedicated', + 'value': 'user', + 'effect': 'NO_SCHEDULE' + }], + 'tags': ['hub-cluster'], + }, + 'autoscaling': { + 'enabled': True, + 'maxNodeCount': max_node_count, + 'minNodeCount': min_node_count + }, + 'management': { + 'autoUpgrade': False, + 'autoRepair': True + }, + } + } + }] + + return {'resources': resources}