1 - Розгортання й доступ до Kubernetes Dashboard

Розгорніть вебінтерфейс (Kubernetes Dashboard) і отримайте до нього доступ.

Kubernetes Dashboard є застарілим та не підтримується.

Проєкт Kubernetes Dashboard заархівовано, і він більше не підтримується активно. Для нових встановлень розгляньте Headlamp.

Примітка:

Про розгортання в кластері, подібне до Kubernetes Dashboard, дивіться настанови зі встановлення Headlamp у кластері.

Dashboard — це вебінтерфейс користувача Kubernetes. За допомогою Dashboard можна розгортати контейнеризовані застосунки в кластері Kubernetes, усувати несправності контейнеризованих застосунків і керувати ресурсами кластера. Також Dashboard дає змогу переглядати застосунки, що працюють у кластері, а ще створювати або змінювати окремі ресурси Kubernetes (як-от Deployments, Jobs, DaemonSets тощо). Наприклад, можна масштабувати Deployment, запустити поетапне оновлення, перезапустити Pod або розгорнути нові застосунки за допомогою майстра розгортання.

Dashboard також надає інформацію про стан ресурсів Kubernetes у кластері та про помилки, що могли виникнути.

Kubernetes Dashboard UI

Розгортання інтерфейсу Dashboard

Примітка:

Наразі Kubernetes Dashboard підтримує лише встановлення за допомогою Helm, оскільки це швидше й дає нам кращий контроль над усіма залежностями, потрібними для роботи Dashboard.

Стандартно інтерфейс Dashboard не розгорнуто. Щоб розгорнути його, виконайте таку команду:

# Додайте репозиторій kubernetes-dashboard
helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/
# Розгорніть Helm Release з назвою "kubernetes-dashboard" за допомогою чарта kubernetes-dashboard
helm upgrade --install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard --create-namespace --namespace kubernetes-dashboard

Доступ до інтерфейсу Dashboard

Щоб захистити дані кластера, Dashboard стандартно розгортається з мінімальною конфігурацією RBAC. Наразі Dashboard підтримує лише вхід за допомогою Bearer Token. Щоб створити токен для цієї демонстрації, скористайтеся нашим посібником зі створення зразка користувача.

Попередження:

Зразок користувача, створений у цьому навчальному матеріалі, матиме адміністративні привілеї й призначений лише для навчання.

Проксі з командного рядка

Увімкнути доступ до Dashboard можна за допомогою інструмента командного рядка kubectl, виконавши таку команду:

kubectl -n kubernetes-dashboard port-forward svc/kubernetes-dashboard-kong-proxy 8443:443

kubectl зробить Dashboard доступним за адресою https://localhost:8443.

Доступ до інтерфейсу можливий лише з машини, на якій виконано команду. Більше параметрів дивіться в kubectl port-forward --help.

Примітка:

Метод автентифікації kubeconfig не підтримує зовнішніх постачальників ідентифікації або автентифікацію на основі сертифікатів X.509.

Вітальна сторінка

Коли ви відкриваєте Dashboard у порожньому кластері, показується вітальна сторінка. Вона містить посилання на цей документ, а також кнопку для розгортання вашого першого застосунку. Крім того, можна переглянути, які системні застосунки стандартно працюють у просторі імен kube-system вашого кластера, наприклад сам Dashboard.

Вітальна сторінка Kubernetes Dashboard

Розгортання контейнеризованих застосунків

Dashboard дає змогу створити й розгорнути контейнеризований застосунок як Deployment і необовʼязковий Service за допомогою простого майстра. Можна або вручну вказати параметри застосунку, або завантажити файл маніфесту YAML чи JSON, що містить конфігурацію застосунку.

Натисніть кнопку CREATE у верхньому правому куті будь-якої сторінки, щоб розпочати.

Встановлення параметрів застосунку

Майстер розгортання очікує від вас таку інформацію:

  • Назва застосунку (обовʼязково): назва вашого застосунку. Мітку з цією назвою буде додано до Deployment і Service (якщо він є), які буде розгорнуто.

    Назва застосунку має бути унікальною в межах вибраного простору імен Kubernetes. Вона має починатися з малої літери, закінчуватися малою літерою або цифрою й містити лише малі літери, цифри та дефіси (-). Довжина обмежена 24 символами. Пробіли на початку й у кінці ігноруються.

  • Образ контейнера (обовʼязково): URL публічного образу контейнера Docker у будь-якому реєстрі або приватного образу (зазвичай розміщеного в Google Container Registry або Docker Hub). Специфікація образу контейнера має закінчуватися двокрапкою.

  • Кількість Podʼів (обовʼязково): цільова кількість Podʼів, у яких ви хочете розгорнути застосунок. Значення має бути додатним цілим числом.

    Буде створено Deployment, щоб підтримувати потрібну кількість Podʼів у вашому кластері.

  • Service (необовʼязково): для деяких частин застосунку (наприклад, фронтендів) може знадобитися відкрити доступ до Service через зовнішню, можливо публічну, IP-адресу поза кластером (зовнішній Service).

    Примітка:

    Для зовнішніх Services може знадобитися відкрити один або кілька портів.

    Інші Services, видимі лише всередині кластера, називаються внутрішніми Services.

    Незалежно від типу Service, якщо ви вирішите створити Service і ваш контейнер слухає порт (вхідний), потрібно вказати два порти. Service буде створено зі зіставленням порту (вхідного) на цільовий порт, який бачить контейнер. Цей Service спрямовуватиме трафік до розгорнутих Podʼів. Підтримувані протоколи: TCP і UDP. Внутрішнім DNS-імʼям цього Service буде значення, вказане вище як назва застосунку.

За потреби можна розгорнути розділ Advanced options, де можна вказати інші налаштування:

  • Опис: текст, який ви введете тут, буде додано як анотацію до Deployment і показано в деталях застосунку.

  • Мітки: стандартні мітки застосунку — це його назва та версія. Можна вказати додаткові мітки, які буде застосовано до Deployment, Service (якщо він є) і Podʼів, як-от release, environment, tier, partition і release track.

    Приклад:

    release=1.0
    tier=frontend
    environment=pod
    track=stable
    
  • Простір імен: Kubernetes підтримує кілька віртуальних кластерів на основі одного фізичного кластера. Ці віртуальні кластери називаються просторами імен. Вони дають змогу розділяти ресурси на логічно названі групи.

    Dashboard пропонує всі доступні простори імен у випадному списку й дає змогу створити новий простір імен. Назва простору імен може містити не більше 63 алфавітно-цифрових символів і дефісів (-), але не може містити великих літер. Назви просторів імен не повинні складатися лише з цифр. Якщо назву задано як число, наприклад 10, Pod буде розміщено у стандартному просторі імен.

    Якщо простір імен створено успішно, його буде вибрано стандартно. Якщо створити його не вдалося, буде вибрано перший простір імен.

  • Secret для завантаження образу: якщо вказаний образ контейнера Docker приватний, він може потребувати облікових даних із Secret для завантаження образу.

    Dashboard пропонує всі доступні Secrets у випадному списку й дає змогу створити новий Secret. Назва Secret має відповідати синтаксису доменного імені DNS, наприклад new.image-pull.secret. Вміст Secret має бути закодований у base64 і вказаний у файлі .dockercfg. Назва Secret може містити не більше 253 символів.

    Якщо Secret для завантаження образу створено успішно, його буде вибрано стандартно. Якщо створити його не вдалося, Secret не застосовується.

  • Вимога до CPU (ядра) та Вимога до памʼяті (MiB): можна вказати мінімальні обмеження ресурсів для контейнера. Стандартно Podʼи працюють без обмежень на CPU і памʼять.

  • Команда запуску та Аргументи команди запуску: стандартно контейнери виконують команду entrypoint, визначену у вказаному образі Docker. За допомогою параметрів і аргументів команди її можна перевизначити.

  • Запуск у привілейованому режимі: це налаштування визначає, чи еквівалентні процеси в привілейованих контейнерах процесам, що виконуються від імені root на хості. Привілейовані контейнери можуть використовувати такі можливості, як керування мережевим стеком і доступ до пристроїв.

  • Змінні середовища: Kubernetes надає відомості про Services через змінні середовища. Можна складати змінні середовища або передавати аргументи командам, використовуючи значення змінних середовища. Їх можна використовувати в застосунках для пошуку Service. Значення можуть посилатися на інші змінні за допомогою синтаксису $(VAR_NAME).

Завантаження файлу YAML або JSON

Kubernetes підтримує декларативну конфігурацію. У цьому стилі вся конфігурація зберігається в маніфестах (файлах конфігурації YAML або JSON). Маніфести використовують схеми ресурсів API Kubernetes.

Замість того щоб вказувати параметри застосунку в майстрі розгортання, можна визначити застосунок в одному чи кількох маніфестах і завантажити файли за допомогою Dashboard.

Використання Dashboard

У наведених нижче розділах описано подання інтерфейсу Kubernetes Dashboard: що вони надають і як їх використовувати.

Коли в кластері визначено обʼєкти Kubernetes, Dashboard показує їх у початковому поданні. Стандартно показано лише обʼєкти з простору імен default; це можна змінити за допомогою селектора простору імен у меню навігації.

Dashboard показує більшість типів обʼєктів Kubernetes та групує їх у кілька категорій меню.

Огляд адміністратора

Для адміністраторів кластерів і просторів імен Dashboard перелічує Nodes, Namespaces і PersistentVolumes та має для них детальні подання. Подання списку Nodes містить метрики використання CPU й памʼяті, агреговані за всіма вузлами. Детальне подання показує метрики вузла, його специфікацію, статус, виділені ресурси, події та Podʼи, що працюють на вузлі.

Робочі навантаження

Показує всі застосунки, що працюють у вибраному просторі імен. Подання перелічує застосунки за типом робочого навантаження (наприклад, Deployments, ReplicaSets, StatefulSets). Кожен тип робочого навантаження можна переглядати окремо. Списки узагальнюють практичну інформацію про робочі навантаження, як-от кількість готових Podʼів у ReplicaSet або поточне використання памʼяті Podʼом.

Детальні подання робочих навантажень показують статус і специфікацію, а також звʼязки між обʼєктами. Наприклад, Podʼи, якими керує ReplicaSet, або нові ReplicaSets і HorizontalPodAutoscalers для Deployments.

Services

Показує ресурси Kubernetes, які дають змогу відкривати доступ до сервісів для зовнішнього світу й виявляти їх усередині кластера. Тому подання Service та Ingress показують Podʼи, на які вони спрямовані, внутрішні точки доступу для зʼєднань усередині кластера та зовнішні точки доступу для зовнішніх користувачів.

Сховище

Подання сховища показує ресурси PersistentVolumeClaim, які застосунки використовують для зберігання даних.

ConfigMaps та Secrets

Показує всі ресурси Kubernetes, що використовуються для поточної конфігурації застосунків, які працюють у кластерах. Подання дає змогу редагувати обʼєкти конфігурації й керувати ними та стандартно показує Secrets прихованими.

Переглядач логів

Списки Podʼів і сторінки деталей містять посилання на переглядач логів, вбудований у Dashboard. Переглядач дає змогу детально вивчати логи контейнерів, що належать одному Podʼу.

Переглядач логів

Що далі

Докладніше дивіться на сторінці проєкту Kubernetes Dashboard.

2 - Доступ до кластерів

У цій темі розглянуто кілька способів взаємодії з кластерами.

Перший доступ за допомогою kubectl

Під час першого доступу до Kubernetes API радимо використовувати Kubernetes CLI — kubectl.

Щоб отримати доступ до кластера, потрібно знати його розташування й мати облікові дані для доступу. Зазвичай це налаштовується автоматично, коли ви проходите посібник «Початок роботи», або хтось інший налаштував кластер і надав вам облікові дані та розташування.

Перевірте розташування та облікові дані, про які знає kubectl, за допомогою цієї команди:

kubectl config view

Багато прикладів знайомлять із використанням kubectl, а повну документацію наведено в довіднику kubectl.

Прямий доступ до REST API

kubectl сам знаходить API-сервер і автентифікується на ньому. Якщо ви хочете звертатися до REST API безпосередньо за допомогою http-клієнта, як-от curl або wget, чи браузера, є кілька способів знайти API-сервер і автентифікуватися:

  • Запустіть kubectl у режимі проксі.
    • Рекомендований підхід.
    • Використовує збережене розташування API-сервера.
    • Перевіряє автентичність API-сервера за допомогою самопідписаного сертифіката. Атака MITM неможлива.
    • Автентифікується на API-сервері.
    • У майбутньому може виконувати інтелектуальне балансування навантаження та перемикання в разі відмови на стороні клієнта.
  • Надайте розташування й облікові дані безпосередньо http-клієнту.
    • Альтернативний підхід.
    • Працює з деякими типами клієнтського коду, які збиваються через використання проксі.
    • Потрібно імпортувати кореневий сертифікат у браузер для захисту від MITM.

Використання kubectl proxy

Наведена нижче команда запускає kubectl у режимі, у якому він працює як зворотний проксі. Він сам знаходить API-сервер і автентифікується. Запустіть її так:

kubectl proxy --port=8080

Докладніше дивіться в описі kubectl proxy.

Після цього можна досліджувати API за допомогою curl, wget або браузера, замінивши localhost на [::1] для IPv6, ось так:

curl http://localhost:8080/api/

Вивід подібний до такого:

{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "10.0.1.149:443"
    }
  ]
}

Без kubectl proxy

Використайте kubectl apply і kubectl describe secret..., щоб створити токен для стандартного ServiceAccount за допомогою grep/cut:

Спочатку створіть Secret, запитавши токен для стандартного ServiceAccount:

kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: default-token
  annotations:
    kubernetes.io/service-account.name: default
type: kubernetes.io/service-account-token
EOF

Далі зачекайте, поки контролер токенів заповнить Secret токеном:

while ! kubectl describe secret default-token | grep -E '^token' >/dev/null; do
  echo "waiting for token..." >&2
  sleep 1
done

Отримайте й використайте згенерований токен:

APISERVER=$(kubectl config view --minify | grep server | cut -f 2- -d ":" | tr -d " ")
TOKEN=$(kubectl describe secret default-token | grep -E '^token' | cut -f2 -d':' | tr -d " ")

curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure

Вивід подібний до такого:

{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "10.0.1.149:443"
    }
  ]
}

За допомогою jsonpath:

APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
TOKEN=$(kubectl get secret default-token -o jsonpath='{.data.token}' | base64 --decode)

curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure

Вивід подібний до такого:

{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "10.0.1.149:443"
    }
  ]
}

У наведених вище прикладах використано прапорець --insecure. Через це запит вразливий до атак MITM. Коли kubectl звертається до кластера, він використовує збережений кореневий сертифікат і клієнтські сертифікати для доступу до сервера. (Вони встановлені в теці ~/.kube.) Оскільки сертифікати кластера зазвичай самопідписані, щоб http-клієнт використовував кореневий сертифікат, може знадобитися спеціальне налаштування.

У деяких кластерах API-сервер не вимагає автентифікації: він може обслуговувати запити на localhost або бути захищеним фаєрволом. Стандарту для цього немає. У розділі Контроль доступу до API описано, як адміністратор кластера може це налаштувати.

Програмний доступ до API

Kubernetes офіційно підтримує клієнтські бібліотеки для Go та Python.

Клієнт Go

  • Щоб отримати бібліотеку, виконайте таку команду: go get k8s.io/client-go@kubernetes-<kubernetes-version-number>, докладні інструкції зі встановлення дивіться в INSTALL.md. Підтримувані версії дивіться на https://github.com/kubernetes/client-go.
  • Напишіть застосунок на основі клієнтів client-go. Зверніть увагу, що client-go визначає власні обʼєкти API, тому за потреби імпортуйте визначення API з client-go, а не з основного репозиторію, наприклад, правильним є import "k8s.io/client-go/kubernetes".

Клієнт Go може використовувати той самий файл kubeconfig, що й CLI kubectl, щоб знайти API-сервер і автентифікуватися на ньому. Дивіться цей приклад.

Якщо застосунок розгорнуто як Pod у кластері, зверніться до наступного розділу.

Клієнт Python

Щоб використовувати клієнт Python, виконайте таку команду: pip install kubernetes. Інші варіанти встановлення дивіться на сторінці Python Client Library.

Клієнт Python може використовувати той самий файл kubeconfig, що й CLI kubectl, щоб знайти API-сервер і автентифікуватися на ньому. Дивіться цей приклад.

Інші мови

Для доступу до API з інших мов існують клієнтські бібліотеки. Про те, як вони автентифікуються, дивіться документацію цих бібліотек.

Доступ до API з Podʼа

Під час доступу до API з Podʼа пошук API-сервера й автентифікація на ньому дещо відрізняються.

Докладніше дивіться в розділі Доступ до API зсередини Podʼа.

Доступ до сервісів, що працюють у кластері

У попередньому розділі описано, як підʼєднатися до API-сервера Kubernetes. Про підʼєднання до інших сервісів, що працюють у кластері Kubernetes, дивіться Доступ до сервісів кластера.

Запит перенаправлення

Можливості перенаправлення визнано застарілими й вилучено. Натомість використовуйте проксі (дивіться нижче).

Так багато проксі

Під час роботи з Kubernetes можна зустріти кілька різних проксі:

  1. kubectl proxy:

    • працює на компʼютері користувача або в Podʼі
    • проксіює з адреси localhost до API-сервера Kubernetes
    • від клієнта до проксі використовується HTTP
    • від проксі до API-сервера використовується HTTPS
    • знаходить API-сервер
    • додає заголовки автентифікації
  2. apiserver proxy:

    • є бастіоном, вбудованим в API-сервер
    • зʼєднує користувача поза кластером з IP-адресами кластера, які інакше можуть бути недосяжними
    • працює в процесах API-сервера
    • від клієнта до проксі використовується HTTPS (або http, якщо так налаштовано API-сервер)
    • від проксі до цілі може використовуватися HTTP або HTTPS на вибір проксі, на основі наявної інформації
    • може використовуватися для доступу до Node, Pod або Service
    • забезпечує балансування навантаження, коли використовується для доступу до Service
  3. kube proxy:

    • працює на кожному вузлі
    • проксіює UDP і TCP
    • не розуміє HTTP
    • забезпечує балансування навантаження
    • використовується лише для доступу до сервісів
  4. Проксі або балансувальник навантаження перед API-сервером (або кількома):

    • наявність і реалізація різняться від кластера до кластера (наприклад, nginx)
    • розташовується між усіма клієнтами та одним чи кількома API-серверами
    • працює як балансувальник навантаження, якщо є кілька API-серверів.
  5. Хмарні балансувальники навантаження для зовнішніх сервісів:

    • надаються деякими хмарними провайдерами (наприклад, AWS ELB, Google Cloud Load Balancer)
    • створюються автоматично, коли сервіс Kubernetes має тип LoadBalancer
    • використовують лише UDP/TCP
    • реалізація залежить від хмарного провайдера.

Користувачам Kubernetes зазвичай не потрібно перейматися нічим, крім перших двох типів. За правильне налаштування решти типів зазвичай відповідає адміністратор кластера.

3 - Використання перенаправлення портів для доступу до застосунків у кластері

На цій сторінці показано, як за допомогою kubectl port-forward підʼєднатися до сервера MongoDB, що працює в кластері Kubernetes. Таке підʼєднання може бути корисним для налагодження бази даних.

Перш ніж ви розпочнете

  • Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:

    Версія вашого Kubernetes сервера має бути не старішою ніж v1.10.

    Для перевірки версії введіть kubectl version.

  • Встановіть MongoDB Shell.

Створення Deployment і Service для MongoDB

  1. Створіть Deployment, що запускає MongoDB:

    kubectl apply -f https://k8s.io/examples/application/mongodb/mongo-deployment.yaml
    

    Вивід успішної команди підтверджує, що Deployment створено:

    deployment.apps/mongo created
    

    Перегляньте статус Podʼа, щоб переконатися, що він готовий:

    kubectl get pods
    

    Вивід показує створений Pod:

    NAME                     READY   STATUS    RESTARTS   AGE
    mongo-75f59d57f4-4nd6q   1/1     Running   0          2m4s
    

    Перегляньте статус Deployment:

    kubectl get deployment
    

    Вивід показує, що Deployment створено:

    NAME    READY   UP-TO-DATE   AVAILABLE   AGE
    mongo   1/1     1            1           2m21s
    

    Deployment автоматично керує ReplicaSet. Перегляньте статус ReplicaSet за допомогою:

    kubectl get replicaset
    

    Вивід показує, що ReplicaSet створено:

    NAME               DESIRED   CURRENT   READY   AGE
    mongo-75f59d57f4   1         1         1       3m12s
    
  2. Створіть Service, щоб відкрити доступ до MongoDB у мережі:

    kubectl apply -f https://k8s.io/examples/application/mongodb/mongo-service.yaml
    

    Вивід успішної команди підтверджує, що Service створено:

    service/mongo created
    

    Перевірте створений Service:

    kubectl get service mongo
    

    Вивід показує створений Service:

    NAME    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)     AGE
    mongo   ClusterIP   10.96.41.183   <none>        27017/TCP   11s
    
  3. Переконайтеся, що сервер MongoDB працює в Podʼі й слухає порт 27017:

    # Замініть mongo-75f59d57f4-4nd6q на назву Podʼа
    kubectl get pod mongo-75f59d57f4-4nd6q --template='{{(index (index .spec.containers 0).ports 0).containerPort}}{{"\n"}}'
    

    Вивід показує порт MongoDB у цьому Podʼі:

    27017
    

    27017 — офіційний порт TCP для MongoDB.

Перенаправлення локального порту на порт Podʼа

  1. kubectl port-forward дозволяє використовувати назву ресурсу, наприклад назву Podʼа, щоб вибрати відповідний Pod для перенаправлення порту.

    # Замініть mongo-75f59d57f4-4nd6q на назву Podʼа
    kubectl port-forward mongo-75f59d57f4-4nd6q 28015:27017
    

    що те саме, що й

    kubectl port-forward pods/mongo-75f59d57f4-4nd6q 28015:27017
    

    або

    kubectl port-forward deployment/mongo 28015:27017
    

    або

    kubectl port-forward replicaset/mongo-75f59d57f4 28015:27017
    

    або

    kubectl port-forward service/mongo 28015:27017
    

    Будь-яка з наведених вище команд працює. Вивід подібний до такого:

    Forwarding from 127.0.0.1:28015 -> 27017
    Forwarding from [::1]:28015 -> 27017
    

    Примітка:

    kubectl port-forward не завершується сам. Щоб продовжити вправи, потрібно відкрити інший термінал.
  2. Запустіть інтерфейс командного рядка MongoDB:

    mongosh --port 28015
    
  3. У командному рядку MongoDB введіть команду ping:

    db.runCommand( { ping: 1 } )
    

    Успішний запит ping повертає:

    { ok: 1 }
    

За бажання дозвольте kubectl вибрати локальний порт

Якщо вам не потрібен конкретний локальний порт, ви можете дозволити kubectl вибрати й призначити його, що позбавить вас потреби розвʼязувати конфлікти локальних портів, за допомогою дещо простішого синтаксису:

kubectl port-forward deployment/mongo :27017

Інструмент kubectl вибирає вільний номер локального порту (уникаючи низьких номерів, оскільки їх можуть використовувати інші застосунки). Вивід подібний до такого:

Forwarding from 127.0.0.1:63753 -> 27017
Forwarding from [::1]:63753 -> 27017

Обговорення

Зʼєднання з локальним портом 28015 перенаправляються на порт 27017 Podʼа, у якому працює сервер MongoDB. Завдяки цьому зʼєднанню ви можете налагоджувати базу даних, що працює в Podʼі, зі своєї локальної робочої станції.

Примітка:

kubectl port-forward реалізовано лише для портів TCP. Підтримка протоколу UDP відстежується в issue 47862.

Авторизація та міркування безпеки

Доступ до kubectl port-forward контролюється механізмами авторизації Kubernetes, такими як контроль доступу на основі ролей (RBAC). Авторизацію забезпечує API-сервер Kubernetes, а не клієнт kubectl.

Щоб використовувати kubectl port-forward, користувач повинен мати дозвіл на доступ до цільового ресурсу (наприклад, Pod або Service) і субресурсу portforward. Зазвичай потрібні дозволи get для pods і create для pods/portforward.

Адміністратори кластерів мають ретельно обмежувати ці дозволи, оскільки перенаправлення портів може надавати прямий мережевий доступ до робочих навантажень і обходити засоби контролю на рівні мережі.

Що далі

Дізнайтеся більше про kubectl port-forward.

4 - Використання Service для доступу до застосунку в кластері

На цій сторінці показано, як створити обʼєкт Service у Kubernetes, за допомогою якого зовнішні клієнти можуть отримати доступ до застосунку, що працює в кластері. Service забезпечує балансування навантаження для застосунку, який має два запущені екземпляри.

Перш ніж ви розпочнете

Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:

Цілі

  • Запустити два екземпляри застосунку Hello World.
  • Створити обʼєкт Service, який відкриває порт вузла.
  • Використовувати обʼєкт Service для доступу до запущеного застосунку.

Створення Service для застосунку, що працює у двох Podʼах

Ось файл конфігурації Deployment застосунку:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-world
spec:
  selector:
    matchLabels:
      run: load-balancer-example
  replicas: 2
  template:
    metadata:
      labels:
        run: load-balancer-example
    spec:
      containers:
        - name: hello-world
          image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0
          ports:
            - containerPort: 8080
              protocol: TCP
  1. Запустіть застосунок Hello World у кластері: створіть Deployment застосунку за допомогою наведеного вище файлу:

    kubectl apply -f https://k8s.io/examples/service/access/hello-application.yaml
    

    Попередня команда створює Deployment і повʼязаний ReplicaSet. ReplicaSet має два Podʼи, кожен з яких запускає застосунок Hello World.

  2. Перегляньте інформацію про Deployment:

    kubectl get deployments hello-world
    kubectl describe deployments hello-world
    
  3. Перегляньте інформацію про ваші обʼєкти ReplicaSet:

    kubectl get replicasets
    kubectl describe replicasets
    
  4. Створіть обʼєкт Service, який відкриває доступ до Deployment:

    kubectl expose deployment hello-world --type=NodePort --name=example-service
    
  5. Перегляньте інформацію про Service:

    kubectl describe services example-service
    

    Вивід подібний до такого:

    Name:                   example-service
    Namespace:              default
    Labels:                 run=load-balancer-example
    Annotations:            <none>
    Selector:               run=load-balancer-example
    Type:                   NodePort
    IP:                     10.32.0.16
    Port:                   <unset> 8080/TCP
    TargetPort:             8080/TCP
    NodePort:               <unset> 31496/TCP
    Endpoints:              10.200.1.4:8080,10.200.2.5:8080
    Session Affinity:       None
    Events:                 <none>
    

    Занотуйте значення NodePort для Service. Наприклад, у попередньому виводі значення NodePort становить 31496.

  6. Виведіть Podʼи, на яких працює застосунок Hello World:

    kubectl get pods --selector="run=load-balancer-example" --output=wide
    

    Вивід подібний до такого:

    NAME                           READY   STATUS    ...  IP           NODE
    hello-world-2895499144-bsbk5   1/1     Running   ...  10.200.1.4   worker1
    hello-world-2895499144-m1pwt   1/1     Running   ...  10.200.2.5   worker2
    
  7. Отримайте публічну IP-адресу одного з вузлів, на якому працює Pod Hello World. Спосіб отримання цієї адреси залежить від того, як налаштовано кластер. Наприклад, якщо ви використовуєте Minikube, адресу вузла можна побачити, виконавши kubectl cluster-info. Якщо ви використовуєте екземпляри Google Compute Engine, переглянути публічні адреси вузлів можна командою gcloud compute instances list.

  8. На вибраному вузлі створіть правило фаєрвола, яке дозволяє TCP-трафік на порт вузла. Наприклад, якщо значення NodePort вашого Service — 31568, створіть правило фаєрвола, яке дозволяє TCP-трафік на порт 31568. Різні хмарні провайдери пропонують різні способи налаштування правил фаєрвола.

  9. Використовуйте адресу вузла та порт вузла для доступу до застосунку Hello World:

    curl http://<public-node-ip>:<node-port>
    

    де <public-node-ip> — публічна IP-адреса вашого вузла, а <node-port> — значення NodePort вашого сервісу. Відповідь на успішний запит — вітальне повідомлення:

    Hello, world!
    Version: 2.0.0
    Hostname: hello-world-cdd4458f4-m47c8
    

Використання файлу конфігурації Service

Замість kubectl expose можна використати файл конфігурації Service, щоб створити Service.

Очищення

Щоб видалити Service, введіть цю команду:

kubectl delete services example-service

Щоб видалити Deployment, ReplicaSet і Podʼи, на яких працює застосунок Hello World, введіть цю команду:

kubectl delete deployment hello-world

Що далі

Скористайтеся навчальним матеріалом Підключення застосунків за допомогою Services.

5 - Зʼєднання фронтенду з бекендом за допомогою Services

Це завдання показує, як створити мікросервіси фронтенду й бекенду. Мікросервіс бекенду — це сервіс привітання. Фронтенд відкриває доступ до бекенду за допомогою nginx та обʼєкта Service Kubernetes.

Цілі

  • Створити й запустити приклад мікросервісу бекенду hello за допомогою обʼєкта Deployment.
  • Використовувати обʼєкт Service для надсилання трафіку до кількох реплік мікросервісу бекенду.
  • Створити й запустити мікросервіс фронтенду nginx, також за допомогою обʼєкта Deployment.
  • Налаштувати мікросервіс фронтенду на надсилання трафіку до мікросервісу бекенду.
  • Використати обʼєкт Service type=LoadBalancer, щоб відкрити доступ до мікросервісу фронтенду ззовні кластера.

Перш ніж ви розпочнете

Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:

Для перевірки версії введіть kubectl version.

Це завдання використовує Services із зовнішніми балансувальниками навантаження, які потребують підтримуваного середовища. Якщо ваше середовище їх не підтримує, натомість можна використати Service типу NodePort.

Створення бекенду за допомогою Deployment

Бекенд — це простий мікросервіс привітання. Ось файл конфігурації Deployment бекенду:

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
spec:
  selector:
    matchLabels:
      app: hello
      tier: backend
      track: stable
  replicas: 3
  template:
    metadata:
      labels:
        app: hello
        tier: backend
        track: stable
    spec:
      containers:
        - name: hello
          image: "gcr.io/google-samples/hello-go-gke:1.0"
          ports:
            - name: http
              containerPort: 80
...

Створіть Deployment для бекенду:

kubectl apply -f https://k8s.io/examples/service/access/backend-deployment.yaml

Перегляньте інформацію про Deployment бекенду:

kubectl describe deployment backend

Вивід подібний до такого:

Name:                           backend
Namespace:                      default
CreationTimestamp:              Mon, 24 Oct 2016 14:21:02 -0700
Labels:                         app=hello
                                tier=backend
                                track=stable
Annotations:                    deployment.kubernetes.io/revision=1
Selector:                       app=hello,tier=backend,track=stable
Replicas:                       3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:                   RollingUpdate
MinReadySeconds:                0
RollingUpdateStrategy:          1 max unavailable, 1 max surge
Pod Template:
  Labels:       app=hello
                tier=backend
                track=stable
  Containers:
   hello:
    Image:              "gcr.io/google-samples/hello-go-gke:1.0"
    Port:               80/TCP
    Environment:        <none>
    Mounts:             <none>
  Volumes:              <none>
Conditions:
  Type          Status  Reason
  ----          ------  ------
  Available     True    MinimumReplicasAvailable
  Progressing   True    NewReplicaSetAvailable
OldReplicaSets:                 <none>
NewReplicaSet:                  hello-3621623197 (3/3 replicas created)
Events:
...

Створення обʼєкта Service hello

Ключовим для надсилання запитів із фронтенду до бекенду є Service бекенду. Service створює постійну IP-адресу й запис імені DNS, щоб мікросервіс бекенду завжди був доступний. Service використовує селектори, щоб визначити Podʼи, до яких спрямовувати трафік.

Спочатку перегляньте файл конфігурації Service:

---
apiVersion: v1
kind: Service
metadata:
  name: hello
spec:
  selector:
    app: hello
    tier: backend
  ports:
  - protocol: TCP
    port: 80
    targetPort: http
...

У файлі конфігурації видно, що Service з назвою hello спрямовує трафік до Podʼів із мітками app: hello і tier: backend.

Створіть Service для бекенду:

kubectl apply -f https://k8s.io/examples/service/access/backend-service.yaml

На цьому етапі у вас є Deployment backend, що виконує три репліки застосунку hello, і Service, який може спрямовувати до них трафік. Однак цей сервіс недоступний і не розвʼязується ззовні кластера.

Створення фронтенду

Тепер, коли бекенд працює, можна створити фронтенд, доступний ззовні кластера, який підʼєднується до бекенду, проксіюючи до нього запити.

Фронтенд надсилає запити до робочих Podʼів бекенду, використовуючи DNS-імʼя, надане Service бекенду. DNS-імʼя — hello, це значення поля name у файлі конфігурації examples/service/access/backend-service.yaml.

Podʼи в Deployment фронтенду запускають образ nginx, налаштований на проксіювання запитів до Service бекенду hello. Ось файл конфігурації nginx:

# The identifier Backend is internal to nginx, and used to name this specific upstream
upstream Backend {
    # hello is the internal DNS name used by the backend Service inside Kubernetes
    server hello;
}

server { listen 80;

location / {
    # The following statement will proxy traffic to the upstream named Backend
    proxy_pass http://Backend;
}

}

Як і бекенд, фронтенд має Deployment і Service. Важлива відмінність між сервісами бекенду й фронтенду в тому, що конфігурація Service фронтенду має type: LoadBalancer, тобто Service використовує балансувальник навантаження, наданий вашим хмарним провайдером, і буде доступний ззовні кластера.

---
apiVersion: v1
kind: Service
metadata:
  name: frontend
spec:
  selector:
    app: hello
    tier: frontend
  ports:
  - protocol: "TCP"
    port: 80
    targetPort: 80
  type: LoadBalancer
...
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  selector:
    matchLabels:
      app: hello
      tier: frontend
      track: stable
  replicas: 1
  template:
    metadata:
      labels:
        app: hello
        tier: frontend
        track: stable
    spec:
      containers:
        - name: nginx
          image: "gcr.io/google-samples/hello-frontend:1.0"
          lifecycle:
            preStop:
              exec:
                command: ["/usr/sbin/nginx","-s","quit"]
...

Створіть Deployment і Service фронтенду:

kubectl apply -f https://k8s.io/examples/service/access/frontend-deployment.yaml
kubectl apply -f https://k8s.io/examples/service/access/frontend-service.yaml

Вивід підтверджує, що обидва ресурси створено:

deployment.apps/frontend created
service/frontend created

Примітка:

Конфігурацію nginx вбудовано в образ контейнера. Кращий спосіб — використати ConfigMap, щоб легше змінювати конфігурацію.

Взаємодія із Service фронтенду

Після створення Service типу LoadBalancer цією командою можна знайти зовнішню IP-адресу:

kubectl get service frontend --watch

Це показує конфігурацію Service frontend і відстежує зміни. Спочатку зовнішня IP-адреса вказана як <pending>:

NAME       TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)  AGE
frontend   LoadBalancer   10.51.252.116   <pending>     80/TCP   10s

Щойно зовнішню IP-адресу буде надано, конфігурація оновиться й міститиме нову IP-адресу в колонці EXTERNAL-IP:

NAME       TYPE           CLUSTER-IP      EXTERNAL-IP        PORT(S)  AGE
frontend   LoadBalancer   10.51.252.116   XXX.XXX.XXX.XXX    80/TCP   1m

Тепер цю IP-адресу можна використовувати для взаємодії із сервісом frontend ззовні кластера.

Надсилання трафіку через фронтенд

Фронтенд і бекенд тепер зʼєднані. Ви можете звернутися до точки доступу командою curl за зовнішньою IP-адресою Service фронтенду.

curl http://${EXTERNAL_IP} # замініть це на EXTERNAL-IP, який ви бачили раніше

Вивід показує повідомлення, згенероване бекендом:

{"message":"Hello"}

Очищення

Щоб видалити Services, введіть цю команду:

kubectl delete services frontend backend

Щоб видалити Deployments, ReplicaSets і Podʼи, у яких працюють застосунки бекенду й фронтенду, введіть цю команду:

kubectl delete deployment frontend backend

Що далі

6 - Створення зовнішнього балансувальника навантаження

На цій сторінці показано, як створити зовнішній балансувальник навантаження.

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

Ви також можете використовувати Ingress замість Service. Докладніше дивіться в документації про Ingress.

Перш ніж ви розпочнете

Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:

Ваш кластер має працювати в хмарі або іншому середовищі, яке вже підтримує налаштування зовнішніх балансувальників навантаження.

Створення Service

Створення Service з маніфесту

Щоб створити зовнішній балансувальник навантаження, додайте такий рядок до маніфесту Service:

    type: LoadBalancer

Ваш маніфест може виглядати так:

apiVersion: v1
kind: Service
metadata:
  name: example-service
spec:
  selector:
    app: example
  ports:
    - port: 8765
      targetPort: 9376
  type: LoadBalancer

Створення Service за допомогою kubectl

Також можна створити сервіс командою kubectl expose із прапорцем --type=LoadBalancer:

kubectl expose deployment example --port=8765 --target-port=9376 \
        --name=example-service --type=LoadBalancer

Ця команда створює новий Service із тими самими селекторами, що й у вказаного ресурсу (у наведеному прикладі — Deployment з назвою example).

Докладніше, зокрема про необовʼязкові прапорці, дивіться в довіднику kubectl expose.

Пошук вашої IP-адреси

Щоб знайти IP-адресу, створену для вашого сервісу, отримайте інформацію про сервіс через kubectl:

kubectl describe services example-service

що має дати вивід, подібний до такого:

Name:                     example-service
Namespace:                default
Labels:                   app=example
Annotations:              <none>
Selector:                 app=example
Type:                     LoadBalancer
IP Families:              <none>
IP:                       10.3.22.96
IPs:                      10.3.22.96
LoadBalancer Ingress:     192.0.2.89
Port:                     <unset>  8765/TCP
TargetPort:               9376/TCP
NodePort:                 <unset>  30593/TCP
Endpoints:                172.17.0.3:9376
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

IP-адреса балансувальника навантаження вказана поруч з LoadBalancer Ingress.

Примітка:

Якщо ви запускаєте сервіс у Minikube, призначену IP-адресу й порт можна знайти за допомогою:

minikube service example-service --url

Збереження вихідної IP-адреси клієнта

Стандартно вихідна IP-адреса, яку бачить цільовий контейнер, не є початковою вихідною IP-адресою клієнта. Щоб увімкнути збереження IP-адреси клієнта, можна налаштувати такі поля в .spec Service:

  • .spec.externalTrafficPolicy — визначає, чи має цей Service маршрутизувати зовнішній трафік до точок доступу на локальному вузлі чи до точок доступу в усьому кластері. Є два варіанти: Cluster (стандартно) і Local. Cluster приховує вихідну IP-адресу клієнта й може спричинити другий перехід на інший вузол, але має добре загальне розподілення навантаження. Local зберігає вихідну IP-адресу клієнта й уникає другого переходу для Services типів LoadBalancer і NodePort, але створює ризик нерівномірного розподілення трафіку.
  • .spec.healthCheckNodePort — задає порт вузла для перевірки справності (числовий номер порту) для сервісу. Якщо ви не вкажете healthCheckNodePort, контролер сервісів виділить порт із діапазону NodePort вашого кластера. Цей діапазон можна налаштувати параметром командного рядка API-сервера --service-node-port-range. Service використовуватиме вказане користувачем значення healthCheckNodePort, якщо ви його задасте, за умови, що type Service — LoadBalancer, а externalTrafficPolicy — Local.

Значення Local для externalTrafficPolicy у маніфесті Service вмикає цю можливість. Наприклад:

apiVersion: v1
kind: Service
metadata:
  name: example-service
spec:
  selector:
    app: example
  ports:
    - port: 8765
      targetPort: 9376
  externalTrafficPolicy: Local
  type: LoadBalancer

Застереження й обмеження під час збереження вихідних IP-адрес

Сервіси балансування навантаження деяких хмарних провайдерів не дозволяють налаштувати різну вагу для кожної цілі.

Коли всі цілі мають однакову вагу під час надсилання трафіку на вузли, зовнішній трафік розподіляється між різними Podʼами нерівномірно. Зовнішній балансувальник навантаження не знає, скільки Podʼів на кожному вузлі використовується як ціль.

Коли NumServicePods << NumNodes або NumServicePods >> NumNodes, розподіл буде досить близьким до рівномірного навіть без ваг.

Внутрішній трафік між Podʼами має поводитися так само, як у Services типу ClusterIP, з однаковою ймовірністю для всіх Podʼів.

Збір сміття балансувальників навантаження

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.17

Зазвичай відповідні ресурси балансувальника навантаження в хмарного провайдера мають бути очищені незабаром після видалення Service типу LoadBalancer. Але відомо, що існують різні крайні випадки, коли хмарні ресурси лишаються без власника після видалення повʼязаного Service. Щоб цьому запобігти, було введено захист Service типу LoadBalancer завершувачами. Завдяки завершувачам ресурс Service не буде видалено, доки не будуть видалені й відповідні ресурси балансувальника навантаження.

Зокрема, якщо Service має type LoadBalancer, контролер сервісів додає завершувач з назвою service.kubernetes.io/load-balancer-cleanup. Завершувач вилучається лише після очищення ресурсу балансувальника навантаження. Це запобігає появі завислих ресурсів балансувальника навантаження навіть у крайніх випадках, наприклад під час збою контролера сервісів.

Постачальники зовнішніх балансувальників навантаження

Важливо зазначити, що шлях даних для цієї можливості забезпечує балансувальник навантаження, зовнішній щодо кластера Kubernetes.

Коли type Service встановлено в LoadBalancer, Kubernetes надає Podʼам у кластері можливості, рівнозначні type ClusterIP, і розширює їх, програмуючи (зовнішній щодо Kubernetes) балансувальник навантаження записами для вузлів, на яких розміщені відповідні Podʼи Kubernetes. Панель управління Kubernetes автоматизує створення зовнішнього балансувальника навантаження, перевірки справності (за потреби) і правила фільтрації пакетів (за потреби). Після того як хмарний провайдер виділить IP-адресу для балансувальника навантаження, панель управління отримує цю зовнішню IP-адресу й заносить її в обʼєкт Service.

Що далі

7 - Отримання переліку всіх образів контейнерів, що працюють у кластері

На цій сторінці показано, як за допомогою kubectl отримати перелік усіх образів контейнерів для Podʼів, що працюють у кластері.

Перш ніж ви розпочнете

Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:

Для перевірки версії введіть kubectl version.

У цій вправі ви за допомогою kubectl отримаєте всі Podʼи, що працюють у кластері, і відформатуєте вивід, щоб отримати перелік контейнерів для кожного з них.

Перелік усіх образів контейнерів у всіх просторах імен

  • Отримайте всі Podʼи у всіх просторах імен за допомогою kubectl get pods --all-namespaces.
  • Відформатуйте вивід, щоб він містив лише перелік назв образів контейнерів, за допомогою -o jsonpath={.items[*].spec['initContainers', 'containers'][*].image}. Це рекурсивно витягне поле image з отриманого json.
  • Відформатуйте вивід за допомогою стандартних інструментів: tr, sort, uniq.
    • Використовуйте tr для заміни пробілів на нові рядки.
    • Використовуйте sort для сортування результатів.
    • Використовуйте uniq для підрахунку образів.
kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec['initContainers', 'containers'][*].image}" |\
tr -s '[[:space:]]' '\n' |\
sort |\
uniq -c

Jsonpath інтерпретується так:

  • .items[*]: для кожного отриманого значення.
  • .spec: отримати spec.
  • ['initContainers', 'containers'][*]: для кожного контейнера.
  • .image: отримати образ.

Примітка:

Під час отримання одного Podʼа за назвою, наприклад kubectl get pod nginx, частину шляху .items[*] слід пропустити, оскільки повертається один Pod, а не список елементів.

Перелік образів контейнерів за Podʼами

Форматування можна додатково контролювати за допомогою операції range, щоб перебирати елементи окремо.

kubectl get pods --all-namespaces -o jsonpath='{range .items[*]}{"\n"}{.metadata.name}{":\t"}{range .spec.containers[*]}{.image}{", "}{end}{end}' |\
sort

Перелік образів контейнерів із фільтрацією за міткою Podʼа

Щоб вибрати лише Podʼи з певною міткою, використовуйте прапорець -l. Наведена нижче команда вибирає лише Podʼи з міткою app=nginx.

kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" -l app=nginx

Перелік образів контейнерів із фільтрацією за простором імен Podʼа

Щоб вибрати лише Podʼи в певному просторі імен, використовуйте прапорець namespace. Наведена нижче команда вибирає лише Podʼи в просторі імен kube-system.

kubectl get pods --namespace kube-system -o jsonpath="{.items[*].spec.containers[*].image}"

Перелік образів контейнерів за допомогою go-template замість jsonpath

Як альтернативу jsonpath kubectl підтримує go-templates для форматування виводу:

kubectl get pods --all-namespaces -o go-template --template="{{range .items}}{{range .spec.containers}}{{.image}} {{end}}{{end}}"

Що далі

Довідка

8 - Взаємодія контейнерів в одному Podʼі за допомогою спільного тому

На цій сторінці показано, як використовувати том для взаємодії двох контейнерів, що працюють в одному Podʼі. Дивіться також, як дозволити процесам взаємодіяти через спільний простір імен процесів між контейнерами.

Перш ніж ви розпочнете

Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:

Для перевірки версії введіть kubectl version.

Створення Podʼа, що запускає два контейнери

У цій вправі ви створите Pod, який запускає два контейнери. Ці контейнери спільно використовують том, через який вони можуть взаємодіяти. Ось файл конфігурації Podʼа:

apiVersion: v1
kind: Pod
metadata:
  name: two-containers
spec:

  restartPolicy: Never

  volumes:
  - name: shared-data
    emptyDir: {}

  containers:

  - name: nginx-container
    image: nginx
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/nginx/html

  - name: debian-container
    image: debian
    volumeMounts:
    - name: shared-data
      mountPath: /pod-data
    command: ["/bin/sh"]
    args: ["-c", "echo Hello from the debian container > /pod-data/index.html"]

У файлі конфігурації видно, що Pod має том з назвою shared-data.

Перший контейнер, вказаний у файлі конфігурації, запускає сервер nginx. Шлях монтування спільного тому — /usr/share/nginx/html. Другий контейнер базується на образі debian і має шлях монтування /pod-data. Другий контейнер виконує таку команду, а потім завершується.

echo Hello from the debian container > /pod-data/index.html

Зверніть увагу, що другий контейнер записує файл index.html в кореневу теку сервера nginx.

Створіть Pod і два контейнери:

kubectl apply -f https://k8s.io/examples/pods/two-container-pod.yaml

Перегляньте інформацію про Pod та контейнери:

kubectl get pod two-containers --output=yaml

Ось частина виводу:

apiVersion: v1
kind: Pod
metadata:
  ...
  name: two-containers
  namespace: default
  ...
spec:
  ...
  containerStatuses:

  - containerID: docker://c1d8abd1 ...
    image: debian
    ...
    lastState:
      terminated:
        ...
    name: debian-container
    ...

  - containerID: docker://96c1ff2c5bb ...
    image: nginx
    ...
    name: nginx-container
    ...
    state:
      running:
    ...

Ви бачите, що контейнер debian завершив роботу, а контейнер nginx досі працює.

Отримайте доступ до оболонки контейнера nginx:

kubectl exec -it two-containers -c nginx-container -- /bin/bash

В оболонці перевірте, що nginx працює:

root@two-containers:/# apt-get update
root@two-containers:/# apt-get install curl procps
root@two-containers:/# ps aux

Вивід подібний до такого:

USER       PID  ...  STAT START   TIME COMMAND
root         1  ...  Ss   21:12   0:00 nginx: master process nginx -g daemon off;

Згадайте, що контейнер debian створив файл index.html у кореневій теці nginx. Використайте curl, щоб надіслати GET-запит на сервер nginx:

root@two-containers:/# curl localhost

Вивід показує, що nginx обслуговує вебсторінку, записану контейнером debian:

Hello from the debian container

Обговорення

Основна причина, чому Podʼи можуть мати кілька контейнерів, — підтримка допоміжних застосунків, які допомагають основному застосунку. Типові приклади допоміжних застосунків — програми для отримання й надсилання даних, а також проксі. Допоміжні й основні застосунки часто мають взаємодіяти між собою. Зазвичай це робиться через спільну файлову систему, як показано в цій вправі, або через петлевий мережевий інтерфейс localhost. Приклад такого шаблону — вебсервер разом із допоміжною програмою, яка перевіряє наявність нових оновлень у репозиторії Git.

Том у цій вправі надає контейнерам спосіб взаємодіяти протягом життя Podʼа. Якщо Pod видалено й створено заново, усі дані, збережені в спільному томі, втрачаються.

Що далі

9 - Налаштування DNS для кластера

Kubernetes пропонує надбудову DNS для кластера, яка стандартно ввімкнена в більшості підтримуваних середовищ. У Kubernetes версії 1.11 і новіших рекомендовано CoreDNS, який стандартно встановлюється з kubeadm.

Докладніше про налаштування CoreDNS для кластера Kubernetes дивіться Налаштування сервісу DNS.

10 - Доступ до сервісів, що працюють у кластерах

На цій сторінці показано, як підʼєднатися до сервісів, що працюють у кластері Kubernetes.

Перш ніж ви розпочнете

Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:

Для перевірки версії введіть kubectl version.

Доступ до сервісів, що працюють у кластері

У Kubernetes вузли, Podʼи і сервіси мають власні IP-адреси. У багатьох випадках IP-адреси вузлів, Podʼів і деяких сервісів у кластері не маршрутизуються, тому вони недосяжні з машини поза кластером, наприклад із вашого настільного компʼютера.

Способи підʼєднання

Є кілька варіантів підʼєднання до вузлів, Podʼів і сервісів ззовні кластера:

  • Доступ до сервісів через публічні IP-адреси.
    • Використайте Service типу NodePort або LoadBalancer, щоб зробити сервіс доступним ззовні кластера. Дивіться документацію про Services і kubectl expose.
    • Залежно від середовища кластера сервіс може стати доступним лише у вашій корпоративній мережі або в інтернеті. Подумайте, чи є сервіс, до якого відкривається доступ, безпечним. Чи виконує він власну автентифікацію?
    • Розміщуйте Podʼи за сервісами. Щоб отримати доступ до одного конкретного Podʼа з набору реплік, наприклад для налагодження, додайте до Podʼа унікальну мітку й створіть новий Service, який вибирає цю мітку.
    • У більшості випадків розробнику застосунків не потрібно звертатися до вузлів безпосередньо за їхніми nodeIP.
  • Доступ до сервісів, вузлів або Podʼів за допомогою дієслова Proxy.
    • Виконує автентифікацію й авторизацію на API-сервері перед доступом до віддаленого сервісу. Використовуйте це, якщо сервіси недостатньо безпечні для відкриття в інтернет, для доступу до портів на IP-адресі вузла або для налагодження.
    • Проксі можуть викликати проблеми для деяких вебзастосунків.
    • Працює лише для HTTP/HTTPS.
    • Описано тут.
  • Доступ з вузла або Podʼа в кластері.
    • Запустіть Pod, а потім підʼєднайтеся до оболонки в ньому за допомогою kubectl exec. З цієї оболонки підʼєднуйтеся до інших вузлів, Podʼів і сервісів.
    • Деякі кластери дозволяють підʼєднатися до вузла кластера через ssh. Звідти ви зможете отримати доступ до сервісів кластера. Це нестандартний спосіб, який працює на одних кластерах і не працює на інших. Браузери та інші інструменти можуть бути не встановлені. DNS кластера може не працювати.

Виявлення вбудованих сервісів

Зазвичай у кластері є кілька сервісів, запущених у kube-system. Отримайте їх список командою kubectl cluster-info:

kubectl cluster-info

Вивід подібний до такого:

Kubernetes master is running at https://192.0.2.1
elasticsearch-logging is running at https://192.0.2.1/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy
kibana-logging is running at https://192.0.2.1/api/v1/namespaces/kube-system/services/kibana-logging/proxy
coredns is running at https://192.0.2.1/api/v1/namespaces/kube-system/services/kube-dns/proxy
grafana is running at https://192.0.2.1/api/v1/namespaces/kube-system/services/monitoring-grafana/proxy
heapster is running at https://192.0.2.1/api/v1/namespaces/kube-system/services/monitoring-heapster/proxy

Тут показано URL проксі-дієслова для доступу до кожного сервісу. Наприклад, у цьому кластері ввімкнено логування на рівні кластера (за допомогою Elasticsearch), до якого можна звернутися за адресою https://192.0.2.1/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/ за наявності відповідних облікових даних або через kubectl proxy, наприклад за адресою http://localhost:8080/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/.

Примітка:

Про те, як передавати облікові дані або використовувати kubectl proxy, дивіться Доступ до кластерів за допомогою API Kubernetes.

Ручне створення URL проксі API-сервера

Як згадано вище, URL проксі сервісу можна отримати командою kubectl cluster-info. Щоб створити URL проксі, які містять точки доступу сервісу, суфікси й параметри, додайте їх до URL проксі сервісу: http://kubernetes_master_address/api/v1/namespaces/namespace_name/services/[https:]service_name[:port_name]/proxy

Якщо ви не задали назву порту, port_name в URL вказувати не потрібно. Також можна використовувати номер порту замість port_name як для іменованих, так і для неіменованих портів.

Стандартно API-сервер проксіює запити до вашого сервісу через HTTP. Щоб використовувати HTTPS, додайте до назви сервісу префікс https:: http://<kubernetes_master_address>/api/v1/namespaces/<namespace_name>/services/<service_name>/proxy

Підтримувані формати сегмента <service_name> в URL:

  • <service_name> — проксіює до стандартного або неіменованого порту через http
  • <service_name>:<port_name> — проксіює до вказаної назви порту або номера порту через http
  • https:<service_name>: — проксіює до стандартного або неіменованого порту через https (зверніть увагу на двокрапку в кінці)
  • https:<service_name>:<port_name> — проксіює до вказаної назви порту або номера порту через https
Приклади
  • Щоб отримати доступ до точки доступу _search?q=user:kimchy сервісу Elasticsearch, використайте:

    http://192.0.2.1/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/_search?q=user:kimchy
    
  • Щоб отримати інформацію про справність кластера Elasticsearch _cluster/health?pretty=true, використайте:

    https://192.0.2.1/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/_cluster/health?pretty=true
    

    Інформація про справність подібна до такої:

    {
      "cluster_name" : "kubernetes_logging",
      "status" : "yellow",
      "timed_out" : false,
      "number_of_nodes" : 1,
      "number_of_data_nodes" : 1,
      "active_primary_shards" : 5,
      "active_shards" : 5,
      "relocating_shards" : 0,
      "initializing_shards" : 0,
      "unassigned_shards" : 5
    }
    
  • Щоб отримати інформацію про справність сервісу Elasticsearch через https _cluster/health?pretty=true, використайте:

    https://192.0.2.1/api/v1/namespaces/kube-system/services/https:elasticsearch-logging:/proxy/_cluster/health?pretty=true
    

Використання браузерів для доступу до сервісів, що працюють у кластері

Ви можете ввести URL проксі API-сервера в адресний рядок браузера. Однак:

  • Браузери зазвичай не можуть передавати токени, тому може знадобитися базова автентифікація (пароль). API-сервер можна налаштувати на прийняття базової автентифікації, але ваш кластер може бути не налаштований на це.
  • Деякі вебзастосунки можуть не працювати, особливо ті, що мають клієнтський javascript, який створює URL, не враховуючи префікс шляху проксі.