Skip to main content

Application Services

Flyte Application Services enable the deployment and management of long-running services and applications. Built on top of Knative, this system provides automated scaling (including scaling to zero), public ingress management, and integrated log streaming.

The architecture is split into a control plane (AppService) and a data plane (InternalAppService). The control plane handles request proxying and status caching, while the data plane interacts directly with Kubernetes via the AppK8sClient to manage Knative Service (KService) resources.

Deploying an Application

To deploy an application, you define a flyteapp.App with a container payload. Flyte transforms this specification into a Knative Service manifest.

app := &flyteapp.App{
Metadata: &flyteapp.Meta{
Id: &flyteapp.Identifier{
Project: "my-project",
Domain: "development",
Name: "web-server",
},
},
Spec: &flyteapp.Spec{
AppPayload: &flyteapp.Spec_Container{
Container: &flytecoreapp.Container{
Image: "nginx:latest",
Ports: []*flytecoreapp.ContainerPort{
{ContainerPort: 80, Name: "http"},
},
},
},
Autoscaling: &flyteapp.Autoscaling{
Replicas: &flyteapp.Autoscaling_ReplicaRange{
Min: 1,
Max: 10,
},
},
},
}

Internally, AppK8sClient.buildKService (in app/internal/k8s/app_client.go) maps this spec to a servingv1.Service. It handles:

  • Naming: Generates a deterministic name using {name}-{project}-{domain}. If this exceeds the 63-character Kubernetes limit, it appends a SHA256 suffix to ensure uniqueness while staying within the limit.
  • Autoscaling: Maps the Autoscaling spec to Knative annotations like autoscaling.knative.dev/min-scale and autoscaling.knative.dev/max-scale.
  • Timeouts: Applies request timeouts to the RevisionSpec, capped by the internalApps.maxRequestTimeout configuration.

Internal Communication

Every deployed app is injected with an INTERNAL_APP_ENDPOINT_PATTERN environment variable. This allows application code to discover and connect to other apps within the same cluster using a predictable URL format: http://{app_fqdn}-{{ project }}-{{ domain }}.flyte.svc.cluster.local

Lifecycle Management

Flyte supports two ways to stop an application: scaling to zero (Stop) and full removal (Delete).

Stopping (Scale to Zero)

When you set an app's DesiredState to STOPPED, the AppK8sClient.Stop method patches the KService.

  1. It sets autoscaling.knative.dev/min-scale and initial-scale to 0.
  2. It applies the networking.knative.dev/visibility: cluster-local label, which removes the app from the public ingress gateway.
  3. It deletes the LatestReadyRevision to force the immediate termination of existing pods, rather than waiting for the standard Knative scale-down window.

Deleting

The Delete operation removes the KService resource entirely from Kubernetes. Unlike Stop, this removes all configuration and history for the app; it must be re-created from scratch to run again.

Networking and Ingress

Flyte manages public access to applications through Kourier (the default Knative ingress provider).

The public URL is generated deterministically by AppK8sClient.PublicIngress based on the internalApps.baseDomain and internalApps.scheme configurations. For an app named myapp in project p1 and domain d1, the URL typically follows the pattern: https://myapp-p1-d1.example.com

Observability and Logs

Flyte provides a streaming log service specifically tuned for Knative-based applications.

Log Streaming

The InternalAppLogsService (in app/internal/service/app_logs_service.go) allows you to tail logs for an entire app or a specific replica (pod). It resolves the app identifier to the current set of active pods and initiates a stream for each.

Sidecar Filtering

Knative injects a queue-proxy sidecar into every pod to manage request queuing and metrics. To ensure you only see relevant application data, the K8sAppLogStreamer (in app/internal/service/app_logs_streamer.go) explicitly filters out this container:

// pickUserContainer returns the primary user container, skipping Knative sidecars.
func pickUserContainer(pod *corev1.Pod) string {
for _, c := range pod.Spec.Containers {
if c.Name != "queue-proxy" {
return c.Name
}
}
return ""
}

Configuration

Application services are configured via the internalApps and apps sections in the Flyte configuration.

SettingDefaultDescription
internalApps.defaultRequestTimeout300sTimeout applied if not specified in the app spec.
internalApps.maxRequestTimeout3600sHard cap on the allowed request timeout.
internalApps.baseDomain(empty)The root domain for public ingress URLs.
internalApps.namespacedNameSuffixTemplate{{ project }}-{{ domain }}Template for internal cluster DNS suffixes.
apps.cacheTtl30sTTL for the control plane's in-memory status cache.

All applications are deployed into a dedicated Kubernetes namespace defined by the AppNamespace constant, which defaults to flyte.