dns策略及配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// pkg/kubelet/network/dns/dns.go

func (c *Configurer) GetPodDNS(pod *v1.Pod) (*runtimeapi.DNSConfig, error) {

// 1.先读取host上的dns配置,读取kubelet配置文件中ResolverConfig,在我们集群是/etc/kubernetes/resolv.conf
dnsConfig, err := c.getHostDNSConfig()

2. 查看pod中设置的dnsPolicy,默认你配置的是什么就是什么,但是对于clusterfirst+hostnetwrok的pod, dnstype会设置为host模式。
dnsType, err := getPodDNSType(pod)

switch dnsType {
case podDNSNone:
// DNSNone should use empty DNS settings as the base.
dnsConfig = &runtimeapi.DNSConfig{}
// 将集群的dns配置作为nameserver,c.clusterDNS
// 只需要传入server, search和options两个参数是固定的,见最下面
case podDNSCluster:
if len(c.clusterDNS) != 0 {
dnsConfig.Servers = []string{}
for _, ip := range c.clusterDNS {
dnsConfig.Servers = append(dnsConfig.Servers, ip.String())
}
dnsConfig.Searches = c.generateSearchesForDNSClusterFirst(dnsConfig.Searches, pod)
dnsConfig.Options = defaultDNSOptions
break
}
// clusterDNS is not known. Pod with ClusterDNSFirst Policy cannot be created.
nodeErrorMsg := fmt.Sprintf("kubelet does not have ClusterDNS IP configured and cannot create Pod using %q policy. Falling back to %q policy.", v1.DNSClusterFirst, v1.DNSDefault)
c.recorder.Eventf(c.nodeRef, v1.EventTypeWarning, "MissingClusterDNS", nodeErrorMsg)
c.recorder.Eventf(pod, v1.EventTypeWarning, "MissingClusterDNS", "pod: %q. %s", format.Pod(pod), nodeErrorMsg)
// Fallback to DNSDefault.
fallthrough
// 使用 kubelet --resolv-conf flag设置的配置,如果没有指定就生成默认的配置。
case podDNSHost:
if c.ResolverConfig == "" {
for _, nodeIP := range c.nodeIPs {
if utilnet.IsIPv6(nodeIP) {
dnsConfig.Servers = append(dnsConfig.Servers, "::1")
} else {
dnsConfig.Servers = append(dnsConfig.Servers, "127.0.0.1")
}
}
if len(dnsConfig.Servers) == 0 {
dnsConfig.Servers = append(dnsConfig.Servers, "127.0.0.1")
}
dnsConfig.Searches = []string{"."}
}
}
// 使用自定义的dns配置
if pod.Spec.DNSConfig != nil {
dnsConfig = appendDNSConfig(dnsConfig, pod.Spec.DNSConfig)
}
// nameserver只有前3个起作用
// search 只有前6个起作用
return c.formDNSConfigFitsLimits(dnsConfig, pod), nil
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func getPodDNSType(pod *v1.Pod) (podDNSType, error) {
// 查看pod中配置的dns策略
dnsPolicy := pod.Spec.DNSPolicy
switch dnsPolicy {
case v1.DNSNone:
return podDNSNone, nil
case v1.DNSClusterFirstWithHostNet:
return podDNSCluster, nil
case v1.DNSClusterFirst:
if !kubecontainer.IsHostNetworkPod(pod) {
return podDNSCluster, nil
}
// Fallback to DNSDefault for pod on hostnetowrk.
fallthrough
case v1.DNSDefault:
return podDNSHost, nil
}
// This should not happen as kube-apiserver should have rejected
// invalid dnsPolicy.
return podDNSCluster, fmt.Errorf(fmt.Sprintf("invalid DNSPolicy=%v", dnsPolicy))
}

默认参数是clusterFirst类型

1
2
3
4
5
6
7
8
9
10
pkg/apis/core/v1/defaults.go

func SetDefaults_PodSpec(obj *v1.PodSpec) {
// New fields added here will break upgrade tests:
// https://github.com/kubernetes/kubernetes/issues/69445
// In most cases the new defaulted field can added to SetDefaults_Pod instead of here, so
// that it only materializes in the Pod object and not all objects with a PodSpec field.
if obj.DNSPolicy == "" {
obj.DNSPolicy = v1.DNSClusterFirst
}

clusterfirst策略时pod使用的的域名解析配置是pod中的/etc/resolv.conf, 其中nameservekube-dns服务地址,而searchoptions配置均是默认的,即

1
2
3
4
5
defaultDNSOptions = []string{"ndots:5"}
// 包含三个domain
clusterSearch := []string{nsSvcDomain, svcDomain, c.ClusterDomain}
svcDomain := fmt.Sprintf("svc.%s", c.ClusterDomain)
nsSvcDomain := fmt.Sprintf("%s.svc.%s", pod.Namespace, c.ClusterDomain)

总结

  1. pod重建导致ip变化,所以pod间服务访问必须使用域名,这就涉及到pod dnsPolicy设置了。将域名解析为正确的ip
  2. pod中设置的dnspolicy参数,默认clusterfirst,有了first,肯定有second, 这里的first指的一般pod, 而hostnetwork的pod配置clusterfirst则会用second,就是用kubelet(–resolv-conf)参数的配置,一般会指向host侧的参数文件,可能是/etc/resolv.conf, 也可能时其他文件。
  3. 如果想用pod里的(clusterfirst),需要设置为ClusterFirstWithHostNet,这也是它起这个名字的意义。