cmd/k8s-operator: allow pod tolerations on nameservers (#17260)
This commit modifies the `DNSConfig` custom resource to allow specifying [tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) on the nameserver pods. This will allow users to dictate where their nameserver pods are located within their clusters. Fixes: https://github.com/tailscale/tailscale/issues/17092 Signed-off-by: David Bond <davidsbond93@gmail.com>
This commit is contained in:
@@ -100,6 +100,49 @@ spec:
|
||||
tag:
|
||||
description: Tag defaults to unstable.
|
||||
type: string
|
||||
pod:
|
||||
description: Pod configuration.
|
||||
type: object
|
||||
properties:
|
||||
tolerations:
|
||||
description: If specified, applies tolerations to the pods deployed by the DNSConfig resource.
|
||||
type: array
|
||||
items:
|
||||
description: |-
|
||||
The pod this Toleration is attached to tolerates any taint that matches
|
||||
the triple <key,value,effect> using the matching operator <operator>.
|
||||
type: object
|
||||
properties:
|
||||
effect:
|
||||
description: |-
|
||||
Effect indicates the taint effect to match. Empty means match all taint effects.
|
||||
When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute.
|
||||
type: string
|
||||
key:
|
||||
description: |-
|
||||
Key is the taint key that the toleration applies to. Empty means match all taint keys.
|
||||
If the key is empty, operator must be Exists; this combination means to match all values and all keys.
|
||||
type: string
|
||||
operator:
|
||||
description: |-
|
||||
Operator represents a key's relationship to the value.
|
||||
Valid operators are Exists and Equal. Defaults to Equal.
|
||||
Exists is equivalent to wildcard for value, so that a pod can
|
||||
tolerate all taints of a particular category.
|
||||
type: string
|
||||
tolerationSeconds:
|
||||
description: |-
|
||||
TolerationSeconds represents the period of time the toleration (which must be
|
||||
of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default,
|
||||
it is not set, which means tolerate the taint forever (do not evict). Zero and
|
||||
negative values will be treated as 0 (evict immediately) by the system.
|
||||
type: integer
|
||||
format: int64
|
||||
value:
|
||||
description: |-
|
||||
Value is the taint value the toleration matches to.
|
||||
If the operator is Exists, the value should be empty, otherwise just a regular string.
|
||||
type: string
|
||||
replicas:
|
||||
description: Replicas specifies how many Pods to create. Defaults to 1.
|
||||
type: integer
|
||||
|
||||
@@ -431,6 +431,49 @@ spec:
|
||||
description: Tag defaults to unstable.
|
||||
type: string
|
||||
type: object
|
||||
pod:
|
||||
description: Pod configuration.
|
||||
properties:
|
||||
tolerations:
|
||||
description: If specified, applies tolerations to the pods deployed by the DNSConfig resource.
|
||||
items:
|
||||
description: |-
|
||||
The pod this Toleration is attached to tolerates any taint that matches
|
||||
the triple <key,value,effect> using the matching operator <operator>.
|
||||
properties:
|
||||
effect:
|
||||
description: |-
|
||||
Effect indicates the taint effect to match. Empty means match all taint effects.
|
||||
When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute.
|
||||
type: string
|
||||
key:
|
||||
description: |-
|
||||
Key is the taint key that the toleration applies to. Empty means match all taint keys.
|
||||
If the key is empty, operator must be Exists; this combination means to match all values and all keys.
|
||||
type: string
|
||||
operator:
|
||||
description: |-
|
||||
Operator represents a key's relationship to the value.
|
||||
Valid operators are Exists and Equal. Defaults to Equal.
|
||||
Exists is equivalent to wildcard for value, so that a pod can
|
||||
tolerate all taints of a particular category.
|
||||
type: string
|
||||
tolerationSeconds:
|
||||
description: |-
|
||||
TolerationSeconds represents the period of time the toleration (which must be
|
||||
of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default,
|
||||
it is not set, which means tolerate the taint forever (do not evict). Zero and
|
||||
negative values will be treated as 0 (evict immediately) by the system.
|
||||
format: int64
|
||||
type: integer
|
||||
value:
|
||||
description: |-
|
||||
Value is the taint value the toleration matches to.
|
||||
If the operator is Exists, the value should be empty, otherwise just a regular string.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
replicas:
|
||||
description: Replicas specifies how many Pods to create. Defaults to 1.
|
||||
format: int32
|
||||
|
||||
@@ -191,6 +191,9 @@ func (a *NameserverReconciler) maybeProvision(ctx context.Context, tsDNSCfg *tsa
|
||||
if tsDNSCfg.Spec.Nameserver.Service != nil {
|
||||
dCfg.clusterIP = tsDNSCfg.Spec.Nameserver.Service.ClusterIP
|
||||
}
|
||||
if tsDNSCfg.Spec.Nameserver.Pod != nil {
|
||||
dCfg.tolerations = tsDNSCfg.Spec.Nameserver.Pod.Tolerations
|
||||
}
|
||||
|
||||
for _, deployable := range []deployable{saDeployable, deployDeployable, svcDeployable, cmDeployable} {
|
||||
if err := deployable.updateObj(ctx, dCfg, a.Client); err != nil {
|
||||
@@ -217,13 +220,14 @@ type deployable struct {
|
||||
}
|
||||
|
||||
type deployConfig struct {
|
||||
replicas int32
|
||||
imageRepo string
|
||||
imageTag string
|
||||
labels map[string]string
|
||||
ownerRefs []metav1.OwnerReference
|
||||
namespace string
|
||||
clusterIP string
|
||||
replicas int32
|
||||
imageRepo string
|
||||
imageTag string
|
||||
labels map[string]string
|
||||
ownerRefs []metav1.OwnerReference
|
||||
namespace string
|
||||
clusterIP string
|
||||
tolerations []corev1.Toleration
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -248,6 +252,7 @@ var (
|
||||
d.ObjectMeta.Namespace = cfg.namespace
|
||||
d.ObjectMeta.Labels = cfg.labels
|
||||
d.ObjectMeta.OwnerReferences = cfg.ownerRefs
|
||||
d.Spec.Template.Spec.Tolerations = cfg.tolerations
|
||||
updateF := func(oldD *appsv1.Deployment) {
|
||||
oldD.Spec = d.Spec
|
||||
}
|
||||
|
||||
@@ -42,6 +42,16 @@ func TestNameserverReconciler(t *testing.T) {
|
||||
Service: &tsapi.NameserverService{
|
||||
ClusterIP: "5.4.3.2",
|
||||
},
|
||||
Pod: &tsapi.NameserverPod{
|
||||
Tolerations: []corev1.Toleration{
|
||||
{
|
||||
Key: "some-key",
|
||||
Operator: corev1.TolerationOpEqual,
|
||||
Value: "some-value",
|
||||
Effect: corev1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -79,6 +89,15 @@ func TestNameserverReconciler(t *testing.T) {
|
||||
wantsDeploy.Spec.Replicas = ptr.To[int32](3)
|
||||
wantsDeploy.Namespace = tsNamespace
|
||||
wantsDeploy.ObjectMeta.Labels = nameserverLabels
|
||||
wantsDeploy.Spec.Template.Spec.Tolerations = []corev1.Toleration{
|
||||
{
|
||||
Key: "some-key",
|
||||
Operator: corev1.TolerationOpEqual,
|
||||
Value: "some-value",
|
||||
Effect: corev1.TaintEffectNoSchedule,
|
||||
},
|
||||
}
|
||||
|
||||
expectEqual(t, fc, wantsDeploy)
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user