mirror of
https://github.com/tailscale/tailscale.git
synced 2025-10-27 11:41:14 +00:00
cmd/k8s-operator: add replica support to nameserver (#17246)
This commit modifies the `DNSConfig` custom resource to allow specifying a replica count when deploying a nameserver. This allows deploying nameservers in a HA configuration. Updates https://github.com/tailscale/corp/issues/32589 Signed-off-by: David Bond <davidsbond93@gmail.com>
This commit is contained in:
@@ -100,6 +100,11 @@ spec:
|
||||
tag:
|
||||
description: Tag defaults to unstable.
|
||||
type: string
|
||||
replicas:
|
||||
description: Replicas specifies how many Pods to create. Defaults to 1.
|
||||
type: integer
|
||||
format: int32
|
||||
minimum: 0
|
||||
service:
|
||||
description: Service configuration.
|
||||
type: object
|
||||
|
||||
@@ -431,6 +431,11 @@ spec:
|
||||
description: Tag defaults to unstable.
|
||||
type: string
|
||||
type: object
|
||||
replicas:
|
||||
description: Replicas specifies how many Pods to create. Defaults to 1.
|
||||
format: int32
|
||||
minimum: 0
|
||||
type: integer
|
||||
service:
|
||||
description: Service configuration.
|
||||
properties:
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
|
||||
"tailscale.com/kube/kubetypes"
|
||||
"tailscale.com/tstime"
|
||||
"tailscale.com/types/ptr"
|
||||
"tailscale.com/util/clientmetric"
|
||||
"tailscale.com/util/set"
|
||||
)
|
||||
@@ -130,7 +131,7 @@ func (a *NameserverReconciler) Reconcile(ctx context.Context, req reconcile.Requ
|
||||
return setStatus(&dnsCfg, metav1.ConditionFalse, reasonNameserverCreationFailed, msg)
|
||||
}
|
||||
}
|
||||
if err := a.maybeProvision(ctx, &dnsCfg, logger); err != nil {
|
||||
if err = a.maybeProvision(ctx, &dnsCfg); err != nil {
|
||||
if strings.Contains(err.Error(), optimisticLockErrorMsg) {
|
||||
logger.Infof("optimistic lock error, retrying: %s", err)
|
||||
return reconcile.Result{}, nil
|
||||
@@ -167,7 +168,7 @@ func nameserverResourceLabels(name, namespace string) map[string]string {
|
||||
return labels
|
||||
}
|
||||
|
||||
func (a *NameserverReconciler) maybeProvision(ctx context.Context, tsDNSCfg *tsapi.DNSConfig, logger *zap.SugaredLogger) error {
|
||||
func (a *NameserverReconciler) maybeProvision(ctx context.Context, tsDNSCfg *tsapi.DNSConfig) error {
|
||||
labels := nameserverResourceLabels(tsDNSCfg.Name, a.tsNamespace)
|
||||
dCfg := &deployConfig{
|
||||
ownerRefs: []metav1.OwnerReference{*metav1.NewControllerRef(tsDNSCfg, tsapi.SchemeGroupVersion.WithKind("DNSConfig"))},
|
||||
@@ -175,6 +176,11 @@ func (a *NameserverReconciler) maybeProvision(ctx context.Context, tsDNSCfg *tsa
|
||||
labels: labels,
|
||||
imageRepo: defaultNameserverImageRepo,
|
||||
imageTag: defaultNameserverImageTag,
|
||||
replicas: 1,
|
||||
}
|
||||
|
||||
if tsDNSCfg.Spec.Nameserver.Replicas != nil {
|
||||
dCfg.replicas = *tsDNSCfg.Spec.Nameserver.Replicas
|
||||
}
|
||||
if tsDNSCfg.Spec.Nameserver.Image != nil && tsDNSCfg.Spec.Nameserver.Image.Repo != "" {
|
||||
dCfg.imageRepo = tsDNSCfg.Spec.Nameserver.Image.Repo
|
||||
@@ -211,6 +217,7 @@ type deployable struct {
|
||||
}
|
||||
|
||||
type deployConfig struct {
|
||||
replicas int32
|
||||
imageRepo string
|
||||
imageTag string
|
||||
labels map[string]string
|
||||
@@ -236,6 +243,7 @@ var (
|
||||
if err := yaml.Unmarshal(deployYaml, &d); err != nil {
|
||||
return fmt.Errorf("error unmarshalling Deployment yaml: %w", err)
|
||||
}
|
||||
d.Spec.Replicas = ptr.To(cfg.replicas)
|
||||
d.Spec.Template.Spec.Containers[0].Image = fmt.Sprintf("%s:%s", cfg.imageRepo, cfg.imageTag)
|
||||
d.ObjectMeta.Namespace = cfg.namespace
|
||||
d.ObjectMeta.Labels = cfg.labels
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
operatorutils "tailscale.com/k8s-operator"
|
||||
tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
|
||||
"tailscale.com/tstest"
|
||||
"tailscale.com/types/ptr"
|
||||
"tailscale.com/util/mak"
|
||||
)
|
||||
|
||||
@@ -33,6 +34,7 @@ func TestNameserverReconciler(t *testing.T) {
|
||||
},
|
||||
Spec: tsapi.DNSConfigSpec{
|
||||
Nameserver: &tsapi.Nameserver{
|
||||
Replicas: ptr.To[int32](3),
|
||||
Image: &tsapi.NameserverImage{
|
||||
Repo: "test",
|
||||
Tag: "v0.0.1",
|
||||
@@ -74,6 +76,7 @@ func TestNameserverReconciler(t *testing.T) {
|
||||
}
|
||||
wantsDeploy.OwnerReferences = []metav1.OwnerReference{*ownerReference}
|
||||
wantsDeploy.Spec.Template.Spec.Containers[0].Image = "test:v0.0.1"
|
||||
wantsDeploy.Spec.Replicas = ptr.To[int32](3)
|
||||
wantsDeploy.Namespace = tsNamespace
|
||||
wantsDeploy.ObjectMeta.Labels = nameserverLabels
|
||||
expectEqual(t, fc, wantsDeploy)
|
||||
|
||||
@@ -443,6 +443,7 @@ _Appears in:_
|
||||
| --- | --- | --- | --- |
|
||||
| `image` _[NameserverImage](#nameserverimage)_ | Nameserver image. Defaults to tailscale/k8s-nameserver:unstable. | | |
|
||||
| `service` _[NameserverService](#nameserverservice)_ | Service configuration. | | |
|
||||
| `replicas` _integer_ | Replicas specifies how many Pods to create. Defaults to 1. | | Minimum: 0 <br /> |
|
||||
|
||||
|
||||
#### NameserverImage
|
||||
|
||||
@@ -84,6 +84,10 @@ type Nameserver struct {
|
||||
// Service configuration.
|
||||
// +optional
|
||||
Service *NameserverService `json:"service,omitempty"`
|
||||
// Replicas specifies how many Pods to create. Defaults to 1.
|
||||
// +optional
|
||||
// +kubebuilder:validation:Minimum=0
|
||||
Replicas *int32 `json:"replicas,omitempty"`
|
||||
}
|
||||
|
||||
type NameserverImage struct {
|
||||
|
||||
@@ -422,6 +422,11 @@ func (in *Nameserver) DeepCopyInto(out *Nameserver) {
|
||||
*out = new(NameserverService)
|
||||
**out = **in
|
||||
}
|
||||
if in.Replicas != nil {
|
||||
in, out := &in.Replicas, &out.Replicas
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Nameserver.
|
||||
|
||||
Reference in New Issue
Block a user