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

На цій сторінці показано, як за допомогою 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.

2 - Використання 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.

3 - Зʼєднання фронтенду з бекендом за допомогою 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

Що далі

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

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

Під час створення 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.

Що далі

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

На цій сторінці показано, як за допомогою 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}}"

Що далі

Довідка

6 - Взаємодія контейнерів в одному 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 видалено й створено заново, усі дані, збережені в спільному томі, втрачаються.

Що далі

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

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

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

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

На цій сторінці показано, як підʼєднатися до сервісів, що працюють у кластері 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, не враховуючи префікс шляху проксі.