1
16
17 package network
18
19 import (
20 "context"
21 "fmt"
22 "time"
23
24 v1 "k8s.io/api/core/v1"
25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26 "k8s.io/kubernetes/test/e2e/framework"
27 e2eservice "k8s.io/kubernetes/test/e2e/framework/service"
28 "k8s.io/kubernetes/test/e2e/network/common"
29
30 "github.com/onsi/ginkgo/v2"
31 )
32
33 var (
34 googleDNSHostname = "dns.google"
35
36
37 moreForeverTestTimeout = 2 * 60 * time.Second
38 )
39
40 type dnsNameserverTest struct {
41 dnsTestCommon
42 }
43
44 func (t *dnsNameserverTest) run(ctx context.Context, isIPv6 bool) {
45 t.init(ctx)
46
47 t.createUtilPodLabel(ctx, "e2e-dns-configmap")
48 ginkgo.DeferCleanup(t.deleteUtilPod)
49 originalConfigMapData := t.fetchDNSConfigMapData(ctx)
50 ginkgo.DeferCleanup(t.restoreDNSConfigMap, originalConfigMapData)
51
52 if isIPv6 {
53 t.createDNSServer(ctx, t.f.Namespace.Name, map[string]string{
54 "abc.acme.local": "2606:4700:4700::1111",
55 "def.acme.local": "2606:4700:4700::2222",
56 "widget.local": "2606:4700:4700::3333",
57 })
58 } else {
59 t.createDNSServer(ctx, t.f.Namespace.Name, map[string]string{
60 "abc.acme.local": "1.1.1.1",
61 "def.acme.local": "2.2.2.2",
62 "widget.local": "3.3.3.3",
63 })
64 }
65 ginkgo.DeferCleanup(t.deleteDNSServerPod)
66
67 if t.name == "coredns" {
68 t.setConfigMap(ctx, &v1.ConfigMap{Data: map[string]string{
69 "Corefile": fmt.Sprintf(`.:53 {
70 health
71 ready
72 kubernetes %v in-addr.arpa ip6.arpa {
73 pods insecure
74 fallthrough in-addr.arpa ip6.arpa
75 ttl 30
76 }
77 forward . %v
78 }
79 acme.local:53 {
80 forward . %v
81 }`, framework.TestContext.ClusterDNSDomain, t.dnsServerPod.Status.PodIP, t.dnsServerPod.Status.PodIP),
82 }})
83
84 t.deleteCoreDNSPods(ctx)
85 } else {
86 t.setConfigMap(ctx, &v1.ConfigMap{Data: map[string]string{
87 "stubDomains": fmt.Sprintf(`{"acme.local":["%v"]}`, t.dnsServerPod.Status.PodIP),
88 "upstreamNameservers": fmt.Sprintf(`["%v"]`, t.dnsServerPod.Status.PodIP),
89 }})
90 }
91
92 if isIPv6 {
93 t.checkDNSRecordFrom(
94 "abc.acme.local",
95 func(actual []string) bool { return len(actual) == 1 && actual[0] == "2606:4700:4700::1111" },
96 "cluster-dns-ipv6",
97 moreForeverTestTimeout)
98 t.checkDNSRecordFrom(
99 "def.acme.local",
100 func(actual []string) bool { return len(actual) == 1 && actual[0] == "2606:4700:4700::2222" },
101 "cluster-dns-ipv6",
102 moreForeverTestTimeout)
103 t.checkDNSRecordFrom(
104 "widget.local",
105 func(actual []string) bool { return len(actual) == 1 && actual[0] == "2606:4700:4700::3333" },
106 "cluster-dns-ipv6",
107 moreForeverTestTimeout)
108 } else {
109 t.checkDNSRecordFrom(
110 "abc.acme.local",
111 func(actual []string) bool { return len(actual) == 1 && actual[0] == "1.1.1.1" },
112 "cluster-dns",
113 moreForeverTestTimeout)
114 t.checkDNSRecordFrom(
115 "def.acme.local",
116 func(actual []string) bool { return len(actual) == 1 && actual[0] == "2.2.2.2" },
117 "cluster-dns",
118 moreForeverTestTimeout)
119 t.checkDNSRecordFrom(
120 "widget.local",
121 func(actual []string) bool { return len(actual) == 1 && actual[0] == "3.3.3.3" },
122 "cluster-dns",
123 moreForeverTestTimeout)
124 }
125
126 t.restoreDNSConfigMap(ctx, originalConfigMapData)
127
128
129 t.checkDNSRecordFrom(
130 "abc.acme.local",
131 func(actual []string) bool { return len(actual) == 0 },
132 "cluster-dns",
133 moreForeverTestTimeout)
134 }
135
136 type dnsPtrFwdTest struct {
137 dnsTestCommon
138 }
139
140 func (t *dnsPtrFwdTest) run(ctx context.Context, isIPv6 bool) {
141 t.init(ctx)
142
143 t.createUtilPodLabel(ctx, "e2e-dns-configmap")
144 ginkgo.DeferCleanup(t.deleteUtilPod)
145 originalConfigMapData := t.fetchDNSConfigMapData(ctx)
146 ginkgo.DeferCleanup(t.restoreDNSConfigMap, originalConfigMapData)
147
148 t.createDNSServerWithPtrRecord(ctx, t.f.Namespace.Name, isIPv6)
149 ginkgo.DeferCleanup(t.deleteDNSServerPod)
150
151
152 if isIPv6 {
153 t.checkDNSRecordFrom(
154 "2001:4860:4860::8888",
155 func(actual []string) bool { return len(actual) == 1 && actual[0] == googleDNSHostname+"." },
156 "ptr-record",
157 moreForeverTestTimeout)
158 } else {
159 t.checkDNSRecordFrom(
160 "8.8.8.8",
161 func(actual []string) bool { return len(actual) == 1 && actual[0] == googleDNSHostname+"." },
162 "ptr-record",
163 moreForeverTestTimeout)
164 }
165
166 if t.name == "coredns" {
167 t.setConfigMap(ctx, &v1.ConfigMap{Data: map[string]string{
168 "Corefile": fmt.Sprintf(`.:53 {
169 health
170 ready
171 kubernetes %v in-addr.arpa ip6.arpa {
172 pods insecure
173 fallthrough in-addr.arpa ip6.arpa
174 ttl 30
175 }
176 forward . %v
177 }`, framework.TestContext.ClusterDNSDomain, t.dnsServerPod.Status.PodIP),
178 }})
179
180 t.deleteCoreDNSPods(ctx)
181 } else {
182 t.setConfigMap(ctx, &v1.ConfigMap{Data: map[string]string{
183 "upstreamNameservers": fmt.Sprintf(`["%v"]`, t.dnsServerPod.Status.PodIP),
184 }})
185 }
186
187 if isIPv6 {
188 t.checkDNSRecordFrom(
189 "2001:db8::29",
190 func(actual []string) bool { return len(actual) == 1 && actual[0] == "my.test." },
191 "ptr-record",
192 moreForeverTestTimeout)
193
194 t.restoreDNSConfigMap(ctx, originalConfigMapData)
195 t.checkDNSRecordFrom(
196 "2001:db8::29",
197 func(actual []string) bool { return len(actual) == 0 },
198 "ptr-record",
199 moreForeverTestTimeout)
200
201 } else {
202 t.checkDNSRecordFrom(
203 "192.0.2.123",
204 func(actual []string) bool { return len(actual) == 1 && actual[0] == "my.test." },
205 "ptr-record",
206 moreForeverTestTimeout)
207
208 t.restoreDNSConfigMap(ctx, originalConfigMapData)
209 t.checkDNSRecordFrom(
210 "192.0.2.123",
211 func(actual []string) bool { return len(actual) == 0 },
212 "ptr-record",
213 moreForeverTestTimeout)
214 }
215 }
216
217 type dnsExternalNameTest struct {
218 dnsTestCommon
219 }
220
221 func (t *dnsExternalNameTest) run(ctx context.Context, isIPv6 bool) {
222 t.init(ctx)
223
224 t.createUtilPodLabel(ctx, "e2e-dns-configmap")
225 ginkgo.DeferCleanup(t.deleteUtilPod)
226 originalConfigMapData := t.fetchDNSConfigMapData(ctx)
227 ginkgo.DeferCleanup(t.restoreDNSConfigMap, originalConfigMapData)
228
229 fooHostname := "foo.example.com"
230 if isIPv6 {
231 t.createDNSServer(ctx, t.f.Namespace.Name, map[string]string{
232 fooHostname: "2001:db8::29",
233 })
234 } else {
235 t.createDNSServer(ctx, t.f.Namespace.Name, map[string]string{
236 fooHostname: "192.0.2.123",
237 })
238 }
239 ginkgo.DeferCleanup(t.deleteDNSServerPod)
240
241 f := t.f
242 serviceName := "dns-externalname-upstream-test"
243 externalNameService := e2eservice.CreateServiceSpec(serviceName, googleDNSHostname, false, nil)
244 if _, err := f.ClientSet.CoreV1().Services(f.Namespace.Name).Create(ctx, externalNameService, metav1.CreateOptions{}); err != nil {
245 ginkgo.Fail(fmt.Sprintf("ginkgo.Failed when creating service: %v", err))
246 }
247 ginkgo.DeferCleanup(f.ClientSet.CoreV1().Services(f.Namespace.Name).Delete, externalNameService.Name, metav1.DeleteOptions{})
248 serviceNameLocal := "dns-externalname-upstream-local"
249 externalNameServiceLocal := e2eservice.CreateServiceSpec(serviceNameLocal, fooHostname, false, nil)
250 if _, err := f.ClientSet.CoreV1().Services(f.Namespace.Name).Create(ctx, externalNameServiceLocal, metav1.CreateOptions{}); err != nil {
251 ginkgo.Fail(fmt.Sprintf("ginkgo.Failed when creating service: %v", err))
252 }
253 ginkgo.DeferCleanup(f.ClientSet.CoreV1().Services(f.Namespace.Name).Delete, externalNameServiceLocal.Name, metav1.DeleteOptions{})
254
255 if isIPv6 {
256 t.checkDNSRecordFrom(
257 fmt.Sprintf("%s.%s.svc.%s", serviceName, f.Namespace.Name, framework.TestContext.ClusterDNSDomain),
258 func(actual []string) bool {
259 return len(actual) >= 1 && actual[0] == googleDNSHostname+"."
260 },
261 "cluster-dns-ipv6",
262 moreForeverTestTimeout)
263 } else {
264 t.checkDNSRecordFrom(
265 fmt.Sprintf("%s.%s.svc.%s", serviceName, f.Namespace.Name, framework.TestContext.ClusterDNSDomain),
266 func(actual []string) bool {
267 return len(actual) >= 1 && actual[0] == googleDNSHostname+"."
268 },
269 "cluster-dns",
270 moreForeverTestTimeout)
271 }
272
273 if t.name == "coredns" {
274 t.setConfigMap(ctx, &v1.ConfigMap{Data: map[string]string{
275 "Corefile": fmt.Sprintf(`.:53 {
276 health
277 ready
278 kubernetes %v in-addr.arpa ip6.arpa {
279 pods insecure
280 fallthrough in-addr.arpa ip6.arpa
281 ttl 30
282 }
283 forward . %v
284 }`, framework.TestContext.ClusterDNSDomain, t.dnsServerPod.Status.PodIP),
285 }})
286
287 t.deleteCoreDNSPods(ctx)
288 } else {
289 t.setConfigMap(ctx, &v1.ConfigMap{Data: map[string]string{
290 "upstreamNameservers": fmt.Sprintf(`["%v"]`, t.dnsServerPod.Status.PodIP),
291 }})
292 }
293 if isIPv6 {
294 t.checkDNSRecordFrom(
295 fmt.Sprintf("%s.%s.svc.%s", serviceNameLocal, f.Namespace.Name, framework.TestContext.ClusterDNSDomain),
296 func(actual []string) bool {
297 return len(actual) >= 2 && actual[0] == fooHostname+"." && actual[1] == "2001:db8::29"
298 },
299 "cluster-dns-ipv6",
300 moreForeverTestTimeout)
301 } else {
302 t.checkDNSRecordFrom(
303 fmt.Sprintf("%s.%s.svc.%s", serviceNameLocal, f.Namespace.Name, framework.TestContext.ClusterDNSDomain),
304 func(actual []string) bool {
305 return len(actual) == 2 && actual[0] == fooHostname+"." && actual[1] == "192.0.2.123"
306 },
307 "cluster-dns",
308 moreForeverTestTimeout)
309 }
310
311 t.restoreDNSConfigMap(ctx, originalConfigMapData)
312 }
313
314 var _ = common.SIGDescribe("DNS configMap nameserver", func() {
315
316 ginkgo.Context("Change stubDomain", func() {
317 nsTest := &dnsNameserverTest{dnsTestCommon: newDNSTestCommon()}
318
319 framework.It("should be able to change stubDomain configuration", framework.WithSlow(), framework.WithSerial(), func(ctx context.Context) {
320 nsTest.c = nsTest.f.ClientSet
321 nsTest.run(ctx, framework.TestContext.ClusterIsIPv6())
322 })
323 })
324
325 ginkgo.Context("Forward PTR lookup", func() {
326 fwdTest := &dnsPtrFwdTest{dnsTestCommon: newDNSTestCommon()}
327
328 framework.It("should forward PTR records lookup to upstream nameserver", framework.WithSlow(), framework.WithSerial(), func(ctx context.Context) {
329 fwdTest.c = fwdTest.f.ClientSet
330 fwdTest.run(ctx, framework.TestContext.ClusterIsIPv6())
331 })
332 })
333
334 ginkgo.Context("Forward external name lookup", func() {
335 externalNameTest := &dnsExternalNameTest{dnsTestCommon: newDNSTestCommon()}
336
337 framework.It("should forward externalname lookup to upstream nameserver", framework.WithSlow(), framework.WithSerial(), func(ctx context.Context) {
338 externalNameTest.c = externalNameTest.f.ClientSet
339 externalNameTest.run(ctx, framework.TestContext.ClusterIsIPv6())
340 })
341 })
342 })
343
View as plain text