mirror of
https://github.com/tailscale/tailscale.git
synced 2025-12-16 06:41:32 +01: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:
parent
a32102f741
commit
e466488a2a
@ -100,6 +100,11 @@ spec:
|
|||||||
tag:
|
tag:
|
||||||
description: Tag defaults to unstable.
|
description: Tag defaults to unstable.
|
||||||
type: string
|
type: string
|
||||||
|
replicas:
|
||||||
|
description: Replicas specifies how many Pods to create. Defaults to 1.
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
minimum: 0
|
||||||
service:
|
service:
|
||||||
description: Service configuration.
|
description: Service configuration.
|
||||||
type: object
|
type: object
|
||||||
|
|||||||
@ -431,6 +431,11 @@ spec:
|
|||||||
description: Tag defaults to unstable.
|
description: Tag defaults to unstable.
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
replicas:
|
||||||
|
description: Replicas specifies how many Pods to create. Defaults to 1.
|
||||||
|
format: int32
|
||||||
|
minimum: 0
|
||||||
|
type: integer
|
||||||
service:
|
service:
|
||||||
description: Service configuration.
|
description: Service configuration.
|
||||||
properties:
|
properties:
|
||||||
|
|||||||
@ -30,6 +30,7 @@ import (
|
|||||||
tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
|
tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
|
||||||
"tailscale.com/kube/kubetypes"
|
"tailscale.com/kube/kubetypes"
|
||||||
"tailscale.com/tstime"
|
"tailscale.com/tstime"
|
||||||
|
"tailscale.com/types/ptr"
|
||||||
"tailscale.com/util/clientmetric"
|
"tailscale.com/util/clientmetric"
|
||||||
"tailscale.com/util/set"
|
"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)
|
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) {
|
if strings.Contains(err.Error(), optimisticLockErrorMsg) {
|
||||||
logger.Infof("optimistic lock error, retrying: %s", err)
|
logger.Infof("optimistic lock error, retrying: %s", err)
|
||||||
return reconcile.Result{}, nil
|
return reconcile.Result{}, nil
|
||||||
@ -167,7 +168,7 @@ func nameserverResourceLabels(name, namespace string) map[string]string {
|
|||||||
return labels
|
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)
|
labels := nameserverResourceLabels(tsDNSCfg.Name, a.tsNamespace)
|
||||||
dCfg := &deployConfig{
|
dCfg := &deployConfig{
|
||||||
ownerRefs: []metav1.OwnerReference{*metav1.NewControllerRef(tsDNSCfg, tsapi.SchemeGroupVersion.WithKind("DNSConfig"))},
|
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,
|
labels: labels,
|
||||||
imageRepo: defaultNameserverImageRepo,
|
imageRepo: defaultNameserverImageRepo,
|
||||||
imageTag: defaultNameserverImageTag,
|
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 != "" {
|
if tsDNSCfg.Spec.Nameserver.Image != nil && tsDNSCfg.Spec.Nameserver.Image.Repo != "" {
|
||||||
dCfg.imageRepo = tsDNSCfg.Spec.Nameserver.Image.Repo
|
dCfg.imageRepo = tsDNSCfg.Spec.Nameserver.Image.Repo
|
||||||
@ -211,6 +217,7 @@ type deployable struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type deployConfig struct {
|
type deployConfig struct {
|
||||||
|
replicas int32
|
||||||
imageRepo string
|
imageRepo string
|
||||||
imageTag string
|
imageTag string
|
||||||
labels map[string]string
|
labels map[string]string
|
||||||
@ -236,6 +243,7 @@ var (
|
|||||||
if err := yaml.Unmarshal(deployYaml, &d); err != nil {
|
if err := yaml.Unmarshal(deployYaml, &d); err != nil {
|
||||||
return fmt.Errorf("error unmarshalling Deployment yaml: %w", err)
|
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.Spec.Template.Spec.Containers[0].Image = fmt.Sprintf("%s:%s", cfg.imageRepo, cfg.imageTag)
|
||||||
d.ObjectMeta.Namespace = cfg.namespace
|
d.ObjectMeta.Namespace = cfg.namespace
|
||||||
d.ObjectMeta.Labels = cfg.labels
|
d.ObjectMeta.Labels = cfg.labels
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import (
|
|||||||
operatorutils "tailscale.com/k8s-operator"
|
operatorutils "tailscale.com/k8s-operator"
|
||||||
tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
|
tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
|
||||||
"tailscale.com/tstest"
|
"tailscale.com/tstest"
|
||||||
|
"tailscale.com/types/ptr"
|
||||||
"tailscale.com/util/mak"
|
"tailscale.com/util/mak"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,6 +34,7 @@ func TestNameserverReconciler(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Spec: tsapi.DNSConfigSpec{
|
Spec: tsapi.DNSConfigSpec{
|
||||||
Nameserver: &tsapi.Nameserver{
|
Nameserver: &tsapi.Nameserver{
|
||||||
|
Replicas: ptr.To[int32](3),
|
||||||
Image: &tsapi.NameserverImage{
|
Image: &tsapi.NameserverImage{
|
||||||
Repo: "test",
|
Repo: "test",
|
||||||
Tag: "v0.0.1",
|
Tag: "v0.0.1",
|
||||||
@ -74,6 +76,7 @@ func TestNameserverReconciler(t *testing.T) {
|
|||||||
}
|
}
|
||||||
wantsDeploy.OwnerReferences = []metav1.OwnerReference{*ownerReference}
|
wantsDeploy.OwnerReferences = []metav1.OwnerReference{*ownerReference}
|
||||||
wantsDeploy.Spec.Template.Spec.Containers[0].Image = "test:v0.0.1"
|
wantsDeploy.Spec.Template.Spec.Containers[0].Image = "test:v0.0.1"
|
||||||
|
wantsDeploy.Spec.Replicas = ptr.To[int32](3)
|
||||||
wantsDeploy.Namespace = tsNamespace
|
wantsDeploy.Namespace = tsNamespace
|
||||||
wantsDeploy.ObjectMeta.Labels = nameserverLabels
|
wantsDeploy.ObjectMeta.Labels = nameserverLabels
|
||||||
expectEqual(t, fc, wantsDeploy)
|
expectEqual(t, fc, wantsDeploy)
|
||||||
|
|||||||
@ -443,6 +443,7 @@ _Appears in:_
|
|||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| `image` _[NameserverImage](#nameserverimage)_ | Nameserver image. Defaults to tailscale/k8s-nameserver:unstable. | | |
|
| `image` _[NameserverImage](#nameserverimage)_ | Nameserver image. Defaults to tailscale/k8s-nameserver:unstable. | | |
|
||||||
| `service` _[NameserverService](#nameserverservice)_ | Service configuration. | | |
|
| `service` _[NameserverService](#nameserverservice)_ | Service configuration. | | |
|
||||||
|
| `replicas` _integer_ | Replicas specifies how many Pods to create. Defaults to 1. | | Minimum: 0 <br /> |
|
||||||
|
|
||||||
|
|
||||||
#### NameserverImage
|
#### NameserverImage
|
||||||
|
|||||||
@ -84,6 +84,10 @@ type Nameserver struct {
|
|||||||
// Service configuration.
|
// Service configuration.
|
||||||
// +optional
|
// +optional
|
||||||
Service *NameserverService `json:"service,omitempty"`
|
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 {
|
type NameserverImage struct {
|
||||||
|
|||||||
@ -422,6 +422,11 @@ func (in *Nameserver) DeepCopyInto(out *Nameserver) {
|
|||||||
*out = new(NameserverService)
|
*out = new(NameserverService)
|
||||||
**out = **in
|
**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.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Nameserver.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user