我尝试构建一个运行需要以下服务的 Pod:
- 通过其 FQDN (
*.cluster.local
) 解析和访问的集群内部服务, - 同时还具有与远程集群的事件 OpenVPN 连接,并通过其 FQDN (
*.cluster.remote
) 解析和访问来自该远程集群的服务。
没有 OpenVPN sidecar 的 Pod 中的服务容器可以使用 *.cluster.local
命名空间访问提供 FQDN 的所有服务。在这种情况下,这是 /etc/resolv.conf
:
nameserver 169.254.25.10
search default.cluster.local svc.cluster.local cluster.local
options ndots:5
当OpenVPN sidecar管理resolv.conf
OpenVPN sidecar 的启动方式如下:
containers:
{{- if .Values.vpn.enabled }}
- name: vpn
image: "ghcr.io/wfg/openvpn-client"
imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
volumeMounts:
- name: vpn-working-directory
mountPath: /data/vpn
env:
- name: KILL_SWITCH
value: "off"
- name: VPN_CONFIG_FILE
value: connection.conf
securityContext:
privileged: true
capabilities:
add:
- "NET_ADMIN"
resources:
limits:
cpu: 100m
memory: 80Mi
requests:
cpu: 25m
memory: 20Mi
{{- end }}
和 OpenVPN 客户端配置包含以下几行:
script-security 2
up /etc/openvpn/up.sh
down /etc/openvpn/down.sh
然后 OpenVPN 客户端将覆盖 resolv.conf
,使其包含以下内容:
nameserver 192.168.255.1
options ndots:5
在这种情况下,*.cluster.remote
中的任何服务都已解析,但*.cluster.local
中的服务均未解析。这是预期的。
当OpenVPN sidecar不管理resolv.conf
,但提供了spec.dnsConfig
从 OpenVPN 客户端配置中删除以下行:
script-security 2
up /etc/openvpn/up.sh
down /etc/openvpn/down.sh
spec.dnsConfig
提供如下:
dnsConfig:
nameservers:
- 192.168.255.1
searches:
- cluster.remote
然后,resolv.conf
将如下所示:
nameserver 192.168.255.1
nameserver 169.254.25.10
search default.cluster.local svc.cluster.local cluster.local cluster.remote
options ndots:5
这适用于 *.cluster.remote
,但不适用于任何 *.cluster.local
,因为只要第一次尝试,就会尝试第二个名称服务器.我注意到有些人会通过设置命名空间轮换和超时 1 秒来绕过这个限制,但这种行为对我来说看起来非常忙碌,我不会考虑这个,甚至不作为解决方法。或者也许我错过了什么。 我的第一个问题是:轮换和超时在这种情况下是否可行?
我的第二个问题是:有什么方法可以使 *.cluster.local
和 *.cluster.remote
DNS 解析从内部的服务容器可靠地工作Pod 和 不使用类似dnsmasq
的东西?
我的第三个问题是:如果 dnsmasq
是必需的,我该如何配置、提供和覆盖 resolv.conf
,同时确保 Kubernetes 提供的名称服务器可以是任何东西(在本例中为 169.254.25.10
)。
最好的, 佐尔坦
最佳答案
我宁愿通过运行 sidecar DNS 服务器来解决问题,因为:
- 更易于实现、维护和理解;
- 毫无意外地发挥作用。
这是一个带有 CoreDNS
的示例 pod:
apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: default
spec:
volumes:
- name: config-volume
configMap:
name: foo-config
items:
- key: Corefile
path: Corefile
dnsPolicy: None # SIgnals Kubernetes that you want to supply your own DNS - otherwise `/etc/resolv.conf` will be overwritten by Kubernetes and there is then no way to update it.
dnsConfig:
nameservers:
- 127.0.0.1 # This will set the local Core DNS as the DNS resolver. When `dnsPolicy` is set, `dnsConfig` must be provided.
containers:
- name: dns
image: coredns/coredns
env:
- name: LOCAL_DNS
value: 10.233.0.3 # insert local DNS IP address (see kube-dns service ClusterIp)
- name: REMOTE_DNS
value: 192.168.255.1 # insert remote DNS IP address
args:
- '-conf'
- /etc/coredns/Corefile
volumeMounts:
- name: config-volume
readOnly: true
mountPath: /etc/coredns
- name: test
image: debian:buster
command:
- bash
- -c
- apt update && apt install -y dnsutils && cat /dev/stdout
---
apiVersion: v1
kind: ConfigMap
metadata:
name: foo-config
namespace: default
data:
Corefile: |
cluster.local:53 {
errors
health
forward . {$LOCAL_DNS}
cache 30
}
cluster.remote:53 {
errors
health
rewrite stop {
# rewrite cluster.remote to cluster.local and back
name suffix cluster.remote cluster.local answer auto
}
forward . {$REMOTE_DNS}
cache 30
}
上面的 CoreDNS
配置只是将 cluster.local
查询转发到本地服务,将 cluster.remote
- 转发到远程服务。使用它我能够解析两个集群的 kubernetes
服务 IP:
❯ k exec -it -n default foo -c test -- bash
root@foo:/# dig @localhost kubernetes.default.svc.cluster.local +short
10.100.0.1
root@foo:/# dig @localhost kubernetes.default.svc.cluster.remote +short
10.43.0.1
更新:
可能,以下核心 DNS 配置就足够了,以防您需要访问互联网以及 cluster.internal
由 Kubernetes 本身提供:
.:53 {
errors
health
forward . {$LOCAL_DNS}
cache 30
}
cluster.remote:53 {
errors
health
forward . {$REMOTE_DNS}
cache 30
}
关于Kubernetes Pod 与 OpenVPN 客户端 sidecar 一起运行,并通过隧道和集群具有功能性 DNS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68661765/