Разоблачение голого металлического кластера kubernetes для интернета - PullRequest
0 голосов
/ 14 января 2019

Я пытаюсь настроить собственный одноузловой кластер 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 Ответ

0 голосов
/ 14 января 2019

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

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

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

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

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

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

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

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

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

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

...