Kubernetes之配置与自定义DNS服务

本文解释如何为kubernetes集群配置及自定义DNS服务。从kubernetes1.11版本开始,coreDNS插件被包含在GA发行版中,并且被kubeadm默认安装。详情:Configuring CoreDNS and Using CoreDNS for Service Discovery。除特别说明,本文讨论的是默认dns插件。

介绍

Kubernetes的DNS功能以插件形式提供,是自动启动的系统内置服务。服务包含如下三个容器:

  • kubedns:监控Kubernetes master的service与endpoint变更,增删改DNS记录,将相关数据保存在内存中,为DNS查询提供服务。
  • dnsmasq: 充当DNS缓存,提高性能。
  • sidecar:挂斗容器,对dnsmasq与kubedns进行单点健康检查。

DNS服务拥有静态IP地址,将各节点kubeletr的–cluster-dns=设置成DNS服务的静态IP地址,当kubelet创建容器时则将此地址传递给容器。Kubernetes的DNS服务基于skyDNS库,支持forward lookups (A records)、service lookups (SRV records)、reverse IP address lookups (PTR records)。

从节点继承DNS配置

当kubelet启动容器时,除使用kubernetes内置的DNS服务,默认从节点继承其DNS配置。此特性使kubernetes系统中的容器DNS行为高度依赖低层节点,建议关闭,设置kubelet–resolv-conf选项为用户自定义配置文件,而非系统默认/etc/resolve.conf,这样容器继承的DNS配置由用户提供的配置文件决定,而非节点,降低耦合度。

配置存根域及上游DNS服务器

集群管理员可通过为kubernetes中DNS服务kube-system:kube-dns提供ConfigMap对象,设置自定义存根域及上游DNS服务器。以下示例为DNS服务配置一个存根域及两个上游DNS服务器:

apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-dns
  namespace: kube-system
data:
  stubDomains: |
    {"acme.local": ["1.2.3.4"]}
  upstreamNameservers: |
    ["8.8.8.8", "8.8.4.4"]

如果查询请求的前缀为”acme.local”则被直接转发到1.2.3.4。下表列出不同域名前缀与DNS服务器对应关系:

未分类

对pod的影响

如果pod Spec之dnsPolicy设置为”Default”或者”Node”,则用户自定义存根服务器与上游服务器对pod没有影响。当值为”Default”时,pod之DNS配置完全从节点继承。如果为Node,则取决于pod Spec中的dnsConfig配置。

当dnsPolicy设置为”ClusterFirst”时,pod的DNS配置分成没无自定义存根域与上游服务器、有自定义存根域与上游服务器两种情况。

无自定义存根域与上游服务器:如果查询请求之域名前缀与集群默认域名匹配,则使用kubernetes内置DNS服务,如果不匹配则使用从节点继承之DNS服务。

有自定义存根域与上游服务器,域名解析流程如下:

  1. 请求首先发送到kube-dns缓存层。

  2. 在缓存层,检查请求的域名前缀并将请求转发到与之匹配的DNS服务器,流程如下:

  • 与集群域名前缀匹配,如“.cluster.local”,则发往kube-dns。

  • 如与存根域匹配,如“.acme.local”, 则发往匹配的存根域服务器。

  • 否则,发往上游服务器。

未分类

ConfigMap选项

未分类

配置CoreDNS

从1.9版本开始,CoreDNS成为GA可选特性,将来可能会取代kube-dns成为默认集群默认DNS解决方案,CoreDNS具备kube-dns所有功能并更强大。在CoreDNS插件内部通过一种Corefile文件管理配置。可以直接将为kube-dns设置的ConfigMap直接指定给CoreDNS,CoreDNS自动将此ConfigMap转换成Corefile。示例如下:

apiVersion: v1
data:
  federations: |
    {"foo" : "foo.feddomain.com"}
  stubDomains: |
    {"abc.com" : ["1.2.3.4"], "my.cluster.local" : ["2.3.4.5"]}
  upstreamNameservers: |
    ["8.8.8.8", "8.8.4.4"]
kind: ConfigMap

转换结果:

.:53 {
        errors
        health
        kubernetes cluster.local  in-addr.arpa ip6.arpa {
           upstream  8.8.8.8 8.8.4.4
           pods insecure
           fallthrough in-addr.arpa ip6.arpa
        }
        federation cluster.local {
           foo foo.feddomain.com
        }
        prometheus :9153
        proxy .  8.8.8.8 8.8.4.4
        cache 30
    }
    abc.com:53 {
        errors
        cache 30
        proxy . 1.2.3.4
    }
    my.cluster.local:53 {
        errors
        cache 30
        proxy . 2.3.4.5
    }

Mysql DNS反向解析导致连接超时过程分析(skip-name-resolve)

MySQL数据库收到一个网络连接后,首先拿到对方的IP地址,然后对这个IP地址进行反向DNS解析从而得到这个IP地址对应的主机名。用主机名在权限系统里面进行权限判断。反向DNS解析是耗费时间的,有可能让用户感觉起来很慢。甚至有的时候,反向解析出来的主机名并没有指向这个IP地址,这时候就无法连接成功了。

可以在配置文件里面禁止MySQL进行反向DNS解析,只需在my.cnf的[mysqld]段落中加入如下行即可:

skip-name-resolve (windows与linux下一样的)

设备在连接mysql时候,等待服务器的banner信息需要4s左右,影响了Mysql服务的连接速度。

通过如下方式进行验证:

1、Telnet端口验证

通过设备和虚拟机(Linux系统)分别Telnet Mysql服务的端口,会出现一下现象:

设备(UAG/SCANNER): telnet后,等待Mysql的服务器端回应大概需要等10s左右。

[DPtech-Developer-Shell]telnet 10.101.0.206 3308

Trying 10.101.0.206...

Connected to 10.101.0.206.

Escape character is '^]'.

E

5.0.67-community-nt-log?Hc95

虚拟机(Ubuntu):telnet后,立即得到了Mysql服务器的返回

[root]~# telnet 10.101.0.206 3308

Trying 10.101.0.206...

Connected to 10.101.0.206.

Escape character is '^]'.

E

5.0.67-community-nt-log?D%(;1$]+,¢!Zdh`'?G)6r]YConnection closed by foreign host.   //这里耗时很短

2、通过程序进行验证

具体源代码见附件:验证程序源代码

源代码基本上是设置了Recv超时后,建立socket连接之后接受数据,收到后计时并输出。

在设备上和虚拟机中的结果分别如下:

设备:

[DPtech-Developer-Shell]/tcpclient_mips 10.101.0.1 3306

花费时间:19553

Recved 68 bytes

@

5.5.2-m2-community%uD3q`n)

虚拟机:

[root]tcp_demo# ./tcpclient 10.101.0.1 3306

花费时间:10525

Recved 68 bytes

@

5.5.2-m2-communitd~k~Y";B

可以发现,设备上大约比Linux服务器多耗时9s,其中10秒钟可能是recv本身超时的时间。

3、通过不同操作系统进行Telnet验证

通过Windows系统和Linux虚拟机、设备,分别通过Telnet进行连接尝试,通过抓包分析得知,只有设备的耗时比较长,其他的耗时都比较短。

抓包时发现设备中的socket建立之后,MYSQL服务器需要发送很多次的NBNS报文后,才会传输banner信息,而Linux虚拟机和Windows系统的主机在这个过程中都没有出现这个问题。

查找了一些资料,关于MYSQL NBNS报文的问题:

Mysql论坛的提问:

http://forums.mysql.com/read.php?11,250982,250982#msg-250982

该问题的答复

http://forums.mysql.com/read.php?11,250982,254683#msg-254683

从答复中来看,貌似是某些版本的问题,临时的解决方案是对Mysql服务器进行配置,不启用Named Pipes,即 命名管道 功能即可解决这个问题。

后经查找相关资料得知,远程连接超时可能由于Mysql默认开启了DNS反向解析的缘故,每次连接时服务器都尝试解析连接客户端的主机名,导致时间比较长。

解决方法是在服务器端的my.ini文件中,[mysqld]这个节下配置一个skip-name-resolve以关闭Mysql默认开启的DNS反向解析就可以了。

再次通过设备和虚拟机或者Windows系统进行Telnet,可以发现连接超时的现象明显不存在了。

另外通过自己写的C代码进行连接的时候也存在同样的问题,修改skip-name-resolve以后,实际上就可以发现该问题已经不存在了:

设备:

[DPtech-Developer-Shell]/tcpclient_mips 10.101.0.1 3306 

花费时间:10520

Recved 68 bytes

@

5.5.2-m2-community[Z44E>G)

虚拟机:

[root]tcp_demo# ./tcpclient 10.101.0.1 3306

花费时间:10521

Recved 68 bytes

@

5.5.2-m2-community7evE5wyx

通过虚拟机Telnet连接另外一个ip 10.101.0.206时候发现速度也比较慢,消耗的时间基本上和设备中相当,可能是由于虚拟机和宿主主机之前不需要进行反向域名解析,或者说是应为系统本身就知道虚拟机IP地址(NAT模式)对应的主机名,所以不需要进行DNS反向解析,导致在虚拟机中出现了特殊情况。

最后得出结论,可能这个问题实际上和设备或者虚拟机,Linux系统、Windows系统没有多大关系,主要由于服务器的反向DNS解析导致该问题。无法从客户端途径去解决,也就是说我们设备无法处理这种情形。