Kubernetes Pod 与 OpenVPN 客户端 sidecar 一起运行,并通过隧道和集群具有功能性 DNS

标签 kubernetes dns openvpn dnsmasq sidecar

我尝试构建一个运行需要以下服务的 Pod:

  1. 通过其 FQDN (*.cluster.local) 解析和访问的集群内部服务,
  2. 同时还具有与远程集群的事件 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/

相关文章:

kubernetes - 使用Katacoda关注Kubernetes

docker - 用于调试的 Golang docker 文件

c# - 在不使用主机文件的情况下添加条目 DNS 客户端解析器缓存

linux - Bash 脚本自动登录 VPN

java - 使用 OpenVPN 创建 VPN

openvpn - 选项错误 : Unrecognized option or missing or extra parameter(s) in client4. ovpn :88: ca (2. 4.7)

networking - 从 Kubernetes 服务访问主机 localhost

kubernetes - K8s,尝试连接外部数据库的 pod 的表观 IP

linux - Perl 套接字如何在 Linux 下解析主机名?

c# - Dns.GetHostAddress(主机名)在 Ubuntu 16.04 中没有这样的设备或地址异常