И как в миникубе настроить

Зачем нужен Ingress?

Некоторым модулям для взаимодействия с запущенным контейнером потребуется какой-либо пользовательский ввод.

Примером этого может быть веб-приложение. Если пользователь не может просматривать приложение в своем веб-браузере, приложение бесполезно.

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

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

В настоящее время существует три способа обработки Ingress с помощью Kubernetes:

  • Контроллеры Ingress
  • Порт узла
  • Балансировщик нагрузки

Контроллеры Ingress

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

Основные игроки в прокси-пространстве имеют реализации контроллеров Ingress, такие как nginx и HAProxy, и есть другие, которые приобрели популярность по мере развития Kubernetes, такие как Traefik и Contour.

Узел Порт

Порт узла - это, по сути, порт в вашем кластере, через который Kubernetes направляет входящий трафик на ваш модуль. Порты портов узла обычно находятся в диапазоне от 30000 до 32767, недостатком является то, что это нестандартный порт для трафика, такого как HTTP и HTTPS. Вы можете редактировать порты, но, как правило, стоит взглянуть на другие варианты, если вы собираетесь по этому пути.

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

Балансировщик нагрузки

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

Реализация балансировщика нагрузки зависит от выбранного балансировщика нагрузки или облака.

Настройка Ingress с помощью minikube

В этом примере мы собираемся пройти процесс настройки Ingress, используя тип Ingress Controller. Реализацией Ingress-контроллера будет nginx, но так же просто использовать другие входящие контроллеры, такие как Traefik.

Прежде всего, убедитесь, что minikube запущен и работает.

➜ minikube start

😄  minikube v1.14.2 on Darwin 10.15.7
✨  Using the hyperkit driver based on existing profile
👍  Starting control plane node minikube in cluster minikube
🔄  Restarting existing hyperkit VM for "minikube" ...
🐳  Preparing Kubernetes v1.19.2 on Docker 19.03.12 ...
🔎  Verifying Kubernetes components...
🌟  Enabled addons: storage-provisioner, default-storageclass
🏄  Done! kubectl is now configured to use "minikube" by default

Нам также необходимо включить поддержку входящего трафика для minikube, что можно сделать с помощью следующей команды

➜ minikube addons enable ingress

🔎  Verifying ingress addon...
🌟  The 'ingress' addon is enabled

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

minikube delete && minikube start --vm=true

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

➜ cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
  name: minikube-example
  labels:
    name: minikube-example
EOF

namespace/minikube-example created

Это создаст пространство имен с именем minikube-example.

➜ kubectl get namespaces

NAME               STATUS   AGE
default            Active   7m29s
kube-node-lease    Active   7m30s
kube-public        Active   7m30s
kube-system        Active   7m31s
minikube-example   Active   39s

Теперь нам нужно развернуть модуль, содержащий веб-приложение. Я часто использую для тестирования один из примеров Google, Hello App.

➜ cat <<EOF | kubectl apply -n minikube-example -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-app
  labels:
    app: test-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: test-app
  template:
    metadata:
      labels:
        app: test-app
    spec:
      containers:
      - name: test-app
        image: gcr.io/google-samples/hello-app:1.0
        ports:
        - containerPort: 8080
EOF

deployment.apps/test-app created

Сейчас я вижу, что поды работают (я использую k9s, отличный инструмент для управления вашим кластером k8s: https://github.com/derailed/k9s).

Я вручную добавил правило переадресации портов, чтобы убедиться, что приложение работает должным образом.

Внизу, кажется, настраивается порт узла на время, в течение которого k9s открыт, но если вы хотите сделать это вручную, это можно сделать, выполнив такую ​​команду:

➜ cat <<EOF | kubectl apply -n minikube-example -f -
apiVersion: v1
kind: Service
metadata:
  name: test-app
  labels:
    name: test-app
spec:
  type: NodePort
  ports:
    - port: 8080
      name: http
  selector:
    app: test-app
EOF
service/test-app created
➜ minikube service --url test-app -n minikube-example
🏃  Starting tunnel for service test-app.
|------------------|----------|-------------|------------------------|
|    NAMESPACE     |   NAME   | TARGET PORT |          URL           |
|------------------|----------|-------------|------------------------|
| minikube-example | test-app |             | http://127.0.0.1:53732 |
|------------------|----------|-------------|------------------------|
http://127.0.0.1:53732
❗  Because you are using a Docker driver on darwin, the terminal needs to be open to run it.
➜ curl http://127.0.0.1:53732/
Hello, world!
Version: 1.0.0
Hostname: test-app-df4854fbc-z9zq9

(Обратите внимание, что селектор использует метку, а не имя, поскольку развертывание создаст имя с уникальным идентификатором с постфиксом. Также не забудьте удалить службу после этого, поскольку вместо этого мы собираемся использовать Ingress Controller).

Хорошо, круто, теперь развертывание и модули существуют, мы можем сосредоточиться на контроллере Ingress.

➜ cat <<EOF | kubectl apply -n minikube-example -f -
---
apiVersion: v1
kind: Service
metadata:
  name: test-app
  labels:
    name: test-app
spec:
  type: NodePort
  ports:
    - port: 8080
      name: http
  selector:
    app: test-app
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minikube-example-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
    - host: minikube-example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: test-app
                port:
                  number: 8080
EOF

service/test-app created
ingress.networking.k8s.io/minikube-example-ingress created

Это создаст входной модуль, который будет передавать весь контент с заголовком хоста minikube-example.com службе с именем test-app.

Чтобы убедиться, что это работает должным образом, выполните следующую команду. (Появление IP может занять пару минут.)

➜ kubectl get ingress -n minikube-example

NAME                       CLASS    HOSTS                  ADDRESS        PORTS   AGE
minikube-example-ingress   <none>   minikube-example.com   192.168.64.4   80      56s

Затем вы должны передать этот IP-адрес в файл хоста, например:

➜ echo '192.168.64.4   minikube-example.com' | sudo tee -a /etc/hosts

А теперь пора попробовать!

➜ curl minikube-example.com

Hello, world!
Version: 1.0.0
Hostname: test-app-df4854fbc-6mjnw

Теперь у вас есть контроллер входящего трафика nginx, работающий на minikube!

Чтобы изменить это и протестировать некоторые вещи, мы собираемся попробовать два бэкэнда и обновить Ingress, чтобы включить их обоих.

Самый простой способ избавиться от того, что мы сделали до сих пор, - это удалить minikube и снова запустить его или использовать другое пространство имен.

➜ minikube delete && minikube start --vm=true && minikube addons enable ingress
🔥  Deleting "minikube" in hyperkit ...
💀  Removed all traces of the "minikube" cluster.
😄  minikube v1.14.2 on Darwin 10.15.7
✨  Automatically selected the hyperkit driver
👍  Starting control plane node minikube in cluster minikube
🔥  Creating hyperkit VM (CPUs=2, Memory=4000MB, Disk=20000MB) ...
🐳  Preparing Kubernetes v1.19.2 on Docker 19.03.12 ...
🔎  Verifying Kubernetes components...
🌟  Enabled addons: default-storageclass, storage-provisioner
🏄  Done! kubectl is now configured to use "minikube" by default
🔎  Verifying ingress addon...
🌟  The 'ingress' addon is enabled

А затем запустите конфиг, похожий на этот:

➜ cat <<EOF | kubectl apply -n minikube-example -f -
--- 
apiVersion: v1
kind: Namespace
metadata:
  name: minikube-example
  labels:
    name: minikube-example
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-app
  labels:
    app: hello-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-app
  template:
    metadata:
      labels:
        app: hello-app
    spec:
      containers:
      - name: hello-app
        image: gcr.io/google-samples/hello-app:1.0
        ports:
        - containerPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: insights-app
  labels:
    app: insights-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: insights-app
  template:
    metadata:
      labels:
        app: insights-app
    spec:
      containers:
      - name: insights-app
        image: yeasy/simple-web:latest
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: hello-app
  labels:
    name: hello-app
spec:
  type: NodePort
  ports:
    - port: 8080
      name: http
  selector:
    app: hello-app
---
apiVersion: v1
kind: Service
metadata:
  name: insights-app
  labels:
    name: insights-app
spec:
  type: NodePort
  ports:
    - port: 80
      name: http
  selector:
    app: insights-app
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minikube-example-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
    - host: minikube-example.com
      http:
        paths:
          - path: /hello
            pathType: Prefix
            backend:
              service:
                name: hello-app
                port:
                  number: 8080    
          - path: /insights
            pathType: Prefix
            backend:
              service:
                name: insights-app
                port:
                  number: 80
EOF
namespace/minikube-example created
deployment.apps/hello-app created
deployment.apps/insights-app created
service/hello-app created
service/insights-app created
ingress.networking.k8s.io/minikube-example-ingress created

Теперь подождите, пока стручки перейдут в рабочее состояние.

Подождите, пока контроллер входящего трафика будет готов.

➜ kubectl get ingress -n minikube-example
NAME                       CLASS    HOSTS                  ADDRESS        PORTS   AGE
minikube-example-ingress   <none>   minikube-example.com   192.168.64.7   80      51s

И обновите файл хоста, чтобы отразить это.

sudo vim /etc/hosts

Теперь проверьте, что оба пути доступны из Ingress.

➜ curl minikube-example.com/hello
Hello, world!
Version: 1.0.0
Hostname: hello-app-5b844b975f-ddrxc

➜ curl minikube-example.com/insights
<!DOCTYPE html> <html> <body><center><h1><font color="blue" face="Georgia, Arial" size=8><em>Real</em></font> Visit Results</h1></center><p style="font-size:150%" >#2020-11-11 12:38:29: <font color="red">1</font> requests from &lt<font color="blue">LOCAL: 172-17-0-2.ingress-nginx-controller-admission.kube-system.svc.cluster.local</font>&gt to WebServer &lt<font color="blue">172.17.0.6</font>&gt</p></body> </html>

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