Не секрет, что у K8S отличное коммьюнити и в целом хорошая документация. В ней можно легко найти ответ на многие вопросы. Но как и любая другая документация, она не может покрывать абсолютно всё. В данной статье я попытаюсь привести подробную инструкцию, как развернуть и настроить Traefik для использования в качестве Ingress-контроллера.


image


Что такое Ingress?


Ingress — это объект API, который управляет внешним доступом к сервисам в кластере, главным образом через HTTP / HTTPS. Чтобы Ingress-ресурс заработал, нужен Ingress-контроллер. Если вы используете GCE, то контроллер Ingress уже развернут в мастер. Однако, если вы самостоятельно загрузили кластер, например с kops на AWS, вам нужно развернуть Ingress-контроллер самостоятельно. На minikube это решается включением надстройки Ingress.


Ingress-контроллеры


Роль Ingress-контроллера могут выполнять NGINX Ingress Controller, Kong, Octavia Ingress Controller и др. В этой статье мы рассмотрим такой инструмент как Traefik и посмотрим, как можно использовать его в качестве Ingress-контроллера для сервисов в кластере.


Зачем?


Зачем использовать Ingress-контроллер, если можно предоставить доступ к каждому сервису через NodePort или LoadBalancer? Если кратко, это позволяет получить одну центральную точку для проксирования всего трафика. То есть, с использованием Ingress-контроллера вам понадобится всего один LoadBalancer для Traefik и ничего больше. Эта связка и будет разруливать весь трафик.


Traefik-компоненты


Traefik объявил о поддержке Kubernetes Ingress в версии 1.4. Однако недавно выпущенный Traefik 1.7 имеет опцию publishedService, которая умеет обновлять поле status в Ingress, чего не было в предыдущих версиях. Ниже представлен список компонентов, которые потребуются для работы.


Создайте:


  • namespace
  • service account
  • TLS secret
  • cluster role
  • cluster role binding
  • configmap
  • deployment
  • service for http and https
  • service для Traefik dashboard
  • Ingress

Namespace


Создайте namespace:


kubectl create namespace traefik

TLS Secret


(прим. пер. — в примере далее автор зачем-то дублирует один и тот же конфиг, актуальный конфиг смотрите в README-файле, представленном по ссылке ниже)


Сначала создайте сертификат:


openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./tls.key -out ./tls.crt -subj "/CN=*.example.com"

Создайте сертификат TLS:


openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./tls.key -out ./tls.crt -subj "/CN=*.example.com"

Создайте Secret:


kubectl create secret tls traefik-ui-tls-cert --key ./tls.key --cert ./tls.crt

Для удобства я сделал README-файл с этими командами и выложил его в свой GitHub.


ConfigMap


---
apiVersion: v1
kind: ConfigMap
metadata:
 name: traefik-configmap
 namespace: traefik
data:
 traefik.toml: |
   defaultEntryPoints = ["http","https"]

   [entryPoints]

     [entryPoints.http]
     address = ":80"

     [entryPoints.https]
     address = ":443"
       [entryPoints.https.tls]
         [[entryPoints.https.tls.certificates]]
         CertFile = "/ssl/tls.crt"
         KeyFile = "/ssl/tls.key"

     [entryPoints.traefik]
       address = ":8080"
       [entryPoints.traefik.auth.basic]
       users = ["admin:$apr1$zjjGWKW4$W2JIcu4m26WzOzzESDF0W/"]

   [kubernetes]
     [kubernetes.ingressEndpoint]
       publishedService = "traefik/traefik"

   [ping]
   entryPoint = "http"

   [api]
   entryPoint = "traefik"

По умолчанию EntryPoints это порты 80 и 443.


EntryPoint http слушает :80 и не имеет дополнительных правил


EntryPoint https слушает :443 и содержит правило для подключения TLS-сертификатов.


EntryPoint traefik слушает :8080 и использует basic-аутентификацию. Имя пользователя — admin, пароль — admin.


Определение соответствующего endpoint Ingress в Kubernetes выполняется путем задания publishService и должно состоять из значения namespace и имени service для Traefik. В данном случае это traefik / traefik.


ping или проверка работоспособности будет использовать entryPoint http.


api или dashboard / ui будут использовать entryPoint traefik.


Обратите внимание, что можно определить дополнительные entryPoints с указанием порта. Этот порт может проксировать трафик на какой-либо порт, вместо динамических портов и NodePort.


ClusterRole


Service account для Traefik должен иметь разрешение на обновление поля Ingress status. Это важный параметр, и он еще не представлен в официальной документации Traefik:


---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
 name: traefik-ingress-controller
rules:
- apiGroups:
 - ""
 resources:
 - services
 - endpoints
 - secrets
 verbs:
 - get
 - list
 - watch
- apiGroups:
 - extensions
 resources:
 - ingresses
 verbs:
 - get
 - list
 - watch
- apiGroups:
 - extensions
 resources:
 - ingresses/status
 verbs:
 - update

Последние 6 строк очень важны для корректной работы.


Deployment


Deployment довольно простой и понятный. Давайте коротко пройдемся по основным блокам:


volumes:
 - name: traefik-ui-tls-cert
   secret:
     secretName: traefik-ui-tls-cert
 - name: traefik-configmap
   configMap:
     name: traefik-configmap

Определите volumes для ConfigMap и Secret, которые затем можно будет использовать в volumeMounts.


volumeMounts:
 - mountPath: "/ssl"
   name: "traefik-ui-tls-cert"
 - mountPath: "/config"
   name: "traefik-configmap"

Проверка работоспособности выполняется по 80 порту, как это было определено в ConfigMap.


Откройте порты для всех entryPoints, указанных в конфигурационном файле:


ports:
 - name: http
   containerPort: 80
 - name: https
   containerPort: 443
 - name: dashboard
   containerPort: 8080

Напоминаю, что некоторые примеры и документация в Интернете устарели, поэтому не упустите секцию args, необходимую для работы Traefik:


args:
- --logLevel=INFO
- --configfile=/config/traefik.toml

Не передавайте дополнительные флаги и аргументы, такие как -api, -ping или -kubernetes, потому что это переопределит настройки, указанные в конфиг-файле.


Service


Первый из сервисов определяет Loadbalancer для entryPoints http и https. Если вы посмотрите Security Group (Ingress) для LoadBalancer, то увидите там открыты порты 80 и 443. K8s создаст LoadBalancer и подключит к узлам, на которых работает Traefik. Если вы хотите создать внутренний ELB, как и я, вам нужно определить аннотации:


---
kind: Service
apiVersion: v1
metadata:
 name: traefik
 namespace: traefik
 annotations: {}
   # service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0
spec:
 selector:
   k8s-app: traefik-ingress
 ports:
 - protocol: TCP
   port: 80
   name: http
 - protocol: TCP
   port: 443
   name: https
 type: LoadBalancer

Service (for Dashboard)


Теперь самое интересное! Поскольку Dashboard использует basic-аутентификацию, мне потребовался https. Для использования SSL нам нужно перенаправлять трафик на порт :8080, на котором работает Dashboard. Как видите, он очень прост. Вся магия происходит в Ingress.


---
kind: Service
apiVersion: v1
metadata:
 name: traefik-dashboard
 namespace: traefik
spec:
 selector:
   k8s-app: traefik-ingress
 ports:
 - port: 8080
   name: dashboard

Ingress (for Dashboard)


Магия заключается в том, что проксирование защищенного трафика к Dashboard'у производится через сам Traefik. Управление Traefik в Ingress производится с помощью аннотаций Traefik:


---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
 name: traefik-dashboard-ingress
 namespace: traefik
 annotations:
   kubernetes.io/ingress.class: traefik
   traefik.ingress.kubernetes.io/frontend-entry-points: http,https
   traefik.ingress.kubernetes.io/redirect-entry-point: https
   traefik.ingress.kubernetes.io/redirect-permanent: "true"
spec:
 rules:
 - host: traefik-ui.example.com
   http:
     paths:
     - path: /
       backend:
         serviceName: traefik-dashboard
         servicePort: 8080

Потребовалось всего 4 простые и понятные аннотации.


Разумеется, для обеспечения полной работоспособности нужно создать DNS-запись traefik-ui.example.com, которая будет указывать на ваш ELB.


Было бы здорово, если бы это (прим. пер.: имеется в виду создание DNS-записей) производилось автоматически? Не проблема, я напишу об автоматическом создании DNS-записей в следующей статье.


Ссылки


Готовый deployment.yaml файл можно скачать в моём репозитории Github. Если в процессе настройки у вас возникнут трудности, не стесняйтесь — спрашивайте.


Напутствие от переводчика


Читайте другие статьи в нашем блоге:


Бэкапы Stateful в Kubernetes


Резервное копирование большого количества разнородных web-проектов


Telegram-бот для Redmine. Как упростить жизнь себе и людям

Комментарии (2)


  1. shurup
    26.10.2018 07:16

    > прим. пер. — в примере далее автор зачем-то дублирует один и тот же конфиг

    Да просто опечатался же человек, продублировал саму команду и не заметил — нет смысла это копировать в переводе :)


    1. mikesidd Автор
      26.10.2018 13:00

      Добрый день! Дело в том, что мы решили оставить текст максимально близким к оригиналу, но с нашим примечанием — чтобы не вводить читателей в заблуждение.