Skip to content
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

WIP: Add new external-dns addon for exposing Ingress, LoadBalancer & Istio external IPs to the host #13333

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/minikube/cmd/config/addons_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func TestAddonsList(t *testing.T) {
Ambassador *interface{} `json:"ambassador"`
}

b := make([]byte, 544)
b := make([]byte, 562)
r, w, err := os.Pipe()
if err != nil {
t.Fatalf("failed to create pipe: %v", err)
Expand Down
26 changes: 26 additions & 0 deletions cmd/minikube/cmd/config/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,32 @@ var addonsConfigureCmd = &cobra.Command{

cfg.KubernetesConfig.CustomIngressCert = customCert

if err := config.SaveProfile(profile, cfg); err != nil {
out.ErrT(style.Fatal, "Failed to save config {{.profile}}", out.V{"profile": profile})
}
case "external-dns":
profile := ClusterFlagValue()
_, cfg := mustload.Partial(profile)

cfg.KubernetesConfig.EnableIstioCrds = AskForYesNoConfirmation("\nDo you want to enable support for Istio CRDs (Gateway & VirtualService)?", posResponses, negResponses)

enableCustomDNSZone := AskForYesNoConfirmation("\nDo you want to override the default DNS zone (default zone is 'demo')?", posResponses, negResponses)
if enableCustomDNSZone {
validator := func(s string) bool {
format := regexp.MustCompile(`^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]).)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$`)
return format.MatchString(s)
}

customDNSZone := AskForStaticValidatedValue("-- Enter custom DNS zone (e.g. example.com): ", validator)
if cfg.KubernetesConfig.CustomDNSZone != "" {
overwrite := AskForYesNoConfirmation("A custom DNS zone has already been set. Do you want to overwrite it?", posResponses, negResponses)
if !overwrite {
break
}
}
cfg.KubernetesConfig.CustomDNSZone = customDNSZone
}

if err := config.SaveProfile(profile, cfg); err != nil {
out.ErrT(style.Fatal, "Failed to save config {{.profile}}", out.V{"profile": profile})
}
Expand Down
4 changes: 4 additions & 0 deletions deploy/addons/assets.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ var (
//go:embed efk/*.tmpl
EfkAssets embed.FS

// ExternalDns assets for external-dns addon
//go:embed external-dns/*.tmpl
ExternalDNSAssets embed.FS

// IngressAssets assets for ingress addon
//go:embed ingress/*.tmpl
IngressAssets embed.FS
Expand Down
20 changes: 20 additions & 0 deletions deploy/addons/external-dns/bind-cm.yaml.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: bind-config
namespace: kube-system
labels:
app.kubernetes.io/name: bind
app.kubernetes.io/part-of: kube-system
kubernetes.io/minikube-addons: external-dns
data:
bind.yaml: |
bind:
domain:
forward: {{ .CustomDNSZone | default "demo" }}.
reverse: 1.168.192.in-addr.arpa.
upstream: 8.8.8.8,8.8.4.4
key:
name: externaldns
secret: G8cuP1DtUfwegpYWaDoNbvwVkMU05Na/qYcv4DHnGHs=
algorithm: hmac-sha256
36 changes: 36 additions & 0 deletions deploy/addons/external-dns/bind-dp.yaml.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: bind
namespace: kube-system
labels:
app.kubernetes.io/name: bind
app.kubernetes.io/part-of: kube-system
kubernetes.io/minikube-addons: external-dns
spec:
selector:
matchLabels:
app.kubernetes.io/name: bind
template:
metadata:
labels:
app.kubernetes.io/name: bind
spec:
hostNetwork: true
containers:
- name: bind
image: {{ .CustomRegistries.Bind | default .ImageRepository | default .Registries.Bind }}{{ .Images.Bind }}
ports:
- name: udp-dns
containerPort: 53
protocol: UDP
- name: tcp-dns
containerPort: 53
protocol: TCP
volumeMounts:
- mountPath: /conf
name: bind-config
volumes:
- name: bind-config
configMap:
name: bind-config
22 changes: 22 additions & 0 deletions deploy/addons/external-dns/bind-service.yaml.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
apiVersion: v1
kind: Service
metadata:
name: bind
namespace: kube-system
labels:
app.kubernetes.io/name: bind
app.kubernetes.io/part-of: kube-system
kubernetes.io/minikube-addons: external-dns
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: bind
ports:
- name: udp-dns
port: 53
protocol: UDP
targetPort: 53
- name: tcp-dns
port: 53
protocol: TCP
targetPort: 53
80 changes: 80 additions & 0 deletions deploy/addons/external-dns/example/example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world-app
namespace: default
spec:
selector:
matchLabels:
app: hello-world-app
template:
metadata:
labels:
app: hello-world-app
spec:
containers:
- name: hello-world-app
image: gcr.io/google-samples/hello-app:1.0
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: hello-world-loadbalanced-service
namespace: default
annotations:
external-dns.alpha.kubernetes.io/hostname: hello-world.demo
spec:
selector:
app: hello-world-app
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: hello-world-internal-service
namespace: default
spec:
selector:
app: hello-world-app
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-world-ingress
namespace: default
spec:
ingressClassName: nginx
rules:
- host: hello-john.demo
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: hello-world-internal-service
port:
number: 80
- host: hello-jane.demo
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: hello-world-internal-service
port:
number: 80
41 changes: 41 additions & 0 deletions deploy/addons/external-dns/externaldns-dp.yaml.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
namespace: kube-system
labels:
app.kubernetes.io/name: external-dns
app.kubernetes.io/part-of: kube-system
kubernetes.io/minikube-addons: external-dns
spec:
selector:
matchLabels:
app.kubernetes.io/name: external-dns
template:
metadata:
labels:
app.kubernetes.io/name: external-dns
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: {{ .CustomRegistries.ExternalDNS | default .ImageRepository | default .Registries.ExternalDNS }}{{ .Images.ExternalDNS }}
args:
- --registry=txt
- --txt-prefix=external-dns-
- --txt-owner-id=k8s
- --provider=rfc2136
- --rfc2136-host=bind
- --rfc2136-port=53
- --rfc2136-zone={{ .CustomDNSZone | default "demo" }}
- --rfc2136-tsig-secret=G8cuP1DtUfwegpYWaDoNbvwVkMU05Na/qYcv4DHnGHs=
- --rfc2136-tsig-secret-alg=hmac-sha256
- --rfc2136-tsig-keyname=externaldns
- --rfc2136-tsig-axfr
- --source=ingress
- --source=service
{{- if .EnableIstioCrds }}
- --source=istio-gateway
- --source=istio-virtualservice
{{- end }}
- --domain-filter={{ .CustomDNSZone | default "demo" }}
65 changes: 65 additions & 0 deletions deploy/addons/external-dns/externaldns-rbac.yaml.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
namespace: kube-system
labels:
app.kubernetes.io/name: external-dns
app.kubernetes.io/part-of: kube-system
kubernetes.io/minikube-addons: external-dns
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: external-dns
labels:
app.kubernetes.io/name: external-dns
app.kubernetes.io/part-of: kube-system
kubernetes.io/minikube-addons: external-dns
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- pods
- nodes
verbs:
- get
- watch
- list
- apiGroups:
- extensions
- networking.k8s.io
resources:
- ingresses
verbs:
- get
- watch
- list
- apiGroups:
- networking.istio.io
resources:
- gateways
- virtualservices
verbs:
- get
- watch
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: external-dns-viewer
labels:
app.kubernetes.io/name: external-dns
app.kubernetes.io/part-of: kube-system
kubernetes.io/minikube-addons: external-dns
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: external-dns
subjects:
- kind: ServiceAccount
name: external-dns
namespace: kube-system
5 changes: 5 additions & 0 deletions pkg/addons/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ var Addons = []*Addon{
set: SetBool,
callbacks: []setFn{EnableOrDisableAddon},
},
{
name: "external-dns",
set: SetBool,
callbacks: []setFn{EnableOrDisableAddon},
},
{
name: "freshpod",
set: SetBool,
Expand Down
34 changes: 34 additions & 0 deletions pkg/minikube/assets/addons.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,36 @@ var Addons = map[string]*Addon{
}, map[string]string{
"IngressController": "k8s.gcr.io",
}),
"external-dns": NewAddon([]*BinAsset{
MustBinAsset(addons.ExternalDNSAssets,
"external-dns/bind-cm.yaml.tmpl",
vmpath.GuestAddonsDir,
"bind-cm.yaml",
"0640"),
MustBinAsset(addons.ExternalDNSAssets,
"external-dns/bind-dp.yaml.tmpl",
vmpath.GuestAddonsDir,
"bind-dp.yaml",
"0640"),
MustBinAsset(addons.ExternalDNSAssets,
"external-dns/bind-service.yaml.tmpl",
vmpath.GuestAddonsDir,
"bind-service.yaml",
"0640"),
MustBinAsset(addons.ExternalDNSAssets,
"external-dns/externaldns-dp.yaml.tmpl",
vmpath.GuestAddonsDir,
"externaldns-dp.yaml",
"0640"),
MustBinAsset(addons.ExternalDNSAssets,
"external-dns/externaldns-rbac.yaml.tmpl",
vmpath.GuestAddonsDir,
"externaldns-rbac.yaml",
"0640"),
}, false, "external-dns", "", map[string]string{
"Bind": "drebes/bind:0.5.1@sha256:ea5b1e684969c990d27f7eeab209c4d7cfa4c341a2a10c037b80823909706865",
"ExternalDNS": "k8s.gcr.io/external-dns/external-dns:v0.10.2@sha256:1fe47236861e3046b1d7b64225f60e6267d23b91a3bd24980911d4c97e641d2d",
}, nil),
"istio-provisioner": NewAddon([]*BinAsset{
MustBinAsset(addons.IstioProvisionerAssets,
"istio-provisioner/istio-operator.yaml.tmpl",
Expand Down Expand Up @@ -809,6 +839,8 @@ func GenerateTemplateData(addon *Addon, cfg config.KubernetesConfig, netInfo Net
LoadBalancerStartIP string
LoadBalancerEndIP string
CustomIngressCert string
EnableIstioCrds bool
CustomDNSZone string
IngressAPIVersion string
ContainerRuntime string
Images map[string]string
Expand All @@ -823,6 +855,8 @@ func GenerateTemplateData(addon *Addon, cfg config.KubernetesConfig, netInfo Net
LoadBalancerStartIP: cfg.LoadBalancerStartIP,
LoadBalancerEndIP: cfg.LoadBalancerEndIP,
CustomIngressCert: cfg.CustomIngressCert,
EnableIstioCrds: cfg.EnableIstioCrds,
CustomDNSZone: cfg.CustomDNSZone,
IngressAPIVersion: "v1", // api version for ingress (eg, "v1beta1"; defaults to "v1" for k8s 1.19+)
ContainerRuntime: cfg.ContainerRuntime,
Images: images,
Expand Down
2 changes: 2 additions & 0 deletions pkg/minikube/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ type KubernetesConfig struct {
LoadBalancerStartIP string // currently only used by MetalLB addon
LoadBalancerEndIP string // currently only used by MetalLB addon
CustomIngressCert string // used by Ingress addon
EnableIstioCrds bool // used by external-dns addon
CustomDNSZone string // used by external-dns addon
ExtraOptions ExtraOptionSlice

ShouldLoadCachedImages bool
Expand Down
Loading