-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
deploy our custom coredns addon #17008
Draft
prezha
wants to merge
11
commits into
kubernetes:master
Choose a base branch
from
prezha:custom-coredns-addon
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
3a8c3f4
deploy our custom coredns addon
prezha b6fce45
cleanup
prezha 8de8137
cleanup
prezha d613285
Merge branch 'kubernetes:master' into custom-coredns-addon
prezha 6f75438
Merge branch 'master' into custom-coredns-addon
prezha 7e8d02b
fix lint complaints
prezha 00a8d76
Merge branch 'kubernetes:master' into custom-coredns-addon
prezha 0da966c
deploy coredns as daemonset
prezha d73a057
Merge branch 'kubernetes:master' into custom-coredns-addon
prezha aca19dc
Merge branch 'kubernetes:master' into custom-coredns-addon
prezha 678c879
Merge branch 'kubernetes:master' into custom-coredns-addon
prezha File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,347 @@ | ||
/* | ||
Copyright 2023 The Kubernetes Authors All rights reserved. | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
// minikube-specific CoreDNS manifests based on the default kubeadm's embedded ones | ||
// ref: https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/phases/addons/dns/manifests.go | ||
|
||
package dns | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"fmt" | ||
"html/template" | ||
"os/exec" | ||
"path" | ||
"strings" | ||
"time" | ||
|
||
"github.com/blang/semver/v4" | ||
"k8s.io/klog/v2" | ||
"k8s.io/minikube/pkg/kapi" | ||
"k8s.io/minikube/pkg/minikube/assets" | ||
"k8s.io/minikube/pkg/minikube/bootstrapper/images" | ||
"k8s.io/minikube/pkg/minikube/command" | ||
"k8s.io/minikube/pkg/minikube/config" | ||
"k8s.io/minikube/pkg/minikube/vmpath" | ||
"k8s.io/minikube/pkg/util" | ||
kconst "k8s.io/minikube/third_party/kubeadm/app/constants" | ||
) | ||
|
||
const ( | ||
// CoreDNSService is the CoreDNS Service manifest | ||
CoreDNSService = ` | ||
apiVersion: v1 | ||
kind: Service | ||
metadata: | ||
labels: | ||
k8s-app: kube-dns | ||
kubernetes.io/cluster-service: "true" | ||
kubernetes.io/name: "CoreDNS" | ||
name: kube-dns | ||
namespace: kube-system | ||
annotations: | ||
prometheus.io/port: "9153" | ||
prometheus.io/scrape: "true" | ||
# Without this resourceVersion value, an update of the Service between versions will yield: | ||
# Service "kube-dns" is invalid: metadata.resourceVersion: Invalid value: "": must be specified for an update | ||
resourceVersion: "0" | ||
spec: | ||
clusterIP: {{ .DNSIP }} | ||
ports: | ||
- name: dns | ||
port: 53 | ||
protocol: UDP | ||
targetPort: 53 | ||
- name: dns-tcp | ||
port: 53 | ||
protocol: TCP | ||
targetPort: 53 | ||
- name: metrics | ||
port: 9153 | ||
protocol: TCP | ||
targetPort: 9153 | ||
selector: | ||
k8s-app: kube-dns | ||
` | ||
|
||
// CoreDNSDeployment is the CoreDNS Deployment manifest | ||
CoreDNSDeployment = ` | ||
apiVersion: apps/v1 | ||
kind: DaemonSet | ||
metadata: | ||
name: {{ .DeploymentName }} | ||
namespace: kube-system | ||
labels: | ||
k8s-app: kube-dns | ||
spec: | ||
selector: | ||
matchLabels: | ||
k8s-app: kube-dns | ||
template: | ||
metadata: | ||
labels: | ||
k8s-app: kube-dns | ||
spec: | ||
priorityClassName: system-cluster-critical | ||
serviceAccountName: coredns | ||
affinity: | ||
# nodeAffinity is used instead of podAntiAffinity to have the daemonset runnable only on control plane nodes | ||
nodeAffinity: | ||
requiredDuringSchedulingIgnoredDuringExecution: | ||
nodeSelectorTerms: | ||
- matchExpressions: | ||
- key: {{ .ControlPlaneTaintKey }} | ||
operator: Exists | ||
tolerations: | ||
- key: CriticalAddonsOnly | ||
operator: Exists | ||
- key: {{ .ControlPlaneTaintKey }} | ||
effect: NoSchedule | ||
nodeSelector: | ||
kubernetes.io/os: linux | ||
containers: | ||
- name: coredns | ||
image: {{ .Image }} | ||
imagePullPolicy: IfNotPresent | ||
resources: | ||
limits: | ||
memory: 170Mi | ||
requests: | ||
cpu: 100m | ||
memory: 70Mi | ||
args: [ "-conf", "/etc/coredns/Corefile" ] | ||
volumeMounts: | ||
- name: config-volume | ||
mountPath: /etc/coredns | ||
readOnly: true | ||
ports: | ||
- containerPort: 53 | ||
name: dns | ||
protocol: UDP | ||
- containerPort: 53 | ||
name: dns-tcp | ||
protocol: TCP | ||
- containerPort: 9153 | ||
name: metrics | ||
protocol: TCP | ||
livenessProbe: | ||
httpGet: | ||
path: /health | ||
port: 8080 | ||
scheme: HTTP | ||
initialDelaySeconds: 60 | ||
timeoutSeconds: 5 | ||
successThreshold: 1 | ||
failureThreshold: 5 | ||
readinessProbe: | ||
httpGet: | ||
path: /ready | ||
port: 8181 | ||
scheme: HTTP | ||
securityContext: | ||
allowPrivilegeEscalation: false | ||
capabilities: | ||
add: | ||
- NET_BIND_SERVICE | ||
drop: | ||
- ALL | ||
readOnlyRootFilesystem: true | ||
dnsPolicy: Default | ||
volumes: | ||
- name: config-volume | ||
configMap: | ||
name: coredns | ||
items: | ||
- key: Corefile | ||
path: Corefile | ||
` | ||
|
||
// CoreDNSConfigMap is the CoreDNS ConfigMap manifest | ||
CoreDNSConfigMap = ` | ||
apiVersion: v1 | ||
kind: ConfigMap | ||
metadata: | ||
name: coredns | ||
namespace: kube-system | ||
data: | ||
Corefile: | | ||
.:53 { | ||
log | ||
errors | ||
health { | ||
lameduck 5s | ||
} | ||
ready | ||
kubernetes {{ .DNSDomain }} in-addr.arpa ip6.arpa { | ||
pods insecure | ||
fallthrough in-addr.arpa ip6.arpa | ||
ttl 30 | ||
} | ||
prometheus :9153 | ||
hosts { | ||
{{ .MinikubeHostIP }} {{ .MinikubeHostFQDN }} | ||
fallthrough | ||
} | ||
forward . /etc/resolv.conf { | ||
max_concurrent 1000 | ||
} | ||
cache 30 | ||
loop | ||
reload | ||
loadbalance | ||
} | ||
` | ||
// CoreDNSClusterRole is the CoreDNS ClusterRole manifest | ||
CoreDNSClusterRole = ` | ||
apiVersion: rbac.authorization.k8s.io/v1 | ||
kind: ClusterRole | ||
metadata: | ||
name: system:coredns | ||
rules: | ||
- apiGroups: | ||
- "" | ||
resources: | ||
- endpoints | ||
- services | ||
- pods | ||
- namespaces | ||
verbs: | ||
- list | ||
- watch | ||
- apiGroups: | ||
- discovery.k8s.io | ||
resources: | ||
- endpointslices | ||
verbs: | ||
- list | ||
- watch | ||
` | ||
// CoreDNSClusterRoleBinding is the CoreDNS Clusterrolebinding manifest | ||
CoreDNSClusterRoleBinding = ` | ||
apiVersion: rbac.authorization.k8s.io/v1 | ||
kind: ClusterRoleBinding | ||
metadata: | ||
name: system:coredns | ||
roleRef: | ||
apiGroup: rbac.authorization.k8s.io | ||
kind: ClusterRole | ||
name: system:coredns | ||
subjects: | ||
- kind: ServiceAccount | ||
name: coredns | ||
namespace: kube-system | ||
` | ||
// CoreDNSServiceAccount is the CoreDNS ServiceAccount manifest | ||
CoreDNSServiceAccount = ` | ||
apiVersion: v1 | ||
kind: ServiceAccount | ||
metadata: | ||
name: coredns | ||
namespace: kube-system | ||
` | ||
) | ||
|
||
// DeployCoreDNS deploys custom CoreDNS addon manifests | ||
func DeployCoreDNS(cc config.ClusterConfig, r command.Runner, hostIP, hostFQDN string) error { | ||
manifests, err := coreDNSManifests(cc, hostIP, hostFQDN) | ||
if err != nil { | ||
return fmt.Errorf("coredns manifests: %v", err) | ||
} | ||
klog.Infof("coredns manifests:\n%s\n", manifests) | ||
|
||
// copy over manifests file | ||
manifestPath := path.Join(vmpath.GuestAddonsDir, "coredns.yaml") | ||
m := assets.NewMemoryAssetTarget(manifests, manifestPath, "0640") | ||
if err := r.Copy(m); err != nil { | ||
return fmt.Errorf("coredns asset copy: %v", err) | ||
} | ||
|
||
// apply manifests file | ||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) | ||
defer cancel() | ||
kubectl := kapi.KubectlBinaryPath(cc.KubernetesConfig.KubernetesVersion) | ||
klog.Infof("applying CoreDNS manifests using %s ...", kubectl) | ||
cmd := exec.CommandContext(ctx, "sudo", kubectl, "apply", fmt.Sprintf("--kubeconfig=%s", path.Join(vmpath.GuestPersistentDir, "kubeconfig")), "-f", manifestPath) | ||
if rr, err := r.RunCmd(cmd); err != nil { | ||
return fmt.Errorf("coredns apply cmd: %q output: %q error: %v", rr.Command(), rr.Output(), err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// coreDNSManifests generates custom CoreDNS addon manifests | ||
func coreDNSManifests(cc config.ClusterConfig, hostIP, hostFQDN string) ([]byte, error) { | ||
toml := CoreDNSServiceAccount + "---" + | ||
CoreDNSClusterRole + "---" + | ||
CoreDNSClusterRoleBinding + "---" + | ||
CoreDNSConfigMap + "---" + | ||
CoreDNSDeployment + "---" + | ||
CoreDNSService | ||
|
||
dnsip, err := kconst.GetDNSIP(cc.KubernetesConfig.ServiceCIDR, true) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
image := "" | ||
imgs, err := images.Kubeadm(cc.KubernetesConfig.ImageRepository, cc.KubernetesConfig.KubernetesVersion) | ||
if err != nil { | ||
return nil, fmt.Errorf("kubeadm images: %v", err) | ||
} | ||
for _, img := range imgs { | ||
if strings.Contains(img, kconst.CoreDNSImageName) { | ||
image = img | ||
break | ||
} | ||
} | ||
if image == "" { | ||
return nil, fmt.Errorf("coredns image not found") | ||
} | ||
|
||
params := struct { | ||
DNSDomain, MinikubeHostIP, MinikubeHostFQDN string | ||
DeploymentName, ControlPlaneTaintKey, Image string | ||
DNSIP string | ||
}{ | ||
DNSDomain: cc.KubernetesConfig.DNSDomain, | ||
MinikubeHostIP: hostIP, | ||
MinikubeHostFQDN: hostFQDN, | ||
DeploymentName: kconst.CoreDNSDeploymentName, | ||
ControlPlaneTaintKey: kconst.LabelNodeRoleControlPlane, | ||
Image: image, | ||
DNSIP: dnsip.String(), | ||
} | ||
|
||
// in k8s v1.20 "node-role.kubernetes.io/control-plane" label was introduced and "node-role.kubernetes.io/master" was deprecated | ||
// ref: https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.20.md#no-really-you-must-read-this-before-you-upgrade | ||
k8sVersion, err := util.ParseKubernetesVersion(cc.KubernetesConfig.KubernetesVersion) | ||
if err != nil { | ||
return nil, fmt.Errorf("parsing Kubernetes version %q: %v", cc.KubernetesConfig.KubernetesVersion, err) | ||
} | ||
|
||
if k8sVersion.LT(semver.Version{Major: 1, Minor: 20}) { | ||
params.ControlPlaneTaintKey = kconst.LabelNodeRoleOldControlPlane | ||
} | ||
|
||
t := template.Must(template.New("coredns").Parse(toml)) | ||
var manifests bytes.Buffer | ||
if err = t.Execute(&manifests, params); err != nil { | ||
return nil, fmt.Errorf("executing CoreDNS template: %v", err) | ||
} | ||
|
||
return manifests.Bytes(), nil | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@prezha one problem I feel like might happen, how do we generate this yaml file and with future kubernetes versions is it gonna change this yaml and we will need to remember to regenrate it ? is there an automated way of generating this to future proof it ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and also if user chooses an older kubernetes we wanna make sure this yaml works there too or we could use the Old way for Non-Default Kubernets version (the latest that runs by default)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@medyagh i thought about and accounted for that:
based on the history of changes, in the past 2+ years, there were no frequent or significant changes to the kubeadm's embedded coredns deployment manifest, which is well over our target extended support policy of last 6 minor versions
based on this, we do not have an automated way to update coredns manifest atm, but i intentionally made it in diff-friendly format so it would be straight-forward finding any differences and upgrade if/when needed in the future - namely:
this would be the default behaviour, and should a user want/need to use the old way - they can do so just by using the
--disable-optimizations
flaglast but not least, as a potential next step, with this "separation", we could relatively easily enable users to provide their own coredns manifest (we'd still need eg, to patch it to inject ip address of host.minikube.internal that's only known during the runtime)