如何向 Google 容器引擎 [GKE] 中的所有 pods 添加名称服务器?
How do I add a nameserver to all pods in Google Container Engine [GKE]?
我正在尝试将我的本地集群迁移到 GKE。为了促进这种转变,我需要能够解析遗留服务的名称。
假设 networking/VPN 是一个已解决的问题。
目前有没有办法用 GKE 做到这一点?
实际上我正在尝试向每个 /etc/resolv.conf
添加一个 NS
有效没有
如果您修改节点的 resolv.conf,pods 将继承更改。
但是,glibc 禁止使用超过 3 个名称服务器或超过 6 个搜索记录。
GCE VM 使用 2 个名称服务器和 3 个搜索来访问节点元数据和项目网络。
GKE 使用 1 个名称服务器和 3 个搜索。
剩下 0 个名称服务器和 0 个搜索。
看到这个问题:https://github.com/kubernetes/kubernetes/issues/9079
这个问题:https://github.com/kubernetes/kubernetes/issues/9132
我想对 Eric 所说的内容进行补充,并对其进行一些修改。
我们在 kubernetes 1.1 "settling period" 期间的一个认识是 resolv.conf 和解析器行为等方面并没有真正的规范。不同的解析器库做不同的事情,这给我们的用户带来了痛苦。
具体来说,一些常见的解析器假定所有 nameserver
都是可替代的,如果您有处理 DNS 命名空间不同部分的名称服务器,它们就会中断。我们决定,对于 kube 1.2,我们不会将多个 nameserver
行传递到容器中。相反,我们只传递 kube-dns 服务器,它处理 cluster.local
查询并将任何其他查询转发到 "upstream" 名称服务器。
我们怎么知道 "upstream" 是什么?我们使用节点的nameservers
。每个 pod 都有一个 dnsPolicy 字段来管理这个选择。最终结果是容器在我们拥有的 resolv.conf 中看到一个 nameserver
,并且该名称服务器处理整个 DNS 命名空间。
这实际上意味着您没有很好的钩子来插入您自己的名称服务器。您可以将 --cluster-dns
标志更改为 kubelets 以指向您自己的 DNS 服务器,然后该服务器将转发到 kube-dns,然后再转发到 "upstream"。问题是 GKE 并不真正支持以这种方式更改标志。 If/when 节点已更新,标志将消失以支持默认值。
可能的解决方案:
让 kubelet 从集群内配置中读取它们的标志。这已经是记录计划,但不在 v1.2
中
让 kube-dns 带一个标志来指示 "upstream" 是什么。 Kube-dns 是一个 "cluster addon",因此最终用户并不真正可变(我们将使用您的集群更新它并丢失您的更改)。
让 kube-dns 从集群内配置中读取其标志,并获取一个指示 "upstream" 是什么的标志。这是一个可行的想法,但可能不适用于 v1.2(为时已晚)。 可能可以将其修补到 v1 中。2.x但这并不是真正的错误修复,而是一个功能。
将您自己的 DNS 服务器放入每个节点上的 resolv.conf,以便 kube-dns 将您用作上游。我不认为 GKE 有办法配置这个不会在节点升级时丢失。您可以编写一个控制器,定期通过 SSH 连接到 VM 并将其写出,然后检查您的 kube-dns 容器是否正确。漂白
我认为正确的答案是使用集群内配置映射来通知 kubelet 或 DNS(或两者)。如果您认为这些可能是可行的答案(尽管存在时间问题),那么如果您打开一个 GitHub 问题进行讨论会很棒。它将在那里获得更多知名度。
我通过在 k8s 集群中设置 dnsmasq 服务并将除 dnsmasq 之外的所有 pods 名称服务器指向 dnsmasq 服务来解决这个问题。
dnsmasq 将根据域后缀将请求转发到正确的名称服务器。
因此内部和外部 vpn 查找都将起作用。
设置 dnsmasq 服务。
pods 可以看起来像这样,确保它至少有 2 pods 因为它需要是 HA。
apiVersion: v1
kind: Pod
metadata:
name: dnsmasq
spec:
containers:
- name: dnsmasq
image: "andyshinn/dnsmasq:2.76"
ports:
- containerPort: 53
hostPort: 53
protocol: UDP
- containerPort: 53
hostPort: 53
protocol: TCP
args: [
"-S", "/consul/10.3.20.86",
"-S", "/consul/10.3.20.88",
"-S", "/consul/10.3.20.90",
"-S", "/your-vpn-domain.dom/10.3.128.22",
"-S", "/your-vpn-domain.dom/10.3.128.23"
]
securityContext:
capabilities:
add:
- NET_ADMIN
添加 resolv-conf 配置映射。
#!/bin/bash
DNS_IP=$(kubectl get svc --template '{{.spec.clusterIP}}' dnsmasq)
DNS_POD=$(kubectl get pod -n kube-system | grep -v kube-dns-autoscaler | grep ^kube-dns | head -1 | awk '{ print ; }')
DOMAIN=$(kubectl describe -n kube-system pod/${DNS_POD} | grep -- --domain= | sed -Ee 's/.*--domain=(.*)\..*//')
SEARCH=$(kubectl exec -n kube-system ${DNS_POD} -c kubedns -- cat /etc/resolv.conf | grep ^search | cut -d' ' -f2-)
VPN_SEARCH="your-vpn-domain.dom"
kubectl create -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: resolv-conf
data:
resolv.conf: |
# This file is created by resolv-conf config map and points to the dnsmasq service.
search default.svc.${DOMAIN} svc.${DOMAIN} ${DOMAIN} ${SEARCH} ${VPN_SEARCH}
nameserver ${DNS_IP}
ndots:5
EOF
在您的 services/pods 中安装 cfgmap。
将此添加到您的 pods
volumeMounts:
- mountPath: /etc/resolv.conf
name: resolv-conf
subPath: resolv.conf
readOnly: true
volumes:
- name: resolv-conf
configMap:
name: resolv-conf
这个解决方案可能会被认为有点丑陋,但目前没有太多其他选择。将来我希望看到 Google Cloud 或 kube-dns 的 dns 转发功能。
Google Cloud 不为指定的 domains/zones 提供 DNS 转发功能,这有点疯狂。
我正在尝试将我的本地集群迁移到 GKE。为了促进这种转变,我需要能够解析遗留服务的名称。
假设 networking/VPN 是一个已解决的问题。
目前有没有办法用 GKE 做到这一点?
实际上我正在尝试向每个 /etc/resolv.conf
添加一个 NS有效没有
如果您修改节点的 resolv.conf,pods 将继承更改。
但是,glibc 禁止使用超过 3 个名称服务器或超过 6 个搜索记录。
GCE VM 使用 2 个名称服务器和 3 个搜索来访问节点元数据和项目网络。 GKE 使用 1 个名称服务器和 3 个搜索。 剩下 0 个名称服务器和 0 个搜索。
看到这个问题:https://github.com/kubernetes/kubernetes/issues/9079 这个问题:https://github.com/kubernetes/kubernetes/issues/9132
我想对 Eric 所说的内容进行补充,并对其进行一些修改。
我们在 kubernetes 1.1 "settling period" 期间的一个认识是 resolv.conf 和解析器行为等方面并没有真正的规范。不同的解析器库做不同的事情,这给我们的用户带来了痛苦。
具体来说,一些常见的解析器假定所有 nameserver
都是可替代的,如果您有处理 DNS 命名空间不同部分的名称服务器,它们就会中断。我们决定,对于 kube 1.2,我们不会将多个 nameserver
行传递到容器中。相反,我们只传递 kube-dns 服务器,它处理 cluster.local
查询并将任何其他查询转发到 "upstream" 名称服务器。
我们怎么知道 "upstream" 是什么?我们使用节点的nameservers
。每个 pod 都有一个 dnsPolicy 字段来管理这个选择。最终结果是容器在我们拥有的 resolv.conf 中看到一个 nameserver
,并且该名称服务器处理整个 DNS 命名空间。
这实际上意味着您没有很好的钩子来插入您自己的名称服务器。您可以将 --cluster-dns
标志更改为 kubelets 以指向您自己的 DNS 服务器,然后该服务器将转发到 kube-dns,然后再转发到 "upstream"。问题是 GKE 并不真正支持以这种方式更改标志。 If/when 节点已更新,标志将消失以支持默认值。
可能的解决方案:
让 kubelet 从集群内配置中读取它们的标志。这已经是记录计划,但不在 v1.2
中
让 kube-dns 带一个标志来指示 "upstream" 是什么。 Kube-dns 是一个 "cluster addon",因此最终用户并不真正可变(我们将使用您的集群更新它并丢失您的更改)。
让 kube-dns 从集群内配置中读取其标志,并获取一个指示 "upstream" 是什么的标志。这是一个可行的想法,但可能不适用于 v1.2(为时已晚)。 可能可以将其修补到 v1 中。2.x但这并不是真正的错误修复,而是一个功能。
将您自己的 DNS 服务器放入每个节点上的 resolv.conf,以便 kube-dns 将您用作上游。我不认为 GKE 有办法配置这个不会在节点升级时丢失。您可以编写一个控制器,定期通过 SSH 连接到 VM 并将其写出,然后检查您的 kube-dns 容器是否正确。漂白
我认为正确的答案是使用集群内配置映射来通知 kubelet 或 DNS(或两者)。如果您认为这些可能是可行的答案(尽管存在时间问题),那么如果您打开一个 GitHub 问题进行讨论会很棒。它将在那里获得更多知名度。
我通过在 k8s 集群中设置 dnsmasq 服务并将除 dnsmasq 之外的所有 pods 名称服务器指向 dnsmasq 服务来解决这个问题。
dnsmasq 将根据域后缀将请求转发到正确的名称服务器。
因此内部和外部 vpn 查找都将起作用。
设置 dnsmasq 服务。
pods 可以看起来像这样,确保它至少有 2 pods 因为它需要是 HA。apiVersion: v1 kind: Pod metadata: name: dnsmasq spec: containers: - name: dnsmasq image: "andyshinn/dnsmasq:2.76" ports: - containerPort: 53 hostPort: 53 protocol: UDP - containerPort: 53 hostPort: 53 protocol: TCP args: [ "-S", "/consul/10.3.20.86", "-S", "/consul/10.3.20.88", "-S", "/consul/10.3.20.90", "-S", "/your-vpn-domain.dom/10.3.128.22", "-S", "/your-vpn-domain.dom/10.3.128.23" ] securityContext: capabilities: add: - NET_ADMIN
添加 resolv-conf 配置映射。
#!/bin/bash DNS_IP=$(kubectl get svc --template '{{.spec.clusterIP}}' dnsmasq) DNS_POD=$(kubectl get pod -n kube-system | grep -v kube-dns-autoscaler | grep ^kube-dns | head -1 | awk '{ print ; }') DOMAIN=$(kubectl describe -n kube-system pod/${DNS_POD} | grep -- --domain= | sed -Ee 's/.*--domain=(.*)\..*//') SEARCH=$(kubectl exec -n kube-system ${DNS_POD} -c kubedns -- cat /etc/resolv.conf | grep ^search | cut -d' ' -f2-) VPN_SEARCH="your-vpn-domain.dom" kubectl create -f - <<EOF apiVersion: v1 kind: ConfigMap metadata: name: resolv-conf data: resolv.conf: | # This file is created by resolv-conf config map and points to the dnsmasq service. search default.svc.${DOMAIN} svc.${DOMAIN} ${DOMAIN} ${SEARCH} ${VPN_SEARCH} nameserver ${DNS_IP} ndots:5 EOF
在您的 services/pods 中安装 cfgmap。 将此添加到您的 pods
volumeMounts: - mountPath: /etc/resolv.conf name: resolv-conf subPath: resolv.conf readOnly: true volumes: - name: resolv-conf configMap: name: resolv-conf
这个解决方案可能会被认为有点丑陋,但目前没有太多其他选择。将来我希望看到 Google Cloud 或 kube-dns 的 dns 转发功能。
Google Cloud 不为指定的 domains/zones 提供 DNS 转发功能,这有点疯狂。