У цьому розділі документації Kubernetes зібрані навчальні матеріали. Кожний матеріал показує, як досягти окремої мети, що більша за одне завдання. Зазвичай навчальний матеріал має декілька розділів, кожен з яких містить певну послідовність дій. До ознайомлення з навчальними матеріалами вам, можливо, знадобиться додати у закладки сторінку з Глосарієм для подальшого консультування.
Основи
Основи Kubernetes - детальний навчальний матеріал з інтерактивними уроками, що допоможе вам зрозуміти Kubernetes і спробувати його базову функціональність.
Якщо ви хочете написати навчальний матеріал, у статті
Використання шаблонів сторінок
ви знайдете інформацію про тип навчальної сторінки і шаблон.
1 - Привіт Minikube
З цього навчального матеріалу ви дізнаєтесь, як запустити у Kubernetes простий Hello World застосунок на Node.js за допомогою Minikube і Katacoda. Katacoda надає безплатне Kubernetes середовище, що доступне у вашому браузері.
Примітка:
Також ви можете навчатись за цим матеріалом, якщо встановили Minikube локально.
Цілі
Розгорнути Hello World застосунок у Minikube.
Запустити застосунок.
Переглянути логи застосунку.
Перш ніж ви розпочнете
У цьому навчальному матеріалі ми використовуємо образ контейнера, зібраний із наступних файлів:
Більше інформації про команду docker build ви знайдете у документації Docker.
Створення Minikube кластера
Натисніть кнопку Запуск термінала
Примітка:
Якщо Minikube встановлений локально, виконайте команду minikube start.
Відкрийте Kubernetes дашборд у браузері:
minikube dashboard
Тільки для Katacoda: у верхній частині вікна термінала натисніть знак плюс, а потім -- Select port to view on Host 1.
Тільки для Katacoda: введіть 30000, а потім натисніть Display Port.
Створення Deployment
Pod у Kubernetes -- це група з одного або декількох контейнерів, що об'єднані разом з метою адміністрування і роботи у мережі. У цьому навчальному матеріалі Pod має лише один контейнер. Kubernetes Deployment перевіряє стан Pod'а і перезапускає контейнер Pod'а, якщо контейнер перестає працювати. Створювати і масштабувати Pod'и рекомендується за допомогою Deployment'ів.
За допомогою команди kubectl create створіть Deployment, який керуватиме Pod'ом. Pod запускає контейнер на основі наданого Docker образу.
За умовчанням, Pod доступний лише за внутрішньою IP-адресою у межах Kubernetes кластера. Для того, щоб контейнер hello-node став доступний за межами віртуальної мережі Kubernetes, Pod необхідно відкрити як Kubernetes Service.
Відкрийте Pod для публічного доступу з інтернету за допомогою команди kubectl expose:
Прапорець `--type=LoadBalancer` вказує, що ви хочете відкрити доступ до Service за межами кластера.
Перегляньте інформацію про Service, який ви щойно створили:
kubectl get services
У виводі ви побачите подібну інформацію:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-node LoadBalancer 10.108.144.78 <pending> 8080:30369/TCP 21s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 23m
Для хмарних провайдерів, що підтримують балансування навантаження, доступ до Service надається через зовнішню IP-адресу. Для Minikube, тип `LoadBalancer` робить Service доступним ззовні за допомогою команди `minikube service`.
Виконайте наступну команду:
minikube service hello-node
Тільки для Katacoda: натисніть знак плюс, а потім -- Select port to view on Host 1.
Тільки для Katacoda: запишіть п'ятизначний номер порту, що відображається напроти 8080 у виводі сервісу. Номер цього порту генерується довільно і тому може бути іншим у вашому випадку. Введіть номер порту у призначене для цього текстове поле і натисніть Display Port. У нашому прикладі номер порту 30369.
Це відкриє вікно браузера, в якому запущений ваш застосунок, і покаже повідомлення "Hello World".
Увімкнення розширень
Minikube має ряд вбудованих розширень, які можна увімкнути, вимкнути і відкрити у локальному Kubernetes оточенні.
Застосунки, що працюють у кластері Kubernetes, виявляють одне одного та взаємодіють між собою й із зовнішнім світом через абстракцію Service. У цьому документі пояснюється, що відбувається з Source IP пакетів, надісланих на різні типи Service, і як ви можете змінити цю поведінку відповідно до ваших потреб.
Мережевий демон, який керує віртуальними IP Service на кожному вузлі
Необхідні умови
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Відкрити доступ до простого застосунку через різні типи Service
Зрозуміти, як кожен тип Service обробляє Source IP NAT
Зрозуміти компроміси, повʼязані зі збереженням Source IP
Source IP для Service з Type=ClusterIP
Пакети, надіслані на ClusterIP зсередини кластера, ніколи не обробляються Source NAT, якщо kube-proxy працює в режимі iptables (типовий режим). Режим kube-proxy можна дізнатися, запитавши http://localhost:10249/proxyMode на вузлі, де працює kube-proxy.
kubectl get nodes
Результат схожий на цей:
NAME STATUS ROLES AGE VERSION
kubernetes-node-6jst Ready <none> 2h v1.13.0
kubernetes-node-cx31 Ready <none> 2h v1.13.0
kubernetes-node-jj1t Ready <none> 2h v1.13.0
Отримайте режим проксі на одному з вузлів (kube-proxy слухає порт 10249):
# Запустіть це в оболонці на вузлі, який хочете запитати.curl http://localhost:10249/proxyMode
Результат:
iptables
Ви можете протестувати збереження Source IP, створивши Service для застосунку source IP:
NODEPORT=$(kubectl get -o jsonpath="{.spec.ports[0].nodePort}" services nodeport)NODES=$(kubectl get nodes -o jsonpath='{ $.items[*].status.addresses[?(@.type=="InternalIP")].address }')
Якщо ви працюєте у хмарного провайдера, можливо, вам доведеться відкрити правило брандмауера для nodes:nodeport, зазначеного вище. Тепер ви можете спробувати звернутися до Service ззовні кластера через виділений вище порт вузла.
for node in $NODES;do curl -s $node:$NODEPORT| grep -i client_address;done
Зверніть увагу, що це неправильні IP клієнтів, це внутрішні IP кластера. Ось що відбувається:
Клієнт надсилає пакет до node2:nodePort
node2 замінює Source IP-адресу (SNAT) у пакеті своєю власною IP-адресою
node2 замінює Destination IP-адресу пакета на IP Podʼа
пакет спрямовується до node 1, а потім до точки доступу
відповідь Podʼа спрямовується назад до node2
відповідь Podʼа надсилається клієнту
Візуально:
Схема. Source IP Type=NodePort з використанням SNAT
Щоб уникнути цього, у Kubernetes є можливість зберегти Source IP клієнта. Якщо ви встановите для service.spec.externalTrafficPolicy значення Local, kube-proxy спрямовує запити лише до локальних точок доступу і не пересилає трафік до інших вузлів. Цей підхід зберігає початкову Source IP-адресу. Якщо локальних точок доступу немає, пакети, надіслані до вузла, відкидаються, тому ви можете покладатися на правильну Source IP-адресу в будь-яких правилах обробки пакетів, які ви можете застосувати до пакета, що проходить до точки доступу.
Встановіть поле service.spec.externalTrafficPolicy так:
for node in $NODES;do curl --connect-timeout 1 -s $node:$NODEPORT| grep -i client_address;done
Вивід подібний до:
client_address=198.51.100.79
Зауважте, що ви отримали лише одну відповідь із правильною IP-адресою клієнта від одного вузла, на якому працює Pod точки доступу.
Ось що відбувається:
клієнт надсилає пакет на node2:nodePort, який не має точок доступу
пакет відкидається
клієнт надсилає пакет на node1:nodePort, який має точки доступу
node1 направляє пакет до точки доступу з правильною Source IP-адресою
Візуально:
Схема. Source IP Type=NodePort зберігає Source IP-адресу клієнта
Source IP для Service з Type=LoadBalancer
Пакети, надіслані на Service з Type=LoadBalancer, типово обробляються Source NAT, оскільки всі вузли Kubernetes, доступні для планування, у стані Ready можуть отримувати трафік від балансувальника навантаження. Тому якщо пакети надходять на вузол без точки доступу, система через проксі спрямовує їх на вузол з точкою доступу, замінюючи Source IP пакета на IP-адресу вузла (як описано в попередньому розділі).
Ви можете перевірити це, відкривши доступ до застосунку source-ip-app через балансувальник навантаження:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
loadbalancer LoadBalancer 10.0.65.118 203.0.113.140 80/TCP 5m
Потім надішліть запит на зовнішню IP-адресу цього Service:
curl 203.0.113.140
Вивід подібний до цього:
CLIENT VALUES:
client_address=10.240.0.5
...
Однак якщо ви працюєте в Google Kubernetes Engine/GCE, встановлення того самого поля service.spec.externalTrafficPolicy у Local змушує вузли без точок доступу Service вилучати себе зі списку вузлів, які отримують трафік від балансувальника навантаження, навмисно не проходячи перевірки стану.
Ви одразу побачите поле service.spec.healthCheckNodePort, виділене Kubernetes:
kubectl get svc loadbalancer -o yaml | grep -i healthCheckNodePort
Вивід подібний до цього:
healthCheckNodePort:32122
Поле service.spec.healthCheckNodePort вказує на порт на кожному вузлі, на якому надається перевірка стану за адресою /healthz. Ви можете перевірити це:
kubectl get pod -o wide -l app=source-ip-app
Вивід подібний до цього:
NAME READY STATUS RESTARTS AGE IP NODE
source-ip-app-826191075-qehz4 1/1 Running 0 20h 10.180.1.136 kubernetes-node-6jst
Використайте curl, щоб запитати /healthz на різних вузлах:
# Виконайте це локально на вузлі, який ви вибралиcurl localhost:32122/healthz
1 Service Endpoints found
На іншому вузлі ви можете отримати інший результат:
# Виконайте це локально на вузлі, який ви вибралиcurl localhost:32122/healthz
No Service Endpoints Found
Контролер, який працює на панелі управління, відповідає за виділення хмарного балансувальника навантаження. Той самий контролер також створює HTTP-перевірки стану, що вказують на цей порт/шлях на кожному вузлі. Зачекайте приблизно 10 секунд, поки 2 вузли без точок доступу не пройдуть перевірки стану, а потім за допомогою curl запитайте IPv4-адресу балансувальника навантаження:
curl 203.0.113.140
Вивід подібний до цього:
CLIENT VALUES:
client_address=198.51.100.79
...
Міжплатформна підтримка
Лише деякі хмарні провайдери підтримують збереження Source IP-адреси через Service з Type=LoadBalancer. Ваш хмарний провайдер може виконати запит на балансувальник навантаження кількома способами:
З проксі, що завершує зʼєднання клієнта та відкриває нове зʼєднання з вашими вузлами/точками доступу. У таких випадках Source IP-адреса завжди буде адресою хмарного балансувальника, а не адресою клієнта.
За допомогою пересилача пакетів (packet forwarder), завдяки чому запити від клієнта, надіслані на VIP балансувальника, потрапляють на вузол із Source IP-адресою клієнта, а не проміжного проксі.
Балансувальники навантаження першої категорії повинні використовувати узгоджений між балансувальником навантаження та бекендом протокол для передачі справжньої IP-адреси клієнта, як-от заголовки HTTP Forwarded або X-FORWARDED-FOR, або протокол proxy. Балансувальники навантаження другої категорії можуть використовувати описану вище можливість, створюючи HTTP-перевірку стану, що вказує на порт, збережений у полі service.spec.healthCheckNodePort Service.