How does Flux handle dependency management between Kustomizations for ordered deployments?
Quick Answer
Flux Kustomizations support a spec.dependsOn field that creates an explicit dependency graph between Kustomizations, ensuring that infrastructure components like databases and message queues are fully reconciled and healthy before dependent application Kustomizations begin their reconciliation, enabling ordered multi-component deployments.
Detailed Answer
Think of Flux Kustomization dependencies like a construction project schedule. You cannot install the plumbing (database) until the foundation (namespace and RBAC) is poured, and you cannot start the interior finishing (application deployment) until the plumbing is inspected and approved (database is healthy). The spec.dependsOn field in a Flux Kustomization acts as the project schedule that defines these predecessor relationships. The Flux kustomize-controller will not begin reconciling a Kustomization until all of its dependencies have successfully reconciled and their resources are in a ready state, just as a construction foreman will not sign off on the next phase until the prerequisite inspection passes.
The dependsOn field accepts a list of references to other Kustomization resources, specified by name and optionally by namespace. When the kustomize-controller evaluates a Kustomization for reconciliation, it first checks whether all dependencies have a Ready condition set to True in their status. If any dependency is not yet ready — whether because it has not been reconciled yet, is currently reconciling, or has failed — the dependent Kustomization is skipped for this reconciliation cycle. This creates a natural ordering where foundational components are deployed and validated before the applications that depend on them. The dependency check happens at every reconciliation interval, not just during the initial deployment, which means that if a dependency later becomes unhealthy due to drift or a failed update, the dependent Kustomizations will also pause until the dependency is restored.
The dependency graph can be arbitrarily deep and wide. A common pattern for a microservices architecture involves four layers: the first layer deploys cluster infrastructure like cert-manager, external-dns, and the ingress controller; the second layer deploys shared middleware like PostgreSQL operators, Redis clusters, and RabbitMQ; the third layer deploys the application databases and message queues for specific services; and the fourth layer deploys the application Deployments and Services. Each layer's Kustomizations declare dependsOn references to the previous layer. The kustomize-controller resolves these dependencies at reconciliation time and processes them in topological order. Circular dependencies are detected and reported as errors in the Kustomization status, preventing deadlock scenarios where two Kustomizations wait for each other indefinitely.
In a production environment running order-service, payments-api, and inventory-service, the dependency graph typically looks like this: the infrastructure Kustomization deploys the PostgreSQL operator and Redis operator, the order-db Kustomization depends on infrastructure and creates the PostgreSQL cluster for the order service, the order-cache Kustomization depends on infrastructure and creates the Redis instance, and finally the order-service Kustomization depends on both order-db and order-cache because the application needs both a database connection and a cache connection to start successfully. The spec.healthChecks field on the database and cache Kustomizations adds explicit health check references to the PostgreSQL and Redis StatefulSets, ensuring that the pods are not just created but actually running and ready before the application Kustomization proceeds. Without these health checks, Flux might consider a Kustomization ready as soon as the manifests are applied, even if the database pods are still starting up.
A critical gotcha is the distinction between a Kustomization being Ready and its underlying resources being healthy. By default, a Kustomization is considered Ready when all manifests have been successfully applied to the cluster, but this does not mean the Pods are running or the Services have endpoints. To enforce actual readiness, you must set spec.wait to true or configure explicit spec.healthChecks that reference specific resources like Deployments or StatefulSets. Without these, the dependent Kustomization starts reconciling immediately after the manifests are applied, potentially causing the application to crash because the database is not yet accepting connections. Another common mistake is not accounting for Kustomization timeout values — if a dependency takes longer to become healthy than the default timeout of five minutes, the dependency is marked as failed and all downstream Kustomizations are blocked. Setting appropriate spec.timeout values based on actual startup times of infrastructure components prevents false failures in the dependency chain.