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
MaxRequestTimeoutconfiguration (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:
- Sets
autoscaling.knative.dev/min-scaleandinitial-scaleto0. - Marks the service as
networking.knative.dev/visibility: cluster-localto remove it from the public gateway. - 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.