Разоблачение голого металлического кластера kubernetes для интернета

Я пытаюсь настроить собственный одноузловой кластер kubernetes на голом выделенном сервере. Я не настолько опытен в разработке, но мне нужен какой-то сервис для моего собственного проекта. Я уже сделал настройку кластера с juju а также conjure-up kubernetes над LXD, У меня работает кластер довольно хорошо.

$ juju status

Model                         Controller                Cloud/Region         Version  SLA          Timestamp
conjure-canonical-kubern-3b3  conjure-up-localhost-db9  localhost/localhost  2.4.3    unsupported  23:49:09Z

App                    Version  Status  Scale  Charm                  Store       Rev  OS      Notes
easyrsa                3.0.1    active      1  easyrsa                jujucharms  195  ubuntu
etcd                   3.2.10   active      3  etcd                   jujucharms  338  ubuntu
flannel                0.10.0   active      2  flannel                jujucharms  351  ubuntu
kubeapi-load-balancer  1.14.0   active      1  kubeapi-load-balancer  jujucharms  525  ubuntu  exposed
kubernetes-master      1.13.1   active      1  kubernetes-master      jujucharms  542  ubuntu
kubernetes-worker      1.13.1   active      1  kubernetes-worker      jujucharms  398  ubuntu  exposed

Unit                      Workload  Agent  Machine  Public address  Ports           Message
easyrsa/0*                active    idle   0        10.213.117.66                   Certificate Authority connected.
etcd/0*                   active    idle   1        10.213.117.171  2379/tcp        Healthy with 3 known peers
etcd/1                    active    idle   2        10.213.117.10   2379/tcp        Healthy with 3 known peers
etcd/2                    active    idle   3        10.213.117.238  2379/tcp        Healthy with 3 known peers
kubeapi-load-balancer/0*  active    idle   4        10.213.117.123  443/tcp         Loadbalancer ready.
kubernetes-master/0*      active    idle   5        10.213.117.172  6443/tcp        Kubernetes master running.
  flannel/1*              active    idle            10.213.117.172                  Flannel subnet 10.1.83.1/24
kubernetes-worker/0*      active    idle   7        10.213.117.136  80/tcp,443/tcp  Kubernetes worker running.
  flannel/4               active    idle            10.213.117.136                  Flannel subnet 10.1.27.1/24

Entity  Meter status  Message
model   amber         user verification pending

Machine  State    DNS             Inst id        Series  AZ  Message
0        started  10.213.117.66   juju-b03445-0  bionic      Running
1        started  10.213.117.171  juju-b03445-1  bionic      Running
2        started  10.213.117.10   juju-b03445-2  bionic      Running
3        started  10.213.117.238  juju-b03445-3  bionic      Running
4        started  10.213.117.123  juju-b03445-4  bionic      Running
5        started  10.213.117.172  juju-b03445-5  bionic      Running
7        started  10.213.117.136  juju-b03445-7  bionic      Running

Я также развернул приложение Hello world для вывода приветствия через порт 8080 внутри стручка и nginx-ingress чтобы он перенаправил трафик на этот сервис на указанном хосте.

NAME                               READY   STATUS    RESTARTS   AGE
pod/hello-world-696b6b59bd-fznwr   1/1     Running   1          176m

NAME                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/example-service   NodePort    10.152.183.53   <none>        8080:30450/TCP   176m
service/kubernetes        ClusterIP   10.152.183.1    <none>        443/TCP          10h

NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/hello-world   1/1     1            1           176m

NAME                                     DESIRED   CURRENT   READY   AGE
replicaset.apps/hello-world-696b6b59bd   1         1         1       176m

Когда я делаю curl localhost как и ожидалось connection refused, который выглядит все еще хорошо, поскольку он не подвергается воздействию кластера. когда я сверну kubernetes-worker/0 с публичным адресом 10.213.117.136 в порту 30450 (который я получаю от kubectl get all)

$ curl 10.213.117.136:30450
Hello Kubernetes!

Все работает как шарм (что очевидно). Когда я делаю

curl -H "Host: testhost.com" 10.213.117.136
Hello Kubernetes!

Он снова работает как шарм! Это означает, что входной контроллер успешно маршрутизирует порт 80 на основе host Правило исправить услуги. На данный момент я на 100% уверен, что кластер работает как надо.

Сейчас я пытаюсь получить доступ к этой услуге через Интернет извне. Когда я загружаю <server_ip> очевидно, ничего не загружается, так как он живет внутри собственного lxd подсети. Поэтому я думал вперед порт 80 с сервера eth0 на этот IP. Поэтому я добавил это правило в iptables

sudo iptables -t nat -A PREROUTING -p tcp -j DNAT --to-destination 10.213.117.136 (Для примера давайте маршрутизируем все, а не только порт 80). Теперь, когда я открываю на своем компьютере http://<server_ip> это загружает!

Так что настоящий вопрос в том, как это сделать на производстве? Должен ли я установить это правило пересылки в iptables? Это нормальный подход или хакерское решение и есть что-то "стандартное", которого мне не хватает? Дело в том, чтобы добавить это правило со статическим worker узел сделает кластер полностью статичным. IP в конце концов изменится, я могу удалить / добавить юниты к работникам и он перестанет работать. Я думал о написании сценария, который получит этот IP-адрес от juju как это:

$ juju status kubernetes-worker/0 --format=json | jq '.machines["7"]."dns-name"'
"10.213.117.136"

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

Как последняя идея, я бегу HAProxy вне кластера, прямо на машине и просто делайте пересылку трафика всем доступным работникам. Это может в конечном итоге также работать. Но все же я не знаю ответа, что это correct решение и что обычно используется в этом случае. Спасибо!

1 ответ

Решение

Так что настоящий вопрос в том, как это сделать на производстве?

Обычный способ сделать это в производственной системе - использовать Сервис.

Самый простой случай - это когда вы просто хотите, чтобы ваше приложение было доступно извне на вашем узле (ах). В этом случае вы можете использовать сервис Type NodePort. Это создаст правила iptables, необходимые для пересылки трафика с IP-адреса хоста на модуль (и), предоставляющие услугу.

Если у вас есть один узел (что не рекомендуется в производстве!), Вы готовы к этому моменту.

Если у вас есть несколько узлов в вашем кластере Kubernetes, все они будут настроены Kubernetes для предоставления доступа к службе (ваши клиенты могут использовать любой из них для доступа к службе). Тем не менее, вам придется решить проблему того, как клиенты узнают, с какими узлами можно связаться...

Есть несколько способов справиться с этим:

  • использовать протокол, понятный клиенту, для публикации доступных в настоящее время IP-адресов (например, DNS),

  • использовать плавающий (аварийный, виртуальный, HA) IP-адрес, управляемый некоторым программным обеспечением на ваших узлах Kubernetes (например, кардиостимулятор /corosync), и направлять клиентов по этому адресу,

  • использовать внешний балансировщик нагрузки, настроенный отдельно, для пересылки трафика на некоторые из рабочих узлов,

  • использовать внешний балансировщик нагрузки, автоматически настроенный Kubernetes с помощью сценария интеграции облачного провайдера (с помощью службы Type LoadBalancer), для пересылки трафика на некоторые из рабочих узлов.

Другие вопросы по тегам