【问题标题】:Add host mapping to /etc/hosts in Kubernetes在 Kubernetes 中添加主机映射到 /etc/hosts
【发布时间】:2016-12-24 07:52:17
【问题描述】:

我对 Kubernetes 中的 DNS 映射有疑问。

我们有一些可以从互联网访问的服务器。全球 DNS 将这些服务器的域名转换为公共互联网 IP。 出于安全考虑,某些服务无法通过公共 IP 访问。

从公司内部,我们将带有私有 IP 的 DNS 映射添加到由 kubernetes 管理的 docker 容器内的 /etc/hosts 以手动访问这些服务器。

我知道 docker 支持命令 --add-host 在执行docker run 时更改/etc/hosts。我不确定最新的 kubernetes 是否支持此命令,例如 kuber 1.41.5

另一方面,我们可以为 docker 容器包装启动脚本,

  • 首先将映射附加到/etc/hosts
  • 启动我们的应用程序

我只想在每个容器中首次运行后更改一次文件。是否有一种简单的方法可以做到这一点,因为开发环境和生产环境之间的映射关系可能不同,或者任何与此相关的命令由 kubernetes 本身提供?

【问题讨论】:

  • 现在可以直接在部署配置中添加。

标签: docker dns kubernetes


【解决方案1】:

要以“半”动态方式将主机名添加到主机文件,可以使用 postStart 挂钩:

spec:
  containers:
  - name: somecontainer
    image: someimage
    lifecycle:
      postStart:
        exec:
          command:
            - "cat"
            - "someip"
            - "somedomain"
            - ">"
            - "/etc/hosts"

然而,更好的方法是在多个阶段使用代表服务的抽象名称。例如,不要使用 database01.production.company.com,而是使用 database01 并设置环境,以便在生产设置中解析为生产环境,在暂存设置中解析为暂存。

最后,还可以编辑 kubedns 设置,以便可以使用 kubernetes DNS 检索外部 DNS 名称。然后,您只需在代码中使用您需要的任何名称,它就会“自动”工作。例如,请参阅https://github.com/kubernetes/kubernetes/issues/23474 了解如何设置(skydns 版本与版本之间有所不同:一些较旧的版本确实无法使用此功能,因此请至少升级到 kube 1.3 以使其正常工作)

【讨论】:

  • 非常感谢您的更新。这很有用。我刚刚阅读了文档kubernetes.io/docs/user-guide/container-environment 并尝试了这个。我认为命令需要稍微更改为exec: command: - "sh" - "-c" - "echo someip somedomain > /etc/hosts"。似乎 kubernetes 只是使用os/exec exec.Command(args).Run() 来运行命令,因此不支持“|,>,>>”。感谢您的帮助:)
  • @qingdaojunzuo 是的,你是对的:所有这些命令部分的命令语法都非常不友好,没有测试就当场猜测它们是错误的秘诀:)
【解决方案2】:

在主机系统上创建一个文件(或秘密),其中包含您需要的所有额外主机(例如 /tmp/extra-hosts)

然后在 K8S 清单中:

spec:
  containers:
    - name: haproxy
      image: haproxy
      lifecycle:
        postStart:
          exec:
            command: ["/bin/sh", "-c", "cat /hosts >> /etc/hosts"]

      volumeMounts:
        - name: haproxy-hosts
          mountPath: /hosts

      volumes:
        - name: haproxy-hosts
          hostPath:
            path: /tmp/extra-hosts

【讨论】:

    【解决方案3】:

    来自kubernetes.io/docs: “除了默认样板,我们可以在 hosts 文件中添加额外的条目来解析 foo.local, bar.local 到 127.0.0.1 和 foo.remote, bar.remote 到 10.1.2.3,我们可以通过添加 HostAliases 到.spec.hostAliases 下的 Pod:"

    你也可以"Configure stub-domain and upstream DNS servers"

    【讨论】:

      【解决方案4】:

      ++ 找到这篇文章在 pod 中添加 /etc/hosts 条目:

      使用 HostAliases 向 Pod /etc/hosts 添加条目: 服务/网络/hostaliases-pod.yaml

      除了默认样板之外,您还可以向 hosts 文件添加其他条目。例如:要将 foo.local、bar.local 解析为 127.0.0.1 并将 foo.remote、bar.remote 解析为 10.1.2.3,您可以在 .spec.hostAliases 下为 Pod 配置 HostAliases:

      apiVersion: v1
      kind: Pod
      metadata:
        name: hostaliases-pod
      spec:
        restartPolicy: Never
        hostAliases:
        - ip: "127.0.0.1"
          hostnames:
          - "foo.local"
          - "bar.local"
        - ip: "10.1.2.3"
          hostnames:
          - "foo.remote"
          - "bar.remote"
        containers:
        - name: cat-hosts
          image: busybox
          command:
          - cat
          args:
          - "/etc/hosts"
      

      来源:https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/

      【讨论】:

        【解决方案5】:

        现在可以直接在部署描述中添加hostAliases 部分。

        作为如何使用hostAliases 部分的完整示例,我还包含了示例部署的周边代码。

        apiVersion : apps/v1
        kind: Deployment
        metadata:
          name: "backend-cluster"
        spec:
          replicas: 1
          selector:
            matchLabels:
              app: "backend"
          template:
            metadata:
              labels:
                app: "backend"
            spec:
              containers:
              - name: "backend"
                image: "exampleregistry.azurecr.io/backend"
                ports:
                - containerPort: 80
              hostAliases:
              - hostnames:
                - "www.example.com"
                ip: "10.0.2.4"
        

        重要的部分只是文件的一部分,为了清楚起见这里省略了:

        ...
              hostAliases:
              - hostnames:
                - "www.example.com"
                ip: "10.0.2.4"
        

        【讨论】:

          【解决方案6】:

          您应该能够在没有选择器的情况下添加 Service 并手动创建 Endpoint 对象,如此处文档中所述 - http://kubernetes.io/docs/user-guide/services/#services-without-selectors

          服务通常抽象出对 Kubernetes Pod 的访问,但它们可以 还抽象其他类型的后端。

          例如:

          您希望在生产中拥有一个外部数据库集群,但在测试中您使用自己的数据库。

          您希望将您的服务指向另一个服务 命名空间或在另一个集群上。

          您正在将工作负载迁移到 Kubernetes 和您的一些后端在 Kubernetes 之外运行。

          【讨论】:

          • 感谢您的回复。在某些情况下,这对我很有用。我们可以在 kubernetes 集群中使用服务名而不是域名/IP。现在我们在集群中有一个服务 A。 A 使用 kafka 和 zookeeper。 Kafka 和 zookeeper 部署在 kube 集群之外。服务 A 从 zookeeper 获取所有带有域名的 kafka brokers。这些域名无法更改为 kube 服务名称,因为它们与 kube 集群外的其他系统共享。这些域名需要翻译成服务A使用的私有IP。有什么方法可以轻松解决这个问题吗?非常感谢您的帮助。
          猜你喜欢
          • 2011-07-05
          • 1970-01-01
          • 1970-01-01
          • 2016-07-08
          • 2017-05-17
          • 2020-07-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多