Clusters
How convoy connects to a target cluster, when Releases can use it, and how its metadata reaches templates.
A Cluster is a target for Releases. It tells convoy how to connect to a Kubernetes API server.
It also holds metadata that mutations and lifecycle hooks can read. Each Release references one
Cluster in its own namespace.
apiVersion: core.convoy.kumodo.io/v1alpha1
kind: Cluster
metadata:
name: convoy-managed
namespace: default
spec:
connectionMode: agentless
agentless:
server: https://convoy-managed-control-plane:6443
auth:
type: kubeconfig
kubeconfig:
secretRef:
name: convoy-managed-kubeconfig
key: kubeconfig
metadata:
type: kind
role: managed
Connection modes#
spec.connectionMode selects how convoy connects to the target API server:
| Mode | How convoy connects |
|---|---|
inCluster | With the configuration of the convoy process. Use it for the cluster where convoy runs. |
agentless | With a kubeconfig from a Secret. kubeconfig is the only auth type that is built. |
agent | Pull mode with an agent in the target cluster is planned. Not built |
For agentless mode with kubeconfig auth:
- convoy reads the Secret in the namespace of the
Cluster.kubeconfig.secretRef.keyselects the key. - The key must hold a full kubeconfig. convoy uses its current context.
- The kubeconfig sets the server, the CA and the credentials. convoy does not use
agentless.serveroragentless.caPublicCertRefto connect.
An auth type that is not built gives Ready=False with reason Unsupported. See
Cluster for all fields.
The controller-manager connects to apply and prune objects. The observer connects to read live objects for drift and health. Both use the same connection code.
The probe#
The cluster controller probes each Cluster:
- It builds a connection from
spec. - It reads the server version through the discovery API.
- It reads the API groups and versions that the server serves.
| Probe result | status.reachable | Ready condition | Other status fields |
|---|---|---|---|
| Success | true | True, reason Reachable | convoy updates lastSeen, discoveredVersion and discoveredAPIVersions. |
| Connection or discovery error | false | False, reason ProbeFailed | The values of the last successful probe stay. |
| Mode or auth type not built | false | False, reason Unsupported | The values of the last successful probe stay. |
After a ProbeFailed result, the controller retries with a rate limit. After an Unsupported
result, it does not retry. It probes all Clusters again at each periodic informer resync.
Reachability gates the Release#
At each reconcile, the Release controller fetches the source, and then reads the target
Cluster. Before rendering, it checks the Cluster:
- If the
Clusterdoes not exist, the Release reportsApplied=False, reasonClusterNotReady. - If
status.reachableisfalse, the Release reportsApplied=False, reasonClusterNotReady.
In both cases convoy does not render and does not apply. It retries the Release as a transient failure. The objects of the last apply stay on the target cluster.
A change to a Cluster does not start a reconcile of its Releases. A Release reads the new
Cluster state at its next reconcile. See Sync policy.
Metadata as template context#
spec.metadata is a map of strings. convoy gives it to templates and CEL expressions as cluster:
spec:
metadata:
region: eu-west-1
tier: production| Value | Go template | CEL |
|---|---|---|
| A metadata key | {{ .cluster.region }} | cluster.region |
The name of the Cluster object | {{ .cluster.name }} | cluster.name |
cluster.namereplaces a metadata key with the namename.- The context never contains credentials, the server address or the status.
- These parts of convoy read the context: mutations, the
from.nameandfrom.pathfields of a mutation, and lifecycle hooks.
A mutation that reads metadata makes the render depend on the Cluster. When you change the
metadata, the render can change. A changed render has a new renderRef, and convoy applies it as
a new rollout. See Rendering.
Deletion#
convoy adds the finalizer cluster.core.convoy.kumodo.io/prune-releases to each Cluster.
spec.deletionPolicy.pruneReleases controls what happens to the Releases that reference the
Cluster:
pruneReleases | What convoy does |
|---|---|
false (default) | convoy deletes the Cluster at once. Its Releases stay, and report ClusterNotReady. |
true | convoy deletes each Release that references the Cluster. The Cluster stays until all those Releases are gone. |
With pruneReleases: true, each Release runs its own deletion while the Cluster still exists.
The deletion policy of each Release applies, for example keepWorkloads and
blockOnClusterUnreachable. See Deletion.
In the code
convoy v0.9.0
internal/clusterconn.(*Connector).Connectinternal/clusterconn/connector.go:64internal/auth.KubeconfigAuthenticator.RESTConfiginternal/auth/kubeconfig.go:37internal/controller/cluster.(*connectorProber).Probeinternal/controller/cluster/prober.go:59internal/controller/cluster.computeStatusinternal/controller/cluster/reconcile.go:45internal/controller/release.(*Controller).stageRenderinternal/controller/release/controller.go:901internal/render.contextValuesinternal/render/mutate.go:328internal/controller/cluster.(*Controller).pruneReleasesinternal/controller/cluster/controller.go:164internal/controller/release.(*Controller).clusterForFinalizeinternal/controller/release/controller.go:646