Как использовать Ingress Resources для обнаружения сервисов, отличных от Kubernetes, с помощью NGINX и BIND DNS

Kubernetes обеспечивает превосходное встроенное обнаружение сервисов через сервисы kubernetes и использует CoreDNS для разрешения сервисов внутри кластера Kubernetes. Ваши приложения в kubernetes могут работать в любом месте кластера, и службы Kubernetes позаботятся о том, чтобы направить их на правильный IP-адрес. Однако в настоящее время большинство организаций не используют Kubernetes на 100 % и имеют смешанные рабочие нагрузки служб, использующих K8S и виртуальные машины. Некоторые находятся на пути миграции с виртуальных машин на K8S и не хотят выполнять миграцию Большого взрыва. В то время как обнаружение сервисов в K8s несложно, Kubernetes не обнаруживает сервисы, работающие на виртуальных машинах, особенно связь Восток-Запад.

Существует множество способов ускорить обнаружение внутренних сервисов между ресурсами Kubernetes и сервисами виртуальных машин и наоборот. Некоторые могут захотеть использовать для этого такие инструменты, как Consul, и это отличный способ сделать это. Однако в этой статье будет описано, как использовать Bind DNS-сервер, собственные входные ресурсы kubernetes и балансировщики нагрузки NGINX, работающие на контейнерах, для предоставления трафика серверным службам, работающим на виртуальной машине. Виртуальная машина, в свою очередь, может обнаруживать службы kubernetes, используя тот же DNS-сервер Bind для динамического обнаружения служб.

Предварительные требования

Вам понадобится контроллер входящего трафика, работающий в кластере kubernetes. Точная конфигурация может варьироваться в зависимости от вашей настройки.

Для получения более подробной информации о локальной установке или настройке Bare-Metal см. https://github.com/kubernetes/ingress-nginx.

В следующих абзацах описывается пример установки, в которой контроллер Nginx Ingress предоставляется через NodePort, а балансировщик нагрузки NGINX находится перед NodePort, чтобы обеспечить единую конечную точку с балансировкой нагрузки для установки.

Он также предоставляет DNS-сервер как NodePort, а балансировщик нагрузки NGINX, описанный в файле nginx.conf, также поддерживает конфигурацию DNS. (Я вернусь к этому позже, когда буду описывать настройку Bind DNS)

Если вы используете облачную настройку kubernetes, вы можете предоставить Ingress Controller и Bind DNS Server как службу LoadBalancer вместо службы NodePort, как описано.

Если контроллеры Ingress предоставляются вам изначально, например, в GKE, вам не нужно выполнять настройку Ingress, а просто подставьте IP-адрес Load Balancer вашего контроллера Ingress.

В любой ситуации вы должны прибыть с IP-адресом балансировщика нагрузки Bind DNS Server (описание позже) и IP-адресом балансировщика нагрузки контроллера входящего трафика.

Если вы хотите использовать пример настройки, выполните следующие действия.

git clone https://github.com/bharatmicrosystems/kubernetes-nginx-service-discovery.git
kubectl apply -f kubernetes-nginx-service-discovery/ingress/mandatory.yaml
kubectl apply -f kubernetes-nginx-service-discovery/ingress/service-nodeport.yaml

Затем вам нужно будет запустить новый экземпляр виртуальной машины, где вам нужно установить nginx и скопировать файл nginx.conf в /etc/nginx/nginx.conf. Файл nginx.conf предполагает, что у вас есть кластер из трех узлов с узлами node01, node02 и node03 в качестве имен хостов для рабочих узлов, вам необходимо изменить файл nginx.conf в соответствии с вашими настройками.

Шаги по установке NGINX представлены на https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-open-source/

Настройка привязки DNS-сервера

Bind DNS Server — один из самых популярных продуктов DNS с открытым исходным кодом, и я поместил его в контейнер, чтобы его можно было использовать в Kubernetes для обеспечения обнаружения служб K8S и других служб.

Локальная настройка

git clone https://github.com/bharatmicrosystems/kubernetes-nginx-service-discovery.git
sed -i "s/example.com/<YOUR DOMAIN>/g" kubernetes-nginx-service-discovery/bind-dns-server/dns-server.yaml
sed -i "s/dns_loadbalancer_ip_value/<YOUR DNS LOAD BALANCER IP>/g" kubernetes-nginx-service-discovery/bind-dns-server/dns-server.yaml
sed -i "s/ingress_loadbalancer_ip_value/<YOUR INGRESS LOAD BALANCER IP>/g" kubernetes-nginx-service-discovery/bind-dns-server/dns-server.yaml
kubectl apply -f kubernetes-nginx-service-discovery/bind-dns-server/dns-server.yaml

Настройка облака

git clone https://github.com/bharatmicrosystems/kubernetes-nginx-service-discovery.git

Отредактируйте файл yaml, чтобы включить внутреннюю настройку балансировщика нагрузки на основе облачного провайдера. Ниже приведен пример Google Kubernetes Engine.

$ vim kubernetes-nginx-service-discovery/bind-dns-server/dns-server-lb-service.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: dns-server
  annotations:
    cloud.google.com/load-balancer-type: "Internal"
  labels:
    app: dns-server
spec:
  type: LoadBalancer
  ports:
  - port: 53
    targetPort: 53
    protocol: UDP
selector:
  app: dns-server

Применить конфигурацию

kubectl apply -f kubernetes-nginx-service-discovery/bind-dns-server/dns-server-lb-service.yaml

Подождите, пока служба балансировщика нагрузки не появится и не покажет IP-адрес балансировщика нагрузки. Получив IP-адрес балансировщика нагрузки, запишите его, так как он потребуется нам на последующих этапах.

sed -i "s/example.com/<YOUR DOMAIN>/g" kubernetes-nginx-service-discovery/bind-dns-server/dns-server-deployment.yaml
sed -i "s/dns_loadbalancer_ip_value/<YOUR DNS LOAD BALANCER IP>/g" kubernetes-nginx-service-discovery/bind-dns-server/dns-server-deployment.yaml
sed -i "s/ingress_loadbalancer_ip_value/<YOUR INGRESS LOAD BALANCER IP>/g" kubernetes-nginx-service-discovery/bind-dns-server/dns-server-deployment.yaml
kubectl apply -f kubernetes-nginx-service-discovery/bind-dns-server/dns-server-deployment.yaml

Сделайте запись в конфигурации coredns для DNS-сервера Bind, которая гарантирует, что любые DNS-запросы, выполняемые в службах K8S, также будут запрашивать DNS-сервер Bind.

kubectl edit -n kube-system cm/coredns
apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health
        kubernetes cluster.local in-addr.arpa ip6.arpa {
           pods insecure
           fallthrough in-addr.arpa ip6.arpa
        }
        prometheus :9153
        forward . 172.16.0.1
        cache 30
        loop
        reload
        loadbalance
    }
+    <YOUR DOMAIN HERE>:53 {
+        errors
+        cache 30
+        forward . <YOUR DNS LOAD BALANCER IP>
+    }

На виртуальной машине, на которой запущена служба, выполните следующее, чтобы обновить запись в файле /etc/resolv.conf.

sed -i "1 i\nameserver <YOUR DNS LOAD BALANCER IP>\noptions timeout:1" /etc/resolv.conf

Настройка балансировщика нагрузки NGINX

sed -i "s/example.com/<YOUR DOMAIN>/g" kubernetes-nginx-service-discovery/nginx-load-balancer/nginx.yaml
kubectl apply -f kubernetes-nginx-service-discovery/nginx-load-balancer/nginx.yaml

Приведенные выше команды запустят балансировщики нагрузки NGINX, которые будут считывать ресурсы Ingress, чтобы настроить себя так, чтобы они указывали на серверные конечные точки, указанные в метках backend-host и backend-port. Ресурсы Ingress, такие как приведенный ниже пример yaml, будут автоматически генерироваться подом, когда агенты, работающие на внутренних машинах, взаимодействуют с REST API, работающим в поде.

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-backend-ingress
  annotations:
    nginx.ingress.kubernetes.io/add-base-url: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
  labels:
    backend-host: "nginx-backend-host1,nginx-backend-host2"
    backend-port: "80"
spec:
  rules:
  - host: nginx.example.com
    http:
      paths:
        - path: /
          backend:
            serviceName: nginx-load-balancer
            servicePort: 80

Установка агента

Агенты работают на внутренних серверах, которые следят за каталогом конфигурации и обращаются к ресурсам nginx-load-balancer, которые доступны на настроенном хосте и порту, как указано в настраиваемых файлах JSON, работающих в агенте. Агент обеспечивает динамическое обнаружение служб, и вы можете свободно перемещать свои рабочие нагрузки на любую виртуальную машину, на которой работает агент. Конфигурационный JSON должен находиться в правильном каталоге на этой виртуальной машине.

Выберите каталог конфигурации и запустите ниже

mkdir -p <configuration_dir>
./kubernetes-nginx-service-discovery/agent/setup.sh <configuration_dir> <domain>

Приведенные выше команды запустят агент как службу systemd. И вы готовы приступить к созданию JSON-файлов конфигурации в каталоге конфигурации.

Ниже приведен пример конфигурации

$ vim <configuration_dir>/example.json
[
{
  "name": "nginx-backend-ingress-example",
  "ingress_host": "nginx.example.com",
  "server_host": "nginx-backend",
  "port": "80"
}
]

У вас может быть несколько файлов конфигурации и множество записей в файле конфигурации. Рекомендуется иметь один файл конфигурации для каждой службы и одну запись в файле для каждой комбинации сервер_хост/порт. Сервер server_host должен быть доступен с рабочих узлов кластера Kubernetes.

Тестирование установки

Установите NGINX на серверной ВМ (см. https://www.nginx.com/resources/wiki/start/topics/tutorials/install/) и создайте JSON-файл конфигурации.

$ vim <configuration_dir>/example.json
[
{
  "name": "nginx-backend-ingress-example",
  "ingress_host": "nginx.<YOUR DOMAIN>",
  "server_host": "<HOST NAME OF THE SERVER>",
  "port": "80"
}
]

Запустите следующее на Backend VM, чтобы увидеть, разрешает ли она DNS и использует ли маршрут Kubernetes для доступа к себе.

$ curl http://nginx.<YOUR DOMAIN>
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Попробуйте запустить ту же команду из контейнера K8S с помощью команды exec, и вы должны получить тот же вывод, который доказывает, что обнаружение служб работает в кластере K8S и за его пределами.

Дальнейшее чтение

Спасибо, что прочитали. Надеюсь, вам понравилась история. Если вам интересно узнать больше, ознакомьтесь со следующими историями, поскольку они могут вас заинтересовать.