From 4a0c62d6f7b5668b2918f63fe7018e2bc887f964 Mon Sep 17 00:00:00 2001 From: Miciah Masters Date: Sun, 21 Mar 2021 20:56:05 -0400 Subject: [PATCH] operator/dns: Add DNS pod placement API This commit implements NE-546. https://issues.redhat.com/browse/NE-546 * operator/v1/types_dns.go (DNSSpec): Add NodePlacement field with type DNSNodePlacement. (DNSNodePlacement): New type. Specify optional node selector and tolerations for DNS pods. * operator/v1/0000_70_dns-operator_00-custom-resource-definition.yaml: * operator/v1/zz_generated.deepcopy.go: * operator/v1/zz_generated.swagger_doc_generated.go: Regenerate. --- ...perator_00-custom-resource-definition.yaml | 67 +++++++++++++++++++ operator/v1/types_dns.go | 45 +++++++++++++ operator/v1/zz_generated.deepcopy.go | 31 +++++++++ .../v1/zz_generated.swagger_doc_generated.go | 15 ++++- 4 files changed, 156 insertions(+), 2 deletions(-) diff --git a/operator/v1/0000_70_dns-operator_00-custom-resource-definition.yaml b/operator/v1/0000_70_dns-operator_00-custom-resource-definition.yaml index d891ca4ed82..7d50cfe76bc 100644 --- a/operator/v1/0000_70_dns-operator_00-custom-resource-definition.yaml +++ b/operator/v1/0000_70_dns-operator_00-custom-resource-definition.yaml @@ -45,6 +45,73 @@ spec: DNS. type: object properties: + nodePlacement: + description: "nodePlacement provides explicit control over the scheduling + of DNS pods. \n Generally, it is useful to run a DNS pod on every + node so that DNS queries are always handled by a local DNS pod instead + of going over the network to a DNS pod on another node. However, + security policies may require restricting the placement of DNS pods + to specific nodes. For example, if a security policy prohibits pods + on arbitrary nodes from communicating with the API, a node selector + can be specified to restrict DNS pods to nodes that are permitted + to communicate with the API. Conversely, if running DNS pods on + nodes with a particular taint is desired, a toleration can be specified + for that taint. \n If unset, defaults are used. See nodePlacement + for more details." + type: object + properties: + nodeSelector: + description: "nodeSelector is the node selector applied to DNS + pods. \n If empty, the default is used, which is currently the + following: \n beta.kubernetes.io/os: linux \n This default + is subject to change. \n If set, the specified selector is used + and replaces the default." + type: object + additionalProperties: + type: string + tolerations: + description: "tolerations is a list of tolerations applied to + DNS pods. \n The default is an empty list. This default is + subject to change. \n See https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/" + type: array + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching 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 servers: description: "servers is a list of DNS resolvers that provide name query delegation for one or more subdomains outside the scope of diff --git a/operator/v1/types_dns.go b/operator/v1/types_dns.go index 5bc36146852..112907c9b34 100644 --- a/operator/v1/types_dns.go +++ b/operator/v1/types_dns.go @@ -2,6 +2,8 @@ package v1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + corev1 "k8s.io/api/core/v1" ) // +genclient @@ -42,6 +44,24 @@ type DNSSpec struct { // // +optional Servers []Server `json:"servers,omitempty"` + + // nodePlacement provides explicit control over the scheduling of DNS + // pods. + // + // Generally, it is useful to run a DNS pod on every node so that DNS + // queries are always handled by a local DNS pod instead of going over + // the network to a DNS pod on another node. However, security policies + // may require restricting the placement of DNS pods to specific nodes. + // For example, if a security policy prohibits pods on arbitrary nodes + // from communicating with the API, a node selector can be specified to + // restrict DNS pods to nodes that are permitted to communicate with the + // API. Conversely, if running DNS pods on nodes with a particular + // taint is desired, a toleration can be specified for that taint. + // + // If unset, defaults are used. See nodePlacement for more details. + // + // +optional + NodePlacement DNSNodePlacement `json:"nodePlacement,omitempty"` } // Server defines the schema for a server that runs per instance of CoreDNS. @@ -73,6 +93,31 @@ type ForwardPlugin struct { Upstreams []string `json:"upstreams"` } +// DNSNodePlacement describes the node scheduling configuration for DNS pods. +type DNSNodePlacement struct { + // nodeSelector is the node selector applied to DNS pods. + // + // If empty, the default is used, which is currently the following: + // + // beta.kubernetes.io/os: linux + // + // This default is subject to change. + // + // If set, the specified selector is used and replaces the default. + // + // +optional + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + + // tolerations is a list of tolerations applied to DNS pods. + // + // The default is an empty list. This default is subject to change. + // + // See https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + // + // +optional + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` +} + const ( // Available indicates the DNS controller daemonset is available. DNSAvailable = "Available" diff --git a/operator/v1/zz_generated.deepcopy.go b/operator/v1/zz_generated.deepcopy.go index 51fcf672b4c..b2f7224bb7c 100644 --- a/operator/v1/zz_generated.deepcopy.go +++ b/operator/v1/zz_generated.deepcopy.go @@ -841,6 +841,36 @@ func (in *DNSList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DNSNodePlacement) DeepCopyInto(out *DNSNodePlacement) { + *out = *in + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]corev1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSNodePlacement. +func (in *DNSNodePlacement) DeepCopy() *DNSNodePlacement { + if in == nil { + return nil + } + out := new(DNSNodePlacement) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DNSSpec) DeepCopyInto(out *DNSSpec) { *out = *in @@ -851,6 +881,7 @@ func (in *DNSSpec) DeepCopyInto(out *DNSSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + in.NodePlacement.DeepCopyInto(&out.NodePlacement) return } diff --git a/operator/v1/zz_generated.swagger_doc_generated.go b/operator/v1/zz_generated.swagger_doc_generated.go index f2177afae13..f5d1e754349 100644 --- a/operator/v1/zz_generated.swagger_doc_generated.go +++ b/operator/v1/zz_generated.swagger_doc_generated.go @@ -363,9 +363,20 @@ func (DNSList) SwaggerDoc() map[string]string { return map_DNSList } +var map_DNSNodePlacement = map[string]string{ + "": "DNSNodePlacement describes the node scheduling configuration for DNS pods.", + "nodeSelector": "nodeSelector is the node selector applied to DNS pods.\n\nIf empty, the default is used, which is currently the following:\n\n beta.kubernetes.io/os: linux\n\nThis default is subject to change.\n\nIf set, the specified selector is used and replaces the default.", + "tolerations": "tolerations is a list of tolerations applied to DNS pods.\n\nThe default is an empty list. This default is subject to change.\n\nSee https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/", +} + +func (DNSNodePlacement) SwaggerDoc() map[string]string { + return map_DNSNodePlacement +} + var map_DNSSpec = map[string]string{ - "": "DNSSpec is the specification of the desired behavior of the DNS.", - "servers": "servers is a list of DNS resolvers that provide name query delegation for one or more subdomains outside the scope of the cluster domain. If servers consists of more than one Server, longest suffix match will be used to determine the Server.\n\nFor example, if there are two Servers, one for \"foo.com\" and another for \"a.foo.com\", and the name query is for \"www.a.foo.com\", it will be routed to the Server with Zone \"a.foo.com\".\n\nIf this field is nil, no servers are created.", + "": "DNSSpec is the specification of the desired behavior of the DNS.", + "servers": "servers is a list of DNS resolvers that provide name query delegation for one or more subdomains outside the scope of the cluster domain. If servers consists of more than one Server, longest suffix match will be used to determine the Server.\n\nFor example, if there are two Servers, one for \"foo.com\" and another for \"a.foo.com\", and the name query is for \"www.a.foo.com\", it will be routed to the Server with Zone \"a.foo.com\".\n\nIf this field is nil, no servers are created.", + "nodePlacement": "nodePlacement provides explicit control over the scheduling of DNS pods.\n\nGenerally, it is useful to run a DNS pod on every node so that DNS queries are always handled by a local DNS pod instead of going over the network to a DNS pod on another node. However, security policies may require restricting the placement of DNS pods to specific nodes. For example, if a security policy prohibits pods on arbitrary nodes from communicating with the API, a node selector can be specified to restrict DNS pods to nodes that are permitted to communicate with the API. Conversely, if running DNS pods on nodes with a particular taint is desired, a toleration can be specified for that taint.\n\nIf unset, defaults are used. See nodePlacement for more details.", } func (DNSSpec) SwaggerDoc() map[string]string {