Skip to main content

Application Lifecycle Management

Flyte manages the lifecycle of applications by orchestrating Knative Services (KServices) within a dedicated Kubernetes namespace. This management layer handles deployment, scaling, state transitions, and real-time status monitoring through the AppK8sClient.

Deploying and Updating Applications

When you create or update an application, Flyte uses the Deploy method to ensure the underlying Knative Service matches your desired specification. This process is designed to be idempotent and efficient.

Idempotent Deployments

To avoid unnecessary Kubernetes API calls and Knative revision churn, Flyte calculates a SHA256 hash of the application specification and stores it in the flyte.org/spec-sha annotation.

// From app/internal/k8s/app_client.go
if !existingStopped && existing.Annotations[annotationSpecSHA] == ksvc.Annotations[annotationSpecSHA] {
logger.Debugf(ctx, "KService %s/%s spec unchanged, skipping update", ns, name)
return nil
}

If you call Deploy with a specification that matches the existing one, Flyte skips the update unless the application was previously in a STOPPED state.

Resource Mapping

Flyte translates the flyteapp.App proto into a Knative Service manifest. This includes:

  • Container Configuration: Mapping images, commands, arguments, and environment variables.
  • Resource Requirements: Converting Flyte resource requests and limits (CPU, Memory, GPU) into Kubernetes ResourceRequirements.
  • Timeouts: Applying request timeouts, capped by the MaxRequestTimeout configuration (default 3600s).

Managing Application State

Flyte distinguishes between "stopping" an application (scaling to zero) and "deleting" it entirely.

Scaling to Zero (Stop)

When you set an application's desired state to STOPPED, Flyte invokes the Stop method. Instead of deleting the Kubernetes resources, it applies a merge patch to the KService that:

  1. Sets autoscaling.knative.dev/min-scale and initial-scale to 0.
  2. Marks the service as networking.knative.dev/visibility: cluster-local to remove it from the public gateway.
  3. Adds the flyte.org/app-stopped: "true" label.

To ensure running pods terminate immediately rather than waiting for the Knative stable window, Flyte force-deletes the LatestReadyRevision:

// From app/internal/k8s/app_client.go
if revName := current.Status.LatestReadyRevisionName; revName != "" {
rev := &servingv1.Revision{
ObjectMeta: metav1.ObjectMeta{Name: revName, Namespace: ns},
}
if delErr := c.k8sClient.Delete(ctx, rev); delErr != nil && !k8serrors.IsNotFound(delErr) {
logger.Warnf(ctx, "Failed to delete Revision %s/%s to stop: %v", ns, revName, delErr)
}
}

Full Deletion

The Delete method removes the KService CRD entirely. Once deleted, the application must be re-created from scratch, as all Knative configuration and revision history are lost.

Internal and External Networking

Flyte automatically configures networking so applications can be reached externally and communicate with each other internally.

Public Ingress

The PublicIngress method generates a deterministic URL for your application based on the BaseDomain and Scheme configured in Flyte. The URL follows the pattern: {scheme}://{name}-{project}-{domain}.{baseDomain}

If the generated name exceeds 63 characters, Flyte appends a deterministic 8-character hash suffix to ensure the name remains a valid Kubernetes DNS label while staying unique.

Service-to-Service Communication

Flyte injects an environment variable named INTERNAL_APP_ENDPOINT_PATTERN into every deployed container. This allows your application code to discover other Flyte apps within the same cluster without going through the public gateway.

The pattern typically looks like: http://{app_fqdn}-{{ project }}-{{ domain }}.flyte.svc.cluster.local

Monitoring and Watch Mechanism

Flyte provides a subscription-based mechanism to monitor application lifecycle events (Create, Update, Delete) in real-time.

Subscribing to Events

You can subscribe to events for a specific application or all applications using the Subscribe method. This returns a channel that receives WatchResponse objects.

// Example of subscribing to events in app/internal/service/internal_app_service.go
ch := s.k8s.Subscribe(appName)
defer s.k8s.Unsubscribe(appName, ch)

for {
select {
case resp, ok := <-ch:
if !ok {
return nil
}
if err := stream.Send(resp); err != nil {
return err
}
case <-ctx.Done():
return ctx.Err()
}
}

Internal Implementation

The AppK8sClient uses a controller-runtime informer to watch KService objects. When a change is detected, handleKServiceEvent converts the Kubernetes event into a Flyte WatchResponse and dispatches it to all active subscribers.

Replica Management

To inspect the live state of an application's pods, use GetReplicas. This method queries Kubernetes pods filtered by the serving.knative.dev/service label. If a specific pod is misbehaving, DeleteReplica allows you to force-delete it, triggering Knative to automatically provision a replacement.