K8S 节点自定义DNS被重写故障

故障场景:

k8s集群内pod需要访问sms.devhub.com获取数据,但是它是一个内网地址,公网DNS无法解析,所以需要在node节点的resolve.conf 添加内网的NDS服务器地址来解决问题,刚添加后是正常的,但是过了几分钟后先又解析不了,检查发现添加的resolve.conf被还原了。

故障原因:

K8s会重写/etc/resolv.conf文件以确保Pod中的DNS解析正确。因为在k8s集群中,Pod可能会被调度到不同的节点上,每个节点可能会有不同的DNS配置。因此,k8s会在每个节点上生成一个新的/etc/resolv.conf文件,并将其复制到每个Pod中,以确保Pod中的DNS解析与节点上的DNS解析一致。

Kubernetes会在每个节点上运行一个名为kubelet的服务,该服务负责管理节点上的Pod。kubelet会通过读取/etc/kubernetes/kubelet.conf文件获取Kubernetes集群中的DNS服务器地址,然后使用这些地址生成新的/etc/resolv.conf文件。kubelet会定期检查/etc/resolv.conf文件是否需要更新,并在必要时重新生成它。

解决方案1

 使用 ConfigMap 来存储 hosts 文件的内容,然后将 ConfigMap 挂载到 Pod 中作为一个文件,从而实现在 Pod 启动的节点增加 hosts 的目的。

方案1步骤:

1.创建一个 ConfigMap,将 hosts 文件的内容作为 ConfigMap 的数据存储起来,例如:

kubectl create configmap my-hosts --from-file=hosts=/etc/hosts

2.在 Pod 的 YAML 文件中添加一个 volume,将 ConfigMap 挂载到 Pod 中:

volumes:
  - name: my-hosts
    configMap:
      name: my-hosts

3.在 Pod 的 YAML 文件中添加一个 volumeMount,将 ConfigMap 中的 hosts 文件挂载到 Pod 的 /etc/hosts 文件中:

volumeMounts:
  - name: my-hosts
    mountPath: /etc/hosts
    subPath: hosts

当 Pod 启动时,k8s就会将 ConfigMap 中的 hosts 文件挂载到 Pod 中,并将其内容写入到 /etc/hosts 文件中,从而实现在 Pod 启动的节点增加 hosts 的目的。

 解决方案2

 在coredns增加A记录解析,实现主机名解析。

方案2步骤:

1.在coredns的configmap的data下添加A记录,修改域名和IP。

data:
  Corefile: |
    .:53 {
        errors
        health {
           lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
           pods insecure
           fallthrough in-addr.arpa ip6.arpa
           ttl 30
        }
        prometheus :9153
        ....
    }


    dms.devhub.com.openstacklocal:53 {
        errors
        template ANY AAAA {
           rcode NXDOMAIN
        }
        template IN A dms.devhub.com.openstacklocal {
            match dms\.devhub\.com\.openstacklocal
            answer "{{ .Name }} 60 IN A 192.168.1.1"
            fallthrough
        }
        cache 30
    }

2.重启coredns的pod

kubectl scale -n kube-system deployment coredns --replicas=0

kubectl scale -n kube-system deployment coredns --replicas=2

解决方案3

启用coredns的插件proxy,读取宿主机的/etc/resolv.conf,只需要在所有master配置好DNS服务器地址。

 方案3步骤:

1.在coredns的configmap的data下添加proxy . /etc/resolw.contf 启用插件:

data:
  Corefile: |
    .:53 {
        errors
        health {
           lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
           pods insecure
           fallthrough in-addr.arpa ip6.arpa
           ttl 30
        }
        prometheus :9153
        proxy . /etc/resolw.contf 
        ......
    }

. 表示要转发的域名是任意域名,/etc/resolv.conf 表示要将 DNS 查询转发到该文件中指定的 DNS 服务器上。

2.在所有master节点添加DNS服务器

echo >> nameserver 8.8.8.8 /etc/resolv.conf

 3.重启coredns的pod

kubectl scale -n kube-system deployment coredns --replicas=0

kubectl scale -n kube-system deployment coredns --replicas=2

总结:

方案1,比较麻烦,需要重启现有的Pod,不适用于实际环境。但不需要实际的DNS服务器。

方案2,实际是增加host 的A记录,不够灵活,需要一条一条增加。但不需要实际的DNS服务器。

方案3,如果master上的 /etc/resolv.conf 中指定了多个 DNS 服务器,CoreDNS 会按照顺序依次尝试这些 DNS 服务器进行解析,直到找到可用的为止。所以需要确保宿主机上的 /etc/resolv.conf 中指定的 DNS 服务器是可用的。

结语:

推荐适用方案3,可以统一规划域名后,不管是开发环境、测试环境还是预生产环境都是相同的域名,通过每个环境的配置不同的本地dns服务解析到不同ip。

你可能感兴趣的:(k8s,kubernetes,运维,网络)