Documentation
¶
Overview ¶
Package certificate implements the Certificate controller: for every Certificate it resolves the ClusterIssuer and the xpki profile, evaluates the policy, decides whether an issuance is needed (needsIssuance in renewal.go), generates the key and the CSR, signs with the Authority, writes the kubernetes.io/tls Secret (secret.go), records the status and requeues itself for the renewal time.
Files: reconciler.go (Reconcile, watches, status), issuance.go (issuer resolution, names, validity, key, CSR, Sign), secret.go (read, conflict detection, write), renewal.go (needsIssuance, renewal time, jitter).
Errors are split: a *permanentError (policy, conflict, a request the issuer rejects) is recorded in the Ready condition and an event and is not retried until the spec, the issuer or the Secret changes; every other error (API server, KMS) is returned so controller-runtime retries it with backoff.
Index ¶
Constants ¶
const ( // ControllerName is the name of the controller in metrics and logs. ControllerName = "certificate" // DefaultMaxConcurrentReconciles is the worker count when the // Reconciler does not set one; Issuer.Sign is safe for concurrent use. DefaultMaxConcurrentReconciles = 4 )
Variables ¶
var CertificateChanged = predicate.Or[client.Object]( predicate.GenerationChangedPredicate{}, predicate.AnnotationChangedPredicate{}, predicate.Funcs{UpdateFunc: func(e event.UpdateEvent) bool { return e.ObjectOld != nil && e.ObjectNew != nil && !equality.Semantic.DeepEqual(e.ObjectOld.GetOwnerReferences(), e.ObjectNew.GetOwnerReferences()) }}, )
CertificateChanged lets through the Certificate updates that can change the outcome of a reconcile: the spec (metadata.generation), the annotations (renew-requested) and the owner references (the Pod of the policy placeholder ${SERVICE_ACCOUNT}). A status-only update, the controller's own status patch included, is dropped: a recorded failure would otherwise enqueue its Certificate again at once, re-sign, record the next attempt and loop without backoff. Creates and deletes pass.
Functions ¶
This section is empty.
Types ¶
type Reconciler ¶
type Reconciler struct {
client.Client
// APIReader reads Secrets the cache does not hold (not labeled
// managed=true) to detect a conflict before creating one.
APIReader client.Reader
Scheme *runtime.Scheme
Authority *authority.Authority
Recorder record.EventRecorder
// Clock is the time source; tests inject a fake.
Clock clock.Clock
// ClusterDomain is the suffix of the Service names
// spec.kubernetesNames adds and the policy placeholder
// ${CLUSTER_DOMAIN}.
ClusterDomain string
// MaxConcurrentReconciles overrides DefaultMaxConcurrentReconciles.
MaxConcurrentReconciles int
}
Reconciler reconciles Certificates.
func (*Reconciler) Reconcile ¶
Reconcile runs the issuance pipeline for one Certificate and patches its status. It returns an error only for transient failures.
func (*Reconciler) SetupWithManager ¶
func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error
SetupWithManager registers the controller: it watches Certificates (CertificateChanged: not their status), the Secrets they own, ClusterIssuers (mapped to their Certificates), Services (mapped to the Certificates that name them) and Namespaces whose labels change (mapped to their Certificates, for the policy namespace selector). Pods are read from the cache (labeled Pods) for the policy placeholder ${SERVICE_ACCOUNT}, not watched: a Pod's ServiceAccount is immutable and its Certificate is garbage-collected with it.