website/content/ru/docs/tutorials/kubernetes-basics/expose/expose-intro.html

177 lines
17 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Создание сервиса для открытия доступа к приложению
weight: 10
description: |-
Узнайте о сервисах в Kubernetes.
Разберитесь, какое отношение к сервисам имеют лейблы и селекторы.
Сделайте приложение доступным вне кластера Kubernetes.
---
<!DOCTYPE html>
<html lang="ru">
<body>
<div class="layout" id="top">
<main class="content">
<div class="row">
<div class="col-md-8">
<h3>Цели</h3>
<ul>
<li>Узнать о сервисах в Kubernetes</li>
<li>Разобраться, какое отношение к сервисам имеют лейблы и селекторы</li>
<li>Сделать приложение доступным вне кластера Kubernetes</li>
</ul>
</div>
<div class="col-md-8">
<h3>Обзор сервисов Kubernetes</h3>
<p><a href="/docs/concepts/workloads/pods/pod-overview/">Под</a> — это расходный материал в Kubernetes. У них есть свой <a href="/docs/concepts/workloads/pods/pod-lifecycle/">жизненный цикл</a>. Когда рабочий узел прекращает работу, запущенные поды в узле также уничтожаются. После этого <a href="/docs/concepts/workloads/controllers/replicaset/">ReplicaSet</a> попытается автоматически вернуть кластер обратно в требуемое состояние, создавая новые поды, чтобы поддержать работоспособность приложения. Другим примером жизни и смерти подов может служить бэкенд для обработки изображений с 3 репликами. Поскольку это взаимозаменяемые реплики, они не влияют на фронтенд-часть, даже если под был уничтожен и пересоздан. Тем не менее, каждый под в кластере Kubernetes имеет уникальный IP-адрес — даже под на одном и том же узле. Поэтому необходим способ автоматической координации изменений между подами, чтобы приложения продолжали функционировать.</p>
<p>Сервис (Service) в Kubernetes — это абстрактный объект, который определяет логический набор подов и политику доступа к ним. Сервисы создают слабую связь между подами, которые от них зависят. Сервис создаётся в формате YAML <a href="/docs/concepts/configuration/overview/#general-configuration-tips">(рекомендуемый формат)</a> или JSON, как и все остальные объекты в Kubernetes. Как правило, набор подов для сервиса определяется <i>селектором лейблов</i> (label selector) — ниже будет описано, в каких случаях может понадобиться сервис без указания селектора (<code>selector</code>) в его спецификации.</p>
<p>Хотя у каждого пода есть уникальный IP-адрес, эти IP-адреса не доступны за пределами кластера без использования сервиса. Сервисы позволяют приложениям принимать трафик. Сервисы могут быть по-разному открыты, в зависимости от значения поля <code>type</code>, указанного в спецификации сервиса:</p>
<ul>
<li><i>ClusterIP</i> (по умолчанию) — открывает доступ к сервису по внутреннему IP-адресу в кластере. Этот тип делает сервис доступным только внутри кластера;</li>
<li><i>NodePort</i> — открывает сервис на том же порту каждого выбранного узла в кластере с помощью NAT. Делает сервис доступным вне кластера через <code>&lt;NodeIP&gt;:&lt;NodePort&gt;</code>. Является надмножеством ClusterIP.</li>
<li><i>LoadBalancer</i> — создает внешний балансировщик нагрузки в текущем облаке (если это поддерживается) и назначает фиксированный внешний IP-адрес для сервиса. Является надмножеством NodePort.</li>
<li><i>ExternalName</i> — открывает доступ к сервису по содержимому поля <code>externalName</code> (например, <code>foo.bar.example.com</code>), возвращая запись <code>CNAME</code> с его значением. При этом прокси не используется. Для этого типа требуется версия <code>kube-dns</code> 1.7+ или CoreDNS 0.0.8+.</li>
</ul>
<p>Более подробно узнать о различных типах сервисах можно в руководстве <a href="/docs/tutorials/services/source-ip/">Использование IP-порта источника</a>. Также изучите <a href="/docs/concepts/services-networking/connect-applications-service">Подключение приложений к сервисам</a>.</p>
<p>Кроме этого, обратите внимание, что в некоторых случаях в сервисах не определяется <code>selector</code> в спецификации. Сервис без <code>selector</code> не будет создавать соответствующий эндпоинт (Endpoint). Таким образом, пользователь может вручную определить эндпоинты для сервиса. Ещё один возможный сценарий создания сервиса без селектора — это строгое использование <code>type: ExternalName</code>.</p>
</div>
<div class="col-md-4">
<div class="content__box content__box_lined">
<h3>Краткое содержание</h3>
<ul>
<li>Открытие внешнего трафика для подов</li>
<li>Балансировка нагрузки трафика между подов</li>
<li>Использование лейблов</li>
</ul>
</div>
<div class="content__box content__box_fill">
<p><i>Сервис Kubernetes (Service) — это уровень абстракции, который определяет логический набор подов, перенаправляет внешний трафик, балансирует нагрузку и реализует service discovery для этих подов.</i></p>
</div>
</div>
</div>
<br>
<div class="row">
<div class="col-md-8">
<h3>Сервисы и лейблы</h3>
</div>
</div>
<div class="row">
<div class="col-md-8">
<p><img src="/docs/tutorials/kubernetes-basics/public/images/module_04_services.svg" width="150%" height="150%"></p>
</div>
</div>
<div class="row">
<div class="col-md-8">
<p>Сервис направляет трафик через набор подов. Сервисы — это абстракция, позволяющая взаимозаменять поды Kubernetes без ущерба для работы приложения. Сервисы в Kubernetes находят и маршрутизируют трафик между зависимыми подами (это могут быть фронтенд- и бэкенд-компоненты приложения).</p>
<p>Сервисы для выбора набора подов используют <a href="/docs/concepts/overview/working-with-objects/labels">лейблы и селекторы</a>. Лейблы — пары ключ-значение, добавленные к объектам; например, они могут использоваться чтобы:</p>
<ul>
<li> идентифицировать объекты для окружений разработки, тестирования и production;</li>
<li> встроить теги версии;</li>
<li> классифицировать объекты через теги.</li>
</ul>
</div>
</div>
<br>
<div class="row">
<div class="col-md-8">
<p><img src="/docs/tutorials/kubernetes-basics/public/images/module_04_labels.svg"></p>
</div>
</div>
<br>
<div class="row">
<div class="col-md-8">
<p>Лейблы могут добавляться во время создания объектов или после этого. Они также могут быть изменены в любое время. Теперь давайте откроем доступ к приложению с помощью создания сервиса и добавим лейблы.</p>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h3>Создание нового сервиса</h3>
<p>Давайте убедимся, что приложение работает. Воспользуемся командой <code>kubectl get</code> и посмотрим на существующие поды:</p>
<p><code><b>kubectl get pods</b></code></p>
<p>Если работающих подов нет, объекты из предыдущих разделов руководства была удалены. В таком случае вернитесь и повторно создайте деплоймент по инструкциям из раздела <a href="/ru/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro#deploy-an-app">Использование kubectl для развёртывания приложения</a>.
После этого подождите несколько секунд и повторно запросите список подов. Как только увидите работающий под, можно следовать инструкциям ниже.</p>
<p>Далее посмотрим на список уже имеющихся сервисов в кластере:</p>
<p><code><b>kubectl get services</b></code></p>
<p>У нас есть сервис под названием <tt>kubernetes</tt>. Его по умолчанию создаёт minikube при запуске кластера.
Чтобы создать новый сервис и сделать его доступным для внешних пользователей, воспользуемся командой <code>expose</code> с указанием типа сервиса NodePort в качестве параметра.</p>
<p><code><b>kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080</b></code></p>
<p>Попробуем подкоманду <code>get services</code> ещё раз:</p>
<p><code><b>kubectl get services</b></code></p>
<p>Теперь у нас есть сервис под названием <tt>kubernetes-bootcamp</tt>. Мы можем увидеть, что у этого сервиса уникальный cluster-IP, внутренний порт и external-IP (IP соответствующего узла).</p>
<p>Чтобы выяснить, какой порт был открыт для внешнего мира (для сервиса со спецификацией <tt>type: NodePort</tt>), выполним подкоманду <code>describe service</code>:</p>
<p><code><b>kubectl describe services/kubernetes-bootcamp</b></code></p>
<p>Объявим переменную окружения <tt>NODE_PORT</tt>, в которую запишем значение назначенного порта узла:</p>
<p><code><b>export NODE_PORT="$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')"</b></code><br />
<code><b>echo "NODE_PORT=$NODE_PORT"</b></code></p>
<p>Теперь можно проверить, что приложение доступно вне кластера, с помощью <code>curl</code>, IP-адреса узла и порта, проброшенного вовне:</p>
<p><code><b>curl http://"$(minikube ip):$NODE_PORT"</b></code></p>
<p>Получим ответ от сервера. Сервис доступен внешнему миру.</p>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h3>Шаг 2: использование лейблов</h3>
<div class="content">
<p>Deployment автоматически создаёт лейбл для пода. Подкоманда <code>describe deployment</code> покажет его название (<em>key</em>):</p>
<p><code><b>kubectl describe deployment</b></code></p>
<p>Воспользуемся этим лейблом при выводе списка подов. Для этого вызовем команду <code>kubectl get pods</code> с флагом <tt>-l</tt> и нужными значениями лейблов в качестве параметра:</p>
<p><code><b>kubectl get pods -l app=kubernetes-bootcamp</b></code></p>
<p>То же самое можно делать при выводе списка сервисов:</p>
<p><code><b>kubectl get services -l app=kubernetes-bootcamp</b></code></p>
<p>Получим имя пода и запишем его в переменную окружения <tt>POD_NAME</tt>:</p>
<p><code><b>export POD_NAME="$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')"</b></code><br />
<code><b>echo "Name of the Pod: $POD_NAME"</b></code></p>
<p>Чтобы добавить новый лейбл, воспользуемся подкомандой <code>label</code>, для которой укажем тип объекта, имя объекта и значение нового лейбла:</p>
<p><code><b>kubectl label pods "$POD_NAME" version=v1</b></code></p>
<p>Новый лейбл добавится к поду (мы зафиксировали версию приложения для этого пода), а мы сможем убедиться в этом с помощью команды <code>describe pod</code>:</p>
<p><code><b>kubectl describe pods "$POD_NAME"</b></code></p>
<p>Как видно, лейбл добавился к нашему поду. Теперь мы можем получить список всех подов, использующих новый лейбл:</p>
<p><code><b>kubectl get pods -l version=v1</b></code></p>
<p>Наш под будет в этом списке.</p>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h3>Удаление сервиса</h3>
<p>Чтобы удалить сервис, воспользуйтесь подкомандой <code>delete service</code>. В ней могут указываться и лейблы:</p>
<p><code><b>kubectl delete service -l app=kubernetes-bootcamp</b></code></p>
<p>Убедитесь, что сервис удалился:</p>
<p><code><b>kubectl get services</b></code></p>
<p>Вывод подтвердит, что сервис был удалён. Убедиться в том, что удалился соответствующий маршрут для внешнего трафика, можно через <tt>curl</tt> к доступному ранее IP и порту:</p>
<p><code><b>curl http://"$(minikube ip):$NODE_PORT"</b></code></p>
<p>Так можно убедиться, что приложение более недоступно снаружи кластера.
Проверить, что приложение всё ещё работает, можно через <tt>curl</tt>, который будет выполнен внутри пода:</p>
<p><code><b>kubectl exec -ti $POD_NAME -- curl http://localhost:8080</b></code></p>
<p>Мы увидим, что приложение запущено. Оно функционирует, потому что за его работу отвечает деплоймент (Deployment). Чтобы остановить приложение, потребуется также удалить и его деплоймент.</p>
</div>
</div>
<div class="row">
<p>
Когда всё готово, переходите к разделу <a href="/ru/docs/tutorials/kubernetes-basics/scale/scale-intro/" title="Запуск нескольких экземпляров приложения">Запуск нескольких экземпляров приложения</a>.</p>
</p>
</div>
</div>
</main>
</div>
</body>
</html>