Обʼєкт API, який керує зовнішнім доступом до сервісів у кластері, зазвичай HTTP.
Ingress може забезпечувати балансування навантаження, обробку (термінацію) SSL і віртуальний хостинг на основі імен.
Проєкт Kubernetes рекомендує використовувати Gateway замість Ingress. API Ingress заморожено.
Це означає, що:
Для ясності цей посібник визначає такі терміни:
Ingress відкриває маршрути HTTP та HTTPS ззовні кластера до сервісів всередині кластера. Маршрутизацію трафіку контролюють правила, визначені в ресурсі Ingress.
Ось простий приклад, де Ingress спрямовує весь свій трафік на один Service:
graph LR; client([клієнт])-. Балансувальник навантаження,
яким керує Ingress .->ingress[Ingress]; ingress-->|правило маршрутизації|service[Service]; subgraph cluster["Кластер"] ingress; service-->pod1[Pod]; service-->pod2[Pod]; end classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000; classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff; classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5; class ingress,service,pod1,pod2 k8s; class client plain; class cluster cluster;
Схема. Ingress
Ingress можна налаштувати так, щоб він надавав сервісам зовнішньодоступні URL, балансував навантаження трафіку, виконував термінацію SSL / TLS та пропонував віртуальний хостинг на основі імен. Контролер Ingress відповідає за виконання Ingress, зазвичай за допомогою балансувальника навантаження, хоча він також може налаштовувати ваш граничний маршрутизатор або додаткові фронтенди, щоб допомогти обробляти трафік.
Ingress не відкриває довільні порти чи протоколи. Для відкриття в інтернет доступу до сервісів, відмінних від HTTP та HTTPS, зазвичай використовується сервіс типу Service.Type=NodePort або Service.Type=LoadBalancer.
Вам потрібно мати контролер Ingress, щоб забезпечити роботу Ingress. Саме лише створення ресурсу Ingress нічого не дає.
Ви можете вибрати з-поміж низки контролерів Ingress.
В ідеалі всі контролери Ingress мають відповідати еталонній специфікації. На практиці різні контролери Ingress працюють трошки по-різному.
Мінімальний приклад ресурсу Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
spec:
ingressClassName: nginx-example
rules:
- http:
paths:
- path: /testpath
pathType: Prefix
backend:
service:
name: test
port:
number: 80
Для Ingress необхідні поля apiVersion, kind, metadata та spec. Назва обʼєкта Ingress повинна бути дійсним імʼям DNS-піддомену. Загальну інформацію про роботу з файлами конфігурації дивіться в розділах розгортання застосунків, налаштування контейнерів, управління ресурсами. Контролери Ingress часто використовують анотації для налаштування поведінки. Ознайомтеся з документацією обраного вами контролера Ingress, щоб дізнатися, які анотації очікуються та/або підтримуються.
Специфікація Ingress містить усю інформацію, необхідну для налаштування балансувальника навантаження чи проксі-сервера. Найважливіше те, що вона містить список правил, які зіставляються з усіма вхідними запитами. Ресурс Ingress підтримує правила лише для спрямування трафіку HTTP(S).
Якщо ingressClassName не вказано, має бути визначений типовий клас Ingress.
Деякі контролери Ingress працюють навіть без визначення типового IngressClass. Навіть якщо ви використовуєте контролер Ingress, який може працювати без будь-якого IngressClass, проєкт Kubernetes все одно рекомендує визначити типовий IngressClass.
Кожне правило HTTP містить таку інформацію:
/testpath), кожен з яких має повʼязаний бекенд, визначений за допомогою service.name та service.port.name або service.port.number. Як хост, так і шлях мають відповідати вмісту вхідного запиту, перш ніж балансувальник навантаження спрямує трафік до вказаного Service.defaultBackend часто налаштовують у контролері Ingress для обслуговування будь-яких запитів, які не відповідають жодному шляху в специфікації.
Ingress без правил спрямовує весь трафік до єдиного типового бекенду, і .spec.defaultBackend — це бекенд, який має обробляти запити в цьому випадку. Зазвичай defaultBackend — це опція конфігурації контролера Ingress, і його не вказують у ваших ресурсах Ingress. Якщо не вказано .spec.rules, то має бути вказаний .spec.defaultBackend. Якщо defaultBackend не встановлено, обробка запитів, які не відповідають жодному з правил, залежить від контролера Ingress (зверніться до документації вашого контролера Ingress, щоб дізнатися, як він обробляє цей випадок).
Якщо жоден із хостів або шляхів в обʼєктах Ingress не відповідає HTTP-запиту, трафік спрямовується до вашого типового бекенду.
Бекенд Resource — це ObjectRef на інший ресурс Kubernetes у тому ж просторі імен, що й обʼєкт Ingress. Resource — це налаштування, взаємовиключне з Service: якщо вказано обидва, перевірка не буде пройдена. Поширене використання бекенду Resource — спрямування вхідних даних до бекенду обʼєктного сховища зі статичними ресурсами.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-resource-backend
spec:
defaultBackend:
resource:
apiGroup: k8s.example.com
kind: StorageBucket
name: static-assets
rules:
- http:
paths:
- path: /icons
pathType: ImplementationSpecific
backend:
resource:
apiGroup: k8s.example.com
kind: StorageBucket
name: icon-assets
Після створення Ingress, наведеного вище, ви можете переглянути його за допомогою такої команди:
kubectl describe ingress ingress-resource-backend
Name: ingress-resource-backend
Namespace: default
Address:
Default backend: APIGroup: k8s.example.com, Kind: StorageBucket, Name: static-assets
Rules:
Host Path Backends
---- ---- --------
*
/icons APIGroup: k8s.example.com, Kind: StorageBucket, Name: icon-assets
Annotations: <none>
Events: <none>
Кожен шлях в Ingress повинен мати відповідний тип шляху. Шляхи, які не містять явного pathType, не пройдуть перевірку. Підтримуються три типи шляхів:
ImplementationSpecific: З цим типом шляху визначення відповідності залежить від IngressClass. Реалізації можуть розглядати його як окремий pathType або обробляти його так само, як типи шляхів Prefix або Exact.
Exact: Точно відповідає URL-шляху з урахуванням регістру.
Prefix: Відповідність визначається за префіксом URL-шляху, розділеного /. Зіставлення виконується з урахуванням регістру і поелементно, за кожним елементом шляху. Елемент шляху — це список міток у шляху, розділених роздільником /. Запит відповідає шляху p, якщо кожен p є поелементним префіксом p шляху запиту.
/foo/bar відповідає /foo/bar/baz, але не відповідає /foo/barbaz).| Тип | Шлях(и) | Шлях(и) запиту | Відповідає? |
|---|---|---|---|
| Prefix | / | (всі шляхи) | Так |
| Exact | /foo | /foo | Так |
| Exact | /foo | /bar | Ні |
| Exact | /foo | /foo/ | Ні |
| Exact | /foo/ | /foo | Ні |
| Prefix | /foo | /foo, /foo/ | Так |
| Prefix | /foo/ | /foo, /foo/ | Так |
| Prefix | /aaa/bb | /aaa/bbb | Ні |
| Prefix | /aaa/bbb | /aaa/bbb | Так |
| Prefix | /aaa/bbb/ | /aaa/bbb | Так, ігнорує кінцевий слеш |
| Prefix | /aaa/bbb | /aaa/bbb/ | Так, збігається з кінцевим слешем |
| Prefix | /aaa/bbb | /aaa/bbb/ccc | Так, збігається з підшляхом |
| Prefix | /aaa/bbb | /aaa/bbbxyz | Ні, не збігається з префіксом рядка |
| Prefix | /, /aaa | /aaa/ccc | Так, збігається з префіксом /aaa |
| Prefix | /, /aaa, /aaa/bbb | /aaa/bbb | Так, збігається з префіксом /aaa/bbb |
| Prefix | /, /aaa, /aaa/bbb | /ccc | Так, збігається з префіксом / |
| Prefix | /aaa | /ccc | Ні, використовується типовий бекенд |
| Змішаний | /foo (Prefix), /foo (Exact) | /foo | Так, перевага надається Exact |
У деяких випадках запиту можуть відповідати кілька шляхів у межах Ingress. У таких випадках перевага надається насамперед найдовшому шляху, що збігається. Якщо два шляхи все ще збігаються однаково, перевага надається шляхам із точним типом шляху перед префіксним типом шляху.
Хости можуть бути точними збігами (наприклад, «foo.bar.com») або шаблонами (наприклад, «*.foo.com»). Точні збіги вимагають, щоб HTTP-заголовок host відповідав полю host. Збіги за шаблоном вимагають, щоб HTTP-заголовок host дорівнював суфіксу правила із шаблоном.
| Хост | Заголовок host | Збіг? |
|---|---|---|
*.foo.com | bar.foo.com | Збіг на основі спільного суфікса |
*.foo.com | baz.bar.foo.com | Немає збігу, шаблон охоплює лише одну DNS-мітку |
*.foo.com | foo.com | Немає збігу, шаблон охоплює лише одну DNS-мітку |
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-wildcard-host
spec:
rules:
- host: "foo.bar.com"
http:
paths:
- pathType: Prefix
path: "/bar"
backend:
service:
name: service1
port:
number: 80
- host: "*.foo.com"
http:
paths:
- pathType: Prefix
path: "/foo"
backend:
service:
name: service2
port:
number: 80
Ingressʼи можуть бути реалізовані різними контролерами, часто з різною конфігурацією. Кожен Ingress повинен вказувати клас — посилання на ресурс IngressClass, який містить додаткову конфігурацію, зокрема імʼя контролера, що має реалізувати цей клас.
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb
spec:
controller: example.com/ingress-controller
parameters:
apiGroup: k8s.example.com
kind: IngressParameters
name: external-lb
Поле .spec.parameters в IngressClass дозволяє посилатися на інший ресурс, який надає конфігурацію, повʼязану з цим IngressClass.
Конкретний тип параметрів залежить від контролера Ingress, який ви вказуєте в полі .spec.controller в IngressClass.
Залежно від вашого контролера Ingress, ви можете використовувати параметри, які встановлюєте на рівні всього кластера або лише для одного простору імен.
Типова область застосування параметрів IngressClass — весь кластер.
Якщо ви встановлюєте поле .spec.parameters і не встановлюєте .spec.parameters.scope, або встановлюєте .spec.parameters.scope у Cluster, тоді IngressClass посилається на ресурс на рівні кластера. kind (у поєднанні з apiGroup) параметрів вказує на API на рівні кластера (можливо, власний ресурс), а name параметрів ідентифікує конкретний ресурс на рівні кластера для цього API.
Наприклад:
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb-1
spec:
controller: example.com/ingress-controller
parameters:
# Параметри для цього IngressClass вказані в
# ClusterIngressParameter (група API k8s.example.net) з назвою
# "external-config-1". Це визначення вказує Kubernetes
# шукати ресурс параметрів на рівні кластера.
scope: Cluster
apiGroup: k8s.example.net
kind: ClusterIngressParameter
name: external-config-1
Якщо ви встановлюєте поле .spec.parameters і встановлюєте .spec.parameters.scope у Namespace, тоді IngressClass посилається на ресурс на рівні простору імен. Ви також повинні встановити поле namespace у .spec.parameters на простір імен, який містить параметри, що ви хочете використовувати.
kind (у поєднанні з apiGroup) параметрів вказує на API на рівні простору імен (наприклад: ConfigMap), а name параметрів ідентифікує конкретний ресурс у просторі імен, який ви вказали в namespace.
Параметри на рівні простору імен допомагають оператору кластера делегувати контроль над конфігурацією (наприклад: налаштування балансувальника навантаження, визначення API-шлюзу), що використовується для робочого навантаження. Якби ви використовували параметр на рівні кластера, то або:
Сам API IngressClass завжди має область застосування на рівні кластера.
Ось приклад IngressClass, який посилається на параметри на рівні простору імен:
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb-2
spec:
controller: example.com/ingress-controller
parameters:
# Параметри для цього IngressClass вказані в
# IngressParameter (група API k8s.example.com) з назвою "external-config",
# що знаходиться в просторі імен "external-configuration".
scope: Namespace
apiGroup: k8s.example.com
kind: IngressParameter
namespace: external-configuration
name: external-config
До того, як у Kubernetes 1.18 було додано ресурс IngressClass та поле ingressClassName, класи Ingress вказувалися за допомогою анотації kubernetes.io/ingress.class в Ingress. Ця анотація ніколи не була формально визначена, але отримала широку підтримку контролерами Ingress.
Новіше поле ingressClassName в Ingress є заміною цієї анотації, але не є її прямим еквівалентом. Тоді як анотація зазвичай використовувалася для посилання на імʼя контролера Ingress, який має реалізувати Ingress, поле є посиланням на ресурс IngressClass, що містить додаткову конфігурацію Ingress, зокрема імʼя контролера Ingress.
Ви можете позначити певний IngressClass як типовий для вашого кластера. Встановлення анотації ingressclass.kubernetes.io/is-default-class у значення true на ресурсі IngressClass забезпечить, що новим Ingress без вказаного поля ingressClassName буде призначено цей типовий IngressClass.
ingressClassName. Ви можете розвʼязати цю проблему, переконавшись, що у вашому кластері як типовий позначено щонайбільше 1 IngressClass.Почніть з визначення типового IngressClass. Втім, рекомендується вказувати типовий IngressClass:
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
labels:
app.kubernetes.io/component: controller
name: example-class
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: k8s.io/example-class
У Kubernetes існують концепції, які дозволяють відкрити доступ до одного Service (див. альтернативи). Ви також можете зробити це за допомогою Ingress, вказавши типовий бекенд без правил.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
spec:
defaultBackend:
service:
name: test
port:
number: 80
Якщо ви створите його за допомогою kubectl apply -f, ви зможете переглянути стан доданого Ingress:
kubectl get ingress test-ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
test-ingress external-lb * 203.0.113.123 80 59s
Де 203.0.113.123 — це IP-адреса, яку виділив контролер Ingress для виконання цього Ingress.
<pending>.Конфігурація розгалуження (fanout) маршрутизує трафік з однієї IP-адреси до більш ніж одного Service на основі запитуваного HTTP URI. Ingress дозволяє звести кількість балансувальників навантаження до мінімуму. Наприклад, таке налаштування:
graph LR; client([клієнт])-. Балансувальник навантаження,
яким керує Ingress .->ingress[Ingress, 178.91.123.132]; ingress-->|/foo|service1[Service service1:4200]; ingress-->|/bar|service2[Service service2:8080]; subgraph cluster["Кластер"] ingress; service1-->pod1[Pod]; service1-->pod2[Pod]; service2-->pod3[Pod]; service2-->pod4[Pod]; end classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000; classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff; classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5; class ingress,service1,service2,pod1,pod2,pod3,pod4 k8s; class client plain; class cluster cluster;
Схема. Розгалуження (fanout) Ingress
Для цього знадобиться Ingress такого вигляду:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: simple-fanout-example
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
pathType: Prefix
backend:
service:
name: service1
port:
number: 4200
- path: /bar
pathType: Prefix
backend:
service:
name: service2
port:
number: 8080
Коли ви створите Ingress за допомогою kubectl apply -f:
kubectl describe ingress simple-fanout-example
Name: simple-fanout-example
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo service1:4200 (10.8.0.90:4200)
/bar service2:8080 (10.8.0.91:8080)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 22s loadbalancer-controller default/test
Контролер Ingress створює специфічний для реалізації балансувальник навантаження, який задовольняє Ingress, за умови, що існують сервіси (service1, service2). Коли це зроблено, ви можете побачити адресу балансувальника навантаження в полі Address.
Віртуальні хости на основі імен підтримують маршрутизацію HTTP-трафіку до кількох імен хостів за однією IP-адресою.
graph LR; client([клієнт])-. Балансувальник навантаження,
яким керує Ingress .->ingress[Ingress, 178.91.123.132]; ingress-->|Host: foo.bar.com|service1[Service service1:80]; ingress-->|Host: bar.foo.com|service2[Service service2:80]; subgraph cluster["Кластер"] ingress; service1-->pod1[Pod]; service1-->pod2[Pod]; service2-->pod3[Pod]; service2-->pod4[Pod]; end classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000; classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff; classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5; class ingress,service1,service2,pod1,pod2,pod3,pod4 k8s; class client plain; class cluster cluster;
Схема. Віртуальний хостинг на основі імен з Ingress
Наступний Ingress вказує балансувальнику навантаження, що стоїть за ним, маршрутизувати запити на основі заголовка Host.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service1
port:
number: 80
- host: bar.foo.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
Якщо ви створюєте ресурс Ingress без визначених у правилах хостів, то будь-який вебтрафік на IP-адресу вашого контролера Ingress може бути зіставлений без потреби у віртуальному хості на основі імен.
Наприклад, наступний Ingress маршрутизує трафік, запитаний для first.bar.com, до service1, для second.bar.com — до service2, а будь-який трафік, заголовок host запиту якого не відповідає first.bar.com і second.bar.com, — до service3.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host-ingress-no-third-host
spec:
rules:
- host: first.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service1
port:
number: 80
- host: second.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
- http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service3
port:
number: 80
Ви можете захистити Ingress, вказавши Secret, що містить приватний ключ і сертифікат TLS. Ресурс Ingress підтримує лише один TLS-порт, 443, і передбачає термінацію TLS у точці входу (трафік до Service та його Podʼів передається відкритим текстом). Якщо розділ конфігурації TLS в Ingress вказує різні хости, вони мультиплексуються на одному порту відповідно до імені хоста, вказаного через розширення TLS SNI (за умови, що контролер Ingress підтримує SNI). Секрет TLS повинен містити ключі з іменами tls.crt та tls.key, які містять сертифікат та приватний ключ для використання з TLS. Наприклад:
apiVersion: v1
kind: Secret
metadata:
name: testsecret-tls
namespace: default
data:
tls.crt: base64 encoded cert
tls.key: base64 encoded key
type: kubernetes.io/tls
Посилання на цей секрет в Ingress вказує контролеру Ingress захистити канал від клієнта до балансувальника навантаження за допомогою TLS. Вам потрібно переконатися, що створений вами секрет TLS походить із сертифіката, який містить Common Name (CN), також відоме як Fully Qualified Domain Name (FQDN), для https-example.foo.com.
hosts у розділі tls мають явно відповідати host у розділі rules.apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-example-ingress
spec:
tls:
- hosts:
- https-example.foo.com
secretName: testsecret-tls
rules:
- host: https-example.foo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service1
port:
number: 80
Контролер Ingress запускається з певними налаштуваннями політики балансування навантаження, які він застосовує до всіх Ingress, як-от алгоритм балансування навантаження, схема ваг бекендів тощо. Складніші концепції балансування навантаження (наприклад, постійні сесії, динамічні ваги) поки що недоступні через Ingress. Натомість ці функції можна отримати через балансувальник навантаження, що використовується для Service.
Також варто зазначити, що хоча перевірки стану не доступні безпосередньо через Ingress, у Kubernetes існують паралельні концепції, як-от проби готовності, які дозволяють досягти того самого результату. Ознайомтеся з документацією конкретного контролера, щоб дізнатися, як він обробляє перевірки стану.
Щоб оновити наявний Ingress і додати новий хост, ви можете відредагувати ресурс:
kubectl describe ingress test
Name: test
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo service1:80 (10.8.0.90:80)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 35s loadbalancer-controller default/test
kubectl edit ingress test
Це відкриє редактор з поточною конфігурацією у форматі YAML. Змініть її, щоб додати новий хост:
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
service:
name: service1
port:
number: 80
path: /foo
pathType: Prefix
- host: bar.baz.com
http:
paths:
- backend:
service:
name: service2
port:
number: 80
path: /foo
pathType: Prefix
..
Після збереження змін kubectl оновлює ресурс в API-сервері, що повідомляє контролеру Ingress, що потрібно переналаштувати балансувальник навантаження.
Перевірте це:
kubectl describe ingress test
Name: test
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo service1:80 (10.8.0.90:80)
bar.baz.com
/foo service2:80 (10.8.0.91:80)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 45s loadbalancer-controller default/test
Ви можете досягти того самого результату, викликавши kubectl replace -f зі зміненим YAML-файлом Ingress.
Методи розподілу трафіку між доменами відмови відрізняються в різних хмарних провайдерів. Подробиці дивіться в документації відповідного контролера Ingress.
Ви можете відкрити доступ до Service різними способами, які безпосередньо не стосуються ресурсу Ingress: