mirror of
https://github.com/tailscale/tailscale.git
synced 2025-12-23 17:16:29 +00:00
cmd/k8s-operator: add multi replica support for recorders (#17864)
This commit adds the `spec.replicas` field to the `Recorder` custom resource that allows for a highly available deployment of `tsrecorder` within a kubernetes cluster. Many changes were required here as the code hard-coded the assumption of a single replica. This has required a few loops, similar to what we do for the `Connector` resource to create auth and state secrets. It was also required to add a check to remove dangling state and auth secrets should the recorder be scaled down. Updates: https://github.com/tailscale/tailscale/issues/17965 Signed-off-by: David Bond <davidsbond93@gmail.com>
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
|
||||
"tailscale.com/types/ptr"
|
||||
)
|
||||
@@ -23,6 +24,7 @@ func TestRecorderSpecs(t *testing.T) {
|
||||
Name: "test",
|
||||
},
|
||||
Spec: tsapi.RecorderSpec{
|
||||
Replicas: ptr.To[int32](3),
|
||||
StatefulSet: tsapi.RecorderStatefulSet{
|
||||
Labels: map[string]string{
|
||||
"ss-label-key": "ss-label-value",
|
||||
@@ -101,10 +103,10 @@ func TestRecorderSpecs(t *testing.T) {
|
||||
}
|
||||
|
||||
// Pod-level.
|
||||
if diff := cmp.Diff(ss.Labels, labels("recorder", "test", tsr.Spec.StatefulSet.Labels)); diff != "" {
|
||||
if diff := cmp.Diff(ss.Labels, tsrLabels("recorder", "test", tsr.Spec.StatefulSet.Labels)); diff != "" {
|
||||
t.Errorf("(-got +want):\n%s", diff)
|
||||
}
|
||||
if diff := cmp.Diff(ss.Spec.Template.Labels, labels("recorder", "test", tsr.Spec.StatefulSet.Pod.Labels)); diff != "" {
|
||||
if diff := cmp.Diff(ss.Spec.Template.Labels, tsrLabels("recorder", "test", tsr.Spec.StatefulSet.Pod.Labels)); diff != "" {
|
||||
t.Errorf("(-got +want):\n%s", diff)
|
||||
}
|
||||
if diff := cmp.Diff(ss.Spec.Template.Spec.Affinity, tsr.Spec.StatefulSet.Pod.Affinity); diff != "" {
|
||||
@@ -124,7 +126,7 @@ func TestRecorderSpecs(t *testing.T) {
|
||||
}
|
||||
|
||||
// Container-level.
|
||||
if diff := cmp.Diff(ss.Spec.Template.Spec.Containers[0].Env, env(tsr, tsLoginServer)); diff != "" {
|
||||
if diff := cmp.Diff(ss.Spec.Template.Spec.Containers[0].Env, tsrEnv(tsr, tsLoginServer)); diff != "" {
|
||||
t.Errorf("(-got +want):\n%s", diff)
|
||||
}
|
||||
if diff := cmp.Diff(ss.Spec.Template.Spec.Containers[0].Image, tsr.Spec.StatefulSet.Pod.Container.Image); diff != "" {
|
||||
@@ -139,5 +141,17 @@ func TestRecorderSpecs(t *testing.T) {
|
||||
if diff := cmp.Diff(ss.Spec.Template.Spec.Containers[0].Resources, tsr.Spec.StatefulSet.Pod.Container.Resources); diff != "" {
|
||||
t.Errorf("(-got +want):\n%s", diff)
|
||||
}
|
||||
|
||||
if *ss.Spec.Replicas != *tsr.Spec.Replicas {
|
||||
t.Errorf("expected %d replicas, got %d", *tsr.Spec.Replicas, *ss.Spec.Replicas)
|
||||
}
|
||||
|
||||
if len(ss.Spec.Template.Spec.Volumes) != int(*tsr.Spec.Replicas)+1 {
|
||||
t.Errorf("expected %d volumes, got %d", *tsr.Spec.Replicas+1, len(ss.Spec.Template.Spec.Volumes))
|
||||
}
|
||||
|
||||
if len(ss.Spec.Template.Spec.Containers[0].VolumeMounts) != int(*tsr.Spec.Replicas)+1 {
|
||||
t.Errorf("expected %d volume mounts, got %d", *tsr.Spec.Replicas+1, len(ss.Spec.Template.Spec.Containers[0].VolumeMounts))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user