Skip to content

Commit

Permalink
[RELEASE] 2024.3.1 (#2305)
Browse files Browse the repository at this point in the history
  • Loading branch information
dcmcand authored Mar 11, 2024
2 parents e9a8f9f + 9f2f8c5 commit 4b89055
Show file tree
Hide file tree
Showing 41 changed files with 867 additions and 65 deletions.
4 changes: 2 additions & 2 deletions .cirun.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ runners:
- name: run-k8s-tests
# Cloud Provider: AWS
cloud: aws
# Instance Type has 4 vcpu, 16 GiB memory, Up to 5 Gbps Network Performance
instance_type: t3a.xlarge
# Instance Type has 8 vcpu, 32 GiB memory, Up to 5 Gbps Network Performance
instance_type: t3a.2xlarge
# Custom AMI with docker/cypress/hub pre-installed
machine_image: ami-0a388df278199ff52
# Region: Oregon
Expand Down
36 changes: 19 additions & 17 deletions .github/workflows/test_local_integration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,24 @@ jobs:
sed -i -E 's/(cpu_guarantee):\s+[0-9\.]+/\1: 0.25/g' "nebari-config.yaml"
sed -i -E 's/(mem_guarantee):\s+[A-Za-z0-9\.]+/\1: 0.25G/g' "nebari-config.yaml"
# Change default JupyterLab theme
cat >> nebari-config.yaml <<- EOM
jupyterlab:
default_settings:
"@jupyterlab/apputils-extension:themes":
theme: JupyterLab Dark
EOM
# Change default value for minio persistence size
cat >> nebari-config.yaml <<- EOM
monitoring:
enabled: true
overrides:
minio:
persistence:
size: 1Gi
EOM
cat nebari-config.yaml
- name: Deploy Nebari
Expand All @@ -106,7 +124,7 @@ jobs:
- name: Basic kubectl checks after deployment
if: always()
run: |
kubectl get all,cm,secret,ing -A
kubectl get all,cm,secret,pv,pvc,ing -A
- name: Check github-actions.nebari.dev resolves
run: |
Expand Down Expand Up @@ -167,22 +185,6 @@ jobs:
run: |
pytest tests/tests_deployment/ -v -s
- name: JupyterHub Notebook Tests
timeout-minutes: 2
# run jhub-client after pytest since jhubctl can cleanup
# the running server
env:
JUPYTERHUB_USERNAME: ${{ env.TEST_USERNAME }}
JUPYTERHUB_PASSWORD: ${{ env.TEST_PASSWORD }}
run: |
sleep 60
jhubctl --verbose run --hub=https://github-actions.nebari.dev\
--auth-type=keycloak \
--validate --no-verify-ssl \
--kernel python3 \
--stop-server \
--notebook tests/tests_deployment/assets/notebook/simple.ipynb \
### CLEANUP AFTER TESTS
- name: Cleanup nebari deployment
if: always()
Expand Down
23 changes: 23 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,29 @@ This file is copied to nebari-dev/nebari-docs using a GitHub Action. -->

## Upcoming Release

## Release 2024.3.1 - March 11, 2024

### What's Changed
* Modify Playwright test to account for changes in JupyterLab UI. by @marcelovilla in https://github.com/nebari-dev/nebari/pull/2232
* Add favicon to jupyterhub theme. by @jbouder in https://github.com/nebari-dev/nebari/pull/2222
* Set min nodes to 0 for worker and user. by @pt247 in https://github.com/nebari-dev/nebari/pull/2168
* Remove `jhub-client` from pyproject.toml by @pavithraes in https://github.com/nebari-dev/nebari/pull/2242
* Include permission validation step to programmatically cloned repos by @viniciusdc in https://github.com/nebari-dev/nebari/pull/2258
* Expose jupyter's preferred dir as a config option by @krassowski in https://github.com/nebari-dev/nebari/pull/2251
* Allow to configure default settings for JupyterLab (`overrides.json`) by @krassowski in https://github.com/nebari-dev/nebari/pull/2249
* Feature/jlab menu customization by @marcelovilla in https://github.com/nebari-dev/nebari/pull/2259
* Add cloud provider to the dask config.json file by @marcelovilla in https://github.com/nebari-dev/nebari/pull/2266
* Fix syntax error in jupyter-server-config Python file by @krassowski in https://github.com/nebari-dev/nebari/pull/2286
* Add "Open VS Code" entry in services by @krassowski in https://github.com/nebari-dev/nebari/pull/2267
* Add Grafana Loki integration by @aktech in https://github.com/nebari-dev/nebari/pull/2156

### New Contributors
* @jbouder made their first contribution in https://github.com/nebari-dev/nebari/pull/2222
* @krassowski made their first contribution in https://github.com/nebari-dev/nebari/pull/2251

**Full Changelog**: https://github.com/nebari-dev/nebari/compare/2024.1.1...2024.3.1


## Release 2024.1.1 - January 17, 2024

### Feature changes and enhancements
Expand Down
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ dev = [
"diagrams",
"escapism",
"importlib-metadata<5.0",
"jhub-client",
"jinja2",
"mypy==1.6.1",
"paramiko",
Expand Down
4 changes: 2 additions & 2 deletions src/_nebari/constants.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CURRENT_RELEASE = "2024.1.1"
CURRENT_RELEASE = "2024.3.1"

# NOTE: Terraform cannot be upgraded further due to Hashicorp licensing changes
# implemented in August 2023.
Expand All @@ -13,7 +13,7 @@

DEFAULT_NEBARI_DASK_VERSION = CURRENT_RELEASE
DEFAULT_NEBARI_IMAGE_TAG = CURRENT_RELEASE
DEFAULT_NEBARI_WORKFLOW_CONTROLLER_IMAGE_TAG = "2024.1.1"
DEFAULT_NEBARI_WORKFLOW_CONTROLLER_IMAGE_TAG = CURRENT_RELEASE

DEFAULT_CONDA_STORE_IMAGE_TAG = "2024.1.1"

Expand Down
40 changes: 40 additions & 0 deletions src/_nebari/provider/cloud/amazon_web_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,46 @@ def aws_get_vpc_id(name: str, namespace: str, region: str) -> Optional[str]:
return None


def set_asg_tags(asg_node_group_map: Dict[str, str], region: str) -> None:
"""Set tags for AWS node scaling from zero to work."""
session = aws_session(region=region)
autoscaling_client = session.client("autoscaling")
tags = []
for asg_name, node_group in asg_node_group_map.items():
tags.append(
{
"Key": "k8s.io/cluster-autoscaler/node-template/label/dedicated",
"Value": node_group,
"ResourceId": asg_name,
"ResourceType": "auto-scaling-group",
"PropagateAtLaunch": True,
}
)
autoscaling_client.create_or_update_tags(Tags=tags)


def aws_get_asg_node_group_mapping(
name: str, namespace: str, region: str
) -> Dict[str, str]:
"""Return a dictionary of autoscaling groups and their associated node groups."""
asg_node_group_mapping = {}
session = aws_session(region=region)
eks = session.client("eks")
node_groups_response = eks.list_nodegroups(
clusterName=f"{name}-{namespace}",
)
node_groups = node_groups_response.get("nodegroups", [])
for nodegroup in node_groups:
response = eks.describe_nodegroup(
clusterName=f"{name}-{namespace}", nodegroupName=nodegroup
)
node_group_name = response["nodegroup"]["nodegroupName"]
auto_scaling_groups = response["nodegroup"]["resources"]["autoScalingGroups"]
for auto_scaling_group in auto_scaling_groups:
asg_node_group_mapping[auto_scaling_group["name"]] = node_group_name
return asg_node_group_mapping


def aws_get_subnet_ids(name: str, namespace: str, region: str) -> List[str]:
"""Return list of subnet IDs for the EKS cluster named `{name}-{namespace}`."""
session = aws_session(region=region)
Expand Down
25 changes: 23 additions & 2 deletions src/_nebari/stages/infrastructure/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,17 @@ class AWSInputVars(schema.Base):
tags: Dict[str, str] = {}


def _calculate_asg_node_group_map(config: schema.Main):
if config.provider == schema.ProviderEnum.aws:
return amazon_web_services.aws_get_asg_node_group_mapping(
config.project_name,
config.namespace,
config.amazon_web_services.region,
)
else:
return {}


def _calculate_node_groups(config: schema.Main):
if config.provider == schema.ProviderEnum.aws:
return {
Expand Down Expand Up @@ -438,10 +449,10 @@ class AmazonWebServicesProvider(schema.Base):
node_groups: Dict[str, AWSNodeGroup] = {
"general": AWSNodeGroup(instance="m5.2xlarge", min_nodes=1, max_nodes=1),
"user": AWSNodeGroup(
instance="m5.xlarge", min_nodes=1, max_nodes=5, single_subnet=False
instance="m5.xlarge", min_nodes=0, max_nodes=5, single_subnet=False
),
"worker": AWSNodeGroup(
instance="m5.xlarge", min_nodes=1, max_nodes=5, single_subnet=False
instance="m5.xlarge", min_nodes=0, max_nodes=5, single_subnet=False
),
}
existing_subnet_ids: List[str] = None
Expand Down Expand Up @@ -814,6 +825,16 @@ def set_outputs(
outputs["node_selectors"] = _calculate_node_groups(self.config)
super().set_outputs(stage_outputs, outputs)

@contextlib.contextmanager
def post_deploy(
self, stage_outputs: Dict[str, Dict[str, Any]], disable_prompt: bool = False
):
asg_node_group_map = _calculate_asg_node_group_map(self.config)
if asg_node_group_map:
amazon_web_services.set_asg_tags(
asg_node_group_map, self.config.amazon_web_services.region
)

@contextlib.contextmanager
def deploy(
self, stage_outputs: Dict[str, Dict[str, Any]], disable_prompt: bool = False
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ resource "aws_eks_node_group" "main" {
max_size = var.node_groups[count.index].max_size
}

labels = {
"dedicated" = var.node_groups[count.index].name
}

lifecycle {
ignore_changes = [
scaling_config[0].desired_size,
Expand All @@ -53,7 +57,9 @@ resource "aws_eks_node_group" "main" {
]

tags = merge({
"kubernetes.io/cluster/${var.name}" = "shared"
# "kubernetes.io/cluster/${var.name}" = "shared"
"k8s.io/cluster-autoscaler/node-template/label/dedicated" = var.node_groups[count.index].name
propagate_at_launch = true
}, var.tags)
}

Expand Down
38 changes: 38 additions & 0 deletions src/_nebari/stages/kubernetes_services/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class JupyterHubTheme(schema.Base):
hub_subtitle: str = "Your open source data science platform"
welcome: str = """Welcome! Learn about Nebari's features and configurations in <a href="https://www.nebari.dev/docs">the documentation</a>. If you have any questions or feedback, reach the team on <a href="https://www.nebari.dev/docs/community#getting-support">Nebari's support forums</a>."""
logo: str = "https://raw.githubusercontent.com/nebari-dev/nebari-design/main/logo-mark/horizontal/Nebari-Logo-Horizontal-Lockup-White-text.svg"
favicon: str = "https://raw.githubusercontent.com/nebari-dev/nebari-design/main/symbol/favicon.ico"
primary_color: str = "#4f4173"
primary_color_dark: str = "#4f4173"
secondary_color: str = "#957da6"
Expand Down Expand Up @@ -198,8 +199,16 @@ class JHubApps(schema.Base):
enabled: bool = False


class MonitoringOverrides(schema.Base):
loki: typing.Dict = {}
promtail: typing.Dict = {}
minio: typing.Dict = {}


class Monitoring(schema.Base):
enabled: bool = True
overrides: MonitoringOverrides = MonitoringOverrides()
minio_enabled: bool = True


class JupyterLabPioneer(schema.Base):
Expand All @@ -226,8 +235,10 @@ class IdleCuller(schema.Base):


class JupyterLab(schema.Base):
default_settings: typing.Dict[str, typing.Any] = {}
idle_culler: IdleCuller = IdleCuller()
initial_repositories: typing.List[typing.Dict[str, str]] = []
preferred_dir: typing.Optional[str] = None


class InputSchema(schema.Base):
Expand Down Expand Up @@ -351,6 +362,9 @@ class CondaStoreInputVars(schema.Base):
class JupyterhubInputVars(schema.Base):
jupyterhub_theme: Dict[str, Any] = Field(alias="jupyterhub-theme")
jupyterlab_image: ImageNameTag = Field(alias="jupyterlab-image")
jupyterlab_default_settings: Dict[str, Any] = Field(
alias="jupyterlab-default-settings"
)
initial_repositories: str = Field(alias="initial-repositories")
jupyterhub_overrides: List[str] = Field(alias="jupyterhub-overrides")
jupyterhub_stared_storage: str = Field(alias="jupyterhub-shared-storage")
Expand All @@ -361,15 +375,26 @@ class JupyterhubInputVars(schema.Base):
idle_culler_settings: Dict[str, Any] = Field(alias="idle-culler-settings")
argo_workflows_enabled: bool = Field(alias="argo-workflows-enabled")
jhub_apps_enabled: bool = Field(alias="jhub-apps-enabled")
cloud_provider: str = Field(alias="cloud-provider")
jupyterlab_preferred_dir: typing.Optional[str] = Field(
alias="jupyterlab-preferred-dir"
)


class DaskGatewayInputVars(schema.Base):
dask_worker_image: ImageNameTag = Field(alias="dask-worker-image")
dask_gateway_profiles: Dict[str, Any] = Field(alias="dask-gateway-profiles")
cloud_provider: str = Field(alias="cloud-provider")


class MonitoringInputVars(schema.Base):
monitoring_enabled: bool = Field(alias="monitoring-enabled")
minio_enabled: bool = Field(alias="minio-enabled")
grafana_loki_overrides: List[str] = Field(alias="grafana-loki-overrides")
grafana_promtail_overrides: List[str] = Field(alias="grafana-promtail-overrides")
grafana_loki_minio_overrides: List[str] = Field(
alias="grafana-loki-minio-overrides"
)


class TelemetryInputVars(schema.Base):
Expand Down Expand Up @@ -410,6 +435,7 @@ def input_vars(self, stage_outputs: Dict[str, Dict[str, Any]]):
realm_id = stage_outputs["stages/06-kubernetes-keycloak-configuration"][
"realm_id"
]["value"]
cloud_provider = self.config.provider.value
jupyterhub_shared_endpoint = (
stage_outputs["stages/02-infrastructure"]
.get("nfs_endpoint", {})
Expand Down Expand Up @@ -485,6 +511,7 @@ def input_vars(self, stage_outputs: Dict[str, Dict[str, Any]]):
),
jupyterhub_stared_storage=self.config.storage.shared_filesystem,
jupyterhub_shared_endpoint=jupyterhub_shared_endpoint,
cloud_provider=cloud_provider,
jupyterhub_profiles=self.config.profiles.dict()["jupyterlab"],
jupyterhub_image=_split_docker_image_name(
self.config.default_images.jupyterhub
Expand All @@ -497,17 +524,28 @@ def input_vars(self, stage_outputs: Dict[str, Dict[str, Any]]):
argo_workflows_enabled=self.config.argo_workflows.enabled,
jhub_apps_enabled=self.config.jhub_apps.enabled,
initial_repositories=str(self.config.jupyterlab.initial_repositories),
jupyterlab_default_settings=self.config.jupyterlab.default_settings,
jupyterlab_preferred_dir=self.config.jupyterlab.preferred_dir,
)

dask_gateway_vars = DaskGatewayInputVars(
dask_worker_image=_split_docker_image_name(
self.config.default_images.dask_worker
),
dask_gateway_profiles=self.config.profiles.dict()["dask_worker"],
cloud_provider=cloud_provider,
)

monitoring_vars = MonitoringInputVars(
monitoring_enabled=self.config.monitoring.enabled,
minio_enabled=self.config.monitoring.minio_enabled,
grafana_loki_overrides=[json.dumps(self.config.monitoring.overrides.loki)],
grafana_promtail_overrides=[
json.dumps(self.config.monitoring.overrides.promtail)
],
grafana_loki_minio_overrides=[
json.dumps(self.config.monitoring.overrides.minio)
],
)

telemetry_vars = TelemetryInputVars(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ variable "dask-gateway-profiles" {
description = "Dask Gateway profiles to expose to user"
}


# =================== RESOURCES =====================
module "dask-gateway" {
source = "./modules/kubernetes/services/dask-gateway"
Expand Down Expand Up @@ -39,4 +38,6 @@ module "dask-gateway" {

# profiles
profiles = var.dask-gateway-profiles

cloud-provider = var.cloud-provider
}
Loading

0 comments on commit 4b89055

Please sign in to comment.