Не секрет, что у K8S отличное коммьюнити и в целом хорошая документация. В ней можно легко найти ответ на многие вопросы. Но как и любая другая документация, она не может покрывать абсолютно всё. В данной статье я попытаюсь привести подробную инструкцию, как развернуть и настроить Traefik для использования в качестве Ingress-контроллера.
Что такое 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. Если в процессе настройки у вас возникнут трудности, не стесняйтесь — спрашивайте.
Напутствие от переводчика
Читайте другие статьи в нашем блоге:
Резервное копирование большого количества разнородных web-проектов
shurup
> прим. пер. — в примере далее автор зачем-то дублирует один и тот же конфиг
Да просто опечатался же человек, продублировал саму команду и не заметил — нет смысла это копировать в переводе :)
mikesidd Автор
Добрый день! Дело в том, что мы решили оставить текст максимально близким к оригиналу, но с нашим примечанием — чтобы не вводить читателей в заблуждение.