Skip to content

Commit dfdffec

Browse files
committed
Migrate NodeCertificateController Certificate creation to SSA
Replace CreateOrUpdate + SetOwnerReference with Apply for the cert-manager Certificate CR. The owner reference is set in the apply configuration metadata. The retry-on-conflict loop is no longer needed since SSA handles concurrent updates correctly. The controller now applies the full certificate spec on every reconcile so IP/DNS changes are picked up immediately.
1 parent b06e1f0 commit dfdffec

1 file changed

Lines changed: 60 additions & 82 deletions

File tree

internal/controller/node_certificate_controller.go

Lines changed: 60 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ import (
2424
"time"
2525

2626
cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
27-
cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
27+
cmapplyv1 "github.com/cert-manager/cert-manager/pkg/client/applyconfigurations/certmanager/v1"
28+
cmapplymetav1 "github.com/cert-manager/cert-manager/pkg/client/applyconfigurations/meta/v1"
2829
corev1 "k8s.io/api/core/v1"
2930
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3031
"k8s.io/apimachinery/pkg/runtime"
31-
"k8s.io/client-go/util/retry"
32+
k8sacmetav1 "k8s.io/client-go/applyconfigurations/meta/v1"
3233
ctrl "sigs.k8s.io/controller-runtime"
3334
k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
34-
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
3535
logger "sigs.k8s.io/controller-runtime/pkg/log"
3636
"sigs.k8s.io/controller-runtime/pkg/predicate"
3737
)
@@ -59,95 +59,77 @@ func (r *NodeCertificateController) ensureCertificate(ctx context.Context, node
5959

6060
secretName, certName := getSecretAndCertName(node.Name)
6161

62-
certificate := &cmapi.Certificate{
63-
TypeMeta: metav1.TypeMeta{
64-
Kind: cmapi.CertificateKind,
65-
APIVersion: cmapi.SchemeGroupVersion.String(),
66-
},
67-
ObjectMeta: metav1.ObjectMeta{
68-
Name: certName,
69-
Namespace: r.namespace,
70-
},
71-
}
72-
73-
update, err := controllerutil.CreateOrUpdate(ctx, r.Client, certificate, func() error {
74-
if err := controllerutil.SetOwnerReference(node, certificate, r.Scheme); err != nil {
75-
return err
76-
}
77-
78-
ipAddressSet := make(map[string]bool)
79-
dnsNameSet := make(map[string]bool)
80-
81-
dnsNameSet[computeHost] = true
62+
ipAddressSet := make(map[string]bool)
63+
dnsNameSet := make(map[string]bool)
8264

83-
for _, addr := range node.Status.Addresses {
84-
if addr.Address == "" {
85-
continue
86-
}
65+
dnsNameSet[computeHost] = true
8766

88-
switch addr.Type {
89-
case corev1.NodeHostName, corev1.NodeInternalDNS, corev1.NodeExternalDNS:
90-
dnsNameSet[addr.Address] = true
91-
case corev1.NodeInternalIP, corev1.NodeExternalIP:
92-
ipAddressSet[addr.Address] = true
93-
}
67+
for _, addr := range node.Status.Addresses {
68+
if addr.Address == "" {
69+
continue
9470
}
9571

96-
ipAddresses := make([]string, 0, len(ipAddressSet))
97-
for k := range ipAddressSet {
98-
ipAddresses = append(ipAddresses, k)
99-
}
100-
101-
slices.Sort(ipAddresses)
102-
103-
dnsNames := make([]string, 0, len(dnsNameSet))
104-
for k := range dnsNameSet {
105-
dnsNames = append(dnsNames, k)
72+
switch addr.Type {
73+
case corev1.NodeHostName, corev1.NodeInternalDNS, corev1.NodeExternalDNS:
74+
dnsNameSet[addr.Address] = true
75+
case corev1.NodeInternalIP, corev1.NodeExternalIP:
76+
ipAddressSet[addr.Address] = true
10677
}
78+
}
10779

108-
slices.Sort(dnsNames)
80+
ipAddresses := make([]string, 0, len(ipAddressSet))
81+
for k := range ipAddressSet {
82+
ipAddresses = append(ipAddresses, k)
83+
}
84+
slices.Sort(ipAddresses)
10985

110-
certificate.Spec = cmapi.CertificateSpec{
111-
SecretName: secretName,
112-
PrivateKey: &cmapi.CertificatePrivateKey{
113-
Algorithm: cmapi.RSAKeyAlgorithm,
114-
Encoding: cmapi.PKCS1,
115-
Size: 4096,
116-
},
86+
dnsNames := make([]string, 0, len(dnsNameSet))
87+
for k := range dnsNameSet {
88+
dnsNames = append(dnsNames, k)
89+
}
90+
slices.Sort(dnsNames)
91+
92+
ownerRef := k8sacmetav1.OwnerReference().
93+
WithAPIVersion(corev1.SchemeGroupVersion.String()).
94+
WithKind("Node").
95+
WithName(node.Name).
96+
WithUID(node.UID)
97+
98+
certApplyCfg := cmapplyv1.Certificate(certName, r.namespace).
99+
WithOwnerReferences(ownerRef).
100+
WithSpec(cmapplyv1.CertificateSpec().
101+
WithSecretName(secretName).
102+
WithPrivateKey(cmapplyv1.CertificatePrivateKey().
103+
WithAlgorithm(cmapi.RSAKeyAlgorithm).
104+
WithEncoding(cmapi.PKCS1).
105+
WithSize(4096)).
117106
// Matching the CA/Browser Forum's maximum duration for 2029
118-
Duration: &metav1.Duration{Duration: 47 * 24 * time.Hour},
119-
RenewBefore: &metav1.Duration{Duration: 37 * 24 * time.Hour},
120-
IsCA: false,
121-
Usages: []cmapi.KeyUsage{
107+
WithDuration(metav1.Duration{Duration: 47 * 24 * time.Hour}).
108+
WithRenewBefore(metav1.Duration{Duration: 37 * 24 * time.Hour}).
109+
WithIsCA(false).
110+
WithUsages(
122111
cmapi.UsageServerAuth,
123112
cmapi.UsageClientAuth,
124113
cmapi.UsageCertSign, // Really?
125114
cmapi.UsageDigitalSignature,
126115
cmapi.UsageKeyEncipherment,
127-
},
128-
Subject: &cmapi.X509Subject{
129-
Organizations: []string{"nova"},
130-
},
131-
CommonName: computeHost,
132-
DNSNames: dnsNames,
133-
IPAddresses: ipAddresses,
134-
IssuerRef: cmmeta.IssuerReference{
135-
Name: r.issuerName,
136-
Kind: cmapi.IssuerKind,
137-
Group: cmapi.SchemeGroupVersion.Group,
138-
},
139-
}
140-
return nil
141-
})
142-
143-
if err != nil {
116+
).
117+
WithSubject(cmapplyv1.X509Subject().
118+
WithOrganizations("nova")).
119+
WithCommonName(computeHost).
120+
WithDNSNames(dnsNames...).
121+
WithIPAddresses(ipAddresses...).
122+
WithIssuerRef(cmapplymetav1.IssuerReference().
123+
WithName(r.issuerName).
124+
WithKind(cmapi.IssuerKind).
125+
WithGroup(cmapi.SchemeGroupVersion.Group)))
126+
127+
if err := r.Apply(ctx, certApplyCfg,
128+
k8sclient.ForceOwnership, k8sclient.FieldOwner(NodeCertificateControllerName)); err != nil {
144129
return err
145130
}
146131

147-
if update != controllerutil.OperationResultNone {
148-
log.Info(fmt.Sprintf("Certificate %s %s", certName, update))
149-
}
150-
132+
log.Info("Applied Certificate " + certName)
151133
return nil
152134
}
153135

@@ -166,12 +148,8 @@ func (r *NodeCertificateController) Reconcile(ctx context.Context, req ctrl.Requ
166148
return ctrl.Result{}, k8sclient.IgnoreNotFound(err)
167149
}
168150

169-
err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
170-
return r.ensureCertificate(ctx, node, node.Name)
171-
})
172-
173-
if err != nil {
174-
return ctrl.Result{}, fmt.Errorf("could not create certificate: %w", err)
151+
if err := r.ensureCertificate(ctx, node, node.Name); err != nil {
152+
return ctrl.Result{}, fmt.Errorf("could not apply certificate: %w", err)
175153
}
176154

177155
return ctrl.Result{}, nil

0 commit comments

Comments
 (0)