From 272dff78ad4e241825d7b04255e4981203f6502d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20K=C5=82osko?= Date: Mon, 24 Jun 2024 18:36:49 +0200 Subject: [PATCH] Change fly clustering to auto (#2672) --- CHANGELOG.md | 2 +- docs/deployment/clustering.md | 8 +-- lib/livebook/hubs/dockerfile.ex | 12 ++-- lib/livebook/teams/deployment_group.ex | 2 +- lib/livebook_web/components/app_components.ex | 68 ++++++++++--------- .../components/form_components.ex | 4 +- .../teams/deployment_group_agent_component.ex | 7 +- .../teams/deployment_group_form_component.ex | 6 +- rel/server/env.sh.eex | 2 +- test/livebook/hubs/dockerfile_test.exs | 24 +++---- 10 files changed, 70 insertions(+), 65 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28b51143f..cc97042b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). * Improved latency for showing completions in Remote execution cell ([#2447](https://github.com/livebook-dev/livebook/pull/2447)) * Reduced the time of `Mix.install/2` when adding a new dependency ([#2499](https://github.com/livebook-dev/livebook/pull/2499)) * Support for Web Bluetooth and Web Serial APIs within iframes ([#2514](https://github.com/livebook-dev/livebook/pull/2514)) -* Support for `LIVEBOOK_CLUSTER=fly` when deploying a Livebook cluster on Fly ([#2519](https://github.com/livebook-dev/livebook/pull/2519)) +* Added `LIVEBOOK_CLUSTER=auto` to automatically configure the cluster on Fly.io ([#2519](https://github.com/livebook-dev/livebook/pull/2519)) * Healthcheck definition to the Livebook Docker image ([#2517](https://github.com/livebook-dev/livebook/pull/2517)) * Persistence of app password in the notebook, encrypted in the stamp metadata ([#2550](https://github.com/livebook-dev/livebook/pull/2550)) * Support for Basic Authentication ZTA ([#2564](https://github.com/livebook-dev/livebook/pull/2564)) diff --git a/docs/deployment/clustering.md b/docs/deployment/clustering.md index 73cebcca9..7f29cae6f 100644 --- a/docs/deployment/clustering.md +++ b/docs/deployment/clustering.md @@ -1,14 +1,14 @@ # Clustering -If you plan to run several Livebook instances behind a load balancer, you need to enable clustering via the `LIVEBOOK_CLUSTER` environment variable in your Docker image. +If you plan to run several Livebook instances behind a load balancer, you need to enable clustering via the `LIVEBOOK_CLUSTER` environment variable. In addition you must set `LIVEBOOK_SECRET_KEY_BASE` and `LIVEBOOK_COOKIE` to different random values (use `openssl rand -base64 48` to generate said values). Depending on the clustering strategy of your choice, you must set additional environment variables, oftentimes, at runtime. When using the Livebook Docker image, you can create a file at `/app/user/env.sh` that exports the necessary environment variables. This file is invoked right before booting Livebook. You may set `LIVEBOOK_CLUSTER` to one of the following values. -## `fly` +## `auto` -It automatically sets up a cluster to run on Fly using DNS configuration. Behind the scenes, it sets the relevant environment variables and enables IPv6 support. +Detects the hosting platform and automatically sets up a cluster using DNS configuration. Currently the only supported platform is Fly.io. ## `dns:QUERY` @@ -16,6 +16,4 @@ Sets up a cluster using DNS for queries for A/AAAA records to discover new nodes * `LIVEBOOK_NODE=livebook_server@MACHINE_IP`, where `MACHINE_IP` is the machine IP of each deployed node - * You must set `LIVEBOOK_SECRET_KEY_BASE` and `LIVEBOOK_COOKIE` to different random values (use `openssl rand -base64 48` to generate said values) - * If your cloud requires IPv6, also set `ERL_AFLAGS="-proto_dist inet6_tcp"` diff --git a/lib/livebook/hubs/dockerfile.ex b/lib/livebook/hubs/dockerfile.ex index ce8bbafb8..3bea1fbef 100644 --- a/lib/livebook/hubs/dockerfile.ex +++ b/lib/livebook/hubs/dockerfile.ex @@ -8,7 +8,7 @@ defmodule Livebook.Hubs.Dockerfile do @type config :: %{ deploy_all: boolean(), docker_tag: String.t(), - clustering: nil | :fly_io, + clustering: nil | :auto | :dns, zta_provider: atom() | nil, zta_key: String.t() | nil } @@ -54,7 +54,7 @@ defmodule Livebook.Hubs.Dockerfile do types = %{ deploy_all: :boolean, docker_tag: :string, - clustering: Ecto.ParameterizedType.init(Ecto.Enum, values: [:fly_io, :dns]), + clustering: Ecto.ParameterizedType.init(Ecto.Enum, values: [:auto, :dns]), zta_provider: Ecto.ParameterizedType.init(Ecto.Enum, values: zta_types), zta_key: :string } @@ -152,14 +152,14 @@ defmodule Livebook.Hubs.Dockerfile do startup = case to_string(config.clustering) do - "fly_io" -> + "auto" -> """ # --- Clustering --- # Set the same Livebook secrets across all nodes ENV LIVEBOOK_SECRET_KEY_BASE "#{secret_key_base}" ENV LIVEBOOK_COOKIE "#{cookie}" - ENV LIVEBOOK_CLUSTER "fly" + ENV LIVEBOOK_CLUSTER "auto" """ "dns" -> @@ -343,9 +343,9 @@ defmodule Livebook.Hubs.Dockerfile do clustering_env = case to_string(config.clustering) do - "fly_io" -> + "auto" -> [ - {"LIVEBOOK_CLUSTER", "fly"}, + {"LIVEBOOK_CLUSTER", "auto"}, {"LIVEBOOK_SECRET_KEY_BASE", secret_key_base}, {"LIVEBOOK_COOKIE", cookie} ] diff --git a/lib/livebook/teams/deployment_group.ex b/lib/livebook/teams/deployment_group.ex index 0a3fb2f56..d4f811fe0 100644 --- a/lib/livebook/teams/deployment_group.ex +++ b/lib/livebook/teams/deployment_group.ex @@ -12,7 +12,7 @@ defmodule Livebook.Teams.DeploymentGroup do field :name, :string field :mode, Ecto.Enum, values: [:online, :offline], default: :online field :hub_id, :string - field :clustering, Ecto.Enum, values: [:fly_io, :dns] + field :clustering, Ecto.Enum, values: [:auto, :dns] field :zta_provider, Ecto.Enum, values: @zta_providers field :zta_key, :string field :url, :string diff --git a/lib/livebook_web/components/app_components.ex b/lib/livebook_web/components/app_components.ex index 468885a0f..2d647c904 100644 --- a/lib/livebook_web/components/app_components.ex +++ b/lib/livebook_web/components/app_components.ex @@ -107,38 +107,42 @@ defmodule LivebookWeb.AppComponents do field={@form[:url]} /> - <.select_field - label="Clustering" - help={ - ~S''' - When running multiple - instances of Livebook, - they need to be connected - into a single cluster. - You must either deploy - it as a single instance - or choose a platform to - enable clustering on. - ''' - } - field={@form[:clustering]} - options={[ - {"Single instance", ""}, - {"Fly.io", "fly_io"}, - {"DNS", "dns"} - ]} - disabled={@disabled} - /> - -
- See the - - Clustering docs - - for more information. +
+ <.select_field + label="Clustering" + help={ + ~S''' + When running multiple + instances of Livebook, + they need to be connected + into a single cluster. + You must either deploy + it as a single instance + or choose a strategy to + connect the instances. + ''' + } + field={@form[:clustering]} + options={[ + {"Automatic", "auto"}, + {"DNS", "dns"}, + {"Single instance", ""} + ]} + disabled={@disabled} + /> +
+ See the + + Clustering docs + + for more information. +
+

+ Automatic clustering is available when deploying to Fly.io. +

diff --git a/lib/livebook_web/components/form_components.ex b/lib/livebook_web/components/form_components.ex index 3b4561ed7..e628d567e 100644 --- a/lib/livebook_web/components/form_components.ex +++ b/lib/livebook_web/components/form_components.ex @@ -494,7 +494,9 @@ defmodule LivebookWeb.FormComponents do {@rest} > - <%= Phoenix.HTML.Form.options_for_select(@options, @value) %> + <%!-- TODO: we use to_string to normalize nil and "", remove + this once fixed upstream https://github.com/phoenixframework/phoenix_html/issues/444 --%> + <%= Phoenix.HTML.Form.options_for_select(@options, to_string(@value)) %>
<.remix_icon icon="arrow-down-s-line" /> diff --git a/lib/livebook_web/live/hub/teams/deployment_group_agent_component.ex b/lib/livebook_web/live/hub/teams/deployment_group_agent_component.ex index 0c30b7a99..493a69e40 100644 --- a/lib/livebook_web/live/hub/teams/deployment_group_agent_component.ex +++ b/lib/livebook_web/live/hub/teams/deployment_group_agent_component.ex @@ -93,7 +93,7 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupAgentComponent do <%= if @agent_key_id do %>
- <.tabs id="deployment-instruction" default={default_tab(@deployment_group)}> + <.tabs id="deployment-instruction" default="docker"> <:tab id="docker" label="Docker">

@@ -145,9 +145,6 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupAgentComponent do String.slice(string, 0, preview_length) <> String.duplicate("•", length - preview_length) end - defp default_tab(%{clustering: :fly_io}), do: "fly_io" - defp default_tab(_deloyment_group), do: "docker" - @impl true def handle_event("select_agent_key", %{"agent_key" => %{"id" => id}}, socket) do id = if(id != "", do: id) @@ -216,7 +213,7 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupAgentComponent do fly secrets set \\ #{envs} - fly deploy + fly deploy --ha=false """ end end diff --git a/lib/livebook_web/live/hub/teams/deployment_group_form_component.ex b/lib/livebook_web/live/hub/teams/deployment_group_form_component.ex index 8b5a11566..fd8cc23d4 100644 --- a/lib/livebook_web/live/hub/teams/deployment_group_form_component.ex +++ b/lib/livebook_web/live/hub/teams/deployment_group_form_component.ex @@ -23,7 +23,11 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupFormComponent do %{} end - {:ok, assign_form(socket, Teams.change_deployment_group(%DeploymentGroup{}, attrs))} + {:ok, + assign_form( + socket, + Teams.change_deployment_group(%DeploymentGroup{clustering: :auto}, attrs) + )} end end diff --git a/rel/server/env.sh.eex b/rel/server/env.sh.eex index 7b2a03d08..2c32e2ffa 100644 --- a/rel/server/env.sh.eex +++ b/rel/server/env.sh.eex @@ -1,4 +1,4 @@ -if [ "$LIVEBOOK_CLUSTER" = "fly" ]; then +if [ "$LIVEBOOK_CLUSTER" = "auto" ] && [ ! -z "$FLY_APP_NAME" ]; then export ERL_AFLAGS="-proto_dist inet6_tcp" export LIVEBOOK_CLUSTER="dns:${FLY_APP_NAME}.internal" if [ ! -z "${LIVEBOOK_NODE}" ]; diff --git a/test/livebook/hubs/dockerfile_test.exs b/test/livebook/hubs/dockerfile_test.exs index 88ded9a6b..c205be864 100644 --- a/test/livebook/hubs/dockerfile_test.exs +++ b/test/livebook/hubs/dockerfile_test.exs @@ -198,14 +198,14 @@ defmodule Livebook.Hubs.DockerfileTest do """ end - test "deploying with fly.io cluster setup" do - config = dockerfile_config(%{clustering: :fly_io}) + test "deploying with auto cluster setup" do + config = dockerfile_config(%{clustering: :auto}) hub = personal_hub() file = Livebook.FileSystem.File.local(p("/notebook.livemd")) dockerfile = Dockerfile.airgapped_dockerfile(config, hub, [], [], file, [], %{}) - assert dockerfile =~ ~s/ENV LIVEBOOK_CLUSTER "fly"/ + assert dockerfile =~ ~s/ENV LIVEBOOK_CLUSTER "auto"/ end test "deploying with dns cluster setup" do @@ -258,13 +258,13 @@ defmodule Livebook.Hubs.DockerfileTest do end test "deploying with fly.io cluster setup" do - config = dockerfile_config(%{clustering: :fly_io}) + config = dockerfile_config(%{clustering: :auto}) hub = team_hub() agent_key = Livebook.Factory.build(:agent_key) %{env: env} = Dockerfile.online_docker_info(config, hub, agent_key) - assert {"LIVEBOOK_CLUSTER", "fly"} in env + assert {"LIVEBOOK_CLUSTER", "auto"} in env end test "deploying with dns cluster setup" do @@ -281,7 +281,7 @@ defmodule Livebook.Hubs.DockerfileTest do describe "warnings/6" do test "warns when session secrets are used" do - config = dockerfile_config(%{clustering: :fly_io}) + config = dockerfile_config(%{clustering: :auto}) hub = personal_hub() app_settings = Livebook.Notebook.AppSettings.new() @@ -295,7 +295,7 @@ defmodule Livebook.Hubs.DockerfileTest do end test "warns when hub secrets are used from personal hub" do - config = dockerfile_config(%{clustering: :fly_io}) + config = dockerfile_config(%{clustering: :auto}) hub = personal_hub() app_settings = Livebook.Notebook.AppSettings.new() @@ -319,7 +319,7 @@ defmodule Livebook.Hubs.DockerfileTest do end test "warns when there is a reference to external file system from personal hub" do - config = dockerfile_config(%{clustering: :fly_io}) + config = dockerfile_config(%{clustering: :auto}) hub = personal_hub() app_settings = Livebook.Notebook.AppSettings.new() @@ -346,7 +346,7 @@ defmodule Livebook.Hubs.DockerfileTest do end test "warns when deploying a directory in personal hub and it has any file systems" do - config = dockerfile_config(%{clustering: :fly_io, deploy_all: true}) + config = dockerfile_config(%{clustering: :auto, deploy_all: true}) hub = personal_hub() app_settings = Livebook.Notebook.AppSettings.new() @@ -361,7 +361,7 @@ defmodule Livebook.Hubs.DockerfileTest do end test "warns when the app has no password in personal hub" do - config = dockerfile_config(%{clustering: :fly_io}) + config = dockerfile_config(%{clustering: :auto}) hub = personal_hub() app_settings = %{Livebook.Notebook.AppSettings.new() | access_type: :public} @@ -370,7 +370,7 @@ defmodule Livebook.Hubs.DockerfileTest do end test "warns when the app has no password and no ZTA in teams hub" do - config = dockerfile_config(%{clustering: :fly_io}) + config = dockerfile_config(%{clustering: :auto}) hub = team_hub() app_settings = %{Livebook.Notebook.AppSettings.new() | access_type: :public} @@ -390,7 +390,7 @@ defmodule Livebook.Hubs.DockerfileTest do assert [warning] = Dockerfile.airgapped_warnings(config, hub, [], [], app_settings, [], %{}) assert warning =~ "The deployment is not configured for clustering" - config = %{config | clustering: :fly_io} + config = %{config | clustering: :auto} assert [] = Dockerfile.airgapped_warnings(config, hub, [], [], app_settings, [], %{}) end