kubernetes + alpine+ php 特别容易出现访问外网/解析外网地址的时候出现超时的问题.
原因
docker容器访问外网的时候,整个完整路径是这样的.
容器–>主机–>外网–>主机–>容器
容器到主机之间的流量要经过源地址转换(SNAT)才能顺利流通.
SNAT就像是一个搬运工,把砖(流量)从容器搬到主机
如果一个主机上面运行多个容器,并发访问外网(特别是PHP这种没有连接池的)时向系统申请可用端口(nf_nat_l4proto_unique_tuple),不可用时+1,然后再申请,再校验.这个过程一多,最终就会导致寻址超时.
说白了是个系统内核问题.
详细的解释见
记一次Docker/Kubernetes上无法解释的连接超时原因探寻之旅
解决方案
最优解
节点升级到 5.1的Linux内核.
iptables升级到1.6.2以上
用基于IPVS模式,尽量少做SNAT/DNAT,支持随机端口SNAT的网络插件启动kubernetes
或者用绕过SNAT的网络插件插件方案,比如阿里云的terway.但这个插件跟阿里云绑定得比较深入,需要每台机器额外购买一个弹性网卡.
次优解
用ds部署name sever,所有节点的DNS解析走节点上的name server,通过最小程度的SNAT+dns cache缓解此类问题.
伪解决方案(不能解决根本问题)
默认的pod的/etc/resolv.conf一般长这样
1
2
3
4
sh-4.2# cat /etc/resolv.conf
nameserver <kube-dns-vip>
search <namespace>.svc.cluster.local svc.cluster.local cluster.local localdomain
options ndots:5
这个配置的意思是,默认nameserver指向kube-dns/core-dns,所有查询中,如果.的个数少于5个,则会根据search中配置的列表依次搜索,如果没有返回,则最后再直接查询域名本 身。ndots就是n个.(dots)的意思
举个例子
1
2
3
4
5
6
7
sh-4.2# host -v baidu.com
Trying "baidu.com.<namespace>.svc.cluster.local"
Trying "baidu.com.svc.cluster.local"
Trying "baidu.com.cluster.local"
Trying "baidu.com.localdomain"
Trying "baidu.com"
......
不使用 alpine 镜像
使用 FQDN
由于域名是从右到左逐级解析的,比如 google.com ,实际上是 google.com.,com后面的.称之为根域名。解析的时候,先解析.,然后解析.com,.com称之为顶级域名,最后解析google。
使用 FQDN:(Fully Qualified Domain Name)全限定域名,是为了尽可能减少内部DNS(比如coreDNS,节点DNS)的解析压力
重开socket
1
2
3
4
5
6
7
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- "/bin/echo 'options single-request-reopen' >> /etc/resolv.conf"
设置重开socket是规避容器并发A,AAAA查询
2级域名直接走上层解析
参考kubernetes 使用基于 alpine 镜像无法正常解析外网DNS 做的
直接运行 sed -i 's/options ndots:5/#options ndots:5/g' /etc/resolv.conf 会报错
alpine的echo命令会吞换行符,而resolv.conf格式不对DNS解析会报错
1
2
3
4
5
dnsConfig:
options:
- name: ndots
value: "2"
- name: single-request-reopen
去掉了options ndots:5,变会默认值1,这样的话,容器内部直接访问
而解析Google.com,实际上是解析Google.com.,.的数量超过1个,这时不走search列表,直接用上层DNS
综上所述,去掉ndots/ndots设为1 降低了频繁DNS查询的可能性。对于外网IP的解析有“奇效”。
但如果该主机运行其他容器(这不废话吗,一个节点不跑多个容器那还用啥kubernetes),其他容器也会并发地请求,SNAT的问题还是会出现,所以说修改/etc/resolv.conf文件并不能解决根本问题
歪门邪道1
1
2
3
4
5
6
7
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- "head -n 2 /etc/resolv.conf > /etc/temp.conf;cat /etc/temp.conf > /etc/resolv.conf;rm -rf /etc/temp.conf"
歪门邪道2
1
2
3
4
5
6
7
initContainers:
- name: alpine
image: alpine
command:
- /bin/sh
- -c
- "head -n 2 /etc/resolv.conf > /etc/temp.conf;cat /etc/temp.conf > /etc/resolv.conf;rm -rf /etc/temp.conf"
衍生的问题
DNAT
容器访问clusterIP(因为是虚拟IP所以需要DNAT)也有可能出现这类超时的问题
访问同 namespace svc 不要强行加戏
non-head service的 virtual domain 格式是<svc>.<namespace>.svc.cluster.local
如果我们容器直接访问<svc>.<namespace>.svc.cluster.local,因为默认DNS设置的问题,解析的次数反而更多。正确的方式是访问<svc>
例子:假设test下面有个s的svc
1
2
3
4
host -v s
# 解析1次
host -v s.test.svc.cluster.local
# 解析4次
所以,访问同namespace其他svc,直接用svc名去访问即可,没必要装逼使用<svc>.<namespace>.svc.cluster.local这种格式。
其他知识
dns记录类型
- A记录:地址记录,用来指定域名的IPv4地址(如:8.8.8.8),如果需要将域名指向一个IP地址,就需要添加A记录。
- CNAME: 如果需要将域名指向另一个域名,再由另一个域名提供ip地址,就需要添加CNAME记录。
- TXT:在这里可以填写任何东西,长度限制255。绝大多数的TXT记录是用来做SPF记录(反垃圾邮件)。
- NS:域名服务器记录,如果需要把子域名交给其他DNS服务商解析,就需要添加NS记录。
- AAAA:用来指定主机名(或域名)对应的IPv6地址(例如:ff06:0:0:0:0:0:0:c3)记录。
- MX:如果需要设置邮箱,让邮箱能收到邮件,就需要添加MX记录。
- 显性URL:从一个地址301重定向到另一个地址的时候,就需要添加显性URL记录(注:DNSPod目前只支持301重定向)。
- 隐性URL:类似于显性URL,区别在于隐性URL不会改变地址栏中的域名。
- SRV:记录了哪台计算机提供了哪个服务。格式为:服务的名字、点、协议的类型,例如:_xmpp-server._tcp。
用到的命令
安装方法:
1
2
3
yum install -y bind-utils
sudo apt-get install -y dnsutils
apk add bind-tools
dig
dig +trace +ndots=5 +search $host
host
host -v $host
参考链接:
kubernetes + alpine + php is particularly prone to timeout issues when accessing external networks/resolving external addresses.
Cause
When docker containers access external networks, the complete path is:
Container –> Host –> External Network –> Host –> Container
Traffic between containers and hosts needs to go through Source Network Address Translation (SNAT) to flow smoothly.
SNAT is like a porter, moving bricks (traffic) from containers to the host.
If multiple containers run on one host and concurrently access external networks (especially PHP which has no connection pool), they request available ports from the system (nf_nat_l4proto_unique_tuple). If unavailable, +1, then request again, then verify. When this process happens too much, it ultimately leads to addressing timeouts.
Simply put, it’s a system kernel issue.
For detailed explanation, see:
Remembering a Journey to Find the Unexplained Connection Timeout on Docker/Kubernetes
Solutions
Optimal Solution
Upgrade nodes to Linux kernel 5.1.
Upgrade iptables to 1.6.2 or above.
Use network plugins based on IPVS mode, minimize SNAT/DNAT, support random port SNAT to start kubernetes.
Or use network plugin solutions that bypass SNAT, such as Alibaba Cloud’s terway. But this plugin is deeply bound to Alibaba Cloud and requires purchasing an additional elastic network interface for each machine.
Suboptimal Solution
Deploy name server with ds, all nodes’ DNS resolution goes through the name server on the node, alleviating this type of problem through minimal SNAT + dns cache.
Pseudo-Solution (Cannot Solve Root Problem)
The default pod’s /etc/resolv.conf usually looks like this:
1
2
3
4
sh-4.2# cat /etc/resolv.conf
nameserver <kube-dns-vip>
search <namespace>.svc.cluster.local svc.cluster.local cluster.local localdomain
options ndots:5
This configuration means the default nameserver points to kube-dns/core-dns. In all queries, if the number of dots is less than 5, it will search according to the list configured in search. If no result is returned, it will finally directly query the domain name itself. ndots means n dots.
For example:
1
2
3
4
5
6
7
sh-4.2# host -v baidu.com
Trying "baidu.com.<namespace>.svc.cluster.local"
Trying "baidu.com.svc.cluster.local"
Trying "baidu.com.cluster.local"
Trying "baidu.com.localdomain"
Trying "baidu.com"
......
Don’t Use alpine Images
Use FQDN
Since domain names are resolved level by level from right to left, for example google.com, it’s actually google.com., the . after com is called the root domain. When resolving, first resolve ., then resolve .com, .com is called the top-level domain, finally resolve google.
Using FQDN: (Fully Qualified Domain Name) is to minimize the resolution pressure on internal DNS (like coreDNS, node DNS) as much as possible.
Reopen Socket
1
2
3
4
5
6
7
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- "/bin/echo 'options single-request-reopen' >> /etc/resolv.conf"
Setting reopen socket is to avoid concurrent A, AAAA queries in containers.
2-Level Domain Directly Goes to Upper-Level Resolution
Reference kubernetes using alpine-based images cannot properly resolve external DNS
Running sed -i 's/options ndots:5/#options ndots:5/g' /etc/resolv.conf directly will error.
alpine’s echo command swallows newlines, and if resolv.conf format is wrong, DNS resolution will error.
1
2
3
4
5
dnsConfig:
options:
- name: ndots
value: "2"
- name: single-request-reopen
Removed options ndots:5, changed to default value 1. This way, containers directly accessing
When resolving Google.com, it’s actually resolving Google.com., the number of dots exceeds 1, so it doesn’t go through the search list, directly uses upper-level DNS.
In summary, removing ndots/setting ndots to 1 reduces the possibility of frequent DNS queries. It has “miraculous effects” for resolving external IPs.
But if this host runs other containers (isn’t this nonsense, if a node doesn’t run multiple containers, why use kubernetes), other containers will also request concurrently, the SNAT problem will still appear, so modifying the /etc/resolv.conf file cannot solve the root problem.
Workaround 1
1
2
3
4
5
6
7
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- "head -n 2 /etc/resolv.conf > /etc/temp.conf;cat /etc/temp.conf > /etc/resolv.conf;rm -rf /etc/temp.conf"
Workaround 2
1
2
3
4
5
6
7
initContainers:
- name: alpine
image: alpine
command:
- /bin/sh
- -c
- "head -n 2 /etc/resolv.conf > /etc/temp.conf;cat /etc/temp.conf > /etc/resolv.conf;rm -rf /etc/temp.conf"
Derived Problems
DNAT
Containers accessing clusterIP (because it’s a virtual IP, DNAT is needed) may also have this type of timeout problem.
Don’t Forcefully Add Drama When Accessing Same Namespace svc
The virtual domain format for non-head service is <svc>.<namespace>.svc.cluster.local
If our container directly accesses <svc>.<namespace>.svc.cluster.local, because of default DNS settings, the number of resolutions is actually more. The correct way is to access <svc>
Example: Assume there’s an s svc under test
1
2
3
4
host -v s
# Resolve 1 time
host -v s.test.svc.cluster.local
# Resolve 4 times
So, when accessing other svc in the same namespace, just use the svc name directly, no need to show off using the <svc>.<namespace>.svc.cluster.local format.
Other Knowledge
DNS Record Types
- A record: Address record, used to specify the IPv4 address of a domain name (e.g., 8.8.8.8). If you need to point a domain name to an IP address, you need to add an A record.
- CNAME: If you need to point a domain name to another domain name, which then provides an IP address, you need to add a CNAME record.
- TXT: You can fill in anything here, length limit 255. The vast majority of TXT records are used for SPF records (anti-spam).
- NS: Name server record. If you need to hand over subdomain resolution to other DNS service providers, you need to add an NS record.
- AAAA: Used to specify the IPv6 address corresponding to a hostname (or domain name) (e.g., ff06:0:0:0:0:0:0:c3) record.
- MX: If you need to set up email so emails can be received, you need to add an MX record.
- Explicit URL: When you need to 301 redirect from one address to another, you need to add an explicit URL record (Note: DNSPod currently only supports 301 redirect).
- Implicit URL: Similar to explicit URL, the difference is that implicit URL doesn’t change the domain name in the address bar.
- SRV: Records which computer provides which service. Format: service name, dot, protocol type, e.g., _xmpp-server._tcp.
Commands Used
Installation method:
1
2
3
yum install -y bind-utils
sudo apt-get install -y dnsutils
apk add bind-tools
dig
dig +trace +ndots=5 +search $host
host
host -v $host
Reference Links:
- Understanding DNAT, SNAT and MASQUERADE in iptables
- Detailed Explanation of Linux Root File System /etc/resolv.conf File
- kube-dns per node #45363
- DNS intermittent delays of 5s #56903
- Racy conntrack and DNS lookup timeouts
- /etc/resolv.conf
- /etc/resolv.conf search and ndots configuration
- DNS for Services and Pods
kubernetes + alpine + phpは、外部ネットワークへのアクセス/外部アドレスの解決時にタイムアウトの問題が特に発生しやすいです。
原因
dockerコンテナが外部ネットワークにアクセスする場合、完全なパスは次のとおりです。
コンテナ –> ホスト –> 外部ネットワーク –> ホスト –> コンテナ
コンテナとホスト間のトラフィックは、ソースネットワークアドレス変換(SNAT)を通過してスムーズに流れる必要があります。
SNATは、コンテナからホストにレンガ(トラフィック)を移動するポーターのようなものです。
1つのホスト上で複数のコンテナが実行され、外部ネットワークに同時にアクセスする場合(特に接続プールがないPHP)、システムから利用可能なポート(nf_nat_l4proto_unique_tuple)を要求します。利用できない場合は+1し、再度要求し、検証します。このプロセスが多すぎると、最終的にアドレッシングタイムアウトが発生します。
簡単に言えば、システムカーネルの問題です。
詳細な説明については、以下を参照してください:
Docker/Kubernetesで説明できない接続タイムアウトの原因を探る旅を記録
解決策
最適解
ノードをLinuxカーネル5.1にアップグレードします。
iptablesを1.6.2以上にアップグレードします。
IPVSモードベースのネットワークプラグインを使用し、SNAT/DNATを最小限に抑え、ランダムポートSNATをサポートしてkubernetesを起動します。
または、SNATをバイパスするネットワークプラグインソリューションを使用します。たとえば、阿里云のterwayです。ただし、このプラグインは阿里云に深くバインドされており、各マシンに追加のエラスティックネットワークインターフェースを購入する必要があります。
次善の策
dsでネームサーバーをデプロイ、すべてのノードのDNS解決はノード上のネームサーバーを通過し、最小限のSNAT + dnsキャッシュを通じてこのタイプの問題を緩和します。
疑似解決策(根本的な問題を解決できない)
デフォルトのpodの/etc/resolv.confは通常次のようになります:
1
2
3
4
sh-4.2# cat /etc/resolv.conf
nameserver <kube-dns-vip>
search <namespace>.svc.cluster.local svc.cluster.local cluster.local localdomain
options ndots:5
この設定は、デフォルトのネームサーバーがkube-dns/core-dnsを指すことを意味します。すべてのクエリで、ドットの数が5未満の場合、searchで設定されたリストに従って検索します。結果が返されない場合、最後にドメイン名自体を直接クエリします。ndotsはn個のドット(dots)を意味します。
例:
1
2
3
4
5
6
7
sh-4.2# host -v baidu.com
Trying "baidu.com.<namespace>.svc.cluster.local"
Trying "baidu.com.svc.cluster.local"
Trying "baidu.com.cluster.local"
Trying "baidu.com.localdomain"
Trying "baidu.com"
......
alpineイメージを使用しない
FQDNを使用
ドメイン名は右から左にレベルごとに解決されるため、たとえばgoogle.comは実際にはgoogle.com.で、comの後の.はルートドメインと呼ばれます。解決する際は、まず.を解決し、次に.comを解決します。.comはトップレベルドメインと呼ばれ、最後にgoogleを解決します。
FQDN(完全修飾ドメイン名)を使用:内部DNS(coreDNS、ノードDNSなど)の解決圧力を可能な限り最小限に抑えるためです。
ソケットを再開
1
2
3
4
5
6
7
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- "/bin/echo 'options single-request-reopen' >> /etc/resolv.conf"
ソケットの再開を設定することは、コンテナ内の同時A、AAAAクエリを回避することです。
2レベルドメインを直接上位解決に送る
kubernetesがalpineベースのイメージを使用して外部DNSを正常に解決できないを参照
sed -i 's/options ndots:5/#options ndots:5/g' /etc/resolv.confを直接実行するとエラーになります。
alpineのechoコマンドは改行を飲み込み、resolv.confの形式が間違っているとDNS解決がエラーになります。
1
2
3
4
5
dnsConfig:
options:
- name: ndots
value: "2"
- name: single-request-reopen
options ndots:5を削除し、デフォルト値1に変更しました。この方法では、コンテナが
Google.comを解決する場合、実際にはGoogle.com.を解決し、ドットの数が1を超えるため、searchリストを通過せず、直接上位DNSを使用します。
要約すると、ndotsを削除/ndotsを1に設定することで、頻繁なDNSクエリの可能性を減らします。外部IPの解決に「奇効」があります。
ただし、このホストが他のコンテナを実行する場合(これは冗談です。ノードが複数のコンテナを実行しない場合、kubernetesを使用する理由はありません)、他のコンテナも同時にリクエストするため、SNATの問題は依然として発生し、/etc/resolv.confファイルを変更しても根本的な問題を解決できません。
回避策1
1
2
3
4
5
6
7
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- "head -n 2 /etc/resolv.conf > /etc/temp.conf;cat /etc/temp.conf > /etc/resolv.conf;rm -rf /etc/temp.conf"
回避策2
1
2
3
4
5
6
7
initContainers:
- name: alpine
image: alpine
command:
- /bin/sh
- -c
- "head -n 2 /etc/resolv.conf > /etc/temp.conf;cat /etc/temp.conf > /etc/resolv.conf;rm -rf /etc/temp.conf"
派生問題
DNAT
コンテナがclusterIPにアクセスする場合(仮想IPであるため、DNATが必要)、このタイプのタイムアウト問題が発生する可能性があります。
同じnamespaceのsvcにアクセスする際に無理に追加しない
非ヘッドサービスの仮想ドメイン形式は<svc>.<namespace>.svc.cluster.localです
コンテナが<svc>.<namespace>.svc.cluster.localに直接アクセスする場合、デフォルトのDNS設定により、解決回数が実際には多くなります。正しい方法は<svc>にアクセスすることです。
例:testの下にsのsvcがあると仮定
1
2
3
4
host -v s
# 1回解決
host -v s.test.svc.cluster.local
# 4回解決
したがって、同じnamespaceの他のsvcにアクセスする場合は、svc名を直接使用するだけで、<svc>.<namespace>.svc.cluster.local形式を使用して見せびらかす必要はありません。
その他の知識
DNSレコードタイプ
- Aレコード:アドレスレコード。ドメイン名のIPv4アドレス(例:8.8.8.8)を指定するために使用されます。ドメイン名をIPアドレスにポイントする必要がある場合は、Aレコードを追加する必要があります。
- CNAME:ドメイン名を別のドメイン名にポイントし、そのドメイン名がIPアドレスを提供する必要がある場合は、CNAMEレコードを追加する必要があります。
- TXT:ここに何でも記入できます。長さ制限は255です。TXTレコードの大部分はSPFレコード(スパム対策)に使用されます。
- NS:ネームサーバーレコード。サブドメインの解決を他のDNSサービスプロバイダーに委任する必要がある場合は、NSレコードを追加する必要があります。
- AAAA:ホスト名(またはドメイン名)に対応するIPv6アドレス(例:ff06:0:0:0:0:0:0:c3)レコードを指定するために使用されます。
- MX:メールを設定してメールを受信できるようにする必要がある場合は、MXレコードを追加する必要があります。
- 明示的URL:あるアドレスから別のアドレスに301リダイレクトする必要がある場合は、明示的URLレコードを追加する必要があります(注:DNSPodは現在301リダイレクトのみをサポートしています)。
- 暗黙的URL:明示的URLと同様ですが、違いは暗黙的URLがアドレスバーのドメイン名を変更しないことです。
- SRV:どのコンピューターがどのサービスを提供するかを記録します。形式:サービス名、ドット、プロトコルタイプ、例:_xmpp-server._tcp。
使用されるコマンド
インストール方法:
1
2
3
yum install -y bind-utils
sudo apt-get install -y dnsutils
apk add bind-tools
dig
dig +trace +ndots=5 +search $host
host
host -v $host
参考リンク:
kubernetes + alpine + php особенно склонны к проблемам с таймаутом при доступе к внешним сетям/разрешении внешних адресов.
Причина
Когда docker-контейнеры обращаются к внешним сетям, полный путь таков:
Контейнер –> Хост –> Внешняя сеть –> Хост –> Контейнер
Трафик между контейнерами и хостами должен проходить через преобразование сетевых адресов источника (SNAT), чтобы течь плавно.
SNAT похож на носильщика, перемещающего кирпичи (трафик) из контейнеров на хост.
Если на одном хосте запущено несколько контейнеров и они одновременно обращаются к внешним сетям (особенно PHP, у которого нет пула соединений), они запрашивают доступные порты у системы (nf_nat_l4proto_unique_tuple). Если недоступно, +1, затем снова запрос, затем проверка. Когда этот процесс происходит слишком часто, это в конечном итоге приводит к таймаутам адресации.
Проще говоря, это проблема ядра системы.
Подробное объяснение см.:
Запись путешествия по поиску необъяснимой причины таймаута соединения на Docker/Kubernetes
Решения
Оптимальное решение
Обновить узлы до ядра Linux 5.1.
Обновить iptables до 1.6.2 или выше.
Использовать сетевые плагины на основе режима IPVS, минимизировать SNAT/DNAT, поддерживать случайный порт SNAT для запуска kubernetes.
Или использовать решения сетевых плагинов, обходящие SNAT, такие как terway от Alibaba Cloud. Но этот плагин глубоко привязан к Alibaba Cloud и требует покупки дополнительного эластичного сетевого интерфейса для каждой машины.
Субоптимальное решение
Развернуть сервер имен с ds, разрешение DNS всех узлов проходит через сервер имен на узле, облегчая этот тип проблемы через минимальный SNAT + dns кэш.
Псевдо-решение (не может решить корневую проблему)
Файл /etc/resolv.conf подов по умолчанию обычно выглядит так:
1
2
3
4
sh-4.2# cat /etc/resolv.conf
nameserver <kube-dns-vip>
search <namespace>.svc.cluster.local svc.cluster.local cluster.local localdomain
options ndots:5
Эта конфигурация означает, что сервер имен по умолчанию указывает на kube-dns/core-dns. Во всех запросах, если количество точек меньше 5, он будет искать согласно списку, настроенному в search. Если результат не возвращен, он в конечном итоге напрямую запросит само доменное имя. ndots означает n точек.
Например:
1
2
3
4
5
6
7
sh-4.2# host -v baidu.com
Trying "baidu.com.<namespace>.svc.cluster.local"
Trying "baidu.com.svc.cluster.local"
Trying "baidu.com.cluster.local"
Trying "baidu.com.localdomain"
Trying "baidu.com"
......
Не использовать образы alpine
Использовать FQDN
Поскольку доменные имена разрешаются уровень за уровнем справа налево, например google.com, это на самом деле google.com., точка после com называется корневым доменом. При разрешении сначала разрешается ., затем разрешается .com, .com называется доменом верхнего уровня, наконец разрешается google.
Использование FQDN: (Полностью квалифицированное доменное имя) предназначено для минимизации давления разрешения на внутренний DNS (например, coreDNS, DNS узла) насколько возможно.
Переоткрыть сокет
1
2
3
4
5
6
7
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- "/bin/echo 'options single-request-reopen' >> /etc/resolv.conf"
Установка переоткрытия сокета предназначена для избежания одновременных A, AAAA запросов в контейнерах.
2-уровневый домен напрямую идет на разрешение верхнего уровня
Ссылка kubernetes использует образы на основе alpine не может правильно разрешить внешний DNS
Запуск sed -i 's/options ndots:5/#options ndots:5/g' /etc/resolv.conf напрямую выдаст ошибку.
Команда echo alpine проглатывает символы новой строки, и если формат resolv.conf неправильный, разрешение DNS выдаст ошибку.
1
2
3
4
5
dnsConfig:
options:
- name: ndots
value: "2"
- name: single-request-reopen
Удален options ndots:5, изменено на значение по умолчанию 1. Таким образом, контейнеры, напрямую обращающиеся к
При разрешении Google.com фактически разрешается Google.com., количество точек превышает 1, поэтому оно не проходит через список search, напрямую использует DNS верхнего уровня.
В итоге, удаление ndots/установка ndots в 1 снижает возможность частых DNS-запросов. Это имеет “чудесные эффекты” для разрешения внешних IP.
Но если этот хост запускает другие контейнеры (разве это не ерунда, если узел не запускает несколько контейнеров, зачем использовать kubernetes), другие контейнеры также будут запрашивать одновременно, проблема SNAT все еще появится, поэтому изменение файла /etc/resolv.conf не может решить корневую проблему.
Обходной путь 1
1
2
3
4
5
6
7
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- "head -n 2 /etc/resolv.conf > /etc/temp.conf;cat /etc/temp.conf > /etc/resolv.conf;rm -rf /etc/temp.conf"
Обходной путь 2
1
2
3
4
5
6
7
initContainers:
- name: alpine
image: alpine
command:
- /bin/sh
- -c
- "head -n 2 /etc/resolv.conf > /etc/temp.conf;cat /etc/temp.conf > /etc/resolv.conf;rm -rf /etc/temp.conf"
Производные проблемы
DNAT
Контейнеры, обращающиеся к clusterIP (поскольку это виртуальный IP, требуется DNAT), также могут иметь этот тип проблемы с таймаутом.
Не принудительно добавлять драму при доступе к svc того же namespace
Формат виртуального домена для не-head service: <svc>.<namespace>.svc.cluster.local
Если наш контейнер напрямую обращается к <svc>.<namespace>.svc.cluster.local, из-за настроек DNS по умолчанию количество разрешений фактически больше. Правильный способ - обращаться к <svc>
Пример: предположим, что под test есть svc s
1
2
3
4
host -v s
# Разрешить 1 раз
host -v s.test.svc.cluster.local
# Разрешить 4 раза
Итак, при доступе к другим svc в том же namespace просто используйте имя svc напрямую, нет необходимости хвастаться использованием формата <svc>.<namespace>.svc.cluster.local.
Другие знания
Типы записей DNS
- A-запись: Запись адреса, используется для указания IPv4-адреса доменного имени (например, 8.8.8.8). Если нужно указать доменное имя на IP-адрес, нужно добавить A-запись.
- CNAME: Если нужно указать доменное имя на другое доменное имя, которое затем предоставляет IP-адрес, нужно добавить CNAME-запись.
- TXT: Здесь можно заполнить что угодно, ограничение длины 255. Подавляющее большинство TXT-записей используется для SPF-записей (антиспам).
- NS: Запись сервера имен. Если нужно передать разрешение поддомена другим поставщикам DNS-услуг, нужно добавить NS-запись.
- AAAA: Используется для указания IPv6-адреса, соответствующего имени хоста (или доменному имени) (например, ff06:0:0:0:0:0:0:c3) запись.
- MX: Если нужно настроить почту, чтобы письма могли быть получены, нужно добавить MX-запись.
- Явный URL: Когда нужно 301-редирект с одного адреса на другой, нужно добавить явную URL-запись (Примечание: DNSPod в настоящее время поддерживает только 301-редирект).
- Неявный URL: Аналогично явному URL, разница в том, что неявный URL не изменяет доменное имя в адресной строке.
- SRV: Записывает, какой компьютер предоставляет какую службу. Формат: имя службы, точка, тип протокола, например, _xmpp-server._tcp.
Используемые команды
Способ установки:
1
2
3
yum install -y bind-utils
sudo apt-get install -y dnsutils
apk add bind-tools
dig
dig +trace +ndots=5 +search $host
host
host -v $host
Ссылки:
- Понимание DNAT, SNAT и MASQUERADE в iptables
- Подробное объяснение файла /etc/resolv.conf корневой файловой системы Linux
- kube-dns per node #45363
- Прерывистые задержки DNS на 5 секунд #56903
- Гонка conntrack и таймауты поиска DNS
- /etc/resolv.conf
- Конфигурация search и ndots в /etc/resolv.conf
- DNS для служб и подов
💬 讨论 / Discussion
对这篇文章有想法?欢迎在 GitHub 上发起讨论。
Have thoughts on this post? Start a discussion on GitHub.