Есть ли способ добавить произвольные записи в kube-dns?

Я буду использовать очень конкретный способ объяснения своей проблемы, но я думаю, что это лучше конкретизировать, чем объяснять абстрактно ...

Скажем, существует реплика MongoDB, установленная вне кластера Kubernetes, но в сети. IP-адреса всех членов набора реплик были разрешены / etc / hosts на серверах приложений и серверах баз данных.

На этапе эксперимента / перехода мне нужно получить доступ к этим серверам mongo db из модулей kubernetes. Однако kubernetes, похоже, не позволяет добавлять пользовательские записи в / etc / hosts в подах / контейнерах.

Наборы реплик MongoDB уже работают с большим набором данных, создание нового набора реплик в кластере не является вариантом.

Поскольку я использую GKE, я полагаю, что следует избегать изменения каких-либо ресурсов в пространстве имен kube-dns. Последнее, что нужно попробовать - настроить или заменить kube-dns, чтобы он соответствовал моим потребностям.

Есть ли способ разрешить IP-адрес пользовательских имен хостов в кластере Kubernetes?

Это просто идея, но если kube2sky может читать некоторые записи configmap и использовать их как записи DNS, это будет здорово. например repl1.mongo.local: 192.168.10.100.

РЕДАКТИРОВАТЬ: я сослался на этот вопрос из https://github.com/kubernetes/kubernetes/issues/12337


person hiroshi    schedule 11.05.2016    source источник


Ответы (5)


Тип внешнего имени требуется для доступа к хостам или IP-адресам за пределами кубернетов.

Следующее сработало для меня.

{
    "kind": "Service",
    "apiVersion": "v1",
    "metadata": {
        "name": "tiny-server-5",
        "namespace": "default"
    },
    "spec": {
        "type": "ExternalName",
        "externalName": "192.168.1.15",
        "ports": [{ "port": 80 }]
    }
}
person Gapmeister66    schedule 12.03.2017
comment
Не используйте это! externalName должен указывать только на внешнее имя, такое как запись DNS. См. Примечание в документации K8S: ExternalName принимает строку адреса IPv4, но как имя DNS, состоящее из цифр, а не как IP-адрес. Внешние имена, похожие на адреса IPv4, не разрешаются CoreDNS или ingress-nginx, поскольку ExternalName предназначено для указания канонического DNS-имени. Чтобы жестко закодировать IP-адрес, рассмотрите возможность использования автономных служб. (kubernetes.io/docs/concepts/services-networking/service/) Моралло ответ правильный. - person Okke; 25.02.2019

Сейчас есть 2 возможных решения этой проблемы:

  1. По подам (добавление изменений к каждому поду, необходимому для разрешения этих доменов)
  2. кластерно (добавление изменений в центральное место, к которому имеют доступ все модули, в нашем случае это DNS)

Начнем с решения, связанного с подами:

Начиная с Kunbernetes 1.7, теперь можно добавлять записи в /etc/hosts пода напрямую, используя .spec.hostAliases

Например: чтобы разрешить foo.local, bar.local в 127.0.0.1 и foo.remote, bar.remote в 10.1.2.3, вы можете настроить HostAliases для Pod в .spec.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"

Кластерное решение:

Начиная с Kubernetes v1.12, CoreDNS является рекомендуемым DNS-сервером, заменяющим kube-dns.. Если ваш кластер изначально использовал kube-dns, вы все равно можете развернуть kube-dns, а не CoreDNS. Я предполагаю, что вы используете CoreDNS в качестве DNS K8S.

В CoreDNS можно добавлять произвольные записи внутри кластерного домена, и таким образом все модули будут разрешать эти записи непосредственно из DNS без необходимости изменять каждый /etc/hosts файл в каждом модуле.

Первое:

Давайте изменим coreos ConfigMap и добавим необходимые изменения:

kubectl edit cm coredns -n kube-system 

apiVersion: v1
kind: ConfigMap
data:
  Corefile: |
    .:53 {
        errors
        health {
          lameduck 5s
        }
        hosts /etc/coredns/customdomains.db example.org {
          fallthrough
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
          pods insecure
          fallthrough in-addr.arpa ip6.arpa
        }
        prometheus :9153
        forward . "/etc/resolv.conf"
        cache 30
        loop
        reload
        loadbalance
    }
  customdomains.db: |
    10.10.1.1 mongo-en-1.example.org
    10.10.1.2 mongo-en-2.example.org
    10.10.1.3 mongo-en-3.example.org
    10.10.1.4 mongo-en-4.example.org

В основном мы добавили две вещи:

  1. Плагин hosts перед плагином kubernetes и использовал параметр fallthrough плагина hosts для удовлетворения нашего случая.

    Чтобы пролить еще немного света на вариант fallthrough. Любой заданный бэкэнд обычно является последним словом для своей зоны - он либо возвращает результат, либо возвращает NXDOMAIN для запроса. Однако иногда это нежелательное поведение, поэтому некоторые плагины поддерживают параметр fallthrough. Когда fallthrough включен, вместо того, чтобы возвращать NXDOMAIN, когда запись не найдена, плагин передает запрос вниз по цепочке. Бэкэнд дальше по цепочке имеет возможность обработать запрос, и этот бэкэнд в нашем случае kubernetes.

  2. Мы добавили новый файл в ConfigMap (customdomains.db) и добавили туда наши пользовательские домены (mongo-en-*.example.org).

И наконец, не забудьте добавить файл customdomains.db в config-volume для шаблона модуля CoreDNS:

kubectl edit -n kube-system deployment coredns
volumes:
        - name: config-volume
          configMap:
            name: coredns
            items:
            - key: Corefile
              path: Corefile
            - key: customdomains.db
              path: customdomains.db

и, наконец, чтобы сообщить CoreDNS о необходимости корректной перезагрузки (каждый модуль работает):

$ kubectl -n kube-system exec coredns-461002909-7mp96 -- kill -SIGUSR1 1
person 0xMH    schedule 17.12.2020

Для записи: альтернативное решение для тех, кто не проверяет упомянутую проблему с github.

Вы можете определить «внешнюю» службу в Kubernetes, не указав какой-либо селектор или ClusterIP. Вы также должны определить соответствующую конечную точку, указывающую на ваш внешний IP-адрес.

Из документации Kubernetes:

{
    "kind": "Service",
    "apiVersion": "v1",
    "metadata": {
        "name": "my-service"
    },
    "spec": {
        "ports": [
            {
                "protocol": "TCP",
                "port": 80,
                "targetPort": 9376
            }
        ]
    }
}
{
    "kind": "Endpoints",
    "apiVersion": "v1",
    "metadata": {
        "name": "my-service"
    },
    "subsets": [
        {
            "addresses": [
                { "ip": "1.2.3.4" }
            ],
            "ports": [
                { "port": 9376 }
            ]
        }
    ]
}

Таким образом, вы можете указать своему приложению внутри контейнеров на my-service:9376, а трафик должен быть перенаправлен на 1.2.3.4:9376.

Ограничения:

  • Используемое DNS-имя должно состоять только из букв, цифр или тире. Вы не можете использовать многоуровневые имена (something.like.this). Это означает, что вам, вероятно, придется изменить свое приложение так, чтобы оно указывало только на your-service, а не на yourservice.domain.tld.
  • Вы можете указать только конкретный IP-адрес, а не DNS-имя. Для этого вы можете определить своего рода псевдоним DNS с помощью службы типа ExternalName.
person morallo    schedule 13.02.2017
comment
Спасибо. Эта информация будет полезна, если требуется имя хоста - ›сопоставление IP. - person hiroshi; 14.02.2017

ОБНОВЛЕНИЕ: 2017-07-03 Kunbernetes 1.7 теперь поддерживает Добавление записей в Pod / etc / hosts с помощью HostAliases.


Решение не о kube-dns, а о / etc / hosts. Во всяком случае, следующий трюк, похоже, пока работает ...

РЕДАКТИРОВАТЬ: изменение / etc / hosts может иметь состояние гонки с системой кубернетов. Позвольте ему повторить попытку.

1) создать configMap

apiVersion: v1
kind: ConfigMap
metadata:
  name: db-hosts
data:
  hosts: |
    10.0.0.1  db1
    10.0.0.2  db2

2) Добавьте сценарий с именем ensure_hosts.sh.

#!/bin/sh                                                                                                           
while true
do
    grep db1 /etc/hosts > /dev/null || cat /mnt/hosts.append/hosts >> /etc/hosts
    sleep 5
done

Не забывайте chmod a+x ensure_hosts.sh.

3) Добавьте сценарий оболочки start.sh ваше изображение

#!/bin/sh
$(dirname "$(realpath "$0")")/ensure_hosts.sh &
exec your-app args...

Не забывай chmod a+x start.sh

4) Используйте configmap как том и запустите start.sh

apiVersion: extensions/v1beta1
kind: Deployment
...
spec:
  template:
    ...
    spec:
      volumes:
      - name: hosts-volume
        configMap:
          name: db-hosts
      ...
      containers:
        command:
        - ./start.sh
        ...
        volumeMounts:
        - name: hosts-volume
          mountPath: /mnt/hosts.append
        ...
person hiroshi    schedule 15.05.2016
comment
Проголосовали против ... Я знаю, это не должен быть правильный ответ, но нам нужно обходное решение. - person hiroshi; 30.09.2016

Использование configMap кажется лучшим способом установки DNS, но это немного сложно, если просто добавить несколько записей (на мой взгляд). Поэтому я добавляю записи в /etc/hosts с помощью сценария оболочки, выполняемого докером CMD.

Например:

Dockerfile

...(ignore)
COPY run.sh /tmp/run.sh
CMD bash /tmp/run.sh

run.sh

#!/bin/bash
echo repl1.mongo.local 192.168.10.100 >> /etc/hosts
# some else command...

Обратите внимание: если вы запускаете БОЛЕЕ ОДНОГО контейнера в модуле, вам необходимо добавить скрипт в каждый контейнер, поскольку кубернеты запускают контейнер случайным образом, /etc/hosts может быть переопределен другим контейнером (который запускается позже).

person gaga5lala    schedule 02.11.2016
comment
Ах, несколько контейнеров в модуле могут перезаписать / etc / hosts ... кажется ... Спасибо за понимание. - person hiroshi; 04.11.2016