From 79ebc81144daa8c695879f63cac4d61e80191e0f Mon Sep 17 00:00:00 2001 From: "M. Adil Fayyaz" <62440954+AdilFayyaz@users.noreply.github.com> Date: Tue, 21 Apr 2026 14:35:06 -0700 Subject: [PATCH 1/6] feat: path based ingress routing for Flyte apps via Traefik + Knative Signed-off-by: M. Adil Fayyaz <62440954+AdilFayyaz@users.noreply.github.com> --- Dockerfile | 1 + Makefile | 37 +- app/config/config.go | 48 + app/internal/config/config.go | 20 +- app/internal/k8s/app_client.go | 353 +++- app/internal/k8s/app_client_test.go | 58 +- app/internal/service/internal_app_service.go | 52 +- .../service/internal_app_service_test.go | 31 +- app/internal/setup.go | 3 +- app/service/app_service.go | 82 +- app/service/app_service_test.go | 16 +- app/setup.go | 7 + .../templates/proxy/traefik-config.yaml | 23 + charts/flyte-sandbox/values.yaml | 185 ++ docker/sandbox-bundled/Makefile | 137 ++ .../sandbox-bundled/manifests/complete.yaml | 1610 +++++++++++++++++ docker/sandbox-bundled/manifests/dev.yaml | 1207 ++++++++++++ flytestdlib/app/app.go | 33 + manager/cmd/main.go | 14 + manager/config.yaml | 40 +- manager/config/config.go | 21 +- runs/config/config.go | 30 - runs/setup.go | 15 +- 23 files changed, 3742 insertions(+), 281 deletions(-) create mode 100644 charts/flyte-sandbox/templates/proxy/traefik-config.yaml create mode 100644 charts/flyte-sandbox/values.yaml create mode 100644 docker/sandbox-bundled/Makefile create mode 100644 docker/sandbox-bundled/manifests/complete.yaml create mode 100644 docker/sandbox-bundled/manifests/dev.yaml diff --git a/Dockerfile b/Dockerfile index d43a445e531..d3bf838fdd0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,6 +17,7 @@ COPY flyteplugins flyteplugins COPY flytestdlib flytestdlib COPY gen/go gen/go COPY actions actions +COPY app app COPY events events COPY runs runs COPY cache_service cache_service diff --git a/Makefile b/Makefile index b983a494d86..d42832464f7 100644 --- a/Makefile +++ b/Makefile @@ -36,33 +36,18 @@ build: verify ## Build all Go service binaries # ============================================================================= .PHONY: sandbox-build -sandbox-build: ## Build and start the flyte sandbox (docker/devbox-bundled) - $(MAKE) -C docker/devbox-bundled build +sandbox-build: ## Build and start the flyte sandbox (docker/sandbox-bundled) + $(MAKE) -C docker/sandbox-bundled build # Run in dev mode with extra arg FLYTE_DEV=True .PHONY: sandbox-run -sandbox-run: ## Start the flyte sandbox without rebuilding the image - $(MAKE) -C docker/devbox-bundled start +sandbox-run: ## Start the flyte sandbox and install Knative with app routing config + $(MAKE) -C docker/sandbox-bundled start FLYTE_DEV=$(FLYTE_DEV) + $(MAKE) -C docker/sandbox-bundled setup-knative .PHONY: sandbox-stop sandbox-stop: ## Stop the flyte sandbox - $(MAKE) -C docker/devbox-bundled stop - -# ============================================================================= -# Devbox Commands -# ============================================================================= - -.PHONY: devbox-build -devbox-build: ## Build and start the flyte devbox cluster (docker/devbox-bundled) - $(MAKE) -C docker/devbox-bundled build - -.PHONY: devbox-run -devbox-run: ## Start the flyte devbox cluster without rebuilding the image - $(MAKE) -C docker/devbox-bundled start - -.PHONY: devbox-stop -devbox-stop: ## Stop the flyte devbox cluster - $(MAKE) -C docker/devbox-bundled stop + $(MAKE) -C docker/sandbox-bundled stop .PHONY: help help: ## Show this help message @@ -83,10 +68,9 @@ sep: # Helper to time a step: $(call timed,step_name,command) define timed @start=$$(date +%s); \ - $(2); rc=$$?; \ + $(2); \ elapsed=$$(( $$(date +%s) - $$start )); \ - echo "⏱ $(1) completed in $${elapsed}s"; \ - exit $$rc + echo "⏱ $(1) completed in $${elapsed}s" endef .PHONY: buf-dep @@ -170,11 +154,6 @@ gen-local: buf mocks go-tidy ## Generate everything using local tools (requires @echo '⚡ Finished generating everything in the gen directory (local)' @$(MAKE) sep -.PHONY: check-crate -check-crate: ## Verify Rust crate compiles using local cargo (faster, no artifacts) - @echo 'Cargo check the generated rust code (local)' - cd gen/rust && cargo check - .PHONY: build-crate build-crate: ## Build Rust crate using local cargo @echo 'Cargo build the generated rust code (local)' diff --git a/app/config/config.go b/app/config/config.go index 6532f30b5c0..b62ad3c1a2a 100644 --- a/app/config/config.go +++ b/app/config/config.go @@ -20,3 +20,51 @@ func DefaultAppConfig() *AppConfig { CacheTTL: 30 * time.Second, } } + +// InternalAppConfig holds configuration for the data plane InternalAppService. +type InternalAppConfig struct { + // Enabled controls whether the InternalAppService is started. + Enabled bool `json:"enabled" pflag:",Enable app deployment controller"` + + // BaseDomain is the base domain used to generate public URLs for apps. + // Apps are exposed at "{name}-{project}-{domain}.{base_domain}". + BaseDomain string `json:"baseDomain" pflag:",Base domain for app public URLs"` + + // Scheme is the URL scheme used for public app URLs ("http" or "https"). + // Defaults to "https" if unset. + Scheme string `json:"scheme" pflag:",URL scheme for app public URLs (http or https)"` + + // DefaultRequestTimeout is the request timeout applied to apps that don't specify one. + DefaultRequestTimeout time.Duration `json:"defaultRequestTimeout" pflag:",Default request timeout for apps"` + + // MaxRequestTimeout is the hard cap on request timeout (Knative max is 3600s). + MaxRequestTimeout time.Duration `json:"maxRequestTimeout" pflag:",Maximum allowed request timeout for apps"` + + // IngressEnabled controls whether a Traefik IngressRoute and Middleware are + // created for each deployed app so it is reachable at + // /// through the Traefik ingress controller. + // Enable this for sandbox/local setups where Traefik is the ingress controller. + IngressEnabled bool `json:"ingressEnabled" pflag:",Create Traefik IngressRoute for each app"` + + // IngressEntryPoint is the Traefik entry point name that app routes are + // attached to (default: "web"). + IngressEntryPoint string `json:"ingressEntryPoint" pflag:",Traefik entry point name for app ingress routes"` + + // IngressBaseURL is the externally reachable base URL of the ingress controller + // (e.g. "http://localhost:30080"). When set, the public URL surfaced for each app + // is built as {IngressBaseURL}/{project}/{domain}/{app} instead of the Knative + // host-based URL. Only used when IngressEnabled is true. + IngressBaseURL string `json:"ingressBaseUrl" pflag:",Base URL of the ingress controller for app public URLs"` + + // DefaultEnvVars is a list of environment variables injected into every KService + // pod at deploy time, in addition to any env vars specified in the app spec. + // Use this to inject cluster-internal endpoints (e.g. _U_EP_OVERRIDE) that app + // processes need to connect back to the Flyte manager. + DefaultEnvVars []EnvVar `json:"defaultEnvVars" pflag:"-,Default env vars injected into every app pod"` +} + +// EnvVar is a name/value environment variable pair for app pod injection. +type EnvVar struct { + Name string `json:"name"` + Value string `json:"value"` +} diff --git a/app/internal/config/config.go b/app/internal/config/config.go index 17e9e01dc23..4aa836ca222 100644 --- a/app/internal/config/config.go +++ b/app/internal/config/config.go @@ -1,19 +1,7 @@ package config -import "time" +import appconfig "github.com/flyteorg/flyte/v2/app/config" -// InternalAppConfig holds configuration for the data plane app deployment controller. -type InternalAppConfig struct { - // Enabled controls whether the app deployment controller is started. - Enabled bool `json:"enabled" pflag:",Enable app deployment controller"` - - // BaseDomain is the base domain used to generate public URLs for apps. - // Apps are exposed at "{name}-{project}-{domain}.{base_domain}". - BaseDomain string `json:"baseDomain" pflag:",Base domain for app public URLs"` - - // DefaultRequestTimeout is the request timeout applied to apps that don't specify one. - DefaultRequestTimeout time.Duration `json:"defaultRequestTimeout" pflag:",Default request timeout for apps"` - - // MaxRequestTimeout is the hard cap on request timeout (Knative max is 3600s). - MaxRequestTimeout time.Duration `json:"maxRequestTimeout" pflag:",Maximum allowed request timeout for apps"` -} +// InternalAppConfig is an alias of the public config type so internal packages +// can import it without depending on the public app/config path directly. +type InternalAppConfig = appconfig.InternalAppConfig diff --git a/app/internal/k8s/app_client.go b/app/internal/k8s/app_client.go index 474823529e6..924f9b39068 100644 --- a/app/internal/k8s/app_client.go +++ b/app/internal/k8s/app_client.go @@ -13,7 +13,10 @@ import ( timestamppb "google.golang.org/protobuf/types/known/timestamppb" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" + k8sresource "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" k8swatch "k8s.io/apimachinery/pkg/watch" servingv1 "knative.dev/serving/pkg/apis/serving/v1" @@ -21,8 +24,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/flyteorg/flyte/v2/app/internal/config" + "github.com/flyteorg/flyte/v2/flytestdlib/k8s" "github.com/flyteorg/flyte/v2/flytestdlib/logger" flyteapp "github.com/flyteorg/flyte/v2/gen/go/flyteidl2/app" + flytecore "github.com/flyteorg/flyte/v2/gen/go/flyteidl2/core" ) const ( @@ -40,6 +45,11 @@ const ( maxKServiceNameLen = 63 ) +var ( + traefikIngressRouteGVK = schema.GroupVersionKind{Group: "traefik.io", Version: "v1alpha1", Kind: "IngressRoute"} + traefikMiddlewareGVK = schema.GroupVersionKind{Group: "traefik.io", Version: "v1alpha1", Kind: "Middleware"} +) + // AppK8sClientInterface defines the KService lifecycle operations for the App service. type AppK8sClientInterface interface { // Deploy creates or updates the KService for the given app. Idempotent — skips @@ -55,10 +65,9 @@ type AppK8sClientInterface interface { GetStatus(ctx context.Context, appID *flyteapp.Identifier) (*flyteapp.Status, error) // List returns apps for the given project/domain scope with optional pagination. - // If appName is non-empty, only the app with that name is returned. // limit=0 means no limit. token is the K8s continue token from a previous call. // Returns the apps, the continue token for the next page (empty if last page), and any error. - List(ctx context.Context, project, domain, appName string, limit uint32, token string) ([]*flyteapp.App, string, error) + List(ctx context.Context, project, domain string, limit uint32, token string) ([]*flyteapp.App, string, error) // Delete removes the KService CRD entirely. The app must be re-created from scratch. // Use Stop to scale to zero while preserving the KService. @@ -104,6 +113,10 @@ func (c *AppK8sClient) Deploy(ctx context.Context, app *flyteapp.App) error { ns := appNamespace(appID.GetProject(), appID.GetDomain()) name := kserviceName(appID) + if err := k8s.EnsureNamespaceExists(ctx, c.k8sClient, ns); err != nil { + return fmt.Errorf("failed to ensure namespace %s: %w", ns, err) + } + ksvc, err := c.buildKService(app) if err != nil { return fmt.Errorf("failed to build KService for app %s: %w", name, err) @@ -116,26 +129,40 @@ func (c *AppK8sClient) Deploy(ctx context.Context, app *flyteapp.App) error { return fmt.Errorf("failed to create KService %s: %w", name, err) } logger.Infof(ctx, "Created KService %s/%s", ns, name) - return nil + return c.deployIngress(ctx, app) } if err != nil { return fmt.Errorf("failed to get KService %s: %w", name, err) } - // Skip update if spec has not changed. + // Skip KService update if spec has not changed, but still ensure ingress exists + // (it may be missing if the app was deployed before ingress support was added). if existing.Annotations[annotationSpecSHA] == ksvc.Annotations[annotationSpecSHA] { logger.Debugf(ctx, "KService %s/%s spec unchanged, skipping update", ns, name) - return nil + return c.deployIngress(ctx, app) } existing.Spec = ksvc.Spec - existing.Labels = ksvc.Labels - existing.Annotations = ksvc.Annotations + // Merge labels and annotations rather than replacing them wholesale. + // Knative sets immutable annotations (e.g. serving.knative.dev/creator) + // on creation; overwriting them causes the admission webhook to reject the update. + if existing.Labels == nil { + existing.Labels = make(map[string]string) + } + for k, v := range ksvc.Labels { + existing.Labels[k] = v + } + if existing.Annotations == nil { + existing.Annotations = make(map[string]string) + } + for k, v := range ksvc.Annotations { + existing.Annotations[k] = v + } if err := c.k8sClient.Update(ctx, existing); err != nil { return fmt.Errorf("failed to update KService %s: %w", name, err) } logger.Infof(ctx, "Updated KService %s/%s", ns, name) - return nil + return c.deployIngress(ctx, app) } // Stop sets max-scale=0 on the KService, scaling it to zero without deleting it. @@ -166,11 +193,13 @@ func (c *AppK8sClient) Delete(ctx context.Context, appID *flyteapp.Identifier) e ksvc.Namespace = ns if err := c.k8sClient.Delete(ctx, ksvc); err != nil { if k8serrors.IsNotFound(err) { + c.deleteIngress(ctx, appID) return nil } return fmt.Errorf("failed to delete KService %s: %w", name, err) } logger.Infof(ctx, "Deleted KService %s/%s", ns, name) + c.deleteIngress(ctx, appID) return nil } @@ -232,17 +261,18 @@ func (c *AppK8sClient) Watch(ctx context.Context, project, domain, appName strin } // openWatch starts a K8s watch from resourceVersion (empty = watch from now). -// AllowWatchBookmarks is always set so K8s sends Bookmark events on every session, -// keeping lastResourceVersion current even when no objects change. func (c *AppK8sClient) openWatch(ctx context.Context, ns string, labels map[string]string, resourceVersion string) (k8swatch.Interface, error) { - rawOpts := &metav1.ListOptions{AllowWatchBookmarks: true} - if resourceVersion != "" { - rawOpts.ResourceVersion = resourceVersion - } opts := []client.ListOption{ client.InNamespace(ns), client.MatchingLabels(labels), - &client.ListOptions{Raw: rawOpts}, + } + if resourceVersion != "" { + opts = append(opts, &client.ListOptions{ + Raw: &metav1.ListOptions{ + ResourceVersion: resourceVersion, + AllowWatchBookmarks: true, + }, + }) } watcher, err := c.k8sClient.Watch(ctx, &servingv1.ServiceList{}, opts...) if err != nil { @@ -252,9 +282,7 @@ func (c *AppK8sClient) openWatch(ctx context.Context, ns string, labels map[stri } // watchLoop is the reconnect loop. It drains watcher until it closes, then -// reopens. Exponential backoff is applied only on K8s Error events; normal -// watch timeouts (clean channel close) reconnect immediately. Closes ch only -// when ctx is cancelled. +// reopens with exponential backoff. Closes ch only when ctx is cancelled. func (c *AppK8sClient) watchLoop( ctx context.Context, ns string, @@ -268,27 +296,21 @@ func (c *AppK8sClient) watchLoop( state := &watchState{backoff: watchBackoffInitial} for { - reconnect, isError := c.drainWatcher(ctx, watcher, ch, state) + reconnect := c.drainWatcher(ctx, watcher, ch, state) if !reconnect { return // ctx cancelled } watcher.Stop() + state.consecutiveErrors++ + delay := state.nextBackoff() + logger.Warnf(ctx, "KService watch in namespace %s closed unexpectedly (attempt %d); reconnecting in %v", + ns, state.consecutiveErrors, delay) - if isError { - state.consecutiveErrors++ - delay := state.nextBackoff() - logger.Warnf(ctx, "KService watch in namespace %s closed with error (attempt %d); reconnecting in %v", - ns, state.consecutiveErrors, delay) - select { - case <-ctx.Done(): - return - case <-time.After(delay): - } - } else { - // Normal K8s watch timeout — reconnect immediately, no backoff. - state.resetBackoff() - logger.Debugf(ctx, "KService watch in namespace %s timed out naturally; reconnecting", ns) + select { + case <-ctx.Done(): + return + case <-time.After(delay): } newWatcher, err := c.openWatch(ctx, ns, labels, state.lastResourceVersion) @@ -303,23 +325,24 @@ func (c *AppK8sClient) watchLoop( } // drainWatcher processes events from watcher until the channel closes or ctx is done. -// Returns (reconnect, isError): reconnect=false means ctx was cancelled (stop the loop); -// isError=true means a K8s Error event triggered the close and backoff should be applied. +// Returns true if reconnect is needed, false if ctx was cancelled. func (c *AppK8sClient) drainWatcher( ctx context.Context, watcher k8swatch.Interface, ch chan<- *flyteapp.WatchResponse, state *watchState, -) (bool, bool) { +) bool { for { select { case <-ctx.Done(): - return false, false + return false case event, ok := <-watcher.ResultChan(): if !ok { - return true, false // normal K8s watch timeout + return true } + c.updateResourceVersion(event, state) + switch event.Type { case k8swatch.Error: if status, ok := event.Object.(*metav1.Status); ok { @@ -328,24 +351,20 @@ func (c *AppK8sClient) drainWatcher( } else { logger.Warnf(ctx, "KService watch received error event (type %T); will reconnect", event.Object) } - return true, true // error — apply backoff on reconnect + return true case k8swatch.Bookmark: - // Update RV immediately — there is no delivery to confirm. - c.updateResourceVersion(event, state) + // resourceVersion already updated — nothing to forward. state.resetBackoff() default: resp := c.kserviceEventToWatchResponse(ctx, event) if resp == nil { continue } + state.resetBackoff() select { case ch <- resp: - // Advance RV only after confirmed delivery so a failed send - // doesn't silently skip the event on the next reconnect. - c.updateResourceVersion(event, state) - state.resetBackoff() case <-ctx.Done(): - return false, false + return false } } } @@ -353,7 +372,7 @@ func (c *AppK8sClient) drainWatcher( } // updateResourceVersion extracts and stores the latest resourceVersion from a watch event. -// For Bookmark events it is called immediately; for data events only after successful delivery. +// Called before event type dispatch so both normal events and Bookmarks checkpoint the position. func (c *AppK8sClient) updateResourceVersion(event k8swatch.Event, state *watchState) { switch event.Type { case k8swatch.Added, k8swatch.Modified, k8swatch.Deleted, k8swatch.Bookmark: @@ -416,16 +435,12 @@ func (c *AppK8sClient) GetStatus(ctx context.Context, appID *flyteapp.Identifier } // List returns apps for the given project/domain scope with optional pagination. -func (c *AppK8sClient) List(ctx context.Context, project, domain, appName string, limit uint32, token string) ([]*flyteapp.App, string, error) { +func (c *AppK8sClient) List(ctx context.Context, project, domain string, limit uint32, token string) ([]*flyteapp.App, string, error) { ns := appNamespace(project, domain) - matchLabels := client.MatchingLabels{labelAppManaged: "true"} - if appName != "" { - matchLabels[labelAppName] = strings.ToLower(appName) - } listOpts := []client.ListOption{ client.InNamespace(ns), - matchLabels, + client.MatchingLabels{labelAppManaged: "true"}, } if limit > 0 { listOpts = append(listOpts, client.Limit(int64(limit))) @@ -451,6 +466,156 @@ func (c *AppK8sClient) List(ctx context.Context, project, domain, appName string return apps, list.Continue, nil } +// publicIngress returns the deterministic public URL for an app using the same +// logic as the service layer so GetStatus/List/Watch are consistent with Create. +func (c *AppK8sClient) publicIngress(id *flyteapp.Identifier) *flyteapp.Ingress { + if c.cfg.IngressEnabled && c.cfg.IngressBaseURL != "" { + return &flyteapp.Ingress{ + PublicUrl: fmt.Sprintf("%s/%s/%s/%s", + strings.TrimRight(c.cfg.IngressBaseURL, "/"), + id.GetProject(), id.GetDomain(), id.GetName(), + ), + } + } + if c.cfg.BaseDomain == "" { + return nil + } + scheme := c.cfg.Scheme + if scheme == "" { + scheme = "https" + } + host := strings.ToLower(fmt.Sprintf("%s-%s-%s.%s", + id.GetName(), id.GetProject(), id.GetDomain(), c.cfg.BaseDomain)) + return &flyteapp.Ingress{PublicUrl: scheme + "://" + host} +} + +// deployIngress creates or updates the Traefik resources for the given app: +// - strip- Middleware: strips /// prefix +// - host- Middleware: rewrites Host to the Knative hostname so Kourier +// can route the request (Knative's K8s service is ExternalName → Kourier) +// - app- IngressRoute: matches PathPrefix and chains both middlewares +// +// No-ops when IngressEnabled is false. +func (c *AppK8sClient) deployIngress(ctx context.Context, app *flyteapp.App) error { + if !c.cfg.IngressEnabled { + return nil + } + appID := app.GetMetadata().GetId() + ns := appNamespace(appID.GetProject(), appID.GetDomain()) + ksvcName := kserviceName(appID) + stripName := "strip-" + ksvcName + hostName := "host-" + ksvcName + routeName := "app-" + ksvcName + pathPrefix := fmt.Sprintf("/%s/%s/%s", appID.GetProject(), appID.GetDomain(), appID.GetName()) + entryPoint := c.cfg.IngressEntryPoint + if entryPoint == "" { + entryPoint = "web" + } + + // Knative's K8s service is ExternalName → kourier-internal. Kourier routes by + // Host header, so we must rewrite it to the deterministic Knative hostname. + // hostname pattern matches the configured domain-template: {name}-{namespace}.{domain} + knativeHost := fmt.Sprintf("%s-%s.%s", ksvcName, ns, c.cfg.BaseDomain) + + stripMW := &unstructured.Unstructured{} + stripMW.SetGroupVersionKind(traefikMiddlewareGVK) + stripMW.SetName(stripName) + stripMW.SetNamespace(ns) + stripMW.Object["spec"] = map[string]interface{}{ + "stripPrefix": map[string]interface{}{ + "prefixes": []interface{}{pathPrefix}, + }, + } + + hostMW := &unstructured.Unstructured{} + hostMW.SetGroupVersionKind(traefikMiddlewareGVK) + hostMW.SetName(hostName) + hostMW.SetNamespace(ns) + hostMW.Object["spec"] = map[string]interface{}{ + "headers": map[string]interface{}{ + "customRequestHeaders": map[string]interface{}{ + "Host": knativeHost, + }, + }, + } + + ir := &unstructured.Unstructured{} + ir.SetGroupVersionKind(traefikIngressRouteGVK) + ir.SetName(routeName) + ir.SetNamespace(ns) + ir.Object["spec"] = map[string]interface{}{ + "entryPoints": []interface{}{entryPoint}, + "routes": []interface{}{ + map[string]interface{}{ + "match": fmt.Sprintf("PathPrefix(`%s`)", pathPrefix), + "kind": "Rule", + "middlewares": []interface{}{ + map[string]interface{}{"name": stripName}, + map[string]interface{}{"name": hostName}, + }, + "services": []interface{}{ + map[string]interface{}{ + "name": ksvcName, + "port": int64(80), + }, + }, + }, + }, + } + + for _, obj := range []*unstructured.Unstructured{stripMW, hostMW, ir} { + existing := &unstructured.Unstructured{} + existing.SetGroupVersionKind(obj.GroupVersionKind()) + err := c.k8sClient.Get(ctx, client.ObjectKey{Name: obj.GetName(), Namespace: obj.GetNamespace()}, existing) + if k8serrors.IsNotFound(err) { + if createErr := c.k8sClient.Create(ctx, obj); createErr != nil { + return fmt.Errorf("failed to create %s %s/%s: %w", obj.GetKind(), ns, obj.GetName(), createErr) + } + logger.Infof(ctx, "Created %s %s/%s", obj.GetKind(), ns, obj.GetName()) + } else if err != nil { + return fmt.Errorf("failed to get %s %s/%s: %w", obj.GetKind(), ns, obj.GetName(), err) + } else { + obj.SetResourceVersion(existing.GetResourceVersion()) + if updateErr := c.k8sClient.Update(ctx, obj); updateErr != nil { + return fmt.Errorf("failed to update %s %s/%s: %w", obj.GetKind(), ns, obj.GetName(), updateErr) + } + logger.Infof(ctx, "Updated %s %s/%s", obj.GetKind(), ns, obj.GetName()) + } + } + return nil +} + +// deleteIngress removes the Traefik IngressRoute and both Middlewares for the given app. +// Errors are logged as warnings — ingress cleanup failure does not block app deletion. +func (c *AppK8sClient) deleteIngress(ctx context.Context, appID *flyteapp.Identifier) { + if !c.cfg.IngressEnabled { + return + } + ns := appNamespace(appID.GetProject(), appID.GetDomain()) + ksvcName := kserviceName(appID) + + type resource struct { + gvk schema.GroupVersionKind + name string + } + resources := []resource{ + {traefikIngressRouteGVK, "app-" + ksvcName}, + {traefikMiddlewareGVK, "strip-" + ksvcName}, + {traefikMiddlewareGVK, "host-" + ksvcName}, + } + for _, r := range resources { + obj := &unstructured.Unstructured{} + obj.SetGroupVersionKind(r.gvk) + obj.SetName(r.name) + obj.SetNamespace(ns) + if err := c.k8sClient.Delete(ctx, obj); err != nil && !k8serrors.IsNotFound(err) { + logger.Warnf(ctx, "Failed to delete %s %s/%s: %v", r.gvk.Kind, ns, r.name, err) + } else { + logger.Infof(ctx, "Deleted %s %s/%s", r.gvk.Kind, ns, r.name) + } + } +} + // --- Helpers --- // kserviceName returns the KService name for an app. Since each app is deployed @@ -495,6 +660,15 @@ func (c *AppK8sClient) buildKService(app *flyteapp.App) (*servingv1.Service, err if err != nil { return nil, err } + // Inject cluster-level default env vars (e.g. _U_EP_OVERRIDE) before user vars + // so they can be overridden by app-specific env vars if needed. + if len(c.cfg.DefaultEnvVars) > 0 && len(podSpec.Containers) > 0 { + defaults := make([]corev1.EnvVar, 0, len(c.cfg.DefaultEnvVars)) + for _, e := range c.cfg.DefaultEnvVars { + defaults = append(defaults, corev1.EnvVar{Name: e.Name, Value: e.Value}) + } + podSpec.Containers[0].Env = append(defaults, podSpec.Containers[0].Env...) + } templateAnnotations := buildAutoscalingAnnotations(spec, c.cfg) @@ -546,9 +720,10 @@ func buildPodSpec(spec *flyteapp.Spec) (corev1.PodSpec, error) { case *flyteapp.Spec_Container: c := p.Container container := corev1.Container{ - Name: "app", - Image: c.GetImage(), - Args: c.GetArgs(), + Name: "app", + Image: c.GetImage(), + Command: c.GetCommand(), + Args: c.GetArgs(), } for _, e := range c.GetEnv() { container.Env = append(container.Env, corev1.EnvVar{ @@ -556,7 +731,17 @@ func buildPodSpec(spec *flyteapp.Spec) (corev1.PodSpec, error) { Value: e.GetValue(), }) } - return corev1.PodSpec{Containers: []corev1.Container{container}}, nil + for _, p := range c.GetPorts() { + container.Ports = append(container.Ports, corev1.ContainerPort{ + ContainerPort: int32(p.GetContainerPort()), + Name: p.GetName(), + }) + } + container.Resources = buildResourceRequirements(c.GetResources()) + return corev1.PodSpec{ + Containers: []corev1.Container{container}, + EnableServiceLinks: boolPtr(false), + }, nil case *flyteapp.Spec_Pod: // K8sPod payloads are not yet supported — the pod spec serialization @@ -568,6 +753,49 @@ func buildPodSpec(spec *flyteapp.Spec) (corev1.PodSpec, error) { } } +// buildResourceRequirements maps flyteidl2 Resources to corev1.ResourceRequirements. +func buildResourceRequirements(res *flytecore.Resources) corev1.ResourceRequirements { + if res == nil { + return corev1.ResourceRequirements{} + } + reqs := corev1.ResourceRequirements{} + if len(res.GetRequests()) > 0 { + reqs.Requests = make(corev1.ResourceList) + for _, e := range res.GetRequests() { + if name, ok := protoResourceName(e.GetName()); ok { + reqs.Requests[name] = k8sresource.MustParse(e.GetValue()) + } + } + } + if len(res.GetLimits()) > 0 { + reqs.Limits = make(corev1.ResourceList) + for _, e := range res.GetLimits() { + if name, ok := protoResourceName(e.GetName()); ok { + reqs.Limits[name] = k8sresource.MustParse(e.GetValue()) + } + } + } + return reqs +} + +// protoResourceName maps a flyteidl2 ResourceName to the equivalent corev1.ResourceName. +func protoResourceName(name flytecore.Resources_ResourceName) (corev1.ResourceName, bool) { + switch name { + case flytecore.Resources_CPU: + return corev1.ResourceCPU, true + case flytecore.Resources_MEMORY: + return corev1.ResourceMemory, true + case flytecore.Resources_STORAGE: + return corev1.ResourceStorage, true + case flytecore.Resources_EPHEMERAL_STORAGE: + return corev1.ResourceEphemeralStorage, true + default: + return "", false + } +} + +func boolPtr(b bool) *bool { return &b } + // buildAutoscalingAnnotations returns the Knative autoscaling annotations for the revision template. func buildAutoscalingAnnotations(spec *flyteapp.Spec, cfg *config.InternalAppConfig) map[string]string { annotations := map[string]string{} @@ -644,10 +872,13 @@ func (c *AppK8sClient) kserviceToStatus(ctx context.Context, ksvc *servingv1.Ser status := statusWithPhase(phase, message) - // Populate ingress URL from KService route status. - if url := ksvc.Status.URL; url != nil { - status.Ingress = &flyteapp.Ingress{ - PublicUrl: url.String(), + // Populate ingress URL from the app annotation so the URL is consistent + // with the Create response regardless of Knative route readiness. + if appIDStr := ksvc.Annotations[annotationAppID]; appIDStr != "" { + parts := strings.SplitN(appIDStr, "/", 3) + if len(parts) == 3 { + appID := &flyteapp.Identifier{Project: parts[0], Domain: parts[1], Name: parts[2]} + status.Ingress = c.publicIngress(appID) } } diff --git a/app/internal/k8s/app_client_test.go b/app/internal/k8s/app_client_test.go index cb04428a297..38c31127051 100644 --- a/app/internal/k8s/app_client_test.go +++ b/app/internal/k8s/app_client_test.go @@ -285,7 +285,7 @@ func TestList(t *testing.T) { }, } - apps, nextToken, err := c.List(context.Background(), "proj", "dev", "", 0, "") + apps, nextToken, err := c.List(context.Background(), "proj", "dev", 0, "") require.NoError(t, err) assert.Empty(t, nextToken) require.Len(t, apps, 1) @@ -682,54 +682,12 @@ func TestWatch_ExponentialBackoff(t *testing.T) { watchBackoffMax = 30 * time.Second }) - // Four watchers that each emit an Error event — only Error events trigger backoff. - // NewFakeWithChanSize(1,...) gives a buffer of 1 so pre-sends don't block before - // the consumer goroutine starts (NewFake() is unbuffered). - calls := make([]watchCall, 4) - for i := range calls { - w := k8swatch.NewFakeWithChanSize(1, false) - calls[i] = watchCall{watcher: w} - w.Error(&metav1.Status{Code: 410, Reason: metav1.StatusReasonExpired, Message: "resource version too old"}) - } - - c, mwc := newMultiClient(t, calls) - - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) - defer cancel() - - start := time.Now() - ch, err := c.Watch(ctx, "proj", "dev", "") - require.NoError(t, err) - - // Wait until at least 4 Watch() calls have been made. - require.Eventually(t, func() bool { - mwc.mu.Lock() - defer mwc.mu.Unlock() - return len(mwc.capturedRVs) >= 4 - }, 2*time.Second, 5*time.Millisecond) - - elapsed := time.Since(start) - // With 10ms+20ms+40ms backoffs before 4th call, minimum elapsed ≈ 70ms. - assert.GreaterOrEqual(t, elapsed, 60*time.Millisecond, "backoff should accumulate across error reconnects") - - cancel() - for range ch { - } -} - -func TestWatch_CleanCloseNoBackoff(t *testing.T) { - watchBackoffInitial = 50 * time.Millisecond - watchBackoffMax = 200 * time.Millisecond - t.Cleanup(func() { - watchBackoffInitial = 1 * time.Second - watchBackoffMax = 30 * time.Second - }) - - // Three watchers that close immediately (clean channel close, no Error event). + // Four watchers that each close immediately. calls := []watchCall{ {watcher: k8swatch.NewFake()}, {watcher: k8swatch.NewFake()}, {watcher: k8swatch.NewFake()}, + {watcher: k8swatch.NewFake()}, } for _, wc := range calls { wc.watcher.(*k8swatch.FakeWatcher).Stop() @@ -744,17 +702,19 @@ func TestWatch_CleanCloseNoBackoff(t *testing.T) { ch, err := c.Watch(ctx, "proj", "dev", "") require.NoError(t, err) + // Wait until at least 4 Watch() calls have been made. require.Eventually(t, func() bool { mwc.mu.Lock() defer mwc.mu.Unlock() - return len(mwc.capturedRVs) >= 3 - }, 500*time.Millisecond, 5*time.Millisecond) + return len(mwc.capturedRVs) >= 4 + }, 2*time.Second, 5*time.Millisecond) elapsed := time.Since(start) - // Clean closes must not apply backoff — all 3 reconnects should be nearly instant. - assert.Less(t, elapsed, 30*time.Millisecond, "clean closes should not apply backoff delay") + // With 10ms+20ms+40ms backoffs before 4th call, minimum elapsed ≈ 70ms. + assert.GreaterOrEqual(t, elapsed, 60*time.Millisecond, "backoff should accumulate across reconnects") cancel() + // Drain the channel to let the goroutine exit. for range ch { } } diff --git a/app/internal/service/internal_app_service.go b/app/internal/service/internal_app_service.go index dc847ec4823..348b36acd8d 100644 --- a/app/internal/service/internal_app_service.go +++ b/app/internal/service/internal_app_service.go @@ -7,7 +7,6 @@ import ( "connectrpc.com/connect" timestamppb "google.golang.org/protobuf/types/known/timestamppb" - k8serrors "k8s.io/apimachinery/pkg/api/errors" appconfig "github.com/flyteorg/flyte/v2/app/internal/config" appk8s "github.com/flyteorg/flyte/v2/app/internal/k8s" @@ -61,23 +60,37 @@ func (s *InternalAppService) Create( LastTransitionTime: timestamppb.Now(), }, }, - Ingress: publicIngress(app.GetMetadata().GetId(), s.cfg.BaseDomain), + Ingress: publicIngress(app.GetMetadata().GetId(), s.cfg), } return connect.NewResponse(&flyteapp.CreateResponse{App: app}), nil } // publicIngress builds the deterministic public URL for an app. -// Pattern: "https://{name}-{project}-{domain}.{base_domain}" -// Returns nil if BaseDomain is not configured. -func publicIngress(id *flyteapp.Identifier, baseDomain string) *flyteapp.Ingress { - if baseDomain == "" { +// When Traefik ingress is enabled (IngressEnabled + IngressBaseURL), the URL is +// path-based: {base}/{project}/{domain}/{app}. +// Otherwise falls back to the Knative host pattern: {scheme}://{name}-{project}-{domain}.{base_domain}. +// Returns nil if neither is configured. +func publicIngress(id *flyteapp.Identifier, cfg *appconfig.InternalAppConfig) *flyteapp.Ingress { + if cfg.IngressEnabled && cfg.IngressBaseURL != "" { + return &flyteapp.Ingress{ + PublicUrl: fmt.Sprintf("%s/%s/%s/%s", + strings.TrimRight(cfg.IngressBaseURL, "/"), + id.GetProject(), id.GetDomain(), id.GetName(), + ), + } + } + if cfg.BaseDomain == "" { return nil } + scheme := cfg.Scheme + if scheme == "" { + scheme = "https" + } host := strings.ToLower(fmt.Sprintf("%s-%s-%s.%s", - id.GetName(), id.GetProject(), id.GetDomain(), baseDomain)) + id.GetName(), id.GetProject(), id.GetDomain(), cfg.BaseDomain)) return &flyteapp.Ingress{ - PublicUrl: "https://" + host, + PublicUrl: scheme + "://" + host, } } @@ -94,9 +107,6 @@ func (s *InternalAppService) Get( status, err := s.k8s.GetStatus(ctx, appID.AppId) if err != nil { - if k8serrors.IsNotFound(err) { - return nil, connect.NewError(connect.CodeNotFound, err) - } return nil, connect.NewError(connect.CodeInternal, err) } @@ -186,7 +196,7 @@ func (s *InternalAppService) List( token = r.GetToken() } - apps, nextToken, err := s.k8s.List(ctx, project, domain, "", limit, token) + apps, nextToken, err := s.k8s.List(ctx, project, domain, limit, token) if err != nil { return nil, connect.NewError(connect.CodeInternal, err) } @@ -215,18 +225,15 @@ func (s *InternalAppService) Watch( return connect.NewError(connect.CodeUnimplemented, fmt.Errorf("org and cluster_id watch targets are not supported by the data plane")) } - // Start watch before listing so no events are lost between the two calls. - ch, err := s.k8s.Watch(ctx, project, domain, appName) - if err != nil { - return connect.NewError(connect.CodeInternal, err) - } - - // Send initial snapshot so the client has current state before streaming changes. - snapshot, _, err := s.k8s.List(ctx, project, domain, appName, 0, "") + // Send initial snapshot so the client has current state before watching for changes. + snapshot, _, err := s.k8s.List(ctx, project, domain, 0, "") if err != nil { return connect.NewError(connect.CodeInternal, err) } for _, app := range snapshot { + if appName != "" && app.GetMetadata().GetId().GetName() != appName { + continue + } if err := stream.Send(&flyteapp.WatchResponse{ Event: &flyteapp.WatchResponse_CreateEvent{ CreateEvent: &flyteapp.CreateEvent{App: app}, @@ -236,6 +243,11 @@ func (s *InternalAppService) Watch( } } + ch, err := s.k8s.Watch(ctx, project, domain, appName) + if err != nil { + return connect.NewError(connect.CodeInternal, err) + } + for { select { case <-ctx.Done(): diff --git a/app/internal/service/internal_app_service_test.go b/app/internal/service/internal_app_service_test.go index c47fa16c9b8..2ece2571ba8 100644 --- a/app/internal/service/internal_app_service_test.go +++ b/app/internal/service/internal_app_service_test.go @@ -2,7 +2,6 @@ package service import ( "context" - "fmt" "net/http" "net/http/httptest" "testing" @@ -12,8 +11,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - kerrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime/schema" appconfig "github.com/flyteorg/flyte/v2/app/internal/config" flyteapp "github.com/flyteorg/flyte/v2/gen/go/flyteidl2/app" @@ -47,8 +44,8 @@ func (m *mockAppK8sClient) GetStatus(ctx context.Context, appID *flyteapp.Identi return args.Get(0).(*flyteapp.Status), args.Error(1) } -func (m *mockAppK8sClient) List(ctx context.Context, project, domain, appName string, limit uint32, token string) ([]*flyteapp.App, string, error) { - args := m.Called(ctx, project, domain, appName, limit, token) +func (m *mockAppK8sClient) List(ctx context.Context, project, domain string, limit uint32, token string) ([]*flyteapp.App, string, error) { + args := m.Called(ctx, project, domain, limit, token) if args.Get(0) == nil { return nil, "", args.Error(2) } @@ -200,22 +197,6 @@ func TestGet_Success(t *testing.T) { k8s.AssertExpectations(t) } -func TestGet_NotFound(t *testing.T) { - k8s := &mockAppK8sClient{} - svc := NewInternalAppService(k8s, testCfg()) - - appID := testAppID() - notFoundErr := fmt.Errorf("KService myapp not found: %w", kerrors.NewNotFound(schema.GroupResource{}, "myapp")) - k8s.On("GetStatus", mock.Anything, appID).Return(nil, notFoundErr) - - _, err := svc.Get(context.Background(), connect.NewRequest(&flyteapp.GetRequest{ - Identifier: &flyteapp.GetRequest_AppId{AppId: appID}, - })) - require.Error(t, err) - assert.Equal(t, connect.CodeNotFound, connect.CodeOf(err)) - k8s.AssertExpectations(t) -} - func TestGet_MissingAppID(t *testing.T) { svc := NewInternalAppService(&mockAppK8sClient{}, testCfg()) @@ -294,7 +275,7 @@ func TestList_ByProject(t *testing.T) { svc := NewInternalAppService(k8s, testCfg()) apps := []*flyteapp.App{testApp()} - k8s.On("List", mock.Anything, "proj", "dev", "", uint32(10), "tok").Return(apps, "nexttok", nil) + k8s.On("List", mock.Anything, "proj", "dev", uint32(10), "tok").Return(apps, "nexttok", nil) resp, err := svc.List(context.Background(), connect.NewRequest(&flyteapp.ListRequest{ FilterBy: &flyteapp.ListRequest_Project{ @@ -312,7 +293,7 @@ func TestList_NoFilter(t *testing.T) { k8s := &mockAppK8sClient{} svc := NewInternalAppService(k8s, testCfg()) - k8s.On("List", mock.Anything, "", "", "", uint32(0), "").Return([]*flyteapp.App{}, "", nil) + k8s.On("List", mock.Anything, "", "", uint32(0), "").Return([]*flyteapp.App{}, "", nil) resp, err := svc.List(context.Background(), connect.NewRequest(&flyteapp.ListRequest{})) require.NoError(t, err) @@ -329,8 +310,8 @@ func TestWatch_InitialSnapshot(t *testing.T) { ch := make(chan *flyteapp.WatchResponse) close(ch) + k8s.On("List", mock.Anything, "proj", "dev", uint32(0), "").Return(apps, "", nil) k8s.On("Watch", mock.Anything, "proj", "dev", "").Return((<-chan *flyteapp.WatchResponse)(ch), nil) - k8s.On("List", mock.Anything, "proj", "dev", "", uint32(0), "").Return(apps, "", nil) client := newTestClient(t, k8s) stream, err := client.Watch(context.Background(), connect.NewRequest(&flyteapp.WatchRequest{ @@ -358,8 +339,8 @@ func TestWatch_AppIDTarget(t *testing.T) { ch := make(chan *flyteapp.WatchResponse) close(ch) + k8s.On("List", mock.Anything, "proj", "dev", uint32(0), "").Return([]*flyteapp.App{}, "", nil) k8s.On("Watch", mock.Anything, "proj", "dev", "myapp").Return((<-chan *flyteapp.WatchResponse)(ch), nil) - k8s.On("List", mock.Anything, "proj", "dev", "myapp", uint32(0), "").Return([]*flyteapp.App{}, "", nil) client := newTestClient(t, k8s) stream, err := client.Watch(context.Background(), connect.NewRequest(&flyteapp.WatchRequest{ diff --git a/app/internal/setup.go b/app/internal/setup.go index 7c7ec7a0c53..91023cb4d7e 100644 --- a/app/internal/setup.go +++ b/app/internal/setup.go @@ -12,6 +12,7 @@ import ( appk8s "github.com/flyteorg/flyte/v2/app/internal/k8s" "github.com/flyteorg/flyte/v2/app/internal/service" "github.com/flyteorg/flyte/v2/gen/go/flyteidl2/app/appconnect" + knativeapp "github.com/flyteorg/flyte/v2/flytestdlib/app" ) // Setup registers the InternalAppService handler on the SetupContext mux. @@ -23,7 +24,7 @@ func Setup(ctx context.Context, sc *stdlibapp.SetupContext, cfg *appconfig.Inter return nil } - if err := stdlibapp.InitAppScheme(); err != nil { + if err := knativeapp.InitAppScheme(); err != nil { return fmt.Errorf("internalapp: failed to register Knative scheme: %w", err) } diff --git a/app/service/app_service.go b/app/service/app_service.go index 55b70738117..e9d9e140747 100644 --- a/app/service/app_service.go +++ b/app/service/app_service.go @@ -3,10 +3,10 @@ package service import ( "context" "fmt" + "sync" "time" "connectrpc.com/connect" - "github.com/hashicorp/golang-lru/v2/expirable" flyteapp "github.com/flyteorg/flyte/v2/gen/go/flyteidl2/app" "github.com/flyteorg/flyte/v2/gen/go/flyteidl2/app/appconnect" @@ -18,20 +18,15 @@ import ( type AppService struct { appconnect.UnimplementedAppServiceHandler internalClient appconnect.AppServiceClient - // cache is nil when cacheTTL=0 (caching disabled). - cache *expirable.LRU[string, *flyteapp.App] + cache *appCache } // NewAppService creates a new AppService. // cacheTTL=0 disables caching (every Get calls InternalAppService). func NewAppService(internalClient appconnect.AppServiceClient, cacheTTL time.Duration) *AppService { - var cache *expirable.LRU[string, *flyteapp.App] - if cacheTTL > 0 { - cache = expirable.NewLRU[string, *flyteapp.App](0, nil, cacheTTL) - } return &AppService{ internalClient: internalClient, - cache: cache, + cache: newAppCache(cacheTTL), } } @@ -47,9 +42,7 @@ func (s *AppService) Create( if err != nil { return nil, err } - if s.cache != nil { - s.cache.Remove(cacheKey(req.Msg.GetApp().GetMetadata().GetId())) - } + s.cache.invalidate(cacheKey(req.Msg.GetApp().GetMetadata().GetId())) return resp, nil } @@ -59,8 +52,8 @@ func (s *AppService) Get( req *connect.Request[flyteapp.GetRequest], ) (*connect.Response[flyteapp.GetResponse], error) { appID, ok := req.Msg.GetIdentifier().(*flyteapp.GetRequest_AppId) - if ok && appID.AppId != nil && s.cache != nil { - if app, hit := s.cache.Get(cacheKey(appID.AppId)); hit { + if ok && appID.AppId != nil { + if app, hit := s.cache.get(cacheKey(appID.AppId)); hit { return connect.NewResponse(&flyteapp.GetResponse{App: app}), nil } } @@ -69,8 +62,8 @@ func (s *AppService) Get( if err != nil { return nil, err } - if ok && appID.AppId != nil && s.cache != nil { - s.cache.Add(cacheKey(appID.AppId), resp.Msg.GetApp()) + if ok && appID.AppId != nil { + s.cache.set(cacheKey(appID.AppId), resp.Msg.GetApp()) } return resp, nil } @@ -84,9 +77,7 @@ func (s *AppService) Update( if err != nil { return nil, err } - if s.cache != nil { - s.cache.Remove(cacheKey(req.Msg.GetApp().GetMetadata().GetId())) - } + s.cache.invalidate(cacheKey(req.Msg.GetApp().GetMetadata().GetId())) return resp, nil } @@ -99,9 +90,7 @@ func (s *AppService) Delete( if err != nil { return nil, err } - if s.cache != nil { - s.cache.Remove(cacheKey(req.Msg.GetAppId())) - } + s.cache.invalidate(cacheKey(req.Msg.GetAppId())) return resp, nil } @@ -132,6 +121,57 @@ func (s *AppService) Watch( return clientStream.Err() } +// --- Cache --- + +type cacheEntry struct { + app *flyteapp.App + expiresAt time.Time +} + +type appCache struct { + mu sync.RWMutex + items map[string]*cacheEntry + ttl time.Duration +} + +func newAppCache(ttl time.Duration) *appCache { + return &appCache{ + items: make(map[string]*cacheEntry), + ttl: ttl, + } +} + +// get returns the cached App for key, or (nil, false) if missing or expired. +func (c *appCache) get(key string) (*flyteapp.App, bool) { + if c.ttl == 0 { + return nil, false + } + c.mu.RLock() + entry, ok := c.items[key] + c.mu.RUnlock() + if !ok || time.Now().After(entry.expiresAt) { + return nil, false + } + return entry.app, true +} + +// set writes the App to the cache with the configured TTL. +func (c *appCache) set(key string, app *flyteapp.App) { + if c.ttl == 0 { + return + } + c.mu.Lock() + c.items[key] = &cacheEntry{app: app, expiresAt: time.Now().Add(c.ttl)} + c.mu.Unlock() +} + +// invalidate removes the cache entry for key. +func (c *appCache) invalidate(key string) { + c.mu.Lock() + delete(c.items, key) + c.mu.Unlock() +} + // cacheKey returns a stable string key for an app identifier. func cacheKey(id *flyteapp.Identifier) string { if id == nil { diff --git a/app/service/app_service_test.go b/app/service/app_service_test.go index 7b623b8ff8b..e985a89568e 100644 --- a/app/service/app_service_test.go +++ b/app/service/app_service_test.go @@ -130,7 +130,7 @@ func TestGet_CacheHit_SkipsInternal(t *testing.T) { // Pre-populate cache. appID := testAppID() - svc.cache.Add(cacheKey(appID), testApp()) + svc.cache.set(cacheKey(appID), testApp()) // Internal should NOT be called. resp, err := svc.Get(context.Background(), connect.NewRequest(&flyteapp.GetRequest{ @@ -146,7 +146,7 @@ func TestGet_CacheExpired_CallsInternal(t *testing.T) { svc := NewAppService(internal, 1*time.Millisecond) appID := testAppID() - svc.cache.Add(cacheKey(appID), testApp()) + svc.cache.set(cacheKey(appID), testApp()) time.Sleep(5 * time.Millisecond) // let TTL expire app := testApp() @@ -169,7 +169,7 @@ func TestCreate_InvalidatesCache(t *testing.T) { app := testApp() // Pre-populate cache so we can confirm it's cleared. - svc.cache.Add(cacheKey(app.Metadata.Id), app) + svc.cache.set(cacheKey(app.Metadata.Id), app) internal.On("Create", mock.Anything, mock.Anything).Return( connect.NewResponse(&flyteapp.CreateResponse{App: app}), nil, @@ -178,7 +178,7 @@ func TestCreate_InvalidatesCache(t *testing.T) { _, err := svc.Create(context.Background(), connect.NewRequest(&flyteapp.CreateRequest{App: app})) require.NoError(t, err) - _, hit := svc.cache.Get(cacheKey(app.Metadata.Id)) + _, hit := svc.cache.get(cacheKey(app.Metadata.Id)) assert.False(t, hit, "cache should be invalidated after Create") internal.AssertExpectations(t) } @@ -188,7 +188,7 @@ func TestUpdate_InvalidatesCache(t *testing.T) { svc := NewAppService(internal, 30*time.Second) app := testApp() - svc.cache.Add(cacheKey(app.Metadata.Id), app) + svc.cache.set(cacheKey(app.Metadata.Id), app) internal.On("Update", mock.Anything, mock.Anything).Return( connect.NewResponse(&flyteapp.UpdateResponse{App: app}), nil, @@ -197,7 +197,7 @@ func TestUpdate_InvalidatesCache(t *testing.T) { _, err := svc.Update(context.Background(), connect.NewRequest(&flyteapp.UpdateRequest{App: app})) require.NoError(t, err) - _, hit := svc.cache.Get(cacheKey(app.Metadata.Id)) + _, hit := svc.cache.get(cacheKey(app.Metadata.Id)) assert.False(t, hit, "cache should be invalidated after Update") internal.AssertExpectations(t) } @@ -207,7 +207,7 @@ func TestDelete_InvalidatesCache(t *testing.T) { svc := NewAppService(internal, 30*time.Second) appID := testAppID() - svc.cache.Add(cacheKey(appID), testApp()) + svc.cache.set(cacheKey(appID), testApp()) internal.On("Delete", mock.Anything, mock.Anything).Return( connect.NewResponse(&flyteapp.DeleteResponse{}), nil, @@ -216,7 +216,7 @@ func TestDelete_InvalidatesCache(t *testing.T) { _, err := svc.Delete(context.Background(), connect.NewRequest(&flyteapp.DeleteRequest{AppId: appID})) require.NoError(t, err) - _, hit := svc.cache.Get(cacheKey(appID)) + _, hit := svc.cache.get(cacheKey(appID)) assert.False(t, hit, "cache should be invalidated after Delete") internal.AssertExpectations(t) } diff --git a/app/setup.go b/app/setup.go index 31fcdd8d6a8..38853d27606 100644 --- a/app/setup.go +++ b/app/setup.go @@ -8,10 +8,17 @@ import ( "github.com/flyteorg/flyte/v2/flytestdlib/logger" appconfig "github.com/flyteorg/flyte/v2/app/config" + appinternal "github.com/flyteorg/flyte/v2/app/internal" "github.com/flyteorg/flyte/v2/app/service" "github.com/flyteorg/flyte/v2/gen/go/flyteidl2/app/appconnect" ) +// SetupInternal registers the data plane InternalAppService on the SetupContext mux. +// It must be called before Setup so the proxy can reach /internal/... on the same mux. +func SetupInternal(ctx context.Context, sc *stdlibapp.SetupContext, cfg *appconfig.InternalAppConfig) error { + return appinternal.Setup(ctx, sc, cfg) +} + // Setup registers the control plane AppService handler on the SetupContext mux. // In unified mode (sc.BaseURL set), the proxy routes to InternalAppService on // the same mux via the /internal prefix — no network hop. In split mode, diff --git a/charts/flyte-sandbox/templates/proxy/traefik-config.yaml b/charts/flyte-sandbox/templates/proxy/traefik-config.yaml new file mode 100644 index 00000000000..ed506c4b234 --- /dev/null +++ b/charts/flyte-sandbox/templates/proxy/traefik-config.yaml @@ -0,0 +1,23 @@ +apiVersion: helm.cattle.io/v1 +kind: HelmChartConfig +metadata: + name: traefik + namespace: kube-system + labels: {{- include "flyte-sandbox.labels" . | nindent 4 }} +spec: + valuesContent: | + service: + type: NodePort + ports: + web: + nodePort: 30080 + transport: + respondingTimeouts: + readTimeout: 0 + websecure: + expose: false + providers: + kubernetesCRD: + allowExternalNameServices: true + kubernetesIngress: + allowExternalNameServices: true diff --git a/charts/flyte-sandbox/values.yaml b/charts/flyte-sandbox/values.yaml new file mode 100644 index 00000000000..2b67b808189 --- /dev/null +++ b/charts/flyte-sandbox/values.yaml @@ -0,0 +1,185 @@ +docker-registry: + enabled: true + image: + tag: sandbox + pullPolicy: Never + persistence: + enabled: false + secrets: + haSharedSecret: flytesandboxsecret + service: + type: NodePort + nodePort: 30000 + +flyte-binary: + nameOverride: flyte-sandbox + enabled: true + configuration: + database: + host: '{{ printf "%s-postgresql" .Release.Name | trunc 63 | trimSuffix "-" }}' + password: postgres + storage: + metadataContainer: flyte-data + userDataContainer: flyte-data + provider: s3 + providerConfig: + s3: + disableSSL: true + v2Signing: true + endpoint: http://{{ printf "%s-minio" .Release.Name | trunc 63 | trimSuffix "-" }}.{{ .Release.Namespace }}:9000 + authType: accesskey + accessKey: minio + secretKey: miniostorage + logging: + level: 5 + inline: + task_resources: + defaults: + cpu: 500m + ephemeralStorage: 0 + gpu: 0 + memory: 1Gi + limits: + cpu: 0 + ephemeralStorage: 0 + gpu: 0 + memory: 0 + storage: + signedURL: + stowConfigOverride: + endpoint: http://localhost:30002 + plugins: + k8s: + default-env-vars: + - FLYTE_AWS_ENDPOINT: http://{{ printf "%s-minio" .Release.Name | trunc 63 | trimSuffix "-" }}.{{ .Release.Namespace }}:9000 + - FLYTE_AWS_ACCESS_KEY_ID: minio + - FLYTE_AWS_SECRET_ACCESS_KEY: miniostorage + - _U_EP_OVERRIDE: '{{ printf "%s-http" .Release.Name }}.{{ .Release.Namespace }}:8090' + - _U_INSECURE: "true" + - _U_USE_ACTIONS: "1" + runs: + database: + postgres: + host: '{{ printf "%s-postgresql" .Release.Name | trunc 63 | trimSuffix "-" }}.{{ .Release.Namespace }}' + port: 5432 + dbName: runs + user: postgres + password: postgres + manager: + internalApps: + enabled: true + baseDomain: "local.flyte.app" + scheme: "http" + ingressEnabled: true + ingressEntryPoint: "web" + ingressBaseUrl: "http://localhost:30080" + defaultEnvVars: + - name: FLYTE_AWS_ENDPOINT + value: 'http://{{ printf "%s-minio" .Release.Name | trunc 63 | trimSuffix "-" }}.{{ .Release.Namespace }}:9000' + - name: FLYTE_AWS_ACCESS_KEY_ID + value: minio + - name: FLYTE_AWS_SECRET_ACCESS_KEY + value: miniostorage + - name: _U_EP_OVERRIDE + value: '{{ printf "%s-http" .Release.Name }}.{{ .Release.Namespace }}:8090' + - name: _U_INSECURE + value: "true" + - name: _U_USE_ACTIONS + value: "1" + inlineConfigMap: '{{ include "flyte-sandbox.configuration.inlineConfigMap" . }}' + clusterResourceTemplates: + inlineConfigMap: '{{ include "flyte-sandbox.clusterResourceTemplates.inlineConfigMap" . }}' + deployment: + image: + repository: flyte-binary-v2 + tag: sandbox + pullPolicy: Never + livenessProbe: + httpGet: + path: /healthz + port: http + initialDelaySeconds: 5 + readinessProbe: + httpGet: + path: /readyz + port: http + initialDelaySeconds: 5 + periodSeconds: 5 + waitForDB: + image: + repository: bitnami/postgresql + tag: sandbox + pullPolicy: Never + rbac: + # This is strictly NOT RECOMMENDED in production clusters, and is only for use + # within local Flyte sandboxes. + # When using cluster resource templates to create additional namespaced roles, + # Flyte is required to have a superset of those permissions. To simplify + # experimenting with new backend plugins that require additional roles be created + # with cluster resource templates (e.g. Spark), we add the following: + extraRules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' + +minio: + enabled: true + image: + tag: sandbox + pullPolicy: Never + auth: + rootUser: minio + rootPassword: miniostorage + defaultBuckets: flyte-data + extraEnvVars: + - name: MINIO_BROWSER_REDIRECT_URL + value: http://localhost:30080/minio + service: + type: NodePort + nodePorts: + api: 30002 + persistence: + enabled: true + existingClaim: '{{ include "flyte-sandbox.persistence.minioVolumeName" . }}' + volumePermissions: + enabled: true + image: + tag: sandbox + pullPolicy: Never + +postgresql: + enabled: true + image: + tag: sandbox + pullPolicy: Never + auth: + postgresPassword: postgres + shmVolume: + enabled: false + primary: + service: + type: NodePort + nodePorts: + postgresql: 30001 + persistence: + enabled: true + existingClaim: '{{ include "flyte-sandbox.persistence.dbVolumeName" . }}' + volumePermissions: + enabled: true + image: + tag: sandbox + pullPolicy: Never + +sandbox: + # dev Routes requests to an instance of Flyte running locally on a developer's + # development environment. This is only usable if the flyte-binary chart is disabled. + dev: false + console: + enabled: true + image: + repository: ghcr.io/flyteorg/flyte-client-v2 + tag: latest + pullPolicy: Never diff --git a/docker/sandbox-bundled/Makefile b/docker/sandbox-bundled/Makefile new file mode 100644 index 00000000000..907cbd1e8ef --- /dev/null +++ b/docker/sandbox-bundled/Makefile @@ -0,0 +1,137 @@ +define FLYTE_BINARY_BUILD +mkdir -p images/tar/$(1) + +docker buildx build \ + --build-arg FLYTECONSOLE_VERSION=$(FLYTECONSOLE_VERSION) \ + --builder flyte-sandbox \ + --platform linux/$(1) \ + --tag flyte-binary-v2:sandbox \ + --output type=docker,dest=images/tar/$(1)/flyte-binary.tar \ + ../.. + +endef + +.PHONY: create_builder +create_builder: + [ -n "$(shell docker buildx ls | awk '/^flyte-sandbox / {print $$1}')" ] || \ + docker buildx create --name flyte-sandbox \ + --driver docker-container --driver-opt image=moby/buildkit:master \ + --buildkitd-flags '--allow-insecure-entitlement security.insecure' \ + --platform linux/arm64,linux/amd64 + +.PHONY: flyte +flyte: FLYTECONSOLE_VERSION := latest +flyte: create_builder + $(foreach arch,amd64 arm64,$(call FLYTE_BINARY_BUILD,$(arch))) + +.PHONY: helm-repos +helm-repos: + helm repo add docker-registry https://twuni.github.io/docker-registry.helm + helm repo add bitnami https://charts.bitnami.com/bitnami + helm repo update + +.PHONY: dep_build +dep_build: helm-repos + cd $(SANDBOX_CHART_DIR) && helm dependency build + +.PHONY: dep_update +dep_update: SANDBOX_CHART_DIR := ../../charts/flyte-sandbox +dep_update: dep_build + cd $(SANDBOX_CHART_DIR)/charts && for f in *.tgz; do tar xzf "$$f"; done + +.PHONY: manifests +manifests: dep_update + mkdir -p manifests + kustomize build \ + --enable-helm \ + --load-restrictor=LoadRestrictionsNone \ + kustomize/complete > manifests/complete.yaml + kustomize build \ + --enable-helm \ + --load-restrictor=LoadRestrictionsNone \ + kustomize/dev > manifests/dev.yaml + +CONSOLE_IMAGE := ghcr.io/flyteorg/flyte-client-v2 +CONSOLE_TAG := latest + +.PHONY: console +console: + mkdir -p images/tar/amd64 images/tar/arm64 + docker pull --platform linux/amd64 $(CONSOLE_IMAGE):$(CONSOLE_TAG) + docker save $(CONSOLE_IMAGE):$(CONSOLE_TAG) -o images/tar/amd64/flyte-client-v2.tar + docker pull --platform linux/arm64 $(CONSOLE_IMAGE):$(CONSOLE_TAG) + docker save $(CONSOLE_IMAGE):$(CONSOLE_TAG) -o images/tar/arm64/flyte-client-v2.tar + +.PHONY: sync-crds +sync-crds: + $(MAKE) -C ../../executor manifests + +.PHONY: build +build: sync-crds flyte console dep_update manifests + docker buildx build --builder flyte-sandbox --allow security.insecure --load \ + --tag flyte-sandbox-v2:latest . + +# Port map +# 6443 - k8s API server +# 30000 - Docker Registry +# 30001 - DB +# 30002 - Minio +# 30080 - Flyte Proxy (Traefik nodePort) +.PHONY: start +start: FLYTE_SANDBOX_IMAGE := flyte-sandbox-v2:latest +start: FLYTE_DEV := False +start: + [ -n "$(shell docker volume ls --filter name=^flyte-sandbox$$ --format {{.Name}})" ] || \ + docker volume create flyte-sandbox + @if [ -z "$(shell docker ps --filter name=^flyte-sandbox$$ --format {{.Names}})" ]; then \ + rm -f $(PWD)/.kube/kubeconfig; \ + docker run --detach --rm --privileged --name flyte-sandbox \ + --add-host "host.docker.internal:host-gateway" \ + --env FLYTE_DEV=$(FLYTE_DEV) \ + --env K3S_KUBECONFIG_OUTPUT=/.kube/kubeconfig \ + --volume $(PWD)/.kube:/.kube \ + --volume flyte-sandbox:/var/lib/flyte/storage \ + --publish "6443":"6443" \ + --publish "30000:30000" \ + --publish "30001:5432" \ + --publish "30002:30002" \ + --publish "30080:30080" \ + $(FLYTE_SANDBOX_IMAGE); \ + fi + @echo "Waiting for kubeconfig..." + @until [ -s $(PWD)/.kube/kubeconfig ]; do sleep 1; done + @# On WSL, the bind-mounted kubeconfig may be root-owned, which makes the host-side cp fail with permission denied. + @docker exec flyte-sandbox chown $(shell id -u):$(shell id -g) /.kube/kubeconfig + @mkdir -p $(HOME)/.kube + @if [ -f $(HOME)/.kube/config ]; then \ + KUBECONFIG=$(PWD)/.kube/kubeconfig:$(HOME)/.kube/config kubectl config view --flatten > /tmp/kubeconfig-merged && \ + mv /tmp/kubeconfig-merged $(HOME)/.kube/config; \ + else \ + cp $(PWD)/.kube/kubeconfig $(HOME)/.kube/config; \ + fi + @echo "Kubeconfig merged into ~/.kube/config" +.PHONY: kubeconfig +.SILENT: kubeconfig +kubeconfig: + sed -i -e "/server:/ s/: .*/: https:\/\/127.0.0.1:$(shell docker port flyte-sandbox | grep ^6443 | awk '{print $$3}' | awk -F: '{print $$2}')/" .kube/kubeconfig + echo "export KUBECONFIG=$(PWD)/.kube/kubeconfig" + +.PHONY: setup-knative +setup-knative: + kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.16.0/serving-crds.yaml + kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.16.0/serving-core.yaml + kubectl apply -f https://github.com/knative-extensions/net-kourier/releases/download/knative-v1.16.0/kourier.yaml + kubectl patch configmap/config-network -n knative-serving --type merge \ + --patch '{"data":{"ingress-class":"kourier.ingress.networking.knative.dev"}}' + kubectl patch configmap/config-network -n knative-serving --type merge \ + --patch '{"data":{"domain-template":"{{.Name}}-{{.Namespace}}.{{.Domain}}"}}' + kubectl patch configmap/config-domain -n knative-serving --type merge \ + --patch '{"data":{"local.flyte.app":""}}' + +.PHONY: stop +stop: + docker stop flyte-sandbox + +.venv: + python -m venv .venv + . .venv/bin/activate && pip install flytekit diff --git a/docker/sandbox-bundled/manifests/complete.yaml b/docker/sandbox-bundled/manifests/complete.yaml new file mode 100644 index 00000000000..3fa833929a5 --- /dev/null +++ b/docker/sandbox-bundled/manifests/complete.yaml @@ -0,0 +1,1610 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: flyte +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.19.0 + name: taskactions.flyte.org +spec: + group: flyte.org + names: + kind: TaskAction + listKind: TaskActionList + plural: taskactions + singular: taskaction + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.runName + name: Run + type: string + - jsonPath: .spec.actionName + name: Action + type: string + - jsonPath: .spec.taskType + name: TaskType + type: string + - jsonPath: .status.conditions[?(@.type=='Progressing')].reason + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=='Progressing')].status + name: Progressing + priority: 1 + type: string + - jsonPath: .status.conditions[?(@.type=='Succeeded')].status + name: Succeeded + priority: 1 + type: string + - jsonPath: .status.conditions[?(@.type=='Failed')].status + name: Failed + priority: 1 + type: string + name: v1 + schema: + openAPIV3Schema: + description: TaskAction is the Schema for the taskactions API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: spec defines the desired state of TaskAction + properties: + actionName: + description: ActionName is the unique name of this action within the + run + maxLength: 30 + minLength: 1 + type: string + cacheKey: + description: |- + CacheKey enables cache lookup/writeback for this task action when set. + This is propagated from workflow.TaskAction.cache_key. + maxLength: 256 + type: string + domain: + description: Domain this action belongs to + maxLength: 63 + minLength: 1 + type: string + envVars: + additionalProperties: + type: string + description: EnvVars are run-scoped environment variables projected + from RunSpec for executor runtime use. + type: object + group: + description: Group is the group this action belongs to, if applicable. + maxLength: 256 + type: string + inputUri: + description: InputURI is the path to the input data for this action + minLength: 1 + type: string + interruptible: + description: Interruptible is the run-scoped interruptibility override + projected from RunSpec. + type: boolean + parentActionName: + description: ParentActionName is the optional name of the parent action + maxLength: 30 + minLength: 1 + type: string + project: + description: Project this action belongs to + maxLength: 63 + minLength: 1 + type: string + runName: + description: RunName is the name of the run this action belongs to + maxLength: 30 + minLength: 1 + type: string + runOutputBase: + description: RunOutputBase is the base path where this action should + write its output + minLength: 1 + type: string + shortName: + description: ShortName is the human-readable display name for this + task + maxLength: 63 + type: string + taskTemplate: + description: TaskTemplate is the proto-serialized core.TaskTemplate + stored inline in etcd + format: byte + type: string + taskType: + description: TaskType identifies which plugin handles this task (e.g. + "container", "spark", "ray") + maxLength: 63 + minLength: 1 + type: string + required: + - actionName + - domain + - inputUri + - project + - runName + - runOutputBase + - taskTemplate + - taskType + type: object + status: + description: status defines the observed state of TaskAction + properties: + attempts: + description: Attempts is the latest observed action attempt number, + starting from 1. + format: int32 + type: integer + cacheStatus: + description: CacheStatus is the latest observed cache lookup result + for this action. + format: int32 + type: integer + conditions: + description: |- + conditions represent the current state of the TaskAction resource. + Each condition has a unique type and reflects the status of a specific aspect of the resource. + + Standard condition types include: + - "Available": the resource is fully functional + - "Progressing": the resource is being created or updated + - "Degraded": the resource failed to reach or maintain its desired state + + The status of each condition is one of True, False, or Unknown. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + phaseHistory: + description: |- + PhaseHistory is an append-only log of phase transitions. Unlike conditions + (which are updated in-place by type), this preserves the full timeline: + Queued → Initializing → Executing → Succeeded/Failed, each with a timestamp. + items: + description: PhaseTransition records a phase change with its timestamp. + properties: + message: + description: Message is an optional human-readable message about + the transition. + type: string + occurredAt: + description: OccurredAt is when this phase transition happened. + format: date-time + type: string + phase: + description: Phase is the phase that was entered (e.g. "Queued", + "Initializing", "Executing", "Succeeded", "Failed"). + type: string + required: + - occurredAt + - phase + type: object + type: array + pluginPhase: + description: PluginPhase is a human-readable representation of the + plugin's current phase. + type: string + pluginPhaseVersion: + description: PluginPhaseVersion is the version of the current plugin + phase. + format: int32 + type: integer + pluginState: + description: PluginState is the Gob-encoded plugin state from the + last reconciliation round. + format: byte + type: string + pluginStateVersion: + description: PluginStateVersion tracks the version of the plugin state + schema for compatibility. + type: integer + stateJson: + description: StateJSON is the JSON serialized NodeStatus that was + last sent to the State Service + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + helm.sh/chart: flyte-binary-v0.2.0 + name: flyte-sandbox + namespace: flyte +--- +apiVersion: v1 +automountServiceAccountToken: true +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: minio + helm.sh/chart: minio-12.6.7 + name: flyte-sandbox-minio + namespace: flyte +secrets: +- name: flyte-sandbox-minio +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: flyte-sandbox-kubernetes-dashboard +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: flyte-sandbox-kubernetes-dashboard +rules: +- apiGroups: + - "" + resourceNames: + - kubernetes-dashboard-key-holder + - kubernetes-dashboard-certs + - kubernetes-dashboard-csrf + resources: + - secrets + verbs: + - get + - update + - delete +- apiGroups: + - "" + resourceNames: + - kubernetes-dashboard-settings + resources: + - configmaps + verbs: + - get + - update +- apiGroups: + - "" + resourceNames: + - heapster + - dashboard-metrics-scraper + resources: + - services + verbs: + - proxy +- apiGroups: + - "" + resourceNames: + - heapster + - 'http:heapster:' + - 'https:heapster:' + - dashboard-metrics-scraper + - http:dashboard-metrics-scraper + resources: + - services/proxy + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + helm.sh/chart: flyte-binary-v0.2.0 + name: flyte-sandbox-cluster-role + namespace: flyte +rules: +- apiGroups: + - "" + resources: + - pods + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - events + verbs: + - create + - delete + - patch + - update +- apiGroups: + - flyte.org + resources: + - taskactions + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - admissionregistration.k8s.io + resources: + - mutatingwebhookconfigurations + verbs: + - create + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - secrets + verbs: + - create + - get + - update +- apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: flyte-sandbox-kubernetes-dashboard-metrics +rules: +- apiGroups: + - metrics.k8s.io + resources: + - pods + - nodes + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: flyte-sandbox-kubernetes-dashboard +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: flyte-sandbox-kubernetes-dashboard +subjects: +- kind: ServiceAccount + name: flyte-sandbox-kubernetes-dashboard + namespace: flyte +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + helm.sh/chart: flyte-binary-v0.2.0 + name: flyte-sandbox-cluster-role-binding + namespace: flyte +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: flyte-sandbox-cluster-role +subjects: +- kind: ServiceAccount + name: flyte-sandbox + namespace: flyte +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: flyte-sandbox-kubernetes-dashboard-metrics +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: flyte-sandbox-kubernetes-dashboard-metrics +subjects: +- kind: ServiceAccount + name: flyte-sandbox-kubernetes-dashboard + namespace: flyte +--- +apiVersion: v1 +data: + 000-core.yaml: | + logger: + show-source: true + level: 5 + webhook: + certDir: /var/run/flyte/certs + localCert: true + secretName: flyte-sandbox-webhook-secret + serviceName: flyte-sandbox-webhook + servicePort: 443 + + actions: + kubernetes: + kubeconfig: "" + namespace: flyte + watchBufferSize: 100 + dataproxy: + download: + maxExpiresIn: 1h + upload: + defaultFileNameLength: 20 + maxExpiresIn: 1h + maxSize: 100Mi + storagePrefix: uploads + manager: + executor: + healthProbePort: 8081 + kubernetes: + burst: 2000 + kubeconfig: "" + namespace: flyte + qps: 1000 + timeout: 30s + server: + host: 0.0.0.0 + port: 8090 + runs: + database: + connMaxLifeTime: 1h + maxIdleConnections: 10 + maxOpenConnections: 100 + postgres: + dbname: flyte + debug: false + host: 127.0.0.1 + options: sslmode=disable + password: "" + port: 5432 + username: postgres + server: + host: 0.0.0.0 + port: 8090 + storagePrefix: s3://flyte-data + watchBufferSize: 100 + secret: + kubernetes: + burst: 200 + clusterName: flyte-sandbox + kubeconfig: "" + namespace: flyte + qps: 100 + timeout: 30s + 001-plugins.yaml: | + tasks: + task-plugins: + default-for-task-types: + container: container + container_array: k8s-array + sidecar: sidecar + enabled-plugins: + - container + - sidecar + - connector-service + - echo + plugins: + logs: + kubernetes-enabled: false + cloudwatch-enabled: false + stackdriver-enabled: false + k8s: + co-pilot: + image: "cr.flyte.org/flyteorg/flytecopilot:v1.16.4" + k8s-array: + logs: + config: + kubernetes-enabled: false + cloudwatch-enabled: false + stackdriver-enabled: false + 002-database.yaml: | + database: + postgres: + username: postgres + host: flyte-sandbox-postgresql + port: 5432 + dbname: flyte + options: "sslmode=disable" + 003-storage.yaml: | + storage: + type: stow + stow: + kind: s3 + config: + region: us-east-1 + disable_ssl: true + v2_signing: true + endpoint: http://flyte-sandbox-minio.flyte:9000 + auth_type: accesskey + container: flyte-data + 100-inline-config.yaml: | + manager: + internalApps: + baseDomain: local.flyte.app + defaultEnvVars: + - name: FLYTE_AWS_ENDPOINT + value: http://flyte-sandbox-minio.flyte:9000 + - name: FLYTE_AWS_ACCESS_KEY_ID + value: minio + - name: FLYTE_AWS_SECRET_ACCESS_KEY + value: miniostorage + - name: _U_EP_OVERRIDE + value: 'flyte-sandbox-http.flyte:8090' + - name: _U_INSECURE + value: "true" + - name: _U_USE_ACTIONS + value: "1" + enabled: true + ingressBaseUrl: http://localhost:30080 + ingressEnabled: true + ingressEntryPoint: web + scheme: http + plugins: + k8s: + default-env-vars: + - FLYTE_AWS_ENDPOINT: http://flyte-sandbox-minio.flyte:9000 + - FLYTE_AWS_ACCESS_KEY_ID: minio + - FLYTE_AWS_SECRET_ACCESS_KEY: miniostorage + - _U_EP_OVERRIDE: 'flyte-sandbox-http.flyte:8090' + - _U_INSECURE: "true" + - _U_USE_ACTIONS: "1" + runs: + database: + postgres: + dbName: runs + host: 'flyte-sandbox-postgresql.flyte' + password: postgres + port: 5432 + user: postgres + storage: + signedURL: + stowConfigOverride: + endpoint: http://localhost:30002 + task_resources: + defaults: + cpu: 500m + ephemeralStorage: 0 + gpu: 0 + memory: 1Gi + limits: + cpu: 0 + ephemeralStorage: 0 + gpu: 0 + memory: 0 +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + helm.sh/chart: flyte-binary-v0.2.0 + name: flyte-sandbox-config + namespace: flyte +--- +apiVersion: v1 +data: + config.yml: |- + health: + storagedriver: + enabled: true + interval: 10s + threshold: 3 + http: + addr: :5000 + debug: + addr: :5001 + prometheus: + enabled: false + path: /metrics + headers: + X-Content-Type-Options: + - nosniff + log: + fields: + service: registry + storage: + cache: + blobdescriptor: inmemory + version: 0.1 +kind: ConfigMap +metadata: + labels: + app: docker-registry + chart: docker-registry-2.2.2 + heritage: Helm + release: flyte-sandbox + name: flyte-sandbox-docker-registry-config + namespace: flyte +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: flyte-sandbox-extra-cluster-resource-templates + namespace: flyte +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: flyte-sandbox-extra-config + namespace: flyte +--- +apiVersion: v1 +data: null +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: kubernetes-dashboard-settings +--- +apiVersion: v1 +kind: Secret +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + helm.sh/chart: flyte-binary-v0.2.0 + name: flyte-sandbox-config-secret + namespace: flyte +stringData: + 012-database-secrets.yaml: | + database: + postgres: + password: "postgres" + 013-storage-secrets.yaml: | + storage: + stow: + config: + access_key_id: "minio" + secret_key: "miniostorage" +type: Opaque +--- +apiVersion: v1 +data: + haSharedSecret: Zmx5dGVzYW5kYm94c2VjcmV0 + proxyPassword: "" + proxyUsername: "" +kind: Secret +metadata: + labels: + app: docker-registry + chart: docker-registry-2.2.2 + heritage: Helm + release: flyte-sandbox + name: flyte-sandbox-docker-registry-secret + namespace: flyte +type: Opaque +--- +apiVersion: v1 +data: + root-password: bWluaW9zdG9yYWdl + root-user: bWluaW8= +kind: Secret +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: minio + helm.sh/chart: minio-12.6.7 + name: flyte-sandbox-minio + namespace: flyte +type: Opaque +--- +apiVersion: v1 +kind: Secret +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: flyte-sandbox-kubernetes-dashboard-certs +type: Opaque +--- +apiVersion: v1 +kind: Secret +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: kubernetes-dashboard-csrf +type: Opaque +--- +apiVersion: v1 +kind: Secret +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: kubernetes-dashboard-key-holder +type: Opaque +--- +apiVersion: v1 +kind: Endpoints +metadata: + labels: + app.kubernetes.io/name: embedded-postgresql + name: flyte-sandbox-postgresql + namespace: flyte +subsets: +- addresses: + - ip: '%{NODE_IP}%' + ports: + - name: tcp-postgresql + port: 5432 +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: flyte-sandbox-console + namespace: flyte +spec: + ports: + - name: http + port: 80 + protocol: TCP + targetPort: http + selector: + app.kubernetes.io/component: console + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: flyte-sandbox +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: docker-registry + chart: docker-registry-2.2.2 + heritage: Helm + release: flyte-sandbox + name: flyte-sandbox-docker-registry + namespace: flyte +spec: + ports: + - name: http-5000 + nodePort: 30000 + port: 5000 + protocol: TCP + targetPort: 5000 + selector: + app: docker-registry + release: flyte-sandbox + type: NodePort +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + helm.sh/chart: flyte-binary-v0.2.0 + name: flyte-sandbox-http + namespace: flyte +spec: + ports: + - name: http + nodePort: null + port: 8090 + targetPort: http + selector: + app.kubernetes.io/component: flyte-binary + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: flyte-sandbox + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: minio + helm.sh/chart: minio-12.6.7 + name: flyte-sandbox-minio + namespace: flyte +spec: + externalTrafficPolicy: Cluster + ports: + - name: minio-api + nodePort: 30002 + port: 9000 + targetPort: minio-api + - name: minio-console + port: 9001 + targetPort: minio-console + selector: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: minio + type: NodePort +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: embedded-postgresql + name: flyte-sandbox-postgresql + namespace: flyte +spec: + ports: + - name: tcp-postgresql + nodePort: 30001 + port: 5432 + targetPort: 5432 + type: NodePort +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + helm.sh/chart: flyte-binary-v0.2.0 + name: flyte-sandbox-webhook + namespace: flyte +spec: + ports: + - name: webhook + port: 443 + protocol: TCP + targetPort: 9443 + selector: + app.kubernetes.io/component: flyte-binary + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: flyte-sandbox +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: kubernetes-dashboard + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + kubernetes.io/cluster-service: "true" + name: flyte-sandbox-kubernetes-dashboard +spec: + ports: + - name: https + port: 443 + targetPort: https + selector: + app.kubernetes.io/component: kubernetes-dashboard + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: kubernetes-dashboard + type: ClusterIP +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: flyte-sandbox-minio-storage + namespace: flyte +spec: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + hostPath: + path: /var/lib/flyte/storage/minio + storageClassName: manual +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: flyte-sandbox-minio-storage + namespace: flyte +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: manual + volumeName: flyte-sandbox-minio-storage +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + helm.sh/chart: flyte-binary-v0.2.0 + name: flyte-sandbox + namespace: flyte +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/component: flyte-binary + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: flyte-sandbox + strategy: + type: Recreate + template: + metadata: + annotations: + checksum/configuration: 65d9d4f74b818affae591f569908d32aa883197a6a90f3b43b5dfd36d0f90a48 + checksum/configuration-secret: 588da2ac84d45dd5285521c58bc6c9969924887acb9674d75802055c3a97d9bb + labels: + app.kubernetes.io/component: flyte-binary + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: flyte-sandbox + spec: + containers: + - args: + - --config + - /etc/flyte/config.d/*.yaml + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + image: flyte-binary-v2:sandbox + imagePullPolicy: Never + livenessProbe: + httpGet: + path: /healthz + port: http + initialDelaySeconds: 5 + name: flyte + ports: + - containerPort: 8090 + name: http + - containerPort: 9443 + name: webhook + readinessProbe: + httpGet: + path: /readyz + port: http + initialDelaySeconds: 5 + periodSeconds: 5 + volumeMounts: + - mountPath: /etc/flyte/config.d + name: config + - mountPath: /var/run/flyte/certs + name: webhook-certs + readOnly: false + initContainers: + - args: + - | + until nc -z flyte-sandbox-postgresql.flyte 5432; do + echo waiting for database + sleep 0.5 + done + command: + - sh + - -ec + image: rancher/mirrored-library-busybox:1.34.1 + imagePullPolicy: Never + name: wait-for-db + serviceAccountName: flyte-sandbox + volumes: + - name: config + projected: + sources: + - configMap: + name: flyte-sandbox-config + - secret: + name: flyte-sandbox-config-secret + - configMap: + name: flyte-sandbox-extra-config + - emptyDir: {} + name: webhook-certs +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: flyte-sandbox-console + namespace: flyte +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/component: console + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: flyte-sandbox + template: + metadata: + labels: + app.kubernetes.io/component: console + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: flyte-sandbox + spec: + containers: + - image: ghcr.io/flyteorg/flyte-client-v2:latest + imagePullPolicy: Never + livenessProbe: + httpGet: + path: /v2 + port: http + initialDelaySeconds: 5 + periodSeconds: 30 + name: console + ports: + - containerPort: 8080 + name: http + protocol: TCP + readinessProbe: + httpGet: + path: /v2 + port: http + initialDelaySeconds: 5 + periodSeconds: 10 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: docker-registry + chart: docker-registry-2.2.2 + heritage: Helm + release: flyte-sandbox + name: flyte-sandbox-docker-registry + namespace: flyte +spec: + minReadySeconds: 5 + replicas: 1 + selector: + matchLabels: + app: docker-registry + release: flyte-sandbox + template: + metadata: + annotations: + checksum/config: 8f50e768255a87f078ba8b9879a0c174c3e045ffb46ac8723d2eedbe293c8d81 + checksum/secret: 829c19e3c86dcb9b7d4c44e6a73463c6a6467d824200e87e2d7999f70dc0f5f9 + labels: + app: docker-registry + release: flyte-sandbox + spec: + containers: + - command: + - /bin/registry + - serve + - /etc/docker/registry/config.yml + env: + - name: REGISTRY_HTTP_SECRET + valueFrom: + secretKeyRef: + key: haSharedSecret + name: flyte-sandbox-docker-registry-secret + - name: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY + value: /var/lib/registry + image: registry:sandbox + imagePullPolicy: Never + livenessProbe: + httpGet: + path: / + port: 5000 + name: docker-registry + ports: + - containerPort: 5000 + readinessProbe: + httpGet: + path: / + port: 5000 + resources: {} + volumeMounts: + - mountPath: /etc/docker/registry + name: flyte-sandbox-docker-registry-config + - mountPath: /var/lib/registry/ + name: data + securityContext: + fsGroup: 1000 + runAsUser: 1000 + volumes: + - configMap: + name: flyte-sandbox-docker-registry-config + name: flyte-sandbox-docker-registry-config + - emptyDir: {} + name: data +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: minio + helm.sh/chart: minio-12.6.7 + name: flyte-sandbox-minio + namespace: flyte +spec: + selector: + matchLabels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: minio + strategy: + type: Recreate + template: + metadata: + annotations: + checksum/credentials-secret: ecce809e3af19025d134846a9a81e163dd41df7e26abf2c6657895d9d13607a9 + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: minio + helm.sh/chart: minio-12.6.7 + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: minio + topologyKey: kubernetes.io/hostname + weight: 1 + containers: + - command: + - minio + - server + - /data + - --console-address + - :9001 + env: + - name: BITNAMI_DEBUG + value: "false" + - name: MINIO_SCHEME + value: http + - name: MINIO_FORCE_NEW_KEYS + value: "no" + - name: MINIO_ROOT_USER + valueFrom: + secretKeyRef: + key: root-user + name: flyte-sandbox-minio + - name: MINIO_ROOT_PASSWORD + valueFrom: + secretKeyRef: + key: root-password + name: flyte-sandbox-minio + - name: MINIO_DEFAULT_BUCKETS + value: flyte-data + - name: MINIO_BROWSER + value: "on" + - name: MINIO_PROMETHEUS_AUTH_TYPE + value: public + - name: MINIO_CONSOLE_PORT_NUMBER + value: "9001" + - name: MINIO_BROWSER_REDIRECT_URL + value: http://localhost:30080/minio + image: docker.io/bitnami/minio:sandbox + imagePullPolicy: Never + livenessProbe: + failureThreshold: 5 + httpGet: + path: /minio/health/live + port: minio-api + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 5 + name: minio + ports: + - containerPort: 9000 + name: minio-api + protocol: TCP + - containerPort: 9001 + name: minio-console + protocol: TCP + readinessProbe: + failureThreshold: 5 + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + tcpSocket: + port: minio-api + timeoutSeconds: 1 + resources: + limits: {} + requests: {} + securityContext: + runAsNonRoot: true + runAsUser: 1001 + volumeMounts: + - mountPath: /data + name: data + initContainers: + - command: + - /bin/bash + - -ec + - | + chown -R 1001:1001 /data + mkdir -p /data/flyte-data + chown 1001:1001 /data/flyte-data + image: docker.io/bitnami/os-shell:sandbox + imagePullPolicy: Never + name: volume-permissions + resources: + limits: {} + requests: {} + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /data + name: data + securityContext: + fsGroup: 1001 + serviceAccountName: flyte-sandbox-minio + volumes: + - name: data + persistentVolumeClaim: + claimName: flyte-sandbox-minio-storage +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: kubernetes-dashboard + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: flyte-sandbox-kubernetes-dashboard +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/component: kubernetes-dashboard + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: kubernetes-dashboard + strategy: + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 + type: RollingUpdate + template: + metadata: + annotations: null + labels: + app.kubernetes.io/component: kubernetes-dashboard + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + spec: + containers: + - args: + - --namespace=flyte + - --auto-generate-certificates + - --metrics-provider=none + image: kubernetesui/dashboard:v2.7.0 + imagePullPolicy: IfNotPresent + livenessProbe: + httpGet: + path: / + port: 8443 + scheme: HTTPS + initialDelaySeconds: 30 + timeoutSeconds: 30 + name: kubernetes-dashboard + ports: + - containerPort: 8443 + name: https + protocol: TCP + resources: + limits: + cpu: 2 + memory: 200Mi + requests: + cpu: 100m + memory: 200Mi + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsGroup: 2001 + runAsUser: 1001 + volumeMounts: + - mountPath: /certs + name: kubernetes-dashboard-certs + - mountPath: /tmp + name: tmp-volume + securityContext: + seccompProfile: + type: RuntimeDefault + serviceAccountName: flyte-sandbox-kubernetes-dashboard + volumes: + - name: kubernetes-dashboard-certs + secret: + secretName: flyte-sandbox-kubernetes-dashboard-certs + - emptyDir: {} + name: tmp-volume +--- +apiVersion: helm.cattle.io/v1 +kind: HelmChartConfig +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: traefik + namespace: kube-system +spec: + valuesContent: | + service: + type: NodePort + ports: + web: + nodePort: 30080 + transport: + respondingTimeouts: + readTimeout: 0 + websecure: + expose: false + providers: + kubernetesCRD: + allowExternalNameServices: true + kubernetesIngress: + allowExternalNameServices: true +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: flyte-sandbox-api + namespace: flyte +spec: + rules: + - http: + paths: + - backend: + service: + name: flyte-sandbox-http + port: + number: 8090 + path: /healthz + pathType: Exact + - backend: + service: + name: flyte-sandbox-http + port: + number: 8090 + path: /readyz + pathType: Exact + - backend: + service: + name: flyte-sandbox-http + port: + number: 8090 + path: /flyteidl2. + pathType: Prefix +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: flyte-sandbox-console + namespace: flyte +spec: + rules: + - http: + paths: + - backend: + service: + name: flyte-sandbox-console + port: + number: 80 + path: /v2 + pathType: Prefix +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + traefik.ingress.kubernetes.io/router.middlewares: flyte-strip-minio@kubernetescrd + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: flyte-sandbox-minio + namespace: flyte +spec: + rules: + - http: + paths: + - backend: + service: + name: flyte-sandbox-minio + port: + number: 9001 + path: /minio + pathType: Prefix +--- +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: strip-minio + namespace: flyte +spec: + stripPrefix: + prefixes: + - /minio diff --git a/docker/sandbox-bundled/manifests/dev.yaml b/docker/sandbox-bundled/manifests/dev.yaml new file mode 100644 index 00000000000..40a6a5678f4 --- /dev/null +++ b/docker/sandbox-bundled/manifests/dev.yaml @@ -0,0 +1,1207 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: flyte +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.19.0 + name: taskactions.flyte.org +spec: + group: flyte.org + names: + kind: TaskAction + listKind: TaskActionList + plural: taskactions + singular: taskaction + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.runName + name: Run + type: string + - jsonPath: .spec.actionName + name: Action + type: string + - jsonPath: .spec.taskType + name: TaskType + type: string + - jsonPath: .status.conditions[?(@.type=='Progressing')].reason + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=='Progressing')].status + name: Progressing + priority: 1 + type: string + - jsonPath: .status.conditions[?(@.type=='Succeeded')].status + name: Succeeded + priority: 1 + type: string + - jsonPath: .status.conditions[?(@.type=='Failed')].status + name: Failed + priority: 1 + type: string + name: v1 + schema: + openAPIV3Schema: + description: TaskAction is the Schema for the taskactions API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: spec defines the desired state of TaskAction + properties: + actionName: + description: ActionName is the unique name of this action within the + run + maxLength: 30 + minLength: 1 + type: string + cacheKey: + description: |- + CacheKey enables cache lookup/writeback for this task action when set. + This is propagated from workflow.TaskAction.cache_key. + maxLength: 256 + type: string + domain: + description: Domain this action belongs to + maxLength: 63 + minLength: 1 + type: string + envVars: + additionalProperties: + type: string + description: EnvVars are run-scoped environment variables projected + from RunSpec for executor runtime use. + type: object + group: + description: Group is the group this action belongs to, if applicable. + maxLength: 256 + type: string + inputUri: + description: InputURI is the path to the input data for this action + minLength: 1 + type: string + interruptible: + description: Interruptible is the run-scoped interruptibility override + projected from RunSpec. + type: boolean + parentActionName: + description: ParentActionName is the optional name of the parent action + maxLength: 30 + minLength: 1 + type: string + project: + description: Project this action belongs to + maxLength: 63 + minLength: 1 + type: string + runName: + description: RunName is the name of the run this action belongs to + maxLength: 30 + minLength: 1 + type: string + runOutputBase: + description: RunOutputBase is the base path where this action should + write its output + minLength: 1 + type: string + shortName: + description: ShortName is the human-readable display name for this + task + maxLength: 63 + type: string + taskTemplate: + description: TaskTemplate is the proto-serialized core.TaskTemplate + stored inline in etcd + format: byte + type: string + taskType: + description: TaskType identifies which plugin handles this task (e.g. + "container", "spark", "ray") + maxLength: 63 + minLength: 1 + type: string + required: + - actionName + - domain + - inputUri + - project + - runName + - runOutputBase + - taskTemplate + - taskType + type: object + status: + description: status defines the observed state of TaskAction + properties: + attempts: + description: Attempts is the latest observed action attempt number, + starting from 1. + format: int32 + type: integer + cacheStatus: + description: CacheStatus is the latest observed cache lookup result + for this action. + format: int32 + type: integer + conditions: + description: |- + conditions represent the current state of the TaskAction resource. + Each condition has a unique type and reflects the status of a specific aspect of the resource. + + Standard condition types include: + - "Available": the resource is fully functional + - "Progressing": the resource is being created or updated + - "Degraded": the resource failed to reach or maintain its desired state + + The status of each condition is one of True, False, or Unknown. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + phaseHistory: + description: |- + PhaseHistory is an append-only log of phase transitions. Unlike conditions + (which are updated in-place by type), this preserves the full timeline: + Queued → Initializing → Executing → Succeeded/Failed, each with a timestamp. + items: + description: PhaseTransition records a phase change with its timestamp. + properties: + message: + description: Message is an optional human-readable message about + the transition. + type: string + occurredAt: + description: OccurredAt is when this phase transition happened. + format: date-time + type: string + phase: + description: Phase is the phase that was entered (e.g. "Queued", + "Initializing", "Executing", "Succeeded", "Failed"). + type: string + required: + - occurredAt + - phase + type: object + type: array + pluginPhase: + description: PluginPhase is a human-readable representation of the + plugin's current phase. + type: string + pluginPhaseVersion: + description: PluginPhaseVersion is the version of the current plugin + phase. + format: int32 + type: integer + pluginState: + description: PluginState is the Gob-encoded plugin state from the + last reconciliation round. + format: byte + type: string + pluginStateVersion: + description: PluginStateVersion tracks the version of the plugin state + schema for compatibility. + type: integer + stateJson: + description: StateJSON is the JSON serialized NodeStatus that was + last sent to the State Service + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: v1 +automountServiceAccountToken: true +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: minio + helm.sh/chart: minio-12.6.7 + name: flyte-sandbox-minio + namespace: flyte +secrets: +- name: flyte-sandbox-minio +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: flyte-sandbox-kubernetes-dashboard +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: flyte-sandbox-kubernetes-dashboard +rules: +- apiGroups: + - "" + resourceNames: + - kubernetes-dashboard-key-holder + - kubernetes-dashboard-certs + - kubernetes-dashboard-csrf + resources: + - secrets + verbs: + - get + - update + - delete +- apiGroups: + - "" + resourceNames: + - kubernetes-dashboard-settings + resources: + - configmaps + verbs: + - get + - update +- apiGroups: + - "" + resourceNames: + - heapster + - dashboard-metrics-scraper + resources: + - services + verbs: + - proxy +- apiGroups: + - "" + resourceNames: + - heapster + - 'http:heapster:' + - 'https:heapster:' + - dashboard-metrics-scraper + - http:dashboard-metrics-scraper + resources: + - services/proxy + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: flyte-sandbox-kubernetes-dashboard-metrics +rules: +- apiGroups: + - metrics.k8s.io + resources: + - pods + - nodes + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: flyte-sandbox-kubernetes-dashboard +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: flyte-sandbox-kubernetes-dashboard +subjects: +- kind: ServiceAccount + name: flyte-sandbox-kubernetes-dashboard + namespace: flyte +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: flyte-sandbox-kubernetes-dashboard-metrics +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: flyte-sandbox-kubernetes-dashboard-metrics +subjects: +- kind: ServiceAccount + name: flyte-sandbox-kubernetes-dashboard + namespace: flyte +--- +apiVersion: v1 +data: + config.yml: |- + health: + storagedriver: + enabled: true + interval: 10s + threshold: 3 + http: + addr: :5000 + debug: + addr: :5001 + prometheus: + enabled: false + path: /metrics + headers: + X-Content-Type-Options: + - nosniff + log: + fields: + service: registry + storage: + cache: + blobdescriptor: inmemory + version: 0.1 +kind: ConfigMap +metadata: + labels: + app: docker-registry + chart: docker-registry-2.2.2 + heritage: Helm + release: flyte-sandbox + name: flyte-sandbox-docker-registry-config + namespace: flyte +--- +apiVersion: v1 +data: null +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: kubernetes-dashboard-settings +--- +apiVersion: v1 +data: + haSharedSecret: Zmx5dGVzYW5kYm94c2VjcmV0 + proxyPassword: "" + proxyUsername: "" +kind: Secret +metadata: + labels: + app: docker-registry + chart: docker-registry-2.2.2 + heritage: Helm + release: flyte-sandbox + name: flyte-sandbox-docker-registry-secret + namespace: flyte +type: Opaque +--- +apiVersion: v1 +data: + root-password: bWluaW9zdG9yYWdl + root-user: bWluaW8= +kind: Secret +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: minio + helm.sh/chart: minio-12.6.7 + name: flyte-sandbox-minio + namespace: flyte +type: Opaque +--- +apiVersion: v1 +kind: Secret +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: flyte-sandbox-kubernetes-dashboard-certs +type: Opaque +--- +apiVersion: v1 +kind: Secret +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: kubernetes-dashboard-csrf +type: Opaque +--- +apiVersion: v1 +kind: Secret +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: kubernetes-dashboard-key-holder +type: Opaque +--- +apiVersion: v1 +kind: Endpoints +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: flyte-sandbox-local + namespace: flyte +subsets: +- addresses: + - ip: '%{HOST_GATEWAY_IP}%' + ports: + - name: http + port: 8090 + protocol: TCP + - name: webhook + port: 9443 + protocol: TCP +--- +apiVersion: v1 +kind: Endpoints +metadata: + labels: + app.kubernetes.io/name: embedded-postgresql + name: flyte-sandbox-postgresql + namespace: flyte +subsets: +- addresses: + - ip: '%{NODE_IP}%' + ports: + - name: tcp-postgresql + port: 5432 +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: flyte-sandbox-console + namespace: flyte +spec: + ports: + - name: http + port: 80 + protocol: TCP + targetPort: http + selector: + app.kubernetes.io/component: console + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: flyte-sandbox +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: docker-registry + chart: docker-registry-2.2.2 + heritage: Helm + release: flyte-sandbox + name: flyte-sandbox-docker-registry + namespace: flyte +spec: + ports: + - name: http-5000 + nodePort: 30000 + port: 5000 + protocol: TCP + targetPort: 5000 + selector: + app: docker-registry + release: flyte-sandbox + type: NodePort +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: flyte-sandbox-local + namespace: flyte +spec: + clusterIP: None + ports: + - name: http + port: 8090 + protocol: TCP + - name: webhook + port: 9443 + protocol: TCP +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: minio + helm.sh/chart: minio-12.6.7 + name: flyte-sandbox-minio + namespace: flyte +spec: + externalTrafficPolicy: Cluster + ports: + - name: minio-api + nodePort: 30002 + port: 9000 + targetPort: minio-api + - name: minio-console + port: 9001 + targetPort: minio-console + selector: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: minio + type: NodePort +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: embedded-postgresql + name: flyte-sandbox-postgresql + namespace: flyte +spec: + ports: + - name: tcp-postgresql + nodePort: 30001 + port: 5432 + targetPort: 5432 + type: NodePort +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: kubernetes-dashboard + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + kubernetes.io/cluster-service: "true" + name: flyte-sandbox-kubernetes-dashboard +spec: + ports: + - name: https + port: 443 + targetPort: https + selector: + app.kubernetes.io/component: kubernetes-dashboard + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: kubernetes-dashboard + type: ClusterIP +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: flyte-sandbox-minio-storage + namespace: flyte +spec: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + hostPath: + path: /var/lib/flyte/storage/minio + storageClassName: manual +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: flyte-sandbox-minio-storage + namespace: flyte +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: manual + volumeName: flyte-sandbox-minio-storage +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: flyte-sandbox-console + namespace: flyte +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/component: console + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: flyte-sandbox + template: + metadata: + labels: + app.kubernetes.io/component: console + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: flyte-sandbox + spec: + containers: + - image: ghcr.io/flyteorg/flyte-client-v2:latest + imagePullPolicy: Never + livenessProbe: + httpGet: + path: /v2 + port: http + initialDelaySeconds: 5 + periodSeconds: 30 + name: console + ports: + - containerPort: 8080 + name: http + protocol: TCP + readinessProbe: + httpGet: + path: /v2 + port: http + initialDelaySeconds: 5 + periodSeconds: 10 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: docker-registry + chart: docker-registry-2.2.2 + heritage: Helm + release: flyte-sandbox + name: flyte-sandbox-docker-registry + namespace: flyte +spec: + minReadySeconds: 5 + replicas: 1 + selector: + matchLabels: + app: docker-registry + release: flyte-sandbox + template: + metadata: + annotations: + checksum/config: 8f50e768255a87f078ba8b9879a0c174c3e045ffb46ac8723d2eedbe293c8d81 + checksum/secret: 829c19e3c86dcb9b7d4c44e6a73463c6a6467d824200e87e2d7999f70dc0f5f9 + labels: + app: docker-registry + release: flyte-sandbox + spec: + containers: + - command: + - /bin/registry + - serve + - /etc/docker/registry/config.yml + env: + - name: REGISTRY_HTTP_SECRET + valueFrom: + secretKeyRef: + key: haSharedSecret + name: flyte-sandbox-docker-registry-secret + - name: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY + value: /var/lib/registry + image: registry:sandbox + imagePullPolicy: Never + livenessProbe: + httpGet: + path: / + port: 5000 + name: docker-registry + ports: + - containerPort: 5000 + readinessProbe: + httpGet: + path: / + port: 5000 + resources: {} + volumeMounts: + - mountPath: /etc/docker/registry + name: flyte-sandbox-docker-registry-config + - mountPath: /var/lib/registry/ + name: data + securityContext: + fsGroup: 1000 + runAsUser: 1000 + volumes: + - configMap: + name: flyte-sandbox-docker-registry-config + name: flyte-sandbox-docker-registry-config + - emptyDir: {} + name: data +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: minio + helm.sh/chart: minio-12.6.7 + name: flyte-sandbox-minio + namespace: flyte +spec: + selector: + matchLabels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: minio + strategy: + type: Recreate + template: + metadata: + annotations: + checksum/credentials-secret: ecce809e3af19025d134846a9a81e163dd41df7e26abf2c6657895d9d13607a9 + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: minio + helm.sh/chart: minio-12.6.7 + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: minio + topologyKey: kubernetes.io/hostname + weight: 1 + containers: + - command: + - minio + - server + - /data + - --console-address + - :9001 + env: + - name: BITNAMI_DEBUG + value: "false" + - name: MINIO_SCHEME + value: http + - name: MINIO_FORCE_NEW_KEYS + value: "no" + - name: MINIO_ROOT_USER + valueFrom: + secretKeyRef: + key: root-user + name: flyte-sandbox-minio + - name: MINIO_ROOT_PASSWORD + valueFrom: + secretKeyRef: + key: root-password + name: flyte-sandbox-minio + - name: MINIO_DEFAULT_BUCKETS + value: flyte-data + - name: MINIO_BROWSER + value: "on" + - name: MINIO_PROMETHEUS_AUTH_TYPE + value: public + - name: MINIO_CONSOLE_PORT_NUMBER + value: "9001" + - name: MINIO_BROWSER_REDIRECT_URL + value: http://localhost:30080/minio + image: docker.io/bitnami/minio:sandbox + imagePullPolicy: Never + livenessProbe: + failureThreshold: 5 + httpGet: + path: /minio/health/live + port: minio-api + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 5 + name: minio + ports: + - containerPort: 9000 + name: minio-api + protocol: TCP + - containerPort: 9001 + name: minio-console + protocol: TCP + readinessProbe: + failureThreshold: 5 + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + tcpSocket: + port: minio-api + timeoutSeconds: 1 + resources: + limits: {} + requests: {} + securityContext: + runAsNonRoot: true + runAsUser: 1001 + volumeMounts: + - mountPath: /data + name: data + initContainers: + - command: + - /bin/bash + - -ec + - | + chown -R 1001:1001 /data + mkdir -p /data/flyte-data + chown 1001:1001 /data/flyte-data + image: docker.io/bitnami/os-shell:sandbox + imagePullPolicy: Never + name: volume-permissions + resources: + limits: {} + requests: {} + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /data + name: data + securityContext: + fsGroup: 1001 + serviceAccountName: flyte-sandbox-minio + volumes: + - name: data + persistentVolumeClaim: + claimName: flyte-sandbox-minio-storage +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: kubernetes-dashboard + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + name: flyte-sandbox-kubernetes-dashboard +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/component: kubernetes-dashboard + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/name: kubernetes-dashboard + strategy: + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 + type: RollingUpdate + template: + metadata: + annotations: null + labels: + app.kubernetes.io/component: kubernetes-dashboard + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubernetes-dashboard + app.kubernetes.io/version: 2.7.0 + helm.sh/chart: kubernetes-dashboard-6.0.0 + spec: + containers: + - args: + - --namespace=flyte + - --auto-generate-certificates + - --metrics-provider=none + image: kubernetesui/dashboard:v2.7.0 + imagePullPolicy: IfNotPresent + livenessProbe: + httpGet: + path: / + port: 8443 + scheme: HTTPS + initialDelaySeconds: 30 + timeoutSeconds: 30 + name: kubernetes-dashboard + ports: + - containerPort: 8443 + name: https + protocol: TCP + resources: + limits: + cpu: 2 + memory: 200Mi + requests: + cpu: 100m + memory: 200Mi + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsGroup: 2001 + runAsUser: 1001 + volumeMounts: + - mountPath: /certs + name: kubernetes-dashboard-certs + - mountPath: /tmp + name: tmp-volume + securityContext: + seccompProfile: + type: RuntimeDefault + serviceAccountName: flyte-sandbox-kubernetes-dashboard + volumes: + - name: kubernetes-dashboard-certs + secret: + secretName: flyte-sandbox-kubernetes-dashboard-certs + - emptyDir: {} + name: tmp-volume +--- +apiVersion: helm.cattle.io/v1 +kind: HelmChartConfig +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: traefik + namespace: kube-system +spec: + valuesContent: | + service: + type: NodePort + ports: + web: + nodePort: 30080 + transport: + respondingTimeouts: + readTimeout: 0 + websecure: + expose: false + providers: + kubernetesCRD: + allowExternalNameServices: true + kubernetesIngress: + allowExternalNameServices: true +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: flyte-sandbox-api + namespace: flyte +spec: + rules: + - http: + paths: + - backend: + service: + name: flyte-sandbox-local + port: + number: 8090 + path: /healthz + pathType: Exact + - backend: + service: + name: flyte-sandbox-local + port: + number: 8090 + path: /readyz + pathType: Exact + - backend: + service: + name: flyte-sandbox-local + port: + number: 8090 + path: /flyteidl2. + pathType: Prefix +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: flyte-sandbox-console + namespace: flyte +spec: + rules: + - http: + paths: + - backend: + service: + name: flyte-sandbox-console + port: + number: 80 + path: /v2 + pathType: Prefix +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + traefik.ingress.kubernetes.io/router.middlewares: flyte-strip-minio@kubernetescrd + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: flyte-sandbox-minio + namespace: flyte +spec: + rules: + - http: + paths: + - backend: + service: + name: flyte-sandbox-minio + port: + number: 9001 + path: /minio + pathType: Prefix +--- +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + labels: + app.kubernetes.io/instance: flyte-sandbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: flyte-sandbox + app.kubernetes.io/version: 1.16.1 + helm.sh/chart: flyte-sandbox-0.1.0 + name: strip-minio + namespace: flyte +spec: + stripPrefix: + prefixes: + - /minio diff --git a/flytestdlib/app/app.go b/flytestdlib/app/app.go index df6b7b75f05..0dcdf88e25f 100644 --- a/flytestdlib/app/app.go +++ b/flytestdlib/app/app.go @@ -1,12 +1,15 @@ package app import ( + "compress/gzip" "context" "errors" "fmt" + "io" "net/http" "os" "os/signal" + "strings" "sync" "syscall" "time" @@ -111,6 +114,7 @@ func (a *App) serve(ctx context.Context) error { if sc.Middleware != nil { handler = sc.Middleware(handler) } + handler = requestGzipDecompressMiddleware(handler) addr := fmt.Sprintf("%s:%d", sc.Host, sc.Port) server = &http.Server{ @@ -193,6 +197,35 @@ func (a *App) serve(ctx context.Context) error { return shutdownErr } +// requestGzipDecompressMiddleware pre-decompresses request bodies that carry +// Content-Encoding: gzip before they reach the connect-rpc handler. +// +// Some HTTP clients (e.g. pyqwest used by the Python connectrpc SDK) compress +// the request body at the application level and set Content-Encoding: gzip, +// but also use chunked transfer encoding for larger payloads. Go's h2c +// framing delivers the body in chunks, so by the time connect-go calls +// gzip.NewReader on the raw body stream the first bytes it receives may be a +// chunk-size line rather than the gzip magic bytes, causing "gzip: invalid +// header". Pre-reading and fully decompressing the body here, before h2c +// framing is involved, sidesteps the problem entirely. +func requestGzipDecompressMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if strings.EqualFold(r.Header.Get("Content-Encoding"), "gzip") { + gr, err := gzip.NewReader(r.Body) + if err == nil { + r2 := r.Clone(r.Context()) + r2.Body = struct { + io.Reader + io.Closer + }{gr, r.Body} + r2.Header.Del("Content-Encoding") + r = r2 + } + } + next.ServeHTTP(w, r) + }) +} + func initConfig(cmd *cobra.Command) error { configAccessor = viper.NewAccessor(config.Options{ SearchPaths: []string{cfgFile, ".", "/etc/flyte/config"}, diff --git a/manager/cmd/main.go b/manager/cmd/main.go index d4c7bdbba99..75f887e8e5e 100644 --- a/manager/cmd/main.go +++ b/manager/cmd/main.go @@ -6,8 +6,10 @@ import ( "net/http" "os" + flyteapp "github.com/flyteorg/flyte/v2/app" "github.com/flyteorg/flyte/v2/actions" "github.com/flyteorg/flyte/v2/flytestdlib/app" + servingv1 "knative.dev/serving/pkg/apis/serving/v1" "github.com/flyteorg/flyte/v2/cache_service" "github.com/flyteorg/flyte/v2/dataproxy" "github.com/flyteorg/flyte/v2/events" @@ -50,6 +52,11 @@ func setup(ctx context.Context, sc *app.SetupContext) error { } sc.DB = db + // Register Knative types into the shared scheme so the K8s client can manage KServices. + if err := servingv1.AddToScheme(executor.Scheme()); err != nil { + return fmt.Errorf("failed to register Knative scheme: %w", err) + } + // Initialize Kubernetes client k8sClient, k8sConfig, err := app.InitKubernetesClient(ctx, app.K8sConfig{ KubeConfig: cfg.Kubernetes.KubeConfig, @@ -82,6 +89,13 @@ func setup(ctx context.Context, sc *app.SetupContext) error { if err := runs.Setup(ctx, sc); err != nil { return err } + // InternalAppService must be mounted before AppService so the proxy can reach it. + if err := flyteapp.SetupInternal(ctx, sc, &cfg.InternalApps); err != nil { + return err + } + if err := flyteapp.Setup(ctx, sc, &cfg.Apps); err != nil { + return err + } if err := dataproxy.Setup(ctx, sc); err != nil { return err } diff --git a/manager/config.yaml b/manager/config.yaml index 9cd43c3140a..4d9c22a3b34 100644 --- a/manager/config.yaml +++ b/manager/config.yaml @@ -13,13 +13,39 @@ manager: namespace: "flyte" kubeconfig: "~/.kube/config" + apps: + cacheTtl: 30s + + internalApps: + enabled: true + baseDomain: "local.flyte.app" + scheme: "http" + defaultRequestTimeout: 300s + maxRequestTimeout: 3600s + ingressEnabled: true + ingressEntryPoint: "web" + ingressBaseUrl: "http://localhost:30080" + defaultEnvVars: + - name: FLYTE_AWS_ENDPOINT + value: "http://flyte-sandbox-minio.flyte.svc.cluster.local:9000" + - name: FLYTE_AWS_ACCESS_KEY_ID + value: "minio" + - name: FLYTE_AWS_SECRET_ACCESS_KEY + value: "miniostorage" + - name: _U_EP_OVERRIDE + value: "flyte-sandbox-local.flyte.svc.cluster.local:8090" + - name: _U_INSECURE + value: "true" + - name: _U_USE_ACTIONS + value: "1" + # Webhook configuration # localCert: true writes the generated TLS cert to disk so the webhook server can read it. webhook: localCert: true certDir: /tmp/flyte/webhook/certs - serviceName: flyte-devbox-local + serviceName: flyte-sandbox-local servicePort: 9443 # Executor configuration @@ -61,10 +87,10 @@ dataproxy: plugins: k8s: default-env-vars: - - FLYTE_AWS_ENDPOINT: "http://rustfs.flyte.svc.cluster.local:9000" - - FLYTE_AWS_ACCESS_KEY_ID: "rustfs" - - FLYTE_AWS_SECRET_ACCESS_KEY: "rustfsstorage" - - _U_EP_OVERRIDE: "flyte-devbox-local.flyte.svc.cluster.local:8090" + - FLYTE_AWS_ENDPOINT: "http://flyte-sandbox-minio.flyte.svc.cluster.local:9000" + - FLYTE_AWS_ACCESS_KEY_ID: "minio" + - FLYTE_AWS_SECRET_ACCESS_KEY: "miniostorage" + - _U_EP_OVERRIDE: "flyte-sandbox-local.flyte.svc.cluster.local:8090" - _U_INSECURE: "true" - _U_USE_ACTIONS: "1" @@ -79,8 +105,8 @@ storage: kind: "s3" config: auth_type: "accesskey" - access_key_id: "rustfs" - secret_key: "rustfsstorage" + access_key_id: "minio" + secret_key: "miniostorage" region: "us-east-1" endpoint: "http://localhost:30002" disable_ssl: "true" diff --git a/manager/config/config.go b/manager/config/config.go index 9beded5ab8b..1a0c07addb7 100644 --- a/manager/config/config.go +++ b/manager/config/config.go @@ -1,6 +1,11 @@ package config -import "github.com/flyteorg/flyte/v2/flytestdlib/config" +import ( + "time" + + appconfig "github.com/flyteorg/flyte/v2/app/config" + "github.com/flyteorg/flyte/v2/flytestdlib/config" +) const configSectionKey = "manager" @@ -16,6 +21,12 @@ type Config struct { // Kubernetes configuration Kubernetes KubernetesConfig `json:"kubernetes"` + + // Apps is the control plane AppService configuration. + Apps appconfig.AppConfig `json:"apps"` + + // InternalApps is the data plane InternalAppService configuration. + InternalApps appconfig.InternalAppConfig `json:"internalApps"` } // ServerConfig holds HTTP server configuration @@ -53,6 +64,14 @@ var defaultConfig = &Config{ Burst: 2000, Timeout: "30s", }, + Apps: appconfig.AppConfig{ + CacheTTL: 30 * time.Second, + }, + InternalApps: appconfig.InternalAppConfig{ + Enabled: false, + DefaultRequestTimeout: 300 * time.Second, + MaxRequestTimeout: 3600 * time.Second, + }, } var configSection = config.MustRegisterSection(configSectionKey, defaultConfig) diff --git a/runs/config/config.go b/runs/config/config.go index 9c2ab1a73ba..e524450da3f 100644 --- a/runs/config/config.go +++ b/runs/config/config.go @@ -1,8 +1,6 @@ package config import ( - "time" - "github.com/flyteorg/flyte/v2/flytestdlib/config" "github.com/flyteorg/flyte/v2/flytestdlib/database" ) @@ -25,13 +23,6 @@ var defaultConfig = &Config{ {ID: "production", Name: "Production"}, {ID: "staging", Name: "Staging"}, }, - TriggerScheduler: TriggerSchedulerConfig{ - Enabled: true, - ResyncInterval: 30 * time.Second, - MaxCatchupRunsPerLoop: 100, - ExecutionQPS: 10.0, - ExecutionBurst: 20, - }, } var configSection = config.MustRegisterSection(configSectionKey, defaultConfig) @@ -60,9 +51,6 @@ type Config struct { // Domains are injected into project responses (not stored per project row). Domains []DomainConfig `json:"domains"` - // TriggerScheduler configures the cron-based trigger scheduler worker. - TriggerScheduler TriggerSchedulerConfig `json:"triggerScheduler"` - } // ServerConfig holds HTTP server configuration @@ -77,24 +65,6 @@ type DomainConfig struct { Name string `json:"name"` } -// TriggerSchedulerConfig controls the cron-based scheduler worker. -type TriggerSchedulerConfig struct { - // Enabled turns the scheduler worker on or off. - Enabled bool `json:"enabled" pflag:",Enable the trigger scheduler worker"` - - // ResyncInterval is how often the scheduler re-reads active triggers from the DB. - ResyncInterval time.Duration `json:"resyncInterval" pflag:",How often to resync active triggers from the database"` - - // MaxCatchupRunsPerLoop caps how many catchup runs are fired per resync loop. - MaxCatchupRunsPerLoop int `json:"maxCatchupRunsPerLoop" pflag:",Maximum catchup runs fired per resync loop"` - - // ExecutionQPS is the token-bucket rate for CreateRun calls (tokens/second). - ExecutionQPS float64 `json:"executionQps" pflag:",Rate limit for CreateRun calls (requests per second)"` - - // ExecutionBurst is the token-bucket burst size. - ExecutionBurst int `json:"executionBurst" pflag:",Burst size for CreateRun rate limiter"` -} - // GetConfig returns the parsed runs configuration func GetConfig() *Config { return configSection.GetConfig().(*Config) diff --git a/runs/setup.go b/runs/setup.go index 88f06639543..67d753ad746 100644 --- a/runs/setup.go +++ b/runs/setup.go @@ -9,7 +9,7 @@ import ( "github.com/flyteorg/flyte/v2/flytestdlib/app" "github.com/flyteorg/flyte/v2/gen/go/flyteidl2/actions/actionsconnect" - "github.com/flyteorg/flyte/v2/gen/go/flyteidl2/auth/authconnect" +"github.com/flyteorg/flyte/v2/gen/go/flyteidl2/auth/authconnect" projectpb "github.com/flyteorg/flyte/v2/gen/go/flyteidl2/project" "github.com/flyteorg/flyte/v2/gen/go/flyteidl2/project/projectconnect" "github.com/flyteorg/flyte/v2/gen/go/flyteidl2/task/taskconnect" @@ -21,7 +21,6 @@ import ( "github.com/flyteorg/flyte/v2/runs/repository/impl" "github.com/flyteorg/flyte/v2/runs/repository/interfaces" "github.com/flyteorg/flyte/v2/runs/repository/models" - "github.com/flyteorg/flyte/v2/runs/scheduler" "github.com/flyteorg/flyte/v2/runs/service" "github.com/flyteorg/flyte/v2/flytestdlib/logger" @@ -92,7 +91,7 @@ func Setup(ctx context.Context, sc *app.SetupContext) error { sc.Mux.Handle(authMetadataPath, authMetadataHandler) logger.Infof(ctx, "Mounted AuthMetadataService at %s", authMetadataPath) - triggerSvc := service.NewTriggerService(repo) +triggerSvc := service.NewTriggerService() triggerPath, triggerHandler := triggerconnect.NewTriggerServiceHandler(triggerSvc) sc.Mux.Handle(triggerPath, triggerHandler) logger.Infof(ctx, "Mounted TriggerService at %s", triggerPath) @@ -124,16 +123,6 @@ func Setup(ctx context.Context, sc *app.SetupContext) error { return fmt.Errorf("runs: failed to seed projects: %w", err) } - if cfg.TriggerScheduler.Enabled { - runsURL := cfg.ActionsServiceURL - if sc.BaseURL != "" { - runsURL = sc.BaseURL - } - worker := scheduler.Start(ctx, repo.TriggerRepo(), cfg.TriggerScheduler, runsURL) - sc.AddWorker("trigger-scheduler", worker) - logger.Infof(ctx, "Registered trigger-scheduler worker") - } - sc.AddReadyCheck(func(r *http.Request) error { if err := sc.DB.PingContext(r.Context()); err != nil { return fmt.Errorf("database ping failed: %w", err) From cd256bada908102235fc496176aebff41802d276 Mon Sep 17 00:00:00 2001 From: "M. Adil Fayyaz" <62440954+AdilFayyaz@users.noreply.github.com> Date: Tue, 21 Apr 2026 14:43:45 -0700 Subject: [PATCH 2/6] fix: restore runs scheduler config, check-crate target, and go.mod tidy Signed-off-by: M. Adil Fayyaz <62440954+AdilFayyaz@users.noreply.github.com> --- Makefile | 5 +++++ go.mod | 1 - go.sum | 2 -- runs/config/config.go | 30 ++++++++++++++++++++++++++++++ runs/setup.go | 15 +++++++++++++-- 5 files changed, 48 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index d42832464f7..3b4ca1210c0 100644 --- a/Makefile +++ b/Makefile @@ -154,6 +154,11 @@ gen-local: buf mocks go-tidy ## Generate everything using local tools (requires @echo '⚡ Finished generating everything in the gen directory (local)' @$(MAKE) sep +.PHONY: check-crate +check-crate: ## Verify Rust crate compiles using local cargo (faster, no artifacts) + @echo 'Cargo check the generated rust code (local)' + cd gen/rust && cargo check + .PHONY: build-crate build-crate: ## Build Rust crate using local cargo @echo 'Cargo build the generated rust code (local)' diff --git a/go.mod b/go.mod index acc2fdce874..d08b80b45f6 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,6 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 github.com/hashicorp/golang-lru v1.0.2 - github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/imdario/mergo v0.3.16 github.com/jackc/pgconn v1.14.3 github.com/jackc/pgx/v5 v5.7.6 diff --git a/go.sum b/go.sum index d2ef7ade542..70757065def 100644 --- a/go.sum +++ b/go.sum @@ -366,8 +366,6 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= -github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= diff --git a/runs/config/config.go b/runs/config/config.go index e524450da3f..9c2ab1a73ba 100644 --- a/runs/config/config.go +++ b/runs/config/config.go @@ -1,6 +1,8 @@ package config import ( + "time" + "github.com/flyteorg/flyte/v2/flytestdlib/config" "github.com/flyteorg/flyte/v2/flytestdlib/database" ) @@ -23,6 +25,13 @@ var defaultConfig = &Config{ {ID: "production", Name: "Production"}, {ID: "staging", Name: "Staging"}, }, + TriggerScheduler: TriggerSchedulerConfig{ + Enabled: true, + ResyncInterval: 30 * time.Second, + MaxCatchupRunsPerLoop: 100, + ExecutionQPS: 10.0, + ExecutionBurst: 20, + }, } var configSection = config.MustRegisterSection(configSectionKey, defaultConfig) @@ -51,6 +60,9 @@ type Config struct { // Domains are injected into project responses (not stored per project row). Domains []DomainConfig `json:"domains"` + // TriggerScheduler configures the cron-based trigger scheduler worker. + TriggerScheduler TriggerSchedulerConfig `json:"triggerScheduler"` + } // ServerConfig holds HTTP server configuration @@ -65,6 +77,24 @@ type DomainConfig struct { Name string `json:"name"` } +// TriggerSchedulerConfig controls the cron-based scheduler worker. +type TriggerSchedulerConfig struct { + // Enabled turns the scheduler worker on or off. + Enabled bool `json:"enabled" pflag:",Enable the trigger scheduler worker"` + + // ResyncInterval is how often the scheduler re-reads active triggers from the DB. + ResyncInterval time.Duration `json:"resyncInterval" pflag:",How often to resync active triggers from the database"` + + // MaxCatchupRunsPerLoop caps how many catchup runs are fired per resync loop. + MaxCatchupRunsPerLoop int `json:"maxCatchupRunsPerLoop" pflag:",Maximum catchup runs fired per resync loop"` + + // ExecutionQPS is the token-bucket rate for CreateRun calls (tokens/second). + ExecutionQPS float64 `json:"executionQps" pflag:",Rate limit for CreateRun calls (requests per second)"` + + // ExecutionBurst is the token-bucket burst size. + ExecutionBurst int `json:"executionBurst" pflag:",Burst size for CreateRun rate limiter"` +} + // GetConfig returns the parsed runs configuration func GetConfig() *Config { return configSection.GetConfig().(*Config) diff --git a/runs/setup.go b/runs/setup.go index 67d753ad746..88f06639543 100644 --- a/runs/setup.go +++ b/runs/setup.go @@ -9,7 +9,7 @@ import ( "github.com/flyteorg/flyte/v2/flytestdlib/app" "github.com/flyteorg/flyte/v2/gen/go/flyteidl2/actions/actionsconnect" -"github.com/flyteorg/flyte/v2/gen/go/flyteidl2/auth/authconnect" + "github.com/flyteorg/flyte/v2/gen/go/flyteidl2/auth/authconnect" projectpb "github.com/flyteorg/flyte/v2/gen/go/flyteidl2/project" "github.com/flyteorg/flyte/v2/gen/go/flyteidl2/project/projectconnect" "github.com/flyteorg/flyte/v2/gen/go/flyteidl2/task/taskconnect" @@ -21,6 +21,7 @@ import ( "github.com/flyteorg/flyte/v2/runs/repository/impl" "github.com/flyteorg/flyte/v2/runs/repository/interfaces" "github.com/flyteorg/flyte/v2/runs/repository/models" + "github.com/flyteorg/flyte/v2/runs/scheduler" "github.com/flyteorg/flyte/v2/runs/service" "github.com/flyteorg/flyte/v2/flytestdlib/logger" @@ -91,7 +92,7 @@ func Setup(ctx context.Context, sc *app.SetupContext) error { sc.Mux.Handle(authMetadataPath, authMetadataHandler) logger.Infof(ctx, "Mounted AuthMetadataService at %s", authMetadataPath) -triggerSvc := service.NewTriggerService() + triggerSvc := service.NewTriggerService(repo) triggerPath, triggerHandler := triggerconnect.NewTriggerServiceHandler(triggerSvc) sc.Mux.Handle(triggerPath, triggerHandler) logger.Infof(ctx, "Mounted TriggerService at %s", triggerPath) @@ -123,6 +124,16 @@ triggerSvc := service.NewTriggerService() return fmt.Errorf("runs: failed to seed projects: %w", err) } + if cfg.TriggerScheduler.Enabled { + runsURL := cfg.ActionsServiceURL + if sc.BaseURL != "" { + runsURL = sc.BaseURL + } + worker := scheduler.Start(ctx, repo.TriggerRepo(), cfg.TriggerScheduler, runsURL) + sc.AddWorker("trigger-scheduler", worker) + logger.Infof(ctx, "Registered trigger-scheduler worker") + } + sc.AddReadyCheck(func(r *http.Request) error { if err := sc.DB.PingContext(r.Context()); err != nil { return fmt.Errorf("database ping failed: %w", err) From 7f7114c039996b052c331063670ef24c221d0827 Mon Sep 17 00:00:00 2001 From: "M. Adil Fayyaz" <62440954+AdilFayyaz@users.noreply.github.com> Date: Tue, 21 Apr 2026 15:33:50 -0700 Subject: [PATCH 3/6] fix: add missing Chart.yaml and templates to flyte-sandbox helm chart Signed-off-by: M. Adil Fayyaz <62440954+AdilFayyaz@users.noreply.github.com> --- charts/flyte-sandbox/.helmignore | 23 ++++ charts/flyte-sandbox/Chart.lock | 10 ++ charts/flyte-sandbox/Chart.yaml | 19 ++++ charts/flyte-sandbox/templates/NOTES.txt | 0 charts/flyte-sandbox/templates/_helpers.tpl | 106 ++++++++++++++++++ ...er-resource-template-inline-configmap.yaml | 7 ++ .../configuration-inline-configmap.yaml | 7 ++ .../templates/console/deployment.yaml | 38 +++++++ .../templates/console/service.yaml | 15 +++ .../templates/local/endpoint.yaml | 19 ++++ .../templates/local/service.yaml | 18 +++ .../templates/proxy/ingress.yaml | 55 +++++++++ .../templates/storage/rustfs/deployment.yaml | 85 ++++++++++++++ .../templates/storage/rustfs/pv.yaml | 17 +++ .../templates/storage/rustfs/pvc.yaml | 17 +++ .../templates/storage/rustfs/secret.yaml | 13 +++ .../templates/storage/rustfs/service.yaml | 19 ++++ 17 files changed, 468 insertions(+) create mode 100644 charts/flyte-sandbox/.helmignore create mode 100644 charts/flyte-sandbox/Chart.lock create mode 100644 charts/flyte-sandbox/Chart.yaml create mode 100644 charts/flyte-sandbox/templates/NOTES.txt create mode 100644 charts/flyte-sandbox/templates/_helpers.tpl create mode 100644 charts/flyte-sandbox/templates/config/cluster-resource-template-inline-configmap.yaml create mode 100644 charts/flyte-sandbox/templates/config/configuration-inline-configmap.yaml create mode 100644 charts/flyte-sandbox/templates/console/deployment.yaml create mode 100644 charts/flyte-sandbox/templates/console/service.yaml create mode 100644 charts/flyte-sandbox/templates/local/endpoint.yaml create mode 100644 charts/flyte-sandbox/templates/local/service.yaml create mode 100644 charts/flyte-sandbox/templates/proxy/ingress.yaml create mode 100644 charts/flyte-sandbox/templates/storage/rustfs/deployment.yaml create mode 100644 charts/flyte-sandbox/templates/storage/rustfs/pv.yaml create mode 100644 charts/flyte-sandbox/templates/storage/rustfs/pvc.yaml create mode 100644 charts/flyte-sandbox/templates/storage/rustfs/secret.yaml create mode 100644 charts/flyte-sandbox/templates/storage/rustfs/service.yaml diff --git a/charts/flyte-sandbox/.helmignore b/charts/flyte-sandbox/.helmignore new file mode 100644 index 00000000000..0e8a0eb36f4 --- /dev/null +++ b/charts/flyte-sandbox/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/flyte-sandbox/Chart.lock b/charts/flyte-sandbox/Chart.lock new file mode 100644 index 00000000000..551f4c2f2f6 --- /dev/null +++ b/charts/flyte-sandbox/Chart.lock @@ -0,0 +1,10 @@ +dependencies: +- name: docker-registry + repository: https://twuni.github.io/docker-registry.helm + version: 2.2.2 +- name: flyte-binary + repository: file://../flyte-binary + version: v0.2.0 + +digest: sha256:bc1e2e37ac2f11f9bf547262643c9076d6c86af661b6ffdee77cc6756d687d6e +generated: "2026-04-14T10:42:50.772509+08:00" diff --git a/charts/flyte-sandbox/Chart.yaml b/charts/flyte-sandbox/Chart.yaml new file mode 100644 index 00000000000..5eeb8593734 --- /dev/null +++ b/charts/flyte-sandbox/Chart.yaml @@ -0,0 +1,19 @@ +apiVersion: v2 +name: flyte-sandbox +description: A Helm chart for the Flyte sandbox cluster with Knative app support + +type: application + +version: 0.1.0 + +appVersion: "1.16.1" + +dependencies: + - name: docker-registry + version: 2.2.2 + repository: https://twuni.github.io/docker-registry.helm + condition: docker-registry.enabled + - name: flyte-binary + version: v0.2.0 + repository: file://../flyte-binary + condition: flyte-binary.enabled diff --git a/charts/flyte-sandbox/templates/NOTES.txt b/charts/flyte-sandbox/templates/NOTES.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/charts/flyte-sandbox/templates/_helpers.tpl b/charts/flyte-sandbox/templates/_helpers.tpl new file mode 100644 index 00000000000..d617539c6c9 --- /dev/null +++ b/charts/flyte-sandbox/templates/_helpers.tpl @@ -0,0 +1,106 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "flyte-sandbox.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "flyte-sandbox.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "flyte-sandbox.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "flyte-sandbox.labels" -}} +helm.sh/chart: {{ include "flyte-sandbox.chart" . }} +{{ include "flyte-sandbox.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "flyte-sandbox.selectorLabels" -}} +app.kubernetes.io/name: {{ include "flyte-sandbox.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "flyte-sandbox.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "flyte-sandbox.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Name of inline ConfigMap containing additional configuration or overrides for Flyte +*/}} +{{- define "flyte-sandbox.configuration.inlineConfigMap" -}} +{{- printf "%s-extra-config" .Release.Name -}} +{{- end }} + +{{/* +Name of inline ConfigMap containing additional cluster resource templates +*/}} +{{- define "flyte-sandbox.clusterResourceTemplates.inlineConfigMap" -}} +{{- printf "%s-extra-cluster-resource-templates" .Release.Name -}} +{{- end }} + +{{/* +Name of PersistentVolume and PersistentVolumeClaim for PostgreSQL database +*/}} +{{- define "flyte-sandbox.persistence.dbVolumeName" -}} +{{- printf "%s-db-storage" .Release.Name -}} +{{- end }} + +{{/* +Name of PersistentVolume and PersistentVolumeClaim for RustFS +*/}} +{{- define "flyte-sandbox.persistence.rustfsVolumeName" -}} +{{- printf "%s-rustfs-storage" .Release.Name -}} +{{- end }} + + +{{/* +Selector labels for console +*/}} +{{- define "flyte-sandbox.consoleSelectorLabels" -}} +{{ include "flyte-sandbox.selectorLabels" . }} +app.kubernetes.io/component: console +{{- end }} + +{{/* +Name of development-mode Flyte headless service +*/}} +{{- define "flyte-sandbox.localHeadlessService" -}} +{{- printf "%s-local" .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- end }} diff --git a/charts/flyte-sandbox/templates/config/cluster-resource-template-inline-configmap.yaml b/charts/flyte-sandbox/templates/config/cluster-resource-template-inline-configmap.yaml new file mode 100644 index 00000000000..a72dcd1e72d --- /dev/null +++ b/charts/flyte-sandbox/templates/config/cluster-resource-template-inline-configmap.yaml @@ -0,0 +1,7 @@ +{{- if ( index .Values "flyte-binary" "enabled" ) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "flyte-sandbox.clusterResourceTemplates.inlineConfigMap" . }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/charts/flyte-sandbox/templates/config/configuration-inline-configmap.yaml b/charts/flyte-sandbox/templates/config/configuration-inline-configmap.yaml new file mode 100644 index 00000000000..7354956a6e1 --- /dev/null +++ b/charts/flyte-sandbox/templates/config/configuration-inline-configmap.yaml @@ -0,0 +1,7 @@ +{{- if ( index .Values "flyte-binary" "enabled" ) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "flyte-sandbox.configuration.inlineConfigMap" . }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/charts/flyte-sandbox/templates/console/deployment.yaml b/charts/flyte-sandbox/templates/console/deployment.yaml new file mode 100644 index 00000000000..68e9030da2e --- /dev/null +++ b/charts/flyte-sandbox/templates/console/deployment.yaml @@ -0,0 +1,38 @@ +{{- if .Values.sandbox.console.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: flyte-console + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "flyte-sandbox.labels" . | nindent 4 }} +spec: + replicas: 1 + selector: + matchLabels: {{- include "flyte-sandbox.consoleSelectorLabels" . | nindent 6 }} + template: + metadata: + labels: {{- include "flyte-sandbox.consoleSelectorLabels" . | nindent 8 }} + spec: + containers: + - name: console + {{- with .Values.sandbox.console.image }} + image: {{ printf "%s:%s" .repository .tag | quote }} + imagePullPolicy: {{ .pullPolicy | quote }} + {{- end }} + ports: + - name: http + containerPort: 8080 + protocol: TCP + readinessProbe: + httpGet: + path: /v2 + port: http + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /v2 + port: http + initialDelaySeconds: 5 + periodSeconds: 30 +{{- end }} diff --git a/charts/flyte-sandbox/templates/console/service.yaml b/charts/flyte-sandbox/templates/console/service.yaml new file mode 100644 index 00000000000..e174486494d --- /dev/null +++ b/charts/flyte-sandbox/templates/console/service.yaml @@ -0,0 +1,15 @@ +{{- if .Values.sandbox.console.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: flyte-console + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "flyte-sandbox.labels" . | nindent 4 }} +spec: + selector: {{- include "flyte-sandbox.consoleSelectorLabels" . | nindent 4 }} + ports: + - name: http + port: 80 + targetPort: http + protocol: TCP +{{- end }} diff --git a/charts/flyte-sandbox/templates/local/endpoint.yaml b/charts/flyte-sandbox/templates/local/endpoint.yaml new file mode 100644 index 00000000000..f313aed788e --- /dev/null +++ b/charts/flyte-sandbox/templates/local/endpoint.yaml @@ -0,0 +1,19 @@ +{{- if and ( not ( index .Values "flyte-binary" "enabled" ) ) .Values.sandbox.dev }} +apiVersion: v1 +kind: Endpoints +metadata: + name: {{ include "flyte-sandbox.localHeadlessService" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "flyte-sandbox.labels" . | nindent 4 }} +subsets: + - addresses: + - ip: '%{HOST_GATEWAY_IP}%' + ports: + - name: http + port: 8090 + protocol: TCP + - name: webhook + port: 9443 + protocol: TCP +{{- end }} diff --git a/charts/flyte-sandbox/templates/local/service.yaml b/charts/flyte-sandbox/templates/local/service.yaml new file mode 100644 index 00000000000..2643120bd06 --- /dev/null +++ b/charts/flyte-sandbox/templates/local/service.yaml @@ -0,0 +1,18 @@ +{{- if and ( not ( index .Values "flyte-binary" "enabled" ) ) .Values.sandbox.dev }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "flyte-sandbox.localHeadlessService" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "flyte-sandbox.labels" . | nindent 4 }} +spec: + clusterIP: None + ports: + - name: http + port: 8090 + protocol: TCP + - name: webhook + port: 9443 + protocol: TCP +{{- end }} diff --git a/charts/flyte-sandbox/templates/proxy/ingress.yaml b/charts/flyte-sandbox/templates/proxy/ingress.yaml new file mode 100644 index 00000000000..62c588e7fdc --- /dev/null +++ b/charts/flyte-sandbox/templates/proxy/ingress.yaml @@ -0,0 +1,55 @@ +{{- if or ( index .Values "flyte-binary" "enabled" ) .Values.sandbox.dev }} +{{- $backendService := "" }} +{{- if index .Values "flyte-binary" "enabled" }} +{{- $backendService = printf "%s-http" ( index .Values "flyte-binary" "fullnameOverride" | default "flyte-binary" ) }} +{{- else }} +{{- $backendService = include "flyte-sandbox.localHeadlessService" . }} +{{- end }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "flyte-sandbox.fullname" . }}-api + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "flyte-sandbox.labels" . | nindent 4 }} +spec: + rules: + - http: + paths: + {{- range $path := list "/healthz" "/readyz" }} + - path: {{ $path }} + pathType: Exact + backend: + service: + name: {{ $backendService }} + port: + number: 8090 + {{- end }} + - path: /flyteidl2. + pathType: Prefix + backend: + service: + name: {{ $backendService }} + port: + number: 8090 +{{- end }} +--- +{{- if .Values.sandbox.console.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: flyte-console + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "flyte-sandbox.labels" . | nindent 4 }} +spec: + rules: + - http: + paths: + - path: /v2 + pathType: Prefix + backend: + service: + name: flyte-console + port: + number: 80 +{{- end }} +--- diff --git a/charts/flyte-sandbox/templates/storage/rustfs/deployment.yaml b/charts/flyte-sandbox/templates/storage/rustfs/deployment.yaml new file mode 100644 index 00000000000..c082d4fb4cd --- /dev/null +++ b/charts/flyte-sandbox/templates/storage/rustfs/deployment.yaml @@ -0,0 +1,85 @@ +{{- if .Values.rustfs.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: rustfs + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "flyte-sandbox.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: rustfs + app.kubernetes.io/instance: {{ .Release.Name }} + strategy: + type: Recreate + template: + metadata: + labels: + app.kubernetes.io/name: rustfs + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + initContainers: + - name: volume-permissions + image: busybox:latest + imagePullPolicy: IfNotPresent + command: + - /bin/sh + - -ec + - | + chown -R 10001:10001 /data + mkdir -p /data/flyte-data + chown 10001:10001 /data/flyte-data + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /data + name: data + containers: + - name: rustfs + image: rustfs/rustfs:sandbox + imagePullPolicy: Never + env: + - name: RUSTFS_ADDRESS + value: "0.0.0.0:9000" + - name: RUSTFS_VOLUMES + value: "/data" + - name: RUSTFS_ACCESS_KEY + valueFrom: + secretKeyRef: + name: rustfs + key: access-key + - name: RUSTFS_SECRET_KEY + valueFrom: + secretKeyRef: + name: rustfs + key: secret-key + ports: + - containerPort: 9000 + name: rustfs-api + protocol: TCP + livenessProbe: + tcpSocket: + port: rustfs-api + initialDelaySeconds: 10 + periodSeconds: 10 + failureThreshold: 5 + readinessProbe: + tcpSocket: + port: rustfs-api + initialDelaySeconds: 5 + periodSeconds: 5 + failureThreshold: 5 + securityContext: + runAsUser: 10001 + runAsNonRoot: true + volumeMounts: + - mountPath: /data + name: data + securityContext: + fsGroup: 10001 + volumes: + - name: data + persistentVolumeClaim: + claimName: {{ include "flyte-sandbox.persistence.rustfsVolumeName" . }} +{{- end }} diff --git a/charts/flyte-sandbox/templates/storage/rustfs/pv.yaml b/charts/flyte-sandbox/templates/storage/rustfs/pv.yaml new file mode 100644 index 00000000000..36d87bfb59f --- /dev/null +++ b/charts/flyte-sandbox/templates/storage/rustfs/pv.yaml @@ -0,0 +1,17 @@ +{{- if .Values.rustfs.enabled }} +apiVersion: v1 +kind: PersistentVolume +metadata: + name: {{ include "flyte-sandbox.persistence.rustfsVolumeName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "flyte-sandbox.labels" . | nindent 4 }} +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + hostPath: + path: "/var/lib/flyte/storage/rustfs" +{{- end }} diff --git a/charts/flyte-sandbox/templates/storage/rustfs/pvc.yaml b/charts/flyte-sandbox/templates/storage/rustfs/pvc.yaml new file mode 100644 index 00000000000..c6fa04098bb --- /dev/null +++ b/charts/flyte-sandbox/templates/storage/rustfs/pvc.yaml @@ -0,0 +1,17 @@ +{{- if .Values.rustfs.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "flyte-sandbox.persistence.rustfsVolumeName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "flyte-sandbox.labels" . | nindent 4 }} +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + volumeName: {{ include "flyte-sandbox.persistence.rustfsVolumeName" . }} +{{- end }} diff --git a/charts/flyte-sandbox/templates/storage/rustfs/secret.yaml b/charts/flyte-sandbox/templates/storage/rustfs/secret.yaml new file mode 100644 index 00000000000..222bd6a221c --- /dev/null +++ b/charts/flyte-sandbox/templates/storage/rustfs/secret.yaml @@ -0,0 +1,13 @@ +{{- if .Values.rustfs.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: rustfs + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "flyte-sandbox.labels" . | nindent 4 }} +type: Opaque +data: + access-key: {{ .Values.rustfs.accessKey | b64enc | quote }} + secret-key: {{ .Values.rustfs.secretKey | b64enc | quote }} +{{- end }} diff --git a/charts/flyte-sandbox/templates/storage/rustfs/service.yaml b/charts/flyte-sandbox/templates/storage/rustfs/service.yaml new file mode 100644 index 00000000000..e0f8a5b0530 --- /dev/null +++ b/charts/flyte-sandbox/templates/storage/rustfs/service.yaml @@ -0,0 +1,19 @@ +{{- if .Values.rustfs.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: rustfs + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "flyte-sandbox.labels" . | nindent 4 }} +spec: + type: NodePort + ports: + - name: rustfs-api + nodePort: 30002 + port: 9000 + targetPort: rustfs-api + selector: + app.kubernetes.io/name: rustfs + app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} From 773301c2b81f180f4acb945d5b8a05d7cd089fe5 Mon Sep 17 00:00:00 2001 From: "M. Adil Fayyaz" <62440954+AdilFayyaz@users.noreply.github.com> Date: Tue, 21 Apr 2026 15:35:38 -0700 Subject: [PATCH 4/6] Revert "fix: add missing Chart.yaml and templates to flyte-sandbox helm chart" This reverts commit ce5fe00b0c67cb925b207df0517e3860bcb75e50. Signed-off-by: M. Adil Fayyaz <62440954+AdilFayyaz@users.noreply.github.com> --- charts/flyte-sandbox/.helmignore | 23 ---- charts/flyte-sandbox/Chart.lock | 10 -- charts/flyte-sandbox/Chart.yaml | 19 ---- charts/flyte-sandbox/templates/NOTES.txt | 0 charts/flyte-sandbox/templates/_helpers.tpl | 106 ------------------ ...er-resource-template-inline-configmap.yaml | 7 -- .../configuration-inline-configmap.yaml | 7 -- .../templates/console/deployment.yaml | 38 ------- .../templates/console/service.yaml | 15 --- .../templates/local/endpoint.yaml | 19 ---- .../templates/local/service.yaml | 18 --- .../templates/proxy/ingress.yaml | 55 --------- .../templates/storage/rustfs/deployment.yaml | 85 -------------- .../templates/storage/rustfs/pv.yaml | 17 --- .../templates/storage/rustfs/pvc.yaml | 17 --- .../templates/storage/rustfs/secret.yaml | 13 --- .../templates/storage/rustfs/service.yaml | 19 ---- 17 files changed, 468 deletions(-) delete mode 100644 charts/flyte-sandbox/.helmignore delete mode 100644 charts/flyte-sandbox/Chart.lock delete mode 100644 charts/flyte-sandbox/Chart.yaml delete mode 100644 charts/flyte-sandbox/templates/NOTES.txt delete mode 100644 charts/flyte-sandbox/templates/_helpers.tpl delete mode 100644 charts/flyte-sandbox/templates/config/cluster-resource-template-inline-configmap.yaml delete mode 100644 charts/flyte-sandbox/templates/config/configuration-inline-configmap.yaml delete mode 100644 charts/flyte-sandbox/templates/console/deployment.yaml delete mode 100644 charts/flyte-sandbox/templates/console/service.yaml delete mode 100644 charts/flyte-sandbox/templates/local/endpoint.yaml delete mode 100644 charts/flyte-sandbox/templates/local/service.yaml delete mode 100644 charts/flyte-sandbox/templates/proxy/ingress.yaml delete mode 100644 charts/flyte-sandbox/templates/storage/rustfs/deployment.yaml delete mode 100644 charts/flyte-sandbox/templates/storage/rustfs/pv.yaml delete mode 100644 charts/flyte-sandbox/templates/storage/rustfs/pvc.yaml delete mode 100644 charts/flyte-sandbox/templates/storage/rustfs/secret.yaml delete mode 100644 charts/flyte-sandbox/templates/storage/rustfs/service.yaml diff --git a/charts/flyte-sandbox/.helmignore b/charts/flyte-sandbox/.helmignore deleted file mode 100644 index 0e8a0eb36f4..00000000000 --- a/charts/flyte-sandbox/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/charts/flyte-sandbox/Chart.lock b/charts/flyte-sandbox/Chart.lock deleted file mode 100644 index 551f4c2f2f6..00000000000 --- a/charts/flyte-sandbox/Chart.lock +++ /dev/null @@ -1,10 +0,0 @@ -dependencies: -- name: docker-registry - repository: https://twuni.github.io/docker-registry.helm - version: 2.2.2 -- name: flyte-binary - repository: file://../flyte-binary - version: v0.2.0 - -digest: sha256:bc1e2e37ac2f11f9bf547262643c9076d6c86af661b6ffdee77cc6756d687d6e -generated: "2026-04-14T10:42:50.772509+08:00" diff --git a/charts/flyte-sandbox/Chart.yaml b/charts/flyte-sandbox/Chart.yaml deleted file mode 100644 index 5eeb8593734..00000000000 --- a/charts/flyte-sandbox/Chart.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v2 -name: flyte-sandbox -description: A Helm chart for the Flyte sandbox cluster with Knative app support - -type: application - -version: 0.1.0 - -appVersion: "1.16.1" - -dependencies: - - name: docker-registry - version: 2.2.2 - repository: https://twuni.github.io/docker-registry.helm - condition: docker-registry.enabled - - name: flyte-binary - version: v0.2.0 - repository: file://../flyte-binary - condition: flyte-binary.enabled diff --git a/charts/flyte-sandbox/templates/NOTES.txt b/charts/flyte-sandbox/templates/NOTES.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/charts/flyte-sandbox/templates/_helpers.tpl b/charts/flyte-sandbox/templates/_helpers.tpl deleted file mode 100644 index d617539c6c9..00000000000 --- a/charts/flyte-sandbox/templates/_helpers.tpl +++ /dev/null @@ -1,106 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "flyte-sandbox.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "flyte-sandbox.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "flyte-sandbox.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "flyte-sandbox.labels" -}} -helm.sh/chart: {{ include "flyte-sandbox.chart" . }} -{{ include "flyte-sandbox.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "flyte-sandbox.selectorLabels" -}} -app.kubernetes.io/name: {{ include "flyte-sandbox.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "flyte-sandbox.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "flyte-sandbox.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} - -{{/* -Name of inline ConfigMap containing additional configuration or overrides for Flyte -*/}} -{{- define "flyte-sandbox.configuration.inlineConfigMap" -}} -{{- printf "%s-extra-config" .Release.Name -}} -{{- end }} - -{{/* -Name of inline ConfigMap containing additional cluster resource templates -*/}} -{{- define "flyte-sandbox.clusterResourceTemplates.inlineConfigMap" -}} -{{- printf "%s-extra-cluster-resource-templates" .Release.Name -}} -{{- end }} - -{{/* -Name of PersistentVolume and PersistentVolumeClaim for PostgreSQL database -*/}} -{{- define "flyte-sandbox.persistence.dbVolumeName" -}} -{{- printf "%s-db-storage" .Release.Name -}} -{{- end }} - -{{/* -Name of PersistentVolume and PersistentVolumeClaim for RustFS -*/}} -{{- define "flyte-sandbox.persistence.rustfsVolumeName" -}} -{{- printf "%s-rustfs-storage" .Release.Name -}} -{{- end }} - - -{{/* -Selector labels for console -*/}} -{{- define "flyte-sandbox.consoleSelectorLabels" -}} -{{ include "flyte-sandbox.selectorLabels" . }} -app.kubernetes.io/component: console -{{- end }} - -{{/* -Name of development-mode Flyte headless service -*/}} -{{- define "flyte-sandbox.localHeadlessService" -}} -{{- printf "%s-local" .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- end }} diff --git a/charts/flyte-sandbox/templates/config/cluster-resource-template-inline-configmap.yaml b/charts/flyte-sandbox/templates/config/cluster-resource-template-inline-configmap.yaml deleted file mode 100644 index a72dcd1e72d..00000000000 --- a/charts/flyte-sandbox/templates/config/cluster-resource-template-inline-configmap.yaml +++ /dev/null @@ -1,7 +0,0 @@ -{{- if ( index .Values "flyte-binary" "enabled" ) }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "flyte-sandbox.clusterResourceTemplates.inlineConfigMap" . }} - namespace: {{ .Release.Namespace | quote }} -{{- end }} diff --git a/charts/flyte-sandbox/templates/config/configuration-inline-configmap.yaml b/charts/flyte-sandbox/templates/config/configuration-inline-configmap.yaml deleted file mode 100644 index 7354956a6e1..00000000000 --- a/charts/flyte-sandbox/templates/config/configuration-inline-configmap.yaml +++ /dev/null @@ -1,7 +0,0 @@ -{{- if ( index .Values "flyte-binary" "enabled" ) }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "flyte-sandbox.configuration.inlineConfigMap" . }} - namespace: {{ .Release.Namespace | quote }} -{{- end }} diff --git a/charts/flyte-sandbox/templates/console/deployment.yaml b/charts/flyte-sandbox/templates/console/deployment.yaml deleted file mode 100644 index 68e9030da2e..00000000000 --- a/charts/flyte-sandbox/templates/console/deployment.yaml +++ /dev/null @@ -1,38 +0,0 @@ -{{- if .Values.sandbox.console.enabled }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: flyte-console - namespace: {{ .Release.Namespace | quote }} - labels: {{- include "flyte-sandbox.labels" . | nindent 4 }} -spec: - replicas: 1 - selector: - matchLabels: {{- include "flyte-sandbox.consoleSelectorLabels" . | nindent 6 }} - template: - metadata: - labels: {{- include "flyte-sandbox.consoleSelectorLabels" . | nindent 8 }} - spec: - containers: - - name: console - {{- with .Values.sandbox.console.image }} - image: {{ printf "%s:%s" .repository .tag | quote }} - imagePullPolicy: {{ .pullPolicy | quote }} - {{- end }} - ports: - - name: http - containerPort: 8080 - protocol: TCP - readinessProbe: - httpGet: - path: /v2 - port: http - initialDelaySeconds: 5 - periodSeconds: 10 - livenessProbe: - httpGet: - path: /v2 - port: http - initialDelaySeconds: 5 - periodSeconds: 30 -{{- end }} diff --git a/charts/flyte-sandbox/templates/console/service.yaml b/charts/flyte-sandbox/templates/console/service.yaml deleted file mode 100644 index e174486494d..00000000000 --- a/charts/flyte-sandbox/templates/console/service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -{{- if .Values.sandbox.console.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: flyte-console - namespace: {{ .Release.Namespace | quote }} - labels: {{- include "flyte-sandbox.labels" . | nindent 4 }} -spec: - selector: {{- include "flyte-sandbox.consoleSelectorLabels" . | nindent 4 }} - ports: - - name: http - port: 80 - targetPort: http - protocol: TCP -{{- end }} diff --git a/charts/flyte-sandbox/templates/local/endpoint.yaml b/charts/flyte-sandbox/templates/local/endpoint.yaml deleted file mode 100644 index f313aed788e..00000000000 --- a/charts/flyte-sandbox/templates/local/endpoint.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- if and ( not ( index .Values "flyte-binary" "enabled" ) ) .Values.sandbox.dev }} -apiVersion: v1 -kind: Endpoints -metadata: - name: {{ include "flyte-sandbox.localHeadlessService" . }} - namespace: {{ .Release.Namespace | quote }} - labels: - {{- include "flyte-sandbox.labels" . | nindent 4 }} -subsets: - - addresses: - - ip: '%{HOST_GATEWAY_IP}%' - ports: - - name: http - port: 8090 - protocol: TCP - - name: webhook - port: 9443 - protocol: TCP -{{- end }} diff --git a/charts/flyte-sandbox/templates/local/service.yaml b/charts/flyte-sandbox/templates/local/service.yaml deleted file mode 100644 index 2643120bd06..00000000000 --- a/charts/flyte-sandbox/templates/local/service.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if and ( not ( index .Values "flyte-binary" "enabled" ) ) .Values.sandbox.dev }} -apiVersion: v1 -kind: Service -metadata: - name: {{ include "flyte-sandbox.localHeadlessService" . }} - namespace: {{ .Release.Namespace | quote }} - labels: - {{- include "flyte-sandbox.labels" . | nindent 4 }} -spec: - clusterIP: None - ports: - - name: http - port: 8090 - protocol: TCP - - name: webhook - port: 9443 - protocol: TCP -{{- end }} diff --git a/charts/flyte-sandbox/templates/proxy/ingress.yaml b/charts/flyte-sandbox/templates/proxy/ingress.yaml deleted file mode 100644 index 62c588e7fdc..00000000000 --- a/charts/flyte-sandbox/templates/proxy/ingress.yaml +++ /dev/null @@ -1,55 +0,0 @@ -{{- if or ( index .Values "flyte-binary" "enabled" ) .Values.sandbox.dev }} -{{- $backendService := "" }} -{{- if index .Values "flyte-binary" "enabled" }} -{{- $backendService = printf "%s-http" ( index .Values "flyte-binary" "fullnameOverride" | default "flyte-binary" ) }} -{{- else }} -{{- $backendService = include "flyte-sandbox.localHeadlessService" . }} -{{- end }} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: {{ include "flyte-sandbox.fullname" . }}-api - namespace: {{ .Release.Namespace | quote }} - labels: {{- include "flyte-sandbox.labels" . | nindent 4 }} -spec: - rules: - - http: - paths: - {{- range $path := list "/healthz" "/readyz" }} - - path: {{ $path }} - pathType: Exact - backend: - service: - name: {{ $backendService }} - port: - number: 8090 - {{- end }} - - path: /flyteidl2. - pathType: Prefix - backend: - service: - name: {{ $backendService }} - port: - number: 8090 -{{- end }} ---- -{{- if .Values.sandbox.console.enabled }} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: flyte-console - namespace: {{ .Release.Namespace | quote }} - labels: {{- include "flyte-sandbox.labels" . | nindent 4 }} -spec: - rules: - - http: - paths: - - path: /v2 - pathType: Prefix - backend: - service: - name: flyte-console - port: - number: 80 -{{- end }} ---- diff --git a/charts/flyte-sandbox/templates/storage/rustfs/deployment.yaml b/charts/flyte-sandbox/templates/storage/rustfs/deployment.yaml deleted file mode 100644 index c082d4fb4cd..00000000000 --- a/charts/flyte-sandbox/templates/storage/rustfs/deployment.yaml +++ /dev/null @@ -1,85 +0,0 @@ -{{- if .Values.rustfs.enabled }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: rustfs - namespace: {{ .Release.Namespace | quote }} - labels: - {{- include "flyte-sandbox.labels" . | nindent 4 }} -spec: - selector: - matchLabels: - app.kubernetes.io/name: rustfs - app.kubernetes.io/instance: {{ .Release.Name }} - strategy: - type: Recreate - template: - metadata: - labels: - app.kubernetes.io/name: rustfs - app.kubernetes.io/instance: {{ .Release.Name }} - spec: - initContainers: - - name: volume-permissions - image: busybox:latest - imagePullPolicy: IfNotPresent - command: - - /bin/sh - - -ec - - | - chown -R 10001:10001 /data - mkdir -p /data/flyte-data - chown 10001:10001 /data/flyte-data - securityContext: - runAsUser: 0 - volumeMounts: - - mountPath: /data - name: data - containers: - - name: rustfs - image: rustfs/rustfs:sandbox - imagePullPolicy: Never - env: - - name: RUSTFS_ADDRESS - value: "0.0.0.0:9000" - - name: RUSTFS_VOLUMES - value: "/data" - - name: RUSTFS_ACCESS_KEY - valueFrom: - secretKeyRef: - name: rustfs - key: access-key - - name: RUSTFS_SECRET_KEY - valueFrom: - secretKeyRef: - name: rustfs - key: secret-key - ports: - - containerPort: 9000 - name: rustfs-api - protocol: TCP - livenessProbe: - tcpSocket: - port: rustfs-api - initialDelaySeconds: 10 - periodSeconds: 10 - failureThreshold: 5 - readinessProbe: - tcpSocket: - port: rustfs-api - initialDelaySeconds: 5 - periodSeconds: 5 - failureThreshold: 5 - securityContext: - runAsUser: 10001 - runAsNonRoot: true - volumeMounts: - - mountPath: /data - name: data - securityContext: - fsGroup: 10001 - volumes: - - name: data - persistentVolumeClaim: - claimName: {{ include "flyte-sandbox.persistence.rustfsVolumeName" . }} -{{- end }} diff --git a/charts/flyte-sandbox/templates/storage/rustfs/pv.yaml b/charts/flyte-sandbox/templates/storage/rustfs/pv.yaml deleted file mode 100644 index 36d87bfb59f..00000000000 --- a/charts/flyte-sandbox/templates/storage/rustfs/pv.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if .Values.rustfs.enabled }} -apiVersion: v1 -kind: PersistentVolume -metadata: - name: {{ include "flyte-sandbox.persistence.rustfsVolumeName" . }} - namespace: {{ .Release.Namespace | quote }} - labels: - {{- include "flyte-sandbox.labels" . | nindent 4 }} -spec: - storageClassName: manual - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - hostPath: - path: "/var/lib/flyte/storage/rustfs" -{{- end }} diff --git a/charts/flyte-sandbox/templates/storage/rustfs/pvc.yaml b/charts/flyte-sandbox/templates/storage/rustfs/pvc.yaml deleted file mode 100644 index c6fa04098bb..00000000000 --- a/charts/flyte-sandbox/templates/storage/rustfs/pvc.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if .Values.rustfs.enabled }} -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: {{ include "flyte-sandbox.persistence.rustfsVolumeName" . }} - namespace: {{ .Release.Namespace | quote }} - labels: - {{- include "flyte-sandbox.labels" . | nindent 4 }} -spec: - storageClassName: manual - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi - volumeName: {{ include "flyte-sandbox.persistence.rustfsVolumeName" . }} -{{- end }} diff --git a/charts/flyte-sandbox/templates/storage/rustfs/secret.yaml b/charts/flyte-sandbox/templates/storage/rustfs/secret.yaml deleted file mode 100644 index 222bd6a221c..00000000000 --- a/charts/flyte-sandbox/templates/storage/rustfs/secret.yaml +++ /dev/null @@ -1,13 +0,0 @@ -{{- if .Values.rustfs.enabled }} -apiVersion: v1 -kind: Secret -metadata: - name: rustfs - namespace: {{ .Release.Namespace | quote }} - labels: - {{- include "flyte-sandbox.labels" . | nindent 4 }} -type: Opaque -data: - access-key: {{ .Values.rustfs.accessKey | b64enc | quote }} - secret-key: {{ .Values.rustfs.secretKey | b64enc | quote }} -{{- end }} diff --git a/charts/flyte-sandbox/templates/storage/rustfs/service.yaml b/charts/flyte-sandbox/templates/storage/rustfs/service.yaml deleted file mode 100644 index e0f8a5b0530..00000000000 --- a/charts/flyte-sandbox/templates/storage/rustfs/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- if .Values.rustfs.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: rustfs - namespace: {{ .Release.Namespace | quote }} - labels: - {{- include "flyte-sandbox.labels" . | nindent 4 }} -spec: - type: NodePort - ports: - - name: rustfs-api - nodePort: 30002 - port: 9000 - targetPort: rustfs-api - selector: - app.kubernetes.io/name: rustfs - app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} From 07e55810a1579afa025728290a4ba85de4685102 Mon Sep 17 00:00:00 2001 From: "M. Adil Fayyaz" <62440954+AdilFayyaz@users.noreply.github.com> Date: Tue, 21 Apr 2026 16:17:55 -0700 Subject: [PATCH 5/6] fix: sandbox to devbox Signed-off-by: M. Adil Fayyaz <62440954+AdilFayyaz@users.noreply.github.com> --- Makefile | 24 +- .../templates/proxy/traefik-config.yaml | 5 + charts/flyte-devbox/values.yaml | 21 + .../templates/proxy/traefik-config.yaml | 23 - charts/flyte-sandbox/values.yaml | 185 -- docker/devbox-bundled/Makefile | 12 + docker/devbox-bundled/manifests/complete.yaml | 28 +- docker/devbox-bundled/manifests/dev.yaml | 5 + docker/sandbox-bundled/Makefile | 137 -- .../sandbox-bundled/manifests/complete.yaml | 1610 ----------------- docker/sandbox-bundled/manifests/dev.yaml | 1207 ------------ manager/config.yaml | 22 +- 12 files changed, 93 insertions(+), 3186 deletions(-) delete mode 100644 charts/flyte-sandbox/templates/proxy/traefik-config.yaml delete mode 100644 charts/flyte-sandbox/values.yaml delete mode 100644 docker/sandbox-bundled/Makefile delete mode 100644 docker/sandbox-bundled/manifests/complete.yaml delete mode 100644 docker/sandbox-bundled/manifests/dev.yaml diff --git a/Makefile b/Makefile index 3b4ca1210c0..a3eab6747d0 100644 --- a/Makefile +++ b/Makefile @@ -32,22 +32,22 @@ build: verify ## Build all Go service binaries $(MAKE) -C executor build # ============================================================================= -# Sandbox Commands +# Devbox Commands # ============================================================================= -.PHONY: sandbox-build -sandbox-build: ## Build and start the flyte sandbox (docker/sandbox-bundled) - $(MAKE) -C docker/sandbox-bundled build +.PHONY: devbox-build +devbox-build: ## Build the flyte devbox image (docker/devbox-bundled) + $(MAKE) -C docker/devbox-bundled build # Run in dev mode with extra arg FLYTE_DEV=True -.PHONY: sandbox-run -sandbox-run: ## Start the flyte sandbox and install Knative with app routing config - $(MAKE) -C docker/sandbox-bundled start FLYTE_DEV=$(FLYTE_DEV) - $(MAKE) -C docker/sandbox-bundled setup-knative - -.PHONY: sandbox-stop -sandbox-stop: ## Stop the flyte sandbox - $(MAKE) -C docker/sandbox-bundled stop +.PHONY: devbox-run +devbox-run: ## Start the flyte devbox and install Knative with app routing config + $(MAKE) -C docker/devbox-bundled start FLYTE_DEV=$(FLYTE_DEV) + $(MAKE) -C docker/devbox-bundled setup-knative + +.PHONY: devbox-stop +devbox-stop: ## Stop the flyte devbox + $(MAKE) -C docker/devbox-bundled stop .PHONY: help help: ## Show this help message diff --git a/charts/flyte-devbox/templates/proxy/traefik-config.yaml b/charts/flyte-devbox/templates/proxy/traefik-config.yaml index 5657b622f81..581444cd77d 100644 --- a/charts/flyte-devbox/templates/proxy/traefik-config.yaml +++ b/charts/flyte-devbox/templates/proxy/traefik-config.yaml @@ -16,3 +16,8 @@ spec: readTimeout: 0 websecure: expose: false + providers: + kubernetesCRD: + allowExternalNameServices: true + kubernetesIngress: + allowExternalNameServices: true diff --git a/charts/flyte-devbox/values.yaml b/charts/flyte-devbox/values.yaml index 85af9a39562..2b0280d3589 100644 --- a/charts/flyte-devbox/values.yaml +++ b/charts/flyte-devbox/values.yaml @@ -66,6 +66,27 @@ flyte-binary: dbName: runs user: postgres password: postgres + manager: + internalApps: + enabled: true + baseDomain: "local.flyte.app" + scheme: "http" + ingressEnabled: true + ingressEntryPoint: "web" + ingressBaseUrl: "http://localhost:30080" + defaultEnvVars: + - name: FLYTE_AWS_ENDPOINT + value: 'http://rustfs.{{ .Release.Namespace }}:9000' + - name: FLYTE_AWS_ACCESS_KEY_ID + value: rustfs + - name: FLYTE_AWS_SECRET_ACCESS_KEY + value: rustfsstorage + - name: _U_EP_OVERRIDE + value: 'flyte-binary-http.{{ .Release.Namespace }}:8090' + - name: _U_INSECURE + value: "true" + - name: _U_USE_ACTIONS + value: "1" inlineConfigMap: '{{ include "flyte-devbox.configuration.inlineConfigMap" . }}' clusterResourceTemplates: inlineConfigMap: '{{ include "flyte-devbox.clusterResourceTemplates.inlineConfigMap" . }}' diff --git a/charts/flyte-sandbox/templates/proxy/traefik-config.yaml b/charts/flyte-sandbox/templates/proxy/traefik-config.yaml deleted file mode 100644 index ed506c4b234..00000000000 --- a/charts/flyte-sandbox/templates/proxy/traefik-config.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: helm.cattle.io/v1 -kind: HelmChartConfig -metadata: - name: traefik - namespace: kube-system - labels: {{- include "flyte-sandbox.labels" . | nindent 4 }} -spec: - valuesContent: | - service: - type: NodePort - ports: - web: - nodePort: 30080 - transport: - respondingTimeouts: - readTimeout: 0 - websecure: - expose: false - providers: - kubernetesCRD: - allowExternalNameServices: true - kubernetesIngress: - allowExternalNameServices: true diff --git a/charts/flyte-sandbox/values.yaml b/charts/flyte-sandbox/values.yaml deleted file mode 100644 index 2b67b808189..00000000000 --- a/charts/flyte-sandbox/values.yaml +++ /dev/null @@ -1,185 +0,0 @@ -docker-registry: - enabled: true - image: - tag: sandbox - pullPolicy: Never - persistence: - enabled: false - secrets: - haSharedSecret: flytesandboxsecret - service: - type: NodePort - nodePort: 30000 - -flyte-binary: - nameOverride: flyte-sandbox - enabled: true - configuration: - database: - host: '{{ printf "%s-postgresql" .Release.Name | trunc 63 | trimSuffix "-" }}' - password: postgres - storage: - metadataContainer: flyte-data - userDataContainer: flyte-data - provider: s3 - providerConfig: - s3: - disableSSL: true - v2Signing: true - endpoint: http://{{ printf "%s-minio" .Release.Name | trunc 63 | trimSuffix "-" }}.{{ .Release.Namespace }}:9000 - authType: accesskey - accessKey: minio - secretKey: miniostorage - logging: - level: 5 - inline: - task_resources: - defaults: - cpu: 500m - ephemeralStorage: 0 - gpu: 0 - memory: 1Gi - limits: - cpu: 0 - ephemeralStorage: 0 - gpu: 0 - memory: 0 - storage: - signedURL: - stowConfigOverride: - endpoint: http://localhost:30002 - plugins: - k8s: - default-env-vars: - - FLYTE_AWS_ENDPOINT: http://{{ printf "%s-minio" .Release.Name | trunc 63 | trimSuffix "-" }}.{{ .Release.Namespace }}:9000 - - FLYTE_AWS_ACCESS_KEY_ID: minio - - FLYTE_AWS_SECRET_ACCESS_KEY: miniostorage - - _U_EP_OVERRIDE: '{{ printf "%s-http" .Release.Name }}.{{ .Release.Namespace }}:8090' - - _U_INSECURE: "true" - - _U_USE_ACTIONS: "1" - runs: - database: - postgres: - host: '{{ printf "%s-postgresql" .Release.Name | trunc 63 | trimSuffix "-" }}.{{ .Release.Namespace }}' - port: 5432 - dbName: runs - user: postgres - password: postgres - manager: - internalApps: - enabled: true - baseDomain: "local.flyte.app" - scheme: "http" - ingressEnabled: true - ingressEntryPoint: "web" - ingressBaseUrl: "http://localhost:30080" - defaultEnvVars: - - name: FLYTE_AWS_ENDPOINT - value: 'http://{{ printf "%s-minio" .Release.Name | trunc 63 | trimSuffix "-" }}.{{ .Release.Namespace }}:9000' - - name: FLYTE_AWS_ACCESS_KEY_ID - value: minio - - name: FLYTE_AWS_SECRET_ACCESS_KEY - value: miniostorage - - name: _U_EP_OVERRIDE - value: '{{ printf "%s-http" .Release.Name }}.{{ .Release.Namespace }}:8090' - - name: _U_INSECURE - value: "true" - - name: _U_USE_ACTIONS - value: "1" - inlineConfigMap: '{{ include "flyte-sandbox.configuration.inlineConfigMap" . }}' - clusterResourceTemplates: - inlineConfigMap: '{{ include "flyte-sandbox.clusterResourceTemplates.inlineConfigMap" . }}' - deployment: - image: - repository: flyte-binary-v2 - tag: sandbox - pullPolicy: Never - livenessProbe: - httpGet: - path: /healthz - port: http - initialDelaySeconds: 5 - readinessProbe: - httpGet: - path: /readyz - port: http - initialDelaySeconds: 5 - periodSeconds: 5 - waitForDB: - image: - repository: bitnami/postgresql - tag: sandbox - pullPolicy: Never - rbac: - # This is strictly NOT RECOMMENDED in production clusters, and is only for use - # within local Flyte sandboxes. - # When using cluster resource templates to create additional namespaced roles, - # Flyte is required to have a superset of those permissions. To simplify - # experimenting with new backend plugins that require additional roles be created - # with cluster resource templates (e.g. Spark), we add the following: - extraRules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' - -minio: - enabled: true - image: - tag: sandbox - pullPolicy: Never - auth: - rootUser: minio - rootPassword: miniostorage - defaultBuckets: flyte-data - extraEnvVars: - - name: MINIO_BROWSER_REDIRECT_URL - value: http://localhost:30080/minio - service: - type: NodePort - nodePorts: - api: 30002 - persistence: - enabled: true - existingClaim: '{{ include "flyte-sandbox.persistence.minioVolumeName" . }}' - volumePermissions: - enabled: true - image: - tag: sandbox - pullPolicy: Never - -postgresql: - enabled: true - image: - tag: sandbox - pullPolicy: Never - auth: - postgresPassword: postgres - shmVolume: - enabled: false - primary: - service: - type: NodePort - nodePorts: - postgresql: 30001 - persistence: - enabled: true - existingClaim: '{{ include "flyte-sandbox.persistence.dbVolumeName" . }}' - volumePermissions: - enabled: true - image: - tag: sandbox - pullPolicy: Never - -sandbox: - # dev Routes requests to an instance of Flyte running locally on a developer's - # development environment. This is only usable if the flyte-binary chart is disabled. - dev: false - console: - enabled: true - image: - repository: ghcr.io/flyteorg/flyte-client-v2 - tag: latest - pullPolicy: Never diff --git a/docker/devbox-bundled/Makefile b/docker/devbox-bundled/Makefile index 79762823e69..0d283b8c676 100644 --- a/docker/devbox-bundled/Makefile +++ b/docker/devbox-bundled/Makefile @@ -114,6 +114,18 @@ kubeconfig: sed -i -e "/server:/ s/: .*/: https:\/\/127.0.0.1:$(shell docker port flyte-devbox | grep ^6443 | awk '{print $$3}' | awk -F: '{print $$2}')/" .kube/kubeconfig echo "export KUBECONFIG=$(PWD)/.kube/kubeconfig" +.PHONY: setup-knative +setup-knative: + kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.21.2/serving-crds.yaml + kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.21.2/serving-core.yaml + kubectl apply -f https://github.com/knative-extensions/net-kourier/releases/download/knative-v1.21.0/kourier.yaml + kubectl patch configmap/config-network -n knative-serving --type merge \ + --patch '{"data":{"ingress-class":"kourier.ingress.networking.knative.dev"}}' + kubectl patch configmap/config-network -n knative-serving --type merge \ + --patch '{"data":{"domain-template":"{{.Name}}-{{.Namespace}}.{{.Domain}}"}}' + kubectl patch configmap/config-domain -n knative-serving --type merge \ + --patch '{"data":{"local.flyte.app":""}}' + .PHONY: stop stop: docker stop --time 5 flyte-devbox diff --git a/docker/devbox-bundled/manifests/complete.yaml b/docker/devbox-bundled/manifests/complete.yaml index f8f9c31b31a..0f9c37f5516 100644 --- a/docker/devbox-bundled/manifests/complete.yaml +++ b/docker/devbox-bundled/manifests/complete.yaml @@ -536,6 +536,27 @@ data: auth_type: accesskey container: flyte-data 100-inline-config.yaml: | + manager: + internalApps: + baseDomain: local.flyte.app + defaultEnvVars: + - name: FLYTE_AWS_ENDPOINT + value: http://rustfs.flyte:9000 + - name: FLYTE_AWS_ACCESS_KEY_ID + value: rustfs + - name: FLYTE_AWS_SECRET_ACCESS_KEY + value: rustfsstorage + - name: _U_EP_OVERRIDE + value: flyte-binary-http.flyte:8090 + - name: _U_INSECURE + value: "true" + - name: _U_USE_ACTIONS + value: "1" + enabled: true + ingressBaseUrl: http://localhost:30080 + ingressEnabled: true + ingressEntryPoint: web + scheme: http plugins: k8s: default-env-vars: @@ -913,7 +934,7 @@ spec: template: metadata: annotations: - checksum/configuration: 646d21c3d7efb87ed1de45515bf092b575b364810dd9264a2d9b2e7b26ddbbcb + checksum/configuration: b923ff0f82e769435cfba822a87e33bfa00a205d47bf39c4dd395fa07d77160a checksum/configuration-secret: e70194084619f4a1d4017093aac6367047167107fd0222513a32a61734629cac labels: app.kubernetes.io/component: flyte-binary @@ -1146,6 +1167,11 @@ spec: readTimeout: 0 websecure: expose: false + providers: + kubernetesCRD: + allowExternalNameServices: true + kubernetesIngress: + allowExternalNameServices: true --- apiVersion: networking.k8s.io/v1 kind: Ingress diff --git a/docker/devbox-bundled/manifests/dev.yaml b/docker/devbox-bundled/manifests/dev.yaml index f6d4bda06ea..db36a0af32d 100644 --- a/docker/devbox-bundled/manifests/dev.yaml +++ b/docker/devbox-bundled/manifests/dev.yaml @@ -760,6 +760,11 @@ spec: readTimeout: 0 websecure: expose: false + providers: + kubernetesCRD: + allowExternalNameServices: true + kubernetesIngress: + allowExternalNameServices: true --- apiVersion: networking.k8s.io/v1 kind: Ingress diff --git a/docker/sandbox-bundled/Makefile b/docker/sandbox-bundled/Makefile deleted file mode 100644 index 907cbd1e8ef..00000000000 --- a/docker/sandbox-bundled/Makefile +++ /dev/null @@ -1,137 +0,0 @@ -define FLYTE_BINARY_BUILD -mkdir -p images/tar/$(1) - -docker buildx build \ - --build-arg FLYTECONSOLE_VERSION=$(FLYTECONSOLE_VERSION) \ - --builder flyte-sandbox \ - --platform linux/$(1) \ - --tag flyte-binary-v2:sandbox \ - --output type=docker,dest=images/tar/$(1)/flyte-binary.tar \ - ../.. - -endef - -.PHONY: create_builder -create_builder: - [ -n "$(shell docker buildx ls | awk '/^flyte-sandbox / {print $$1}')" ] || \ - docker buildx create --name flyte-sandbox \ - --driver docker-container --driver-opt image=moby/buildkit:master \ - --buildkitd-flags '--allow-insecure-entitlement security.insecure' \ - --platform linux/arm64,linux/amd64 - -.PHONY: flyte -flyte: FLYTECONSOLE_VERSION := latest -flyte: create_builder - $(foreach arch,amd64 arm64,$(call FLYTE_BINARY_BUILD,$(arch))) - -.PHONY: helm-repos -helm-repos: - helm repo add docker-registry https://twuni.github.io/docker-registry.helm - helm repo add bitnami https://charts.bitnami.com/bitnami - helm repo update - -.PHONY: dep_build -dep_build: helm-repos - cd $(SANDBOX_CHART_DIR) && helm dependency build - -.PHONY: dep_update -dep_update: SANDBOX_CHART_DIR := ../../charts/flyte-sandbox -dep_update: dep_build - cd $(SANDBOX_CHART_DIR)/charts && for f in *.tgz; do tar xzf "$$f"; done - -.PHONY: manifests -manifests: dep_update - mkdir -p manifests - kustomize build \ - --enable-helm \ - --load-restrictor=LoadRestrictionsNone \ - kustomize/complete > manifests/complete.yaml - kustomize build \ - --enable-helm \ - --load-restrictor=LoadRestrictionsNone \ - kustomize/dev > manifests/dev.yaml - -CONSOLE_IMAGE := ghcr.io/flyteorg/flyte-client-v2 -CONSOLE_TAG := latest - -.PHONY: console -console: - mkdir -p images/tar/amd64 images/tar/arm64 - docker pull --platform linux/amd64 $(CONSOLE_IMAGE):$(CONSOLE_TAG) - docker save $(CONSOLE_IMAGE):$(CONSOLE_TAG) -o images/tar/amd64/flyte-client-v2.tar - docker pull --platform linux/arm64 $(CONSOLE_IMAGE):$(CONSOLE_TAG) - docker save $(CONSOLE_IMAGE):$(CONSOLE_TAG) -o images/tar/arm64/flyte-client-v2.tar - -.PHONY: sync-crds -sync-crds: - $(MAKE) -C ../../executor manifests - -.PHONY: build -build: sync-crds flyte console dep_update manifests - docker buildx build --builder flyte-sandbox --allow security.insecure --load \ - --tag flyte-sandbox-v2:latest . - -# Port map -# 6443 - k8s API server -# 30000 - Docker Registry -# 30001 - DB -# 30002 - Minio -# 30080 - Flyte Proxy (Traefik nodePort) -.PHONY: start -start: FLYTE_SANDBOX_IMAGE := flyte-sandbox-v2:latest -start: FLYTE_DEV := False -start: - [ -n "$(shell docker volume ls --filter name=^flyte-sandbox$$ --format {{.Name}})" ] || \ - docker volume create flyte-sandbox - @if [ -z "$(shell docker ps --filter name=^flyte-sandbox$$ --format {{.Names}})" ]; then \ - rm -f $(PWD)/.kube/kubeconfig; \ - docker run --detach --rm --privileged --name flyte-sandbox \ - --add-host "host.docker.internal:host-gateway" \ - --env FLYTE_DEV=$(FLYTE_DEV) \ - --env K3S_KUBECONFIG_OUTPUT=/.kube/kubeconfig \ - --volume $(PWD)/.kube:/.kube \ - --volume flyte-sandbox:/var/lib/flyte/storage \ - --publish "6443":"6443" \ - --publish "30000:30000" \ - --publish "30001:5432" \ - --publish "30002:30002" \ - --publish "30080:30080" \ - $(FLYTE_SANDBOX_IMAGE); \ - fi - @echo "Waiting for kubeconfig..." - @until [ -s $(PWD)/.kube/kubeconfig ]; do sleep 1; done - @# On WSL, the bind-mounted kubeconfig may be root-owned, which makes the host-side cp fail with permission denied. - @docker exec flyte-sandbox chown $(shell id -u):$(shell id -g) /.kube/kubeconfig - @mkdir -p $(HOME)/.kube - @if [ -f $(HOME)/.kube/config ]; then \ - KUBECONFIG=$(PWD)/.kube/kubeconfig:$(HOME)/.kube/config kubectl config view --flatten > /tmp/kubeconfig-merged && \ - mv /tmp/kubeconfig-merged $(HOME)/.kube/config; \ - else \ - cp $(PWD)/.kube/kubeconfig $(HOME)/.kube/config; \ - fi - @echo "Kubeconfig merged into ~/.kube/config" -.PHONY: kubeconfig -.SILENT: kubeconfig -kubeconfig: - sed -i -e "/server:/ s/: .*/: https:\/\/127.0.0.1:$(shell docker port flyte-sandbox | grep ^6443 | awk '{print $$3}' | awk -F: '{print $$2}')/" .kube/kubeconfig - echo "export KUBECONFIG=$(PWD)/.kube/kubeconfig" - -.PHONY: setup-knative -setup-knative: - kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.16.0/serving-crds.yaml - kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.16.0/serving-core.yaml - kubectl apply -f https://github.com/knative-extensions/net-kourier/releases/download/knative-v1.16.0/kourier.yaml - kubectl patch configmap/config-network -n knative-serving --type merge \ - --patch '{"data":{"ingress-class":"kourier.ingress.networking.knative.dev"}}' - kubectl patch configmap/config-network -n knative-serving --type merge \ - --patch '{"data":{"domain-template":"{{.Name}}-{{.Namespace}}.{{.Domain}}"}}' - kubectl patch configmap/config-domain -n knative-serving --type merge \ - --patch '{"data":{"local.flyte.app":""}}' - -.PHONY: stop -stop: - docker stop flyte-sandbox - -.venv: - python -m venv .venv - . .venv/bin/activate && pip install flytekit diff --git a/docker/sandbox-bundled/manifests/complete.yaml b/docker/sandbox-bundled/manifests/complete.yaml deleted file mode 100644 index 3fa833929a5..00000000000 --- a/docker/sandbox-bundled/manifests/complete.yaml +++ /dev/null @@ -1,1610 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: flyte ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.19.0 - name: taskactions.flyte.org -spec: - group: flyte.org - names: - kind: TaskAction - listKind: TaskActionList - plural: taskactions - singular: taskaction - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.runName - name: Run - type: string - - jsonPath: .spec.actionName - name: Action - type: string - - jsonPath: .spec.taskType - name: TaskType - type: string - - jsonPath: .status.conditions[?(@.type=='Progressing')].reason - name: Status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=='Progressing')].status - name: Progressing - priority: 1 - type: string - - jsonPath: .status.conditions[?(@.type=='Succeeded')].status - name: Succeeded - priority: 1 - type: string - - jsonPath: .status.conditions[?(@.type=='Failed')].status - name: Failed - priority: 1 - type: string - name: v1 - schema: - openAPIV3Schema: - description: TaskAction is the Schema for the taskactions API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: spec defines the desired state of TaskAction - properties: - actionName: - description: ActionName is the unique name of this action within the - run - maxLength: 30 - minLength: 1 - type: string - cacheKey: - description: |- - CacheKey enables cache lookup/writeback for this task action when set. - This is propagated from workflow.TaskAction.cache_key. - maxLength: 256 - type: string - domain: - description: Domain this action belongs to - maxLength: 63 - minLength: 1 - type: string - envVars: - additionalProperties: - type: string - description: EnvVars are run-scoped environment variables projected - from RunSpec for executor runtime use. - type: object - group: - description: Group is the group this action belongs to, if applicable. - maxLength: 256 - type: string - inputUri: - description: InputURI is the path to the input data for this action - minLength: 1 - type: string - interruptible: - description: Interruptible is the run-scoped interruptibility override - projected from RunSpec. - type: boolean - parentActionName: - description: ParentActionName is the optional name of the parent action - maxLength: 30 - minLength: 1 - type: string - project: - description: Project this action belongs to - maxLength: 63 - minLength: 1 - type: string - runName: - description: RunName is the name of the run this action belongs to - maxLength: 30 - minLength: 1 - type: string - runOutputBase: - description: RunOutputBase is the base path where this action should - write its output - minLength: 1 - type: string - shortName: - description: ShortName is the human-readable display name for this - task - maxLength: 63 - type: string - taskTemplate: - description: TaskTemplate is the proto-serialized core.TaskTemplate - stored inline in etcd - format: byte - type: string - taskType: - description: TaskType identifies which plugin handles this task (e.g. - "container", "spark", "ray") - maxLength: 63 - minLength: 1 - type: string - required: - - actionName - - domain - - inputUri - - project - - runName - - runOutputBase - - taskTemplate - - taskType - type: object - status: - description: status defines the observed state of TaskAction - properties: - attempts: - description: Attempts is the latest observed action attempt number, - starting from 1. - format: int32 - type: integer - cacheStatus: - description: CacheStatus is the latest observed cache lookup result - for this action. - format: int32 - type: integer - conditions: - description: |- - conditions represent the current state of the TaskAction resource. - Each condition has a unique type and reflects the status of a specific aspect of the resource. - - Standard condition types include: - - "Available": the resource is fully functional - - "Progressing": the resource is being created or updated - - "Degraded": the resource failed to reach or maintain its desired state - - The status of each condition is one of True, False, or Unknown. - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - phaseHistory: - description: |- - PhaseHistory is an append-only log of phase transitions. Unlike conditions - (which are updated in-place by type), this preserves the full timeline: - Queued → Initializing → Executing → Succeeded/Failed, each with a timestamp. - items: - description: PhaseTransition records a phase change with its timestamp. - properties: - message: - description: Message is an optional human-readable message about - the transition. - type: string - occurredAt: - description: OccurredAt is when this phase transition happened. - format: date-time - type: string - phase: - description: Phase is the phase that was entered (e.g. "Queued", - "Initializing", "Executing", "Succeeded", "Failed"). - type: string - required: - - occurredAt - - phase - type: object - type: array - pluginPhase: - description: PluginPhase is a human-readable representation of the - plugin's current phase. - type: string - pluginPhaseVersion: - description: PluginPhaseVersion is the version of the current plugin - phase. - format: int32 - type: integer - pluginState: - description: PluginState is the Gob-encoded plugin state from the - last reconciliation round. - format: byte - type: string - pluginStateVersion: - description: PluginStateVersion tracks the version of the plugin state - schema for compatibility. - type: integer - stateJson: - description: StateJSON is the JSON serialized NodeStatus that was - last sent to the State Service - type: string - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - helm.sh/chart: flyte-binary-v0.2.0 - name: flyte-sandbox - namespace: flyte ---- -apiVersion: v1 -automountServiceAccountToken: true -kind: ServiceAccount -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: minio - helm.sh/chart: minio-12.6.7 - name: flyte-sandbox-minio - namespace: flyte -secrets: -- name: flyte-sandbox-minio ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: flyte-sandbox-kubernetes-dashboard ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: flyte-sandbox-kubernetes-dashboard -rules: -- apiGroups: - - "" - resourceNames: - - kubernetes-dashboard-key-holder - - kubernetes-dashboard-certs - - kubernetes-dashboard-csrf - resources: - - secrets - verbs: - - get - - update - - delete -- apiGroups: - - "" - resourceNames: - - kubernetes-dashboard-settings - resources: - - configmaps - verbs: - - get - - update -- apiGroups: - - "" - resourceNames: - - heapster - - dashboard-metrics-scraper - resources: - - services - verbs: - - proxy -- apiGroups: - - "" - resourceNames: - - heapster - - 'http:heapster:' - - 'https:heapster:' - - dashboard-metrics-scraper - - http:dashboard-metrics-scraper - resources: - - services/proxy - verbs: - - get ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - helm.sh/chart: flyte-binary-v0.2.0 - name: flyte-sandbox-cluster-role - namespace: flyte -rules: -- apiGroups: - - "" - resources: - - pods - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - "" - resources: - - events - verbs: - - create - - delete - - patch - - update -- apiGroups: - - flyte.org - resources: - - taskactions - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - admissionregistration.k8s.io - resources: - - mutatingwebhookconfigurations - verbs: - - create - - get - - list - - patch - - update - - watch -- apiGroups: - - "" - resources: - - secrets - verbs: - - create - - get - - update -- apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: flyte-sandbox-kubernetes-dashboard-metrics -rules: -- apiGroups: - - metrics.k8s.io - resources: - - pods - - nodes - verbs: - - get - - list - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: flyte-sandbox-kubernetes-dashboard -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: flyte-sandbox-kubernetes-dashboard -subjects: -- kind: ServiceAccount - name: flyte-sandbox-kubernetes-dashboard - namespace: flyte ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - helm.sh/chart: flyte-binary-v0.2.0 - name: flyte-sandbox-cluster-role-binding - namespace: flyte -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: flyte-sandbox-cluster-role -subjects: -- kind: ServiceAccount - name: flyte-sandbox - namespace: flyte ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: flyte-sandbox-kubernetes-dashboard-metrics -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: flyte-sandbox-kubernetes-dashboard-metrics -subjects: -- kind: ServiceAccount - name: flyte-sandbox-kubernetes-dashboard - namespace: flyte ---- -apiVersion: v1 -data: - 000-core.yaml: | - logger: - show-source: true - level: 5 - webhook: - certDir: /var/run/flyte/certs - localCert: true - secretName: flyte-sandbox-webhook-secret - serviceName: flyte-sandbox-webhook - servicePort: 443 - - actions: - kubernetes: - kubeconfig: "" - namespace: flyte - watchBufferSize: 100 - dataproxy: - download: - maxExpiresIn: 1h - upload: - defaultFileNameLength: 20 - maxExpiresIn: 1h - maxSize: 100Mi - storagePrefix: uploads - manager: - executor: - healthProbePort: 8081 - kubernetes: - burst: 2000 - kubeconfig: "" - namespace: flyte - qps: 1000 - timeout: 30s - server: - host: 0.0.0.0 - port: 8090 - runs: - database: - connMaxLifeTime: 1h - maxIdleConnections: 10 - maxOpenConnections: 100 - postgres: - dbname: flyte - debug: false - host: 127.0.0.1 - options: sslmode=disable - password: "" - port: 5432 - username: postgres - server: - host: 0.0.0.0 - port: 8090 - storagePrefix: s3://flyte-data - watchBufferSize: 100 - secret: - kubernetes: - burst: 200 - clusterName: flyte-sandbox - kubeconfig: "" - namespace: flyte - qps: 100 - timeout: 30s - 001-plugins.yaml: | - tasks: - task-plugins: - default-for-task-types: - container: container - container_array: k8s-array - sidecar: sidecar - enabled-plugins: - - container - - sidecar - - connector-service - - echo - plugins: - logs: - kubernetes-enabled: false - cloudwatch-enabled: false - stackdriver-enabled: false - k8s: - co-pilot: - image: "cr.flyte.org/flyteorg/flytecopilot:v1.16.4" - k8s-array: - logs: - config: - kubernetes-enabled: false - cloudwatch-enabled: false - stackdriver-enabled: false - 002-database.yaml: | - database: - postgres: - username: postgres - host: flyte-sandbox-postgresql - port: 5432 - dbname: flyte - options: "sslmode=disable" - 003-storage.yaml: | - storage: - type: stow - stow: - kind: s3 - config: - region: us-east-1 - disable_ssl: true - v2_signing: true - endpoint: http://flyte-sandbox-minio.flyte:9000 - auth_type: accesskey - container: flyte-data - 100-inline-config.yaml: | - manager: - internalApps: - baseDomain: local.flyte.app - defaultEnvVars: - - name: FLYTE_AWS_ENDPOINT - value: http://flyte-sandbox-minio.flyte:9000 - - name: FLYTE_AWS_ACCESS_KEY_ID - value: minio - - name: FLYTE_AWS_SECRET_ACCESS_KEY - value: miniostorage - - name: _U_EP_OVERRIDE - value: 'flyte-sandbox-http.flyte:8090' - - name: _U_INSECURE - value: "true" - - name: _U_USE_ACTIONS - value: "1" - enabled: true - ingressBaseUrl: http://localhost:30080 - ingressEnabled: true - ingressEntryPoint: web - scheme: http - plugins: - k8s: - default-env-vars: - - FLYTE_AWS_ENDPOINT: http://flyte-sandbox-minio.flyte:9000 - - FLYTE_AWS_ACCESS_KEY_ID: minio - - FLYTE_AWS_SECRET_ACCESS_KEY: miniostorage - - _U_EP_OVERRIDE: 'flyte-sandbox-http.flyte:8090' - - _U_INSECURE: "true" - - _U_USE_ACTIONS: "1" - runs: - database: - postgres: - dbName: runs - host: 'flyte-sandbox-postgresql.flyte' - password: postgres - port: 5432 - user: postgres - storage: - signedURL: - stowConfigOverride: - endpoint: http://localhost:30002 - task_resources: - defaults: - cpu: 500m - ephemeralStorage: 0 - gpu: 0 - memory: 1Gi - limits: - cpu: 0 - ephemeralStorage: 0 - gpu: 0 - memory: 0 -kind: ConfigMap -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - helm.sh/chart: flyte-binary-v0.2.0 - name: flyte-sandbox-config - namespace: flyte ---- -apiVersion: v1 -data: - config.yml: |- - health: - storagedriver: - enabled: true - interval: 10s - threshold: 3 - http: - addr: :5000 - debug: - addr: :5001 - prometheus: - enabled: false - path: /metrics - headers: - X-Content-Type-Options: - - nosniff - log: - fields: - service: registry - storage: - cache: - blobdescriptor: inmemory - version: 0.1 -kind: ConfigMap -metadata: - labels: - app: docker-registry - chart: docker-registry-2.2.2 - heritage: Helm - release: flyte-sandbox - name: flyte-sandbox-docker-registry-config - namespace: flyte ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: flyte-sandbox-extra-cluster-resource-templates - namespace: flyte ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: flyte-sandbox-extra-config - namespace: flyte ---- -apiVersion: v1 -data: null -kind: ConfigMap -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: kubernetes-dashboard-settings ---- -apiVersion: v1 -kind: Secret -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - helm.sh/chart: flyte-binary-v0.2.0 - name: flyte-sandbox-config-secret - namespace: flyte -stringData: - 012-database-secrets.yaml: | - database: - postgres: - password: "postgres" - 013-storage-secrets.yaml: | - storage: - stow: - config: - access_key_id: "minio" - secret_key: "miniostorage" -type: Opaque ---- -apiVersion: v1 -data: - haSharedSecret: Zmx5dGVzYW5kYm94c2VjcmV0 - proxyPassword: "" - proxyUsername: "" -kind: Secret -metadata: - labels: - app: docker-registry - chart: docker-registry-2.2.2 - heritage: Helm - release: flyte-sandbox - name: flyte-sandbox-docker-registry-secret - namespace: flyte -type: Opaque ---- -apiVersion: v1 -data: - root-password: bWluaW9zdG9yYWdl - root-user: bWluaW8= -kind: Secret -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: minio - helm.sh/chart: minio-12.6.7 - name: flyte-sandbox-minio - namespace: flyte -type: Opaque ---- -apiVersion: v1 -kind: Secret -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: flyte-sandbox-kubernetes-dashboard-certs -type: Opaque ---- -apiVersion: v1 -kind: Secret -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: kubernetes-dashboard-csrf -type: Opaque ---- -apiVersion: v1 -kind: Secret -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: kubernetes-dashboard-key-holder -type: Opaque ---- -apiVersion: v1 -kind: Endpoints -metadata: - labels: - app.kubernetes.io/name: embedded-postgresql - name: flyte-sandbox-postgresql - namespace: flyte -subsets: -- addresses: - - ip: '%{NODE_IP}%' - ports: - - name: tcp-postgresql - port: 5432 ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: flyte-sandbox-console - namespace: flyte -spec: - ports: - - name: http - port: 80 - protocol: TCP - targetPort: http - selector: - app.kubernetes.io/component: console - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: flyte-sandbox ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app: docker-registry - chart: docker-registry-2.2.2 - heritage: Helm - release: flyte-sandbox - name: flyte-sandbox-docker-registry - namespace: flyte -spec: - ports: - - name: http-5000 - nodePort: 30000 - port: 5000 - protocol: TCP - targetPort: 5000 - selector: - app: docker-registry - release: flyte-sandbox - type: NodePort ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - helm.sh/chart: flyte-binary-v0.2.0 - name: flyte-sandbox-http - namespace: flyte -spec: - ports: - - name: http - nodePort: null - port: 8090 - targetPort: http - selector: - app.kubernetes.io/component: flyte-binary - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: flyte-sandbox - type: ClusterIP ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: minio - helm.sh/chart: minio-12.6.7 - name: flyte-sandbox-minio - namespace: flyte -spec: - externalTrafficPolicy: Cluster - ports: - - name: minio-api - nodePort: 30002 - port: 9000 - targetPort: minio-api - - name: minio-console - port: 9001 - targetPort: minio-console - selector: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: minio - type: NodePort ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: embedded-postgresql - name: flyte-sandbox-postgresql - namespace: flyte -spec: - ports: - - name: tcp-postgresql - nodePort: 30001 - port: 5432 - targetPort: 5432 - type: NodePort ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - helm.sh/chart: flyte-binary-v0.2.0 - name: flyte-sandbox-webhook - namespace: flyte -spec: - ports: - - name: webhook - port: 443 - protocol: TCP - targetPort: 9443 - selector: - app.kubernetes.io/component: flyte-binary - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: flyte-sandbox ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/component: kubernetes-dashboard - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - kubernetes.io/cluster-service: "true" - name: flyte-sandbox-kubernetes-dashboard -spec: - ports: - - name: https - port: 443 - targetPort: https - selector: - app.kubernetes.io/component: kubernetes-dashboard - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: kubernetes-dashboard - type: ClusterIP ---- -apiVersion: v1 -kind: PersistentVolume -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: flyte-sandbox-minio-storage - namespace: flyte -spec: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - hostPath: - path: /var/lib/flyte/storage/minio - storageClassName: manual ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: flyte-sandbox-minio-storage - namespace: flyte -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi - storageClassName: manual - volumeName: flyte-sandbox-minio-storage ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - helm.sh/chart: flyte-binary-v0.2.0 - name: flyte-sandbox - namespace: flyte -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/component: flyte-binary - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: flyte-sandbox - strategy: - type: Recreate - template: - metadata: - annotations: - checksum/configuration: 65d9d4f74b818affae591f569908d32aa883197a6a90f3b43b5dfd36d0f90a48 - checksum/configuration-secret: 588da2ac84d45dd5285521c58bc6c9969924887acb9674d75802055c3a97d9bb - labels: - app.kubernetes.io/component: flyte-binary - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: flyte-sandbox - spec: - containers: - - args: - - --config - - /etc/flyte/config.d/*.yaml - env: - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - image: flyte-binary-v2:sandbox - imagePullPolicy: Never - livenessProbe: - httpGet: - path: /healthz - port: http - initialDelaySeconds: 5 - name: flyte - ports: - - containerPort: 8090 - name: http - - containerPort: 9443 - name: webhook - readinessProbe: - httpGet: - path: /readyz - port: http - initialDelaySeconds: 5 - periodSeconds: 5 - volumeMounts: - - mountPath: /etc/flyte/config.d - name: config - - mountPath: /var/run/flyte/certs - name: webhook-certs - readOnly: false - initContainers: - - args: - - | - until nc -z flyte-sandbox-postgresql.flyte 5432; do - echo waiting for database - sleep 0.5 - done - command: - - sh - - -ec - image: rancher/mirrored-library-busybox:1.34.1 - imagePullPolicy: Never - name: wait-for-db - serviceAccountName: flyte-sandbox - volumes: - - name: config - projected: - sources: - - configMap: - name: flyte-sandbox-config - - secret: - name: flyte-sandbox-config-secret - - configMap: - name: flyte-sandbox-extra-config - - emptyDir: {} - name: webhook-certs ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: flyte-sandbox-console - namespace: flyte -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/component: console - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: flyte-sandbox - template: - metadata: - labels: - app.kubernetes.io/component: console - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: flyte-sandbox - spec: - containers: - - image: ghcr.io/flyteorg/flyte-client-v2:latest - imagePullPolicy: Never - livenessProbe: - httpGet: - path: /v2 - port: http - initialDelaySeconds: 5 - periodSeconds: 30 - name: console - ports: - - containerPort: 8080 - name: http - protocol: TCP - readinessProbe: - httpGet: - path: /v2 - port: http - initialDelaySeconds: 5 - periodSeconds: 10 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: docker-registry - chart: docker-registry-2.2.2 - heritage: Helm - release: flyte-sandbox - name: flyte-sandbox-docker-registry - namespace: flyte -spec: - minReadySeconds: 5 - replicas: 1 - selector: - matchLabels: - app: docker-registry - release: flyte-sandbox - template: - metadata: - annotations: - checksum/config: 8f50e768255a87f078ba8b9879a0c174c3e045ffb46ac8723d2eedbe293c8d81 - checksum/secret: 829c19e3c86dcb9b7d4c44e6a73463c6a6467d824200e87e2d7999f70dc0f5f9 - labels: - app: docker-registry - release: flyte-sandbox - spec: - containers: - - command: - - /bin/registry - - serve - - /etc/docker/registry/config.yml - env: - - name: REGISTRY_HTTP_SECRET - valueFrom: - secretKeyRef: - key: haSharedSecret - name: flyte-sandbox-docker-registry-secret - - name: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY - value: /var/lib/registry - image: registry:sandbox - imagePullPolicy: Never - livenessProbe: - httpGet: - path: / - port: 5000 - name: docker-registry - ports: - - containerPort: 5000 - readinessProbe: - httpGet: - path: / - port: 5000 - resources: {} - volumeMounts: - - mountPath: /etc/docker/registry - name: flyte-sandbox-docker-registry-config - - mountPath: /var/lib/registry/ - name: data - securityContext: - fsGroup: 1000 - runAsUser: 1000 - volumes: - - configMap: - name: flyte-sandbox-docker-registry-config - name: flyte-sandbox-docker-registry-config - - emptyDir: {} - name: data ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: minio - helm.sh/chart: minio-12.6.7 - name: flyte-sandbox-minio - namespace: flyte -spec: - selector: - matchLabels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: minio - strategy: - type: Recreate - template: - metadata: - annotations: - checksum/credentials-secret: ecce809e3af19025d134846a9a81e163dd41df7e26abf2c6657895d9d13607a9 - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: minio - helm.sh/chart: minio-12.6.7 - spec: - affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - podAffinityTerm: - labelSelector: - matchLabels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: minio - topologyKey: kubernetes.io/hostname - weight: 1 - containers: - - command: - - minio - - server - - /data - - --console-address - - :9001 - env: - - name: BITNAMI_DEBUG - value: "false" - - name: MINIO_SCHEME - value: http - - name: MINIO_FORCE_NEW_KEYS - value: "no" - - name: MINIO_ROOT_USER - valueFrom: - secretKeyRef: - key: root-user - name: flyte-sandbox-minio - - name: MINIO_ROOT_PASSWORD - valueFrom: - secretKeyRef: - key: root-password - name: flyte-sandbox-minio - - name: MINIO_DEFAULT_BUCKETS - value: flyte-data - - name: MINIO_BROWSER - value: "on" - - name: MINIO_PROMETHEUS_AUTH_TYPE - value: public - - name: MINIO_CONSOLE_PORT_NUMBER - value: "9001" - - name: MINIO_BROWSER_REDIRECT_URL - value: http://localhost:30080/minio - image: docker.io/bitnami/minio:sandbox - imagePullPolicy: Never - livenessProbe: - failureThreshold: 5 - httpGet: - path: /minio/health/live - port: minio-api - scheme: HTTP - initialDelaySeconds: 5 - periodSeconds: 5 - successThreshold: 1 - timeoutSeconds: 5 - name: minio - ports: - - containerPort: 9000 - name: minio-api - protocol: TCP - - containerPort: 9001 - name: minio-console - protocol: TCP - readinessProbe: - failureThreshold: 5 - initialDelaySeconds: 5 - periodSeconds: 5 - successThreshold: 1 - tcpSocket: - port: minio-api - timeoutSeconds: 1 - resources: - limits: {} - requests: {} - securityContext: - runAsNonRoot: true - runAsUser: 1001 - volumeMounts: - - mountPath: /data - name: data - initContainers: - - command: - - /bin/bash - - -ec - - | - chown -R 1001:1001 /data - mkdir -p /data/flyte-data - chown 1001:1001 /data/flyte-data - image: docker.io/bitnami/os-shell:sandbox - imagePullPolicy: Never - name: volume-permissions - resources: - limits: {} - requests: {} - securityContext: - runAsUser: 0 - volumeMounts: - - mountPath: /data - name: data - securityContext: - fsGroup: 1001 - serviceAccountName: flyte-sandbox-minio - volumes: - - name: data - persistentVolumeClaim: - claimName: flyte-sandbox-minio-storage ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/component: kubernetes-dashboard - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: flyte-sandbox-kubernetes-dashboard -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/component: kubernetes-dashboard - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: kubernetes-dashboard - strategy: - rollingUpdate: - maxSurge: 0 - maxUnavailable: 1 - type: RollingUpdate - template: - metadata: - annotations: null - labels: - app.kubernetes.io/component: kubernetes-dashboard - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - spec: - containers: - - args: - - --namespace=flyte - - --auto-generate-certificates - - --metrics-provider=none - image: kubernetesui/dashboard:v2.7.0 - imagePullPolicy: IfNotPresent - livenessProbe: - httpGet: - path: / - port: 8443 - scheme: HTTPS - initialDelaySeconds: 30 - timeoutSeconds: 30 - name: kubernetes-dashboard - ports: - - containerPort: 8443 - name: https - protocol: TCP - resources: - limits: - cpu: 2 - memory: 200Mi - requests: - cpu: 100m - memory: 200Mi - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - runAsGroup: 2001 - runAsUser: 1001 - volumeMounts: - - mountPath: /certs - name: kubernetes-dashboard-certs - - mountPath: /tmp - name: tmp-volume - securityContext: - seccompProfile: - type: RuntimeDefault - serviceAccountName: flyte-sandbox-kubernetes-dashboard - volumes: - - name: kubernetes-dashboard-certs - secret: - secretName: flyte-sandbox-kubernetes-dashboard-certs - - emptyDir: {} - name: tmp-volume ---- -apiVersion: helm.cattle.io/v1 -kind: HelmChartConfig -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: traefik - namespace: kube-system -spec: - valuesContent: | - service: - type: NodePort - ports: - web: - nodePort: 30080 - transport: - respondingTimeouts: - readTimeout: 0 - websecure: - expose: false - providers: - kubernetesCRD: - allowExternalNameServices: true - kubernetesIngress: - allowExternalNameServices: true ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: flyte-sandbox-api - namespace: flyte -spec: - rules: - - http: - paths: - - backend: - service: - name: flyte-sandbox-http - port: - number: 8090 - path: /healthz - pathType: Exact - - backend: - service: - name: flyte-sandbox-http - port: - number: 8090 - path: /readyz - pathType: Exact - - backend: - service: - name: flyte-sandbox-http - port: - number: 8090 - path: /flyteidl2. - pathType: Prefix ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: flyte-sandbox-console - namespace: flyte -spec: - rules: - - http: - paths: - - backend: - service: - name: flyte-sandbox-console - port: - number: 80 - path: /v2 - pathType: Prefix ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - annotations: - traefik.ingress.kubernetes.io/router.middlewares: flyte-strip-minio@kubernetescrd - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: flyte-sandbox-minio - namespace: flyte -spec: - rules: - - http: - paths: - - backend: - service: - name: flyte-sandbox-minio - port: - number: 9001 - path: /minio - pathType: Prefix ---- -apiVersion: traefik.io/v1alpha1 -kind: Middleware -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: strip-minio - namespace: flyte -spec: - stripPrefix: - prefixes: - - /minio diff --git a/docker/sandbox-bundled/manifests/dev.yaml b/docker/sandbox-bundled/manifests/dev.yaml deleted file mode 100644 index 40a6a5678f4..00000000000 --- a/docker/sandbox-bundled/manifests/dev.yaml +++ /dev/null @@ -1,1207 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: flyte ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.19.0 - name: taskactions.flyte.org -spec: - group: flyte.org - names: - kind: TaskAction - listKind: TaskActionList - plural: taskactions - singular: taskaction - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.runName - name: Run - type: string - - jsonPath: .spec.actionName - name: Action - type: string - - jsonPath: .spec.taskType - name: TaskType - type: string - - jsonPath: .status.conditions[?(@.type=='Progressing')].reason - name: Status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=='Progressing')].status - name: Progressing - priority: 1 - type: string - - jsonPath: .status.conditions[?(@.type=='Succeeded')].status - name: Succeeded - priority: 1 - type: string - - jsonPath: .status.conditions[?(@.type=='Failed')].status - name: Failed - priority: 1 - type: string - name: v1 - schema: - openAPIV3Schema: - description: TaskAction is the Schema for the taskactions API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: spec defines the desired state of TaskAction - properties: - actionName: - description: ActionName is the unique name of this action within the - run - maxLength: 30 - minLength: 1 - type: string - cacheKey: - description: |- - CacheKey enables cache lookup/writeback for this task action when set. - This is propagated from workflow.TaskAction.cache_key. - maxLength: 256 - type: string - domain: - description: Domain this action belongs to - maxLength: 63 - minLength: 1 - type: string - envVars: - additionalProperties: - type: string - description: EnvVars are run-scoped environment variables projected - from RunSpec for executor runtime use. - type: object - group: - description: Group is the group this action belongs to, if applicable. - maxLength: 256 - type: string - inputUri: - description: InputURI is the path to the input data for this action - minLength: 1 - type: string - interruptible: - description: Interruptible is the run-scoped interruptibility override - projected from RunSpec. - type: boolean - parentActionName: - description: ParentActionName is the optional name of the parent action - maxLength: 30 - minLength: 1 - type: string - project: - description: Project this action belongs to - maxLength: 63 - minLength: 1 - type: string - runName: - description: RunName is the name of the run this action belongs to - maxLength: 30 - minLength: 1 - type: string - runOutputBase: - description: RunOutputBase is the base path where this action should - write its output - minLength: 1 - type: string - shortName: - description: ShortName is the human-readable display name for this - task - maxLength: 63 - type: string - taskTemplate: - description: TaskTemplate is the proto-serialized core.TaskTemplate - stored inline in etcd - format: byte - type: string - taskType: - description: TaskType identifies which plugin handles this task (e.g. - "container", "spark", "ray") - maxLength: 63 - minLength: 1 - type: string - required: - - actionName - - domain - - inputUri - - project - - runName - - runOutputBase - - taskTemplate - - taskType - type: object - status: - description: status defines the observed state of TaskAction - properties: - attempts: - description: Attempts is the latest observed action attempt number, - starting from 1. - format: int32 - type: integer - cacheStatus: - description: CacheStatus is the latest observed cache lookup result - for this action. - format: int32 - type: integer - conditions: - description: |- - conditions represent the current state of the TaskAction resource. - Each condition has a unique type and reflects the status of a specific aspect of the resource. - - Standard condition types include: - - "Available": the resource is fully functional - - "Progressing": the resource is being created or updated - - "Degraded": the resource failed to reach or maintain its desired state - - The status of each condition is one of True, False, or Unknown. - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - phaseHistory: - description: |- - PhaseHistory is an append-only log of phase transitions. Unlike conditions - (which are updated in-place by type), this preserves the full timeline: - Queued → Initializing → Executing → Succeeded/Failed, each with a timestamp. - items: - description: PhaseTransition records a phase change with its timestamp. - properties: - message: - description: Message is an optional human-readable message about - the transition. - type: string - occurredAt: - description: OccurredAt is when this phase transition happened. - format: date-time - type: string - phase: - description: Phase is the phase that was entered (e.g. "Queued", - "Initializing", "Executing", "Succeeded", "Failed"). - type: string - required: - - occurredAt - - phase - type: object - type: array - pluginPhase: - description: PluginPhase is a human-readable representation of the - plugin's current phase. - type: string - pluginPhaseVersion: - description: PluginPhaseVersion is the version of the current plugin - phase. - format: int32 - type: integer - pluginState: - description: PluginState is the Gob-encoded plugin state from the - last reconciliation round. - format: byte - type: string - pluginStateVersion: - description: PluginStateVersion tracks the version of the plugin state - schema for compatibility. - type: integer - stateJson: - description: StateJSON is the JSON serialized NodeStatus that was - last sent to the State Service - type: string - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: v1 -automountServiceAccountToken: true -kind: ServiceAccount -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: minio - helm.sh/chart: minio-12.6.7 - name: flyte-sandbox-minio - namespace: flyte -secrets: -- name: flyte-sandbox-minio ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: flyte-sandbox-kubernetes-dashboard ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: flyte-sandbox-kubernetes-dashboard -rules: -- apiGroups: - - "" - resourceNames: - - kubernetes-dashboard-key-holder - - kubernetes-dashboard-certs - - kubernetes-dashboard-csrf - resources: - - secrets - verbs: - - get - - update - - delete -- apiGroups: - - "" - resourceNames: - - kubernetes-dashboard-settings - resources: - - configmaps - verbs: - - get - - update -- apiGroups: - - "" - resourceNames: - - heapster - - dashboard-metrics-scraper - resources: - - services - verbs: - - proxy -- apiGroups: - - "" - resourceNames: - - heapster - - 'http:heapster:' - - 'https:heapster:' - - dashboard-metrics-scraper - - http:dashboard-metrics-scraper - resources: - - services/proxy - verbs: - - get ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: flyte-sandbox-kubernetes-dashboard-metrics -rules: -- apiGroups: - - metrics.k8s.io - resources: - - pods - - nodes - verbs: - - get - - list - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: flyte-sandbox-kubernetes-dashboard -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: flyte-sandbox-kubernetes-dashboard -subjects: -- kind: ServiceAccount - name: flyte-sandbox-kubernetes-dashboard - namespace: flyte ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: flyte-sandbox-kubernetes-dashboard-metrics -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: flyte-sandbox-kubernetes-dashboard-metrics -subjects: -- kind: ServiceAccount - name: flyte-sandbox-kubernetes-dashboard - namespace: flyte ---- -apiVersion: v1 -data: - config.yml: |- - health: - storagedriver: - enabled: true - interval: 10s - threshold: 3 - http: - addr: :5000 - debug: - addr: :5001 - prometheus: - enabled: false - path: /metrics - headers: - X-Content-Type-Options: - - nosniff - log: - fields: - service: registry - storage: - cache: - blobdescriptor: inmemory - version: 0.1 -kind: ConfigMap -metadata: - labels: - app: docker-registry - chart: docker-registry-2.2.2 - heritage: Helm - release: flyte-sandbox - name: flyte-sandbox-docker-registry-config - namespace: flyte ---- -apiVersion: v1 -data: null -kind: ConfigMap -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: kubernetes-dashboard-settings ---- -apiVersion: v1 -data: - haSharedSecret: Zmx5dGVzYW5kYm94c2VjcmV0 - proxyPassword: "" - proxyUsername: "" -kind: Secret -metadata: - labels: - app: docker-registry - chart: docker-registry-2.2.2 - heritage: Helm - release: flyte-sandbox - name: flyte-sandbox-docker-registry-secret - namespace: flyte -type: Opaque ---- -apiVersion: v1 -data: - root-password: bWluaW9zdG9yYWdl - root-user: bWluaW8= -kind: Secret -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: minio - helm.sh/chart: minio-12.6.7 - name: flyte-sandbox-minio - namespace: flyte -type: Opaque ---- -apiVersion: v1 -kind: Secret -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: flyte-sandbox-kubernetes-dashboard-certs -type: Opaque ---- -apiVersion: v1 -kind: Secret -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: kubernetes-dashboard-csrf -type: Opaque ---- -apiVersion: v1 -kind: Secret -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: kubernetes-dashboard-key-holder -type: Opaque ---- -apiVersion: v1 -kind: Endpoints -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: flyte-sandbox-local - namespace: flyte -subsets: -- addresses: - - ip: '%{HOST_GATEWAY_IP}%' - ports: - - name: http - port: 8090 - protocol: TCP - - name: webhook - port: 9443 - protocol: TCP ---- -apiVersion: v1 -kind: Endpoints -metadata: - labels: - app.kubernetes.io/name: embedded-postgresql - name: flyte-sandbox-postgresql - namespace: flyte -subsets: -- addresses: - - ip: '%{NODE_IP}%' - ports: - - name: tcp-postgresql - port: 5432 ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: flyte-sandbox-console - namespace: flyte -spec: - ports: - - name: http - port: 80 - protocol: TCP - targetPort: http - selector: - app.kubernetes.io/component: console - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: flyte-sandbox ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app: docker-registry - chart: docker-registry-2.2.2 - heritage: Helm - release: flyte-sandbox - name: flyte-sandbox-docker-registry - namespace: flyte -spec: - ports: - - name: http-5000 - nodePort: 30000 - port: 5000 - protocol: TCP - targetPort: 5000 - selector: - app: docker-registry - release: flyte-sandbox - type: NodePort ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: flyte-sandbox-local - namespace: flyte -spec: - clusterIP: None - ports: - - name: http - port: 8090 - protocol: TCP - - name: webhook - port: 9443 - protocol: TCP ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: minio - helm.sh/chart: minio-12.6.7 - name: flyte-sandbox-minio - namespace: flyte -spec: - externalTrafficPolicy: Cluster - ports: - - name: minio-api - nodePort: 30002 - port: 9000 - targetPort: minio-api - - name: minio-console - port: 9001 - targetPort: minio-console - selector: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: minio - type: NodePort ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: embedded-postgresql - name: flyte-sandbox-postgresql - namespace: flyte -spec: - ports: - - name: tcp-postgresql - nodePort: 30001 - port: 5432 - targetPort: 5432 - type: NodePort ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/component: kubernetes-dashboard - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - kubernetes.io/cluster-service: "true" - name: flyte-sandbox-kubernetes-dashboard -spec: - ports: - - name: https - port: 443 - targetPort: https - selector: - app.kubernetes.io/component: kubernetes-dashboard - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: kubernetes-dashboard - type: ClusterIP ---- -apiVersion: v1 -kind: PersistentVolume -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: flyte-sandbox-minio-storage - namespace: flyte -spec: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - hostPath: - path: /var/lib/flyte/storage/minio - storageClassName: manual ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: flyte-sandbox-minio-storage - namespace: flyte -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi - storageClassName: manual - volumeName: flyte-sandbox-minio-storage ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: flyte-sandbox-console - namespace: flyte -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/component: console - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: flyte-sandbox - template: - metadata: - labels: - app.kubernetes.io/component: console - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: flyte-sandbox - spec: - containers: - - image: ghcr.io/flyteorg/flyte-client-v2:latest - imagePullPolicy: Never - livenessProbe: - httpGet: - path: /v2 - port: http - initialDelaySeconds: 5 - periodSeconds: 30 - name: console - ports: - - containerPort: 8080 - name: http - protocol: TCP - readinessProbe: - httpGet: - path: /v2 - port: http - initialDelaySeconds: 5 - periodSeconds: 10 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: docker-registry - chart: docker-registry-2.2.2 - heritage: Helm - release: flyte-sandbox - name: flyte-sandbox-docker-registry - namespace: flyte -spec: - minReadySeconds: 5 - replicas: 1 - selector: - matchLabels: - app: docker-registry - release: flyte-sandbox - template: - metadata: - annotations: - checksum/config: 8f50e768255a87f078ba8b9879a0c174c3e045ffb46ac8723d2eedbe293c8d81 - checksum/secret: 829c19e3c86dcb9b7d4c44e6a73463c6a6467d824200e87e2d7999f70dc0f5f9 - labels: - app: docker-registry - release: flyte-sandbox - spec: - containers: - - command: - - /bin/registry - - serve - - /etc/docker/registry/config.yml - env: - - name: REGISTRY_HTTP_SECRET - valueFrom: - secretKeyRef: - key: haSharedSecret - name: flyte-sandbox-docker-registry-secret - - name: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY - value: /var/lib/registry - image: registry:sandbox - imagePullPolicy: Never - livenessProbe: - httpGet: - path: / - port: 5000 - name: docker-registry - ports: - - containerPort: 5000 - readinessProbe: - httpGet: - path: / - port: 5000 - resources: {} - volumeMounts: - - mountPath: /etc/docker/registry - name: flyte-sandbox-docker-registry-config - - mountPath: /var/lib/registry/ - name: data - securityContext: - fsGroup: 1000 - runAsUser: 1000 - volumes: - - configMap: - name: flyte-sandbox-docker-registry-config - name: flyte-sandbox-docker-registry-config - - emptyDir: {} - name: data ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: minio - helm.sh/chart: minio-12.6.7 - name: flyte-sandbox-minio - namespace: flyte -spec: - selector: - matchLabels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: minio - strategy: - type: Recreate - template: - metadata: - annotations: - checksum/credentials-secret: ecce809e3af19025d134846a9a81e163dd41df7e26abf2c6657895d9d13607a9 - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: minio - helm.sh/chart: minio-12.6.7 - spec: - affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - podAffinityTerm: - labelSelector: - matchLabels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: minio - topologyKey: kubernetes.io/hostname - weight: 1 - containers: - - command: - - minio - - server - - /data - - --console-address - - :9001 - env: - - name: BITNAMI_DEBUG - value: "false" - - name: MINIO_SCHEME - value: http - - name: MINIO_FORCE_NEW_KEYS - value: "no" - - name: MINIO_ROOT_USER - valueFrom: - secretKeyRef: - key: root-user - name: flyte-sandbox-minio - - name: MINIO_ROOT_PASSWORD - valueFrom: - secretKeyRef: - key: root-password - name: flyte-sandbox-minio - - name: MINIO_DEFAULT_BUCKETS - value: flyte-data - - name: MINIO_BROWSER - value: "on" - - name: MINIO_PROMETHEUS_AUTH_TYPE - value: public - - name: MINIO_CONSOLE_PORT_NUMBER - value: "9001" - - name: MINIO_BROWSER_REDIRECT_URL - value: http://localhost:30080/minio - image: docker.io/bitnami/minio:sandbox - imagePullPolicy: Never - livenessProbe: - failureThreshold: 5 - httpGet: - path: /minio/health/live - port: minio-api - scheme: HTTP - initialDelaySeconds: 5 - periodSeconds: 5 - successThreshold: 1 - timeoutSeconds: 5 - name: minio - ports: - - containerPort: 9000 - name: minio-api - protocol: TCP - - containerPort: 9001 - name: minio-console - protocol: TCP - readinessProbe: - failureThreshold: 5 - initialDelaySeconds: 5 - periodSeconds: 5 - successThreshold: 1 - tcpSocket: - port: minio-api - timeoutSeconds: 1 - resources: - limits: {} - requests: {} - securityContext: - runAsNonRoot: true - runAsUser: 1001 - volumeMounts: - - mountPath: /data - name: data - initContainers: - - command: - - /bin/bash - - -ec - - | - chown -R 1001:1001 /data - mkdir -p /data/flyte-data - chown 1001:1001 /data/flyte-data - image: docker.io/bitnami/os-shell:sandbox - imagePullPolicy: Never - name: volume-permissions - resources: - limits: {} - requests: {} - securityContext: - runAsUser: 0 - volumeMounts: - - mountPath: /data - name: data - securityContext: - fsGroup: 1001 - serviceAccountName: flyte-sandbox-minio - volumes: - - name: data - persistentVolumeClaim: - claimName: flyte-sandbox-minio-storage ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/component: kubernetes-dashboard - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - name: flyte-sandbox-kubernetes-dashboard -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/component: kubernetes-dashboard - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/name: kubernetes-dashboard - strategy: - rollingUpdate: - maxSurge: 0 - maxUnavailable: 1 - type: RollingUpdate - template: - metadata: - annotations: null - labels: - app.kubernetes.io/component: kubernetes-dashboard - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: kubernetes-dashboard - app.kubernetes.io/version: 2.7.0 - helm.sh/chart: kubernetes-dashboard-6.0.0 - spec: - containers: - - args: - - --namespace=flyte - - --auto-generate-certificates - - --metrics-provider=none - image: kubernetesui/dashboard:v2.7.0 - imagePullPolicy: IfNotPresent - livenessProbe: - httpGet: - path: / - port: 8443 - scheme: HTTPS - initialDelaySeconds: 30 - timeoutSeconds: 30 - name: kubernetes-dashboard - ports: - - containerPort: 8443 - name: https - protocol: TCP - resources: - limits: - cpu: 2 - memory: 200Mi - requests: - cpu: 100m - memory: 200Mi - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - runAsGroup: 2001 - runAsUser: 1001 - volumeMounts: - - mountPath: /certs - name: kubernetes-dashboard-certs - - mountPath: /tmp - name: tmp-volume - securityContext: - seccompProfile: - type: RuntimeDefault - serviceAccountName: flyte-sandbox-kubernetes-dashboard - volumes: - - name: kubernetes-dashboard-certs - secret: - secretName: flyte-sandbox-kubernetes-dashboard-certs - - emptyDir: {} - name: tmp-volume ---- -apiVersion: helm.cattle.io/v1 -kind: HelmChartConfig -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: traefik - namespace: kube-system -spec: - valuesContent: | - service: - type: NodePort - ports: - web: - nodePort: 30080 - transport: - respondingTimeouts: - readTimeout: 0 - websecure: - expose: false - providers: - kubernetesCRD: - allowExternalNameServices: true - kubernetesIngress: - allowExternalNameServices: true ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: flyte-sandbox-api - namespace: flyte -spec: - rules: - - http: - paths: - - backend: - service: - name: flyte-sandbox-local - port: - number: 8090 - path: /healthz - pathType: Exact - - backend: - service: - name: flyte-sandbox-local - port: - number: 8090 - path: /readyz - pathType: Exact - - backend: - service: - name: flyte-sandbox-local - port: - number: 8090 - path: /flyteidl2. - pathType: Prefix ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: flyte-sandbox-console - namespace: flyte -spec: - rules: - - http: - paths: - - backend: - service: - name: flyte-sandbox-console - port: - number: 80 - path: /v2 - pathType: Prefix ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - annotations: - traefik.ingress.kubernetes.io/router.middlewares: flyte-strip-minio@kubernetescrd - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: flyte-sandbox-minio - namespace: flyte -spec: - rules: - - http: - paths: - - backend: - service: - name: flyte-sandbox-minio - port: - number: 9001 - path: /minio - pathType: Prefix ---- -apiVersion: traefik.io/v1alpha1 -kind: Middleware -metadata: - labels: - app.kubernetes.io/instance: flyte-sandbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: flyte-sandbox - app.kubernetes.io/version: 1.16.1 - helm.sh/chart: flyte-sandbox-0.1.0 - name: strip-minio - namespace: flyte -spec: - stripPrefix: - prefixes: - - /minio diff --git a/manager/config.yaml b/manager/config.yaml index 4d9c22a3b34..22517a28013 100644 --- a/manager/config.yaml +++ b/manager/config.yaml @@ -27,13 +27,13 @@ manager: ingressBaseUrl: "http://localhost:30080" defaultEnvVars: - name: FLYTE_AWS_ENDPOINT - value: "http://flyte-sandbox-minio.flyte.svc.cluster.local:9000" + value: "http://rustfs.flyte.svc.cluster.local:9000" - name: FLYTE_AWS_ACCESS_KEY_ID - value: "minio" + value: "rustfs" - name: FLYTE_AWS_SECRET_ACCESS_KEY - value: "miniostorage" + value: "rustfsstorage" - name: _U_EP_OVERRIDE - value: "flyte-sandbox-local.flyte.svc.cluster.local:8090" + value: "flyte-binary-http.flyte.svc.cluster.local:8090" - name: _U_INSECURE value: "true" - name: _U_USE_ACTIONS @@ -45,7 +45,7 @@ manager: webhook: localCert: true certDir: /tmp/flyte/webhook/certs - serviceName: flyte-sandbox-local + serviceName: flyte-devbox-local servicePort: 9443 # Executor configuration @@ -87,10 +87,10 @@ dataproxy: plugins: k8s: default-env-vars: - - FLYTE_AWS_ENDPOINT: "http://flyte-sandbox-minio.flyte.svc.cluster.local:9000" - - FLYTE_AWS_ACCESS_KEY_ID: "minio" - - FLYTE_AWS_SECRET_ACCESS_KEY: "miniostorage" - - _U_EP_OVERRIDE: "flyte-sandbox-local.flyte.svc.cluster.local:8090" + - FLYTE_AWS_ENDPOINT: "http://rustfs.flyte.svc.cluster.local:9000" + - FLYTE_AWS_ACCESS_KEY_ID: "rustfs" + - FLYTE_AWS_SECRET_ACCESS_KEY: "rustfsstorage" + - _U_EP_OVERRIDE: "flyte-binary-http.flyte.svc.cluster.local:8090" - _U_INSECURE: "true" - _U_USE_ACTIONS: "1" @@ -105,8 +105,8 @@ storage: kind: "s3" config: auth_type: "accesskey" - access_key_id: "minio" - secret_key: "miniostorage" + access_key_id: "rustfs" + secret_key: "rustfsstorage" region: "us-east-1" endpoint: "http://localhost:30002" disable_ssl: "true" From cfe2961768d1fd37e69513e903b59ca6cc6f98d6 Mon Sep 17 00:00:00 2001 From: "M. Adil Fayyaz" <62440954+AdilFayyaz@users.noreply.github.com> Date: Tue, 21 Apr 2026 16:58:01 -0700 Subject: [PATCH 6/6] fix: url routing + knative version Signed-off-by: M. Adil Fayyaz <62440954+AdilFayyaz@users.noreply.github.com> --- app/config/config.go | 18 +++++--- app/internal/k8s/app_client.go | 46 +++++++++---------- app/internal/service/internal_app_service.go | 21 +++++---- .../service/internal_app_service_test.go | 23 +++++++++- .../templates/proxy/traefik-config.yaml | 8 ++++ charts/flyte-devbox/values.yaml | 5 +- docker/devbox-bundled/Makefile | 2 + docker/devbox-bundled/manifests/complete.yaml | 15 ++++-- docker/devbox-bundled/manifests/dev.yaml | 8 ++++ manager/config.yaml | 5 +- 10 files changed, 102 insertions(+), 49 deletions(-) diff --git a/app/config/config.go b/app/config/config.go index b62ad3c1a2a..fe547080a01 100644 --- a/app/config/config.go +++ b/app/config/config.go @@ -42,19 +42,23 @@ type InternalAppConfig struct { // IngressEnabled controls whether a Traefik IngressRoute and Middleware are // created for each deployed app so it is reachable at - // /// through the Traefik ingress controller. + // {name}-{project}-{domain}.{IngressAppsDomain}:{IngressAppsPort} through Traefik. // Enable this for sandbox/local setups where Traefik is the ingress controller. IngressEnabled bool `json:"ingressEnabled" pflag:",Create Traefik IngressRoute for each app"` // IngressEntryPoint is the Traefik entry point name that app routes are - // attached to (default: "web"). + // attached to (default: "apps"). IngressEntryPoint string `json:"ingressEntryPoint" pflag:",Traefik entry point name for app ingress routes"` - // IngressBaseURL is the externally reachable base URL of the ingress controller - // (e.g. "http://localhost:30080"). When set, the public URL surfaced for each app - // is built as {IngressBaseURL}/{project}/{domain}/{app} instead of the Knative - // host-based URL. Only used when IngressEnabled is true. - IngressBaseURL string `json:"ingressBaseUrl" pflag:",Base URL of the ingress controller for app public URLs"` + // IngressAppsDomain is the domain suffix for subdomain-based app URLs. + // Apps are exposed at {name}-{project}-{domain}.{IngressAppsDomain}. + // Use "localhost" for local devbox (resolves without /etc/hosts on macOS/Linux). + // Windows users can override to e.g. "localtest.me". + IngressAppsDomain string `json:"ingressAppsDomain" pflag:",Domain suffix for app subdomain URLs"` + + // IngressAppsPort is the port appended to the public app URL (e.g. 30081). + // Set to 0 to omit the port when behind a standard 80/443 proxy. + IngressAppsPort int `json:"ingressAppsPort" pflag:",Port for app subdomain URLs (0 = omit)"` // DefaultEnvVars is a list of environment variables injected into every KService // pod at deploy time, in addition to any env vars specified in the app spec. diff --git a/app/internal/k8s/app_client.go b/app/internal/k8s/app_client.go index 924f9b39068..e79f4860721 100644 --- a/app/internal/k8s/app_client.go +++ b/app/internal/k8s/app_client.go @@ -469,13 +469,18 @@ func (c *AppK8sClient) List(ctx context.Context, project, domain string, limit u // publicIngress returns the deterministic public URL for an app using the same // logic as the service layer so GetStatus/List/Watch are consistent with Create. func (c *AppK8sClient) publicIngress(id *flyteapp.Identifier) *flyteapp.Ingress { - if c.cfg.IngressEnabled && c.cfg.IngressBaseURL != "" { - return &flyteapp.Ingress{ - PublicUrl: fmt.Sprintf("%s/%s/%s/%s", - strings.TrimRight(c.cfg.IngressBaseURL, "/"), - id.GetProject(), id.GetDomain(), id.GetName(), - ), + if c.cfg.IngressEnabled && c.cfg.IngressAppsDomain != "" { + scheme := c.cfg.Scheme + if scheme == "" { + scheme = "http" } + host := strings.ToLower(fmt.Sprintf("%s-%s-%s.%s", + id.GetName(), id.GetProject(), id.GetDomain(), c.cfg.IngressAppsDomain)) + url := scheme + "://" + host + if c.cfg.IngressAppsPort != 0 { + url += fmt.Sprintf(":%d", c.cfg.IngressAppsPort) + } + return &flyteapp.Ingress{PublicUrl: url} } if c.cfg.BaseDomain == "" { return nil @@ -490,10 +495,9 @@ func (c *AppK8sClient) publicIngress(id *flyteapp.Identifier) *flyteapp.Ingress } // deployIngress creates or updates the Traefik resources for the given app: -// - strip- Middleware: strips /// prefix // - host- Middleware: rewrites Host to the Knative hostname so Kourier // can route the request (Knative's K8s service is ExternalName → Kourier) -// - app- IngressRoute: matches PathPrefix and chains both middlewares +// - app- IngressRoute: matches Host header and applies the middleware // // No-ops when IngressEnabled is false. func (c *AppK8sClient) deployIngress(ctx context.Context, app *flyteapp.App) error { @@ -503,13 +507,13 @@ func (c *AppK8sClient) deployIngress(ctx context.Context, app *flyteapp.App) err appID := app.GetMetadata().GetId() ns := appNamespace(appID.GetProject(), appID.GetDomain()) ksvcName := kserviceName(appID) - stripName := "strip-" + ksvcName hostName := "host-" + ksvcName routeName := "app-" + ksvcName - pathPrefix := fmt.Sprintf("/%s/%s/%s", appID.GetProject(), appID.GetDomain(), appID.GetName()) + appHost := strings.ToLower(fmt.Sprintf("%s-%s-%s.%s", + appID.GetName(), appID.GetProject(), appID.GetDomain(), c.cfg.IngressAppsDomain)) entryPoint := c.cfg.IngressEntryPoint if entryPoint == "" { - entryPoint = "web" + entryPoint = "apps" } // Knative's K8s service is ExternalName → kourier-internal. Kourier routes by @@ -517,16 +521,6 @@ func (c *AppK8sClient) deployIngress(ctx context.Context, app *flyteapp.App) err // hostname pattern matches the configured domain-template: {name}-{namespace}.{domain} knativeHost := fmt.Sprintf("%s-%s.%s", ksvcName, ns, c.cfg.BaseDomain) - stripMW := &unstructured.Unstructured{} - stripMW.SetGroupVersionKind(traefikMiddlewareGVK) - stripMW.SetName(stripName) - stripMW.SetNamespace(ns) - stripMW.Object["spec"] = map[string]interface{}{ - "stripPrefix": map[string]interface{}{ - "prefixes": []interface{}{pathPrefix}, - }, - } - hostMW := &unstructured.Unstructured{} hostMW.SetGroupVersionKind(traefikMiddlewareGVK) hostMW.SetName(hostName) @@ -535,6 +529,10 @@ func (c *AppK8sClient) deployIngress(ctx context.Context, app *flyteapp.App) err "headers": map[string]interface{}{ "customRequestHeaders": map[string]interface{}{ "Host": knativeHost, + // Rewrite Origin to match the Knative host so that apps with + // XSRF/CORS origin checks (e.g. Streamlit) accept the connection. + // Safe for devbox — XSRF provides no value in a local environment. + "Origin": "http://" + knativeHost, }, }, } @@ -547,10 +545,9 @@ func (c *AppK8sClient) deployIngress(ctx context.Context, app *flyteapp.App) err "entryPoints": []interface{}{entryPoint}, "routes": []interface{}{ map[string]interface{}{ - "match": fmt.Sprintf("PathPrefix(`%s`)", pathPrefix), + "match": fmt.Sprintf("Host(`%s`)", appHost), "kind": "Rule", "middlewares": []interface{}{ - map[string]interface{}{"name": stripName}, map[string]interface{}{"name": hostName}, }, "services": []interface{}{ @@ -563,7 +560,7 @@ func (c *AppK8sClient) deployIngress(ctx context.Context, app *flyteapp.App) err }, } - for _, obj := range []*unstructured.Unstructured{stripMW, hostMW, ir} { + for _, obj := range []*unstructured.Unstructured{hostMW, ir} { existing := &unstructured.Unstructured{} existing.SetGroupVersionKind(obj.GroupVersionKind()) err := c.k8sClient.Get(ctx, client.ObjectKey{Name: obj.GetName(), Namespace: obj.GetNamespace()}, existing) @@ -600,7 +597,6 @@ func (c *AppK8sClient) deleteIngress(ctx context.Context, appID *flyteapp.Identi } resources := []resource{ {traefikIngressRouteGVK, "app-" + ksvcName}, - {traefikMiddlewareGVK, "strip-" + ksvcName}, {traefikMiddlewareGVK, "host-" + ksvcName}, } for _, r := range resources { diff --git a/app/internal/service/internal_app_service.go b/app/internal/service/internal_app_service.go index 348b36acd8d..41b4bf2b91f 100644 --- a/app/internal/service/internal_app_service.go +++ b/app/internal/service/internal_app_service.go @@ -67,18 +67,23 @@ func (s *InternalAppService) Create( } // publicIngress builds the deterministic public URL for an app. -// When Traefik ingress is enabled (IngressEnabled + IngressBaseURL), the URL is -// path-based: {base}/{project}/{domain}/{app}. +// When Traefik ingress is enabled (IngressEnabled + IngressAppsDomain), the URL is +// subdomain-based: {scheme}://{name}-{project}-{domain}.{IngressAppsDomain}[:{IngressAppsPort}]. // Otherwise falls back to the Knative host pattern: {scheme}://{name}-{project}-{domain}.{base_domain}. // Returns nil if neither is configured. func publicIngress(id *flyteapp.Identifier, cfg *appconfig.InternalAppConfig) *flyteapp.Ingress { - if cfg.IngressEnabled && cfg.IngressBaseURL != "" { - return &flyteapp.Ingress{ - PublicUrl: fmt.Sprintf("%s/%s/%s/%s", - strings.TrimRight(cfg.IngressBaseURL, "/"), - id.GetProject(), id.GetDomain(), id.GetName(), - ), + if cfg.IngressEnabled && cfg.IngressAppsDomain != "" { + scheme := cfg.Scheme + if scheme == "" { + scheme = "http" } + host := strings.ToLower(fmt.Sprintf("%s-%s-%s.%s", + id.GetName(), id.GetProject(), id.GetDomain(), cfg.IngressAppsDomain)) + url := scheme + "://" + host + if cfg.IngressAppsPort != 0 { + url += fmt.Sprintf(":%d", cfg.IngressAppsPort) + } + return &flyteapp.Ingress{PublicUrl: url} } if cfg.BaseDomain == "" { return nil diff --git a/app/internal/service/internal_app_service_test.go b/app/internal/service/internal_app_service_test.go index 2ece2571ba8..2aa07125aa7 100644 --- a/app/internal/service/internal_app_service_test.go +++ b/app/internal/service/internal_app_service_test.go @@ -77,7 +77,9 @@ func (m *mockAppK8sClient) Watch(ctx context.Context, project, domain, appName s func testCfg() *appconfig.InternalAppConfig { return &appconfig.InternalAppConfig{ Enabled: true, - BaseDomain: "apps.example.com", + IngressEnabled: true, + IngressAppsDomain: "example.com", + Scheme: "https", DefaultRequestTimeout: 5 * time.Minute, MaxRequestTimeout: time.Hour, } @@ -128,7 +130,7 @@ func TestCreate_Success(t *testing.T) { resp, err := svc.Create(context.Background(), connect.NewRequest(&flyteapp.CreateRequest{App: app})) require.NoError(t, err) assert.Equal(t, flyteapp.Status_DEPLOYMENT_STATUS_PENDING, resp.Msg.App.Status.Conditions[0].DeploymentStatus) - assert.Equal(t, "https://myapp-proj-dev.apps.example.com", resp.Msg.App.Status.Ingress.PublicUrl) + assert.Equal(t, "https://myapp-proj-dev.example.com", resp.Msg.App.Status.Ingress.PublicUrl) k8s.AssertExpectations(t) } @@ -165,9 +167,26 @@ func TestCreate_MissingPayload(t *testing.T) { assert.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err)) } +func TestCreate_IngressWithPort(t *testing.T) { + k8s := &mockAppK8sClient{} + cfg := testCfg() + cfg.IngressAppsPort = 30081 + svc := NewInternalAppService(k8s, cfg) + + app := testApp() + k8s.On("Deploy", mock.Anything, app).Return(nil) + + resp, err := svc.Create(context.Background(), connect.NewRequest(&flyteapp.CreateRequest{App: app})) + require.NoError(t, err) + assert.Equal(t, "https://myapp-proj-dev.example.com:30081", resp.Msg.App.Status.Ingress.PublicUrl) + k8s.AssertExpectations(t) +} + func TestCreate_NoBaseDomain_NoIngress(t *testing.T) { k8s := &mockAppK8sClient{} cfg := testCfg() + cfg.IngressEnabled = false + cfg.IngressAppsDomain = "" cfg.BaseDomain = "" svc := NewInternalAppService(k8s, cfg) diff --git a/charts/flyte-devbox/templates/proxy/traefik-config.yaml b/charts/flyte-devbox/templates/proxy/traefik-config.yaml index 581444cd77d..854d8616d52 100644 --- a/charts/flyte-devbox/templates/proxy/traefik-config.yaml +++ b/charts/flyte-devbox/templates/proxy/traefik-config.yaml @@ -14,6 +14,14 @@ spec: transport: respondingTimeouts: readTimeout: 0 + apps: + port: 30081 + nodePort: 30081 + expose: + default: true + transport: + respondingTimeouts: + readTimeout: 0 websecure: expose: false providers: diff --git a/charts/flyte-devbox/values.yaml b/charts/flyte-devbox/values.yaml index 2b0280d3589..1cf06ec0129 100644 --- a/charts/flyte-devbox/values.yaml +++ b/charts/flyte-devbox/values.yaml @@ -72,8 +72,9 @@ flyte-binary: baseDomain: "local.flyte.app" scheme: "http" ingressEnabled: true - ingressEntryPoint: "web" - ingressBaseUrl: "http://localhost:30080" + ingressEntryPoint: "apps" + ingressAppsDomain: "localhost" + ingressAppsPort: 30081 defaultEnvVars: - name: FLYTE_AWS_ENDPOINT value: 'http://rustfs.{{ .Release.Namespace }}:9000' diff --git a/docker/devbox-bundled/Makefile b/docker/devbox-bundled/Makefile index 0d283b8c676..ddf29f4b270 100644 --- a/docker/devbox-bundled/Makefile +++ b/docker/devbox-bundled/Makefile @@ -74,6 +74,7 @@ build-gpu: build # 30001 - DB # 30002 - RustFS # 30080 - Flyte Proxy +# 30081 - Flyte Apps .PHONY: start start: FLYTE_DEVBOX_IMAGE := flyte-devbox:latest start: FLYTE_DEV := False @@ -93,6 +94,7 @@ start: --publish "30001:5432" \ --publish "30002:30002" \ --publish "30080:30080" \ + --publish "30081:30081" \ $(FLYTE_DEVBOX_IMAGE); \ fi @echo "Waiting for kubeconfig..." diff --git a/docker/devbox-bundled/manifests/complete.yaml b/docker/devbox-bundled/manifests/complete.yaml index 0f9c37f5516..262ad487739 100644 --- a/docker/devbox-bundled/manifests/complete.yaml +++ b/docker/devbox-bundled/manifests/complete.yaml @@ -553,9 +553,10 @@ data: - name: _U_USE_ACTIONS value: "1" enabled: true - ingressBaseUrl: http://localhost:30080 + ingressAppsDomain: localhost + ingressAppsPort: 30081 ingressEnabled: true - ingressEntryPoint: web + ingressEntryPoint: apps scheme: http plugins: k8s: @@ -934,7 +935,7 @@ spec: template: metadata: annotations: - checksum/configuration: b923ff0f82e769435cfba822a87e33bfa00a205d47bf39c4dd395fa07d77160a + checksum/configuration: 709f0513c6d5a65b47f3e9d42696c92cecfdc3073acac33c7ad32340a645bef4 checksum/configuration-secret: e70194084619f4a1d4017093aac6367047167107fd0222513a32a61734629cac labels: app.kubernetes.io/component: flyte-binary @@ -1165,6 +1166,14 @@ spec: transport: respondingTimeouts: readTimeout: 0 + apps: + port: 30081 + nodePort: 30081 + expose: + default: true + transport: + respondingTimeouts: + readTimeout: 0 websecure: expose: false providers: diff --git a/docker/devbox-bundled/manifests/dev.yaml b/docker/devbox-bundled/manifests/dev.yaml index db36a0af32d..41b78ad5640 100644 --- a/docker/devbox-bundled/manifests/dev.yaml +++ b/docker/devbox-bundled/manifests/dev.yaml @@ -758,6 +758,14 @@ spec: transport: respondingTimeouts: readTimeout: 0 + apps: + port: 30081 + nodePort: 30081 + expose: + default: true + transport: + respondingTimeouts: + readTimeout: 0 websecure: expose: false providers: diff --git a/manager/config.yaml b/manager/config.yaml index 22517a28013..21488787237 100644 --- a/manager/config.yaml +++ b/manager/config.yaml @@ -23,8 +23,9 @@ manager: defaultRequestTimeout: 300s maxRequestTimeout: 3600s ingressEnabled: true - ingressEntryPoint: "web" - ingressBaseUrl: "http://localhost:30080" + ingressEntryPoint: "apps" + ingressAppsDomain: "localhost" + ingressAppsPort: 30081 defaultEnvVars: - name: FLYTE_AWS_ENDPOINT value: "http://rustfs.flyte.svc.cluster.local:9000"