Skip to content

Commit fcf8249

Browse files
committed
Improve KCP etcd client crt/key caching
Signed-off-by: Stefan Büringer [email protected]
1 parent 1477456 commit fcf8249

File tree

4 files changed

+31
-36
lines changed

4 files changed

+31
-36
lines changed

controlplane/kubeadm/internal/cluster.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"go.uber.org/zap"
2828
corev1 "k8s.io/api/core/v1"
2929
apierrors "k8s.io/apimachinery/pkg/api/errors"
30+
"k8s.io/apimachinery/pkg/types"
3031
"k8s.io/client-go/rest"
3132
"sigs.k8s.io/controller-runtime/pkg/client"
3233

@@ -44,7 +45,7 @@ type ManagementCluster interface {
4445

4546
GetMachinesForCluster(ctx context.Context, cluster *clusterv1.Cluster, filters ...collections.Func) (collections.Machines, error)
4647
GetMachinePoolsForCluster(ctx context.Context, cluster *clusterv1.Cluster) (*clusterv1.MachinePoolList, error)
47-
GetWorkloadCluster(ctx context.Context, clusterKey client.ObjectKey, keyEncryptionAlgorithm bootstrapv1.EncryptionAlgorithmType) (WorkloadCluster, error)
48+
GetWorkloadCluster(ctx context.Context, cluster *clusterv1.Cluster, keyEncryptionAlgorithm bootstrapv1.EncryptionAlgorithmType) (WorkloadCluster, error)
4849
}
4950

5051
// Management holds operations on the management cluster.
@@ -61,13 +62,14 @@ type Management struct {
6162
// ClientCertEntry is an Entry for the Cache that stores the client cert.
6263
type ClientCertEntry struct {
6364
Cluster client.ObjectKey
65+
ClusterUID types.UID
6466
ClientCert *tls.Certificate
6567
EncryptionAlgorithm bootstrapv1.EncryptionAlgorithmType
6668
}
6769

6870
// Key returns the cache key of a ClientCertEntry.
6971
func (r ClientCertEntry) Key() string {
70-
return fmt.Sprintf("%s/%s", r.Cluster.String(), r.EncryptionAlgorithm)
72+
return fmt.Sprintf("%s/%s/%s", r.Cluster.String(), r.ClusterUID, r.EncryptionAlgorithm)
7173
}
7274

7375
// RemoteClusterConnectionError represents a failure to connect to a remote cluster.
@@ -113,7 +115,9 @@ func (m *Management) GetMachinePoolsForCluster(ctx context.Context, cluster *clu
113115

114116
// GetWorkloadCluster builds a cluster object.
115117
// The cluster comes with an etcd client generator to connect to any etcd pod living on a managed machine.
116-
func (m *Management) GetWorkloadCluster(ctx context.Context, clusterKey client.ObjectKey, keyEncryptionAlgorithm bootstrapv1.EncryptionAlgorithmType) (WorkloadCluster, error) {
118+
func (m *Management) GetWorkloadCluster(ctx context.Context, cluster *clusterv1.Cluster, keyEncryptionAlgorithm bootstrapv1.EncryptionAlgorithmType) (WorkloadCluster, error) {
119+
clusterKey := client.ObjectKeyFromObject(cluster)
120+
117121
// TODO(chuckha): Inject this dependency.
118122
// TODO(chuckha): memoize this function. The workload client only exists as long as a reconciliation loop.
119123
restConfig, err := m.ClusterCache.GetRESTConfig(ctx, clusterKey)
@@ -142,15 +146,16 @@ func (m *Management) GetWorkloadCluster(ctx context.Context, clusterKey client.O
142146
var clientCert tls.Certificate
143147
if keyData != nil {
144148
// Get client cert from cache if possible, otherwise generate it and add it to the cache.
145-
if entry, ok := m.ClientCertCache.Has(ClientCertEntry{Cluster: clusterKey, EncryptionAlgorithm: keyEncryptionAlgorithm}.Key()); ok {
149+
// Note: The caching assumes that the etcd CA is not rotated during the lifetime of a Cluster.
150+
if entry, ok := m.ClientCertCache.Has(ClientCertEntry{Cluster: clusterKey, ClusterUID: cluster.UID, EncryptionAlgorithm: keyEncryptionAlgorithm}.Key()); ok {
146151
clientCert = *entry.ClientCert
147152
} else {
148153
// The client cert expires after 10 years, but that's okay as the cache has a TTL of 1 day.
149154
clientCert, err = generateClientCert(crtData, keyData, keyEncryptionAlgorithm)
150155
if err != nil {
151156
return nil, err
152157
}
153-
m.ClientCertCache.Add(ClientCertEntry{Cluster: clusterKey, ClientCert: &clientCert, EncryptionAlgorithm: keyEncryptionAlgorithm})
158+
m.ClientCertCache.Add(ClientCertEntry{Cluster: clusterKey, ClusterUID: cluster.UID, ClientCert: &clientCert, EncryptionAlgorithm: keyEncryptionAlgorithm})
154159
}
155160
} else {
156161
clientCert, err = m.getAPIServerEtcdClientCert(ctx, clusterKey)

controlplane/kubeadm/internal/cluster_test.go

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,6 @@ func TestGetWorkloadCluster(t *testing.T) {
161161
secret.KubeconfigDataName: testEnvKubeconfig,
162162
},
163163
}
164-
clusterKey := client.ObjectKey{
165-
Name: "my-cluster",
166-
Namespace: ns.Name,
167-
}
168164

169165
tests := []struct {
170166
name string
@@ -173,40 +169,34 @@ func TestGetWorkloadCluster(t *testing.T) {
173169
expectErr bool
174170
}{
175171
{
176-
name: "returns a workload cluster",
177-
clusterKey: clusterKey,
178-
objs: []client.Object{etcdSecret.DeepCopy(), kubeconfigSecret.DeepCopy()},
179-
expectErr: false,
172+
name: "returns a workload cluster",
173+
objs: []client.Object{etcdSecret.DeepCopy(), kubeconfigSecret.DeepCopy()},
174+
expectErr: false,
180175
},
181176
{
182-
name: "returns error if cannot get rest.Config from kubeconfigSecret",
183-
clusterKey: clusterKey,
184-
objs: []client.Object{etcdSecret.DeepCopy()},
185-
expectErr: true,
177+
name: "returns error if cannot get rest.Config from kubeconfigSecret",
178+
objs: []client.Object{etcdSecret.DeepCopy()},
179+
expectErr: true,
186180
},
187181
{
188-
name: "returns error if unable to find the etcd secret",
189-
clusterKey: clusterKey,
190-
objs: []client.Object{kubeconfigSecret.DeepCopy()},
191-
expectErr: true,
182+
name: "returns error if unable to find the etcd secret",
183+
objs: []client.Object{kubeconfigSecret.DeepCopy()},
184+
expectErr: true,
192185
},
193186
{
194-
name: "returns error if unable to find the certificate in the etcd secret",
195-
clusterKey: clusterKey,
196-
objs: []client.Object{emptyCrtEtcdSecret.DeepCopy(), kubeconfigSecret.DeepCopy()},
197-
expectErr: true,
187+
name: "returns error if unable to find the certificate in the etcd secret",
188+
objs: []client.Object{emptyCrtEtcdSecret.DeepCopy(), kubeconfigSecret.DeepCopy()},
189+
expectErr: true,
198190
},
199191
{
200-
name: "returns error if unable to find the key in the etcd secret",
201-
clusterKey: clusterKey,
202-
objs: []client.Object{emptyKeyEtcdSecret.DeepCopy(), kubeconfigSecret.DeepCopy()},
203-
expectErr: true,
192+
name: "returns error if unable to find the key in the etcd secret",
193+
objs: []client.Object{emptyKeyEtcdSecret.DeepCopy(), kubeconfigSecret.DeepCopy()},
194+
expectErr: true,
204195
},
205196
{
206-
name: "returns error if unable to generate client cert",
207-
clusterKey: clusterKey,
208-
objs: []client.Object{badCrtEtcdSecret.DeepCopy(), kubeconfigSecret.DeepCopy()},
209-
expectErr: true,
197+
name: "returns error if unable to generate client cert",
198+
objs: []client.Object{badCrtEtcdSecret.DeepCopy(), kubeconfigSecret.DeepCopy()},
199+
expectErr: true,
210200
},
211201
}
212202

@@ -250,7 +240,7 @@ func TestGetWorkloadCluster(t *testing.T) {
250240
})
251241
g.Expect(err).ToNot(HaveOccurred())
252242

253-
workloadCluster, err := m.GetWorkloadCluster(ctx, tt.clusterKey, bootstrapv1.EncryptionAlgorithmRSA2048)
243+
workloadCluster, err := m.GetWorkloadCluster(ctx, cluster, bootstrapv1.EncryptionAlgorithmRSA2048)
254244
if tt.expectErr {
255245
g.Expect(err).To(HaveOccurred())
256246
g.Expect(workloadCluster).To(BeNil())

controlplane/kubeadm/internal/control_plane.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ func (c *ControlPlane) GetWorkloadCluster(ctx context.Context) (WorkloadCluster,
394394
return c.workloadCluster, nil
395395
}
396396

397-
workloadCluster, err := c.managementCluster.GetWorkloadCluster(ctx, client.ObjectKeyFromObject(c.Cluster), c.GetKeyEncryptionAlgorithm())
397+
workloadCluster, err := c.managementCluster.GetWorkloadCluster(ctx, c.Cluster, c.GetKeyEncryptionAlgorithm())
398398
if err != nil {
399399
return nil, err
400400
}

controlplane/kubeadm/internal/controllers/fakes_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func (f *fakeManagementCluster) List(ctx context.Context, list client.ObjectList
4949
return f.Reader.List(ctx, list, opts...)
5050
}
5151

52-
func (f *fakeManagementCluster) GetWorkloadCluster(_ context.Context, _ client.ObjectKey, _ bootstrapv1.EncryptionAlgorithmType) (internal.WorkloadCluster, error) {
52+
func (f *fakeManagementCluster) GetWorkloadCluster(_ context.Context, _ *clusterv1.Cluster, _ bootstrapv1.EncryptionAlgorithmType) (internal.WorkloadCluster, error) {
5353
return f.Workload, f.WorkloadErr
5454
}
5555

0 commit comments

Comments
 (0)