Поиск по сайту:

Основные компоненты кластера Kubernetes


На этой странице

  1. Плоскость управления Kubernetes
    1. Кьюб-аписатель
    2. Куб-контроллер-менеджер
    3. Кьюб-планировщик
    4. База данных etcd

    1. Кубелет
    2. Прокси-сервер kube
    3. Среда выполнения контейнера

    1. Поды — основа Kubernetes

    1. Тома
    2. Постоянные тома, заявки на постоянные тома и классы хранения

    Kubernetes — это платформа с открытым исходным кодом для управления контейнерными рабочими нагрузками и службами, которая упрощает декларативную настройку и автоматизацию. Название Kubernetes произошло от греческого, что означает «рулевой» или «лоцман». Он портативный, а также расширяемый и имеет быстрорастущую экосистему. Сервисы и инструменты Kubernetes широко доступны.

    В этой статье мы рассмотрим основные компоненты Kubernetes с высоты 10 000 футов, от того, из чего состоит каждый контейнер, до того, как контейнер в поде развертывается и планируется для каждого из рабочих процессов. Крайне важно понимать все особенности кластера Kubernetes, чтобы иметь возможность развернуть и спроектировать решение на основе Kubernetes в качестве оркестратора для контейнерных приложений.

    Вот краткая информация о вещах, которые мы собираемся осветить в этой статье:

    • Компоненты панели управления
    • Компоненты рабочего процесса Kubernetes
    • Модули как основные строительные блоки
    • Службы Kubernetes, балансировщики нагрузки и контроллеры Ingress.
    • Развертывания Kubernetes и наборы демонов
    • Постоянное хранилище в Kubernetes

    Плоскость управления Kubernetes

    На главных узлах Kubernetes работают основные службы уровня управления; не все сервисы должны находиться на одном узле; однако из соображений централизации и практичности их часто развертывают таким образом. Это, очевидно, вызывает вопросы о доступности услуг; однако их можно легко преодолеть, имея несколько узлов и предоставляя запросы на балансировку нагрузки для достижения высокодоступного набора главных узлов.

    Мастер-ноды состоят из четырех основных сервисов:

    • Кьюб-аписатель
    • Кьюб-планировщик
    • Куб-контроллер-менеджер
    • База данных etcd

    Главные узлы могут работать либо на физических серверах, виртуальных машинах, либо в частном или общедоступном облаке, но не рекомендуется запускать на них рабочие нагрузки контейнеров. Мы увидим больше об этом позже.

    На следующей схеме показаны компоненты главных узлов Kubernetes:

    kube-apiserver

    Сервер API — это то, что связывает все вместе. Это интерфейс REST API кластера, который получает манифесты для создания, обновления и удаления объектов API, таких как сервисы, модули, Ingress и другие.

    kube-apiserver – это единственный сервис, с которым нам следует поговорить; кроме того, он единственный, кто пишет и взаимодействует с базой данных etcd для регистрации состояния кластера. С помощью команды kubectl мы будем отправлять команды для взаимодействия с ним. Это будет наш швейцарский армейский нож, когда дело дойдет до Kubernetes.

    kube-контроллер-менеджер

    В двух словах, демон kube-controller-manager представляет собой набор бесконечных циклов управления, которые для простоты поставляются в одном двоичном файле. Он следит за определенным желаемым состоянием кластера и следит за его достижением и удовлетворением, перемещая все элементы, необходимые для его достижения. kube-controller-manager — это не просто один контроллер; он содержит несколько разных циклов, которые отслеживают разные компоненты в кластере. Некоторыми из них являются контроллер службы, контроллер пространства имен, контроллер учетных записей службы и многие другие. Вы можете найти каждый контроллер и его определение в репозитории Kubernetes GitHub: https://github.com/kubernetes/kubernetes/tree/master/pkg/controller.

    kube-планировщик

    Планировщик kube-scheduler распределяет ваши вновь созданные модули на узлы с достаточным пространством для удовлетворения потребностей в ресурсах модулей. По сути, он слушает kube-apiserver и kube-controller-manager на предмет вновь созданных модулей, которые помещаются в очередь, а затем планируются планировщиком на доступный узел. Определение kube-scheduler можно найти здесь: https://github.com/kubernetes/kubernetes/blob/master/pkg/scheduler.

    Помимо вычислительных ресурсов, kube-scheduler также считывает правила привязки и антипривязки узлов, чтобы выяснить, может ли узел запускать этот модуль.

    База данных etcd

    База данных etcd – это очень надежное согласованное хранилище ключей и значений, которое используется для хранения состояния кластера Kubernetes. Он содержит текущее состояние модулей, в которых работает узел, сколько узлов в настоящее время имеет кластер, каково состояние этих узлов, сколько запущено реплик развертывания, имена служб и другие.

    Как мы упоминали ранее, только kube-apiserver общается с базой данных etcd. Если kube-controller-manager необходимо проверить состояние кластера, он будет проходить через сервер API, чтобы получить состояние из базы данных etcd, вместо того, чтобы напрямую запрашивать хранилище etcd. То же самое происходит с kube-scheduler, если планировщик должен сообщить, что модуль был остановлен или выделен другому узлу; он сообщит серверу API, а сервер API сохранит текущее состояние в базе данных etcd.

    С помощью etcd мы рассмотрели все основные компоненты для наших главных узлов Kubernetes, чтобы мы были готовы управлять нашим кластером. Но кластер состоит не только из мастеров; нам по-прежнему нужны узлы, которые будут выполнять тяжелую работу, запуская наши приложения.

    Рабочие узлы Kubernetes

    Рабочие узлы, которые выполняют эту задачу в Kubernetes, называются просто узлами. Раньше, примерно в 2014 году, их называли миньонами, но позже этот термин заменили просто узлами, так как название путало с терминологией Salts и заставляло людей думать, что Salt играет важную роль в Kubernetes.

    Эти узлы — единственное место, где вы будете запускать рабочие нагрузки, поскольку не рекомендуется размещать контейнеры или нагрузки на главных узлах, поскольку они должны быть доступны для управления всем кластером. Узлы очень просты с точки зрения компонентов; им требуется всего три службы для выполнения своей задачи:

    • Кубелет
    • Kube-прокси
    • Среда выполнения контейнера

    Давайте рассмотрим эти три компонента немного подробнее.

    кубелет

    Kubelet — низкоуровневый компонент Kubernetes и один из самых важных после kube-apiserver; оба эти компонента необходимы для подготовки модулей/контейнеров в кластере. kubelet — это служба, которая работает на узлах Kubernetes и слушает сервер API для создания пода. kubelet отвечает только за запуск/остановку и проверку работоспособности контейнеров в подах; kubelet не сможет управлять никакими контейнерами, созданными не им.

    Kubelet достигает целей, взаимодействуя со средой выполнения контейнера через интерфейс среды выполнения контейнера (CRI). CRI обеспечивает возможность подключения к kubelet через клиент gRPC, который может взаимодействовать с различными средами выполнения контейнеров. Как мы упоминали ранее, Kubernetes поддерживает несколько сред выполнения контейнеров для развертывания контейнеров, и именно поэтому достигается такая разнообразная поддержка разных движков.

    Вы можете проверить исходный код kubelet через https://github.com/kubernetes/kubernetes/tree/master/pkg/kubelet.

    kube-прокси

    Kube-proxy – это служба, которая находится на каждом узле кластера и обеспечивает связь между модулями, контейнерами и узлами. Этот сервис отслеживает kube-apiserver на наличие изменений в определенных сервисах (сервис — это своего рода логический балансировщик нагрузки в Kubernetes; мы углубимся в сервисы позже в этой статье) и поддерживает сеть в актуальном состоянии с помощью правил iptables, которые перенаправляют трафик на правильные конечные точки. Kube-proxy также устанавливает правила в iptables, которые выполняют произвольную балансировку нагрузки между модулями за службой.

    Вот пример правила iptables, созданного kube-proxy:

    -A KUBE-SERVICES -d 10.0.162.61/32 -p tcp -m comment --comment \по умолчанию/пример: не имеет конечных точек\ -m tcp --dport 80 -j REJECT --reject-with icmp-port -недостижимый

    Обратите внимание, что это сервис без конечных точек (за ним нет модулей).

    Время выполнения контейнера

    Чтобы иметь возможность запускать контейнеры, нам требуется среда выполнения контейнера. Это базовый движок, который будет создавать контейнеры в ядре узлов для запуска наших модулей. Kubelet будет общаться с этой средой выполнения и будет запускать или останавливать наши контейнеры по требованию.

    В настоящее время Kubernetes поддерживает любую среду выполнения контейнера, совместимую с OCI, например Docker, rkt, runc, runsc и т. д.

    Вы можете обратиться к этому https://github.com/opencontainers/runtime-spec, чтобы узнать больше обо всех спецификациях на странице OCI Git-Hub.

    Теперь, когда мы изучили все основные компоненты, образующие кластер, давайте теперь посмотрим, что с ними можно сделать и как Kubernetes поможет нам организовать и управлять нашими контейнерными приложениями.

    Объекты Кубернета

    Объекты Kubernetes именно таковы: это логические постоянные объекты или абстракции, которые будут представлять состояние вашего кластера. Вы отвечаете за то, чтобы сообщать Kubernetes о желаемом состоянии этого объекта, чтобы он мог поддерживать его и убедиться, что объект существует.

    Чтобы создать объект, у него должны быть две вещи: статус и его спецификация. Статус предоставляется Kubernetes, и это текущее состояние объекта. Kubernetes будет управлять этим статусом и обновлять его по мере необходимости, чтобы он соответствовал желаемому состоянию. С другой стороны, поле спецификации — это то, что вы предоставляете Kubernetes, и то, что вы сообщаете ему для описания желаемого объекта. Например, образ, который вы хотите запустить в контейнере, количество контейнеров этого образа, которые вы хотите запустить, и так далее.

    У каждого объекта есть определенные поля спецификации для типа выполняемой задачи, и вы будете предоставлять эти спецификации в файле YAML, который отправляется на kube-apiserver с помощью kubectl, который преобразует его в JSON и отправляет в виде запроса API. . Далее в этой статье мы углубимся в каждый объект и его поля спецификаций.

    Вот пример YAML, отправленного в kubectl:

    кошка << EOF | kubectl create -f -kind: ServiceapiVersion: v1metadata: Name: frontend-servicespec: selector:   web: frontend ports: - protocol: TCP   port: 80   targetPort: 9256EOF

    Основные поля определения объекта – самые первые, и они не будут меняться от объекта к объекту и не требуют пояснений. Давайте быстро взглянем на них:

    • kind. Поле типа сообщает Kubernetes, какой тип объекта вы определяете: модуль, служба, развертывание и т. д.
    • apiVersion: поскольку Kubernetes поддерживает несколько версий API, нам нужно указать путь REST API, на который мы хотим отправить наше определение.
    • метаданные: это вложенное поле, что означает, что у вас есть еще несколько подполей для метаданных, где вы будете писать основные определения, такие как имя вашего объекта, назначая его определенному пространству имен, а также помечая его меткой. чтобы связать ваш объект с другими объектами Kubernetes

    Итак, мы рассмотрели наиболее часто используемые поля и их содержимое; вы можете узнать больше о соглашениях API Kuberntes по адресу https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md.

    Некоторые поля объекта могут быть изменены позже после создания объекта, но это будет зависеть от объекта и поля, которое вы хотите изменить.

    Ниже приведен краткий список различных объектов Kubernetes, которые вы можете создать:

    • Под
    • Объем
    • Сервис
    • Развертывание
    • Вход
    • Секрет
    • Карта конфигурации

    И многое другое.

    Давайте подробнее рассмотрим каждый из этих предметов.

    Поды — основа Kubernetes

    Поды — это самые основные объекты в Kubernetes, а также самые важные. Все вращается вокруг них; можно сказать, что Kubernetes для стручков! Все остальные объекты здесь, чтобы служить им, и все задачи, которые они выполняют, заключаются в том, чтобы заставить модули достичь желаемого состояния.

    Итак, что такое стручок и почему стручки так важны?

    Под — это логический объект, который запускает один или несколько контейнеров вместе в одном сетевом пространстве имен, одном и том же межпроцессном взаимодействии (IPC) и, иногда, в зависимости от версии Kubernetes, в одном и том же пространстве имен идентификатора процесса (PID). Это потому, что именно они будут управлять нашими контейнерами и, следовательно, будут в центре внимания. Весь смысл Kubernetes в том, чтобы быть оркестратором контейнеров, а благодаря модулям мы делаем оркестровку возможной.

    Как мы упоминали ранее, контейнеры в одном и том же модуле живут в «пузыре», где они могут общаться друг с другом через локальный хост, поскольку они локальны друг для друга. Один контейнер в модуле имеет тот же IP-адрес, что и другой контейнер, потому что они совместно используют сетевое пространство имен, но в большинстве случаев вы будете работать один на один, то есть один контейнер на модуль. . Несколько контейнеров на модуль используются только в очень специфических сценариях, например, когда приложению требуется помощник, такой как средство передачи данных или прокси-сервер, которому необходимо быстро и надежно взаимодействовать с основным приложением.

    Способ, которым вы определяете модуль, такой же, как и для любого другого объекта Kubernetes: через YAML, который содержит все спецификации и определения модуля:

    вид: PodapiVersion: v1metadata:name: hello-podlabels:  hello: podspec:  containers:    - name: hello-container      image: alpine      args:      - echo      - \Hello World\

    Давайте рассмотрим основные определения модуля, необходимые в поле спецификации для создания нашего модуля:

    • Контейнеры. Контейнер — это массив; следовательно, у нас есть набор из нескольких подполей под ним. По сути, это то, что определяет контейнеры, которые будут работать в модуле. Мы можем указать имя для контейнера, изображение, из которого будет создан побочный продукт, а также аргументы или команду, которые нам нужны для запуска. Разница между аргументами и командами такая же, как разница между CMD и ENTRYPOINT. Обратите внимание, что все поля, которые мы только что прошли, относятся к массиву контейнеров. Они не являются непосредственной частью спецификации модуля.
    • restartPolicy: именно это поле и указывает Kubernetes, что делать с контейнером, и применяется ко всем контейнерам в модуле в случае нулевого или ненулевого кода выхода. Вы можете выбрать один из вариантов: Никогда, При сбое или Всегда. Всегда будет значением по умолчанию, если не определена политика перезапуска.

    Это самые основные характеристики, которые вы собираетесь объявить в модуле; другие спецификации потребуют от вас немного больше базовых знаний о том, как их использовать и как они взаимодействуют с различными другими объектами Kubernetes. Мы вернемся к ним позже в этой статье; некоторые из них следующие:

    • Объем
    • Окруж.
    • Порты
    • Политика DNS
    • инитконтейнеры
    • селектор узлов
    • Ограничения ресурсов и запросы

    Чтобы просмотреть модули, которые в данный момент работают в вашем кластере, вы можете запустить kubectl get pods:

    [email :~$kubectl get podsNAME      СТАТУС ГОТОВНОСТИ    ПЕРЕЗАПУСКИ AGEbusybox   1/1 Работает   120 5d

    Кроме того, вы можете запускать модули kubectl описания без указания какого-либо модуля. Это распечатает описание каждого модуля, работающего в кластере. В этом случае это будет только модуль busybox, так как в данный момент работает только он:

    [Электронная почта защищена]: ~ $kubectl Опишите Podsname: BusyBoxNamespace: DefaultPriority: 0porityClassName: Узел: AKS-AGENTPOOL-10515745-2/10.240.0.6. 0600Labels: Аннотация: Статус: Runningip: 10.244.1.7containers: ravinbox: [...] (вывод усечен для чтения). ---                ----      ------- Обычный  Получено 45 с (x121 за 5 дней)  kubelet, aks-agentpool-10515745-2  Образ контейнера \busybox\ уже присутствует на машинеОбычный  Создано 44 с (x121 за 5 дней)  kubelet , aks-agentpool-10515745-2  Создан контейнерОбычный Запущено 44 с (x121 более 5 дней)  kubelet, aks-agentpool-10515745-2  Запущен контейнер

    Стручки смертны. После того, как он умрет или будет удален, его нельзя будет восстановить. Его IP и запущенные на нем контейнеры исчезнут; они совершенно эфемерны. Данные в модулях, смонтированных как том, могут сохраниться или не сохраниться, в зависимости от того, как вы их настроили. Если наши модули умирают и мы их теряем, как нам убедиться, что все наши микросервисы работают? Что ж, развертывание — вот ответ.

    Развертывания

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

    Здесь в игру вступают развертывания. Благодаря развертыванию мы можем управлять нашими модулями с помощью контроллера. Это позволяет нам не только решать, сколько мы хотим запустить, но также можем управлять обновлениями, изменяя версию образа или сам образ, на котором работают наши контейнеры. Развертывания — это то, с чем вы будете работать большую часть времени. У развертываний, а также модулей и любых других объектов, о которых мы упоминали ранее, у них есть собственное определение внутри файла YAML:

    apiVersion: apps/v1kind: Deploymentmetadata: name: nginx-deployment labels:   deployment: nginxspec: replicas: 3 selector:   matchLabels:     app: nginx template:   metadata:     labels:       app: nginx   spec:     container:     - name: nginx       image : nginx:1.7.9       порты:       - containerPort: 80

    Давайте начнем изучать их определение.

    В начале YAML у нас есть более общие поля, такие как apiVersion, вид и метаданные. Но в спецификации мы найдем конкретные параметры для этого объекта API.

    В спецификации мы можем добавить следующие поля:

    Селектор: с помощью поля «Селектор» развертывание будет знать, на какие модули следует ориентироваться при применении изменений. Есть два поля, которые вы будете использовать под селектором: matchLabels и matchExpressions. При использовании matchLabels селектор будет использовать ярлыки модулей (пары ключ/значение). Важно отметить, что все ярлыки, которые вы укажете здесь, будут объединены по И. Это означает, что для модуля потребуются все ярлыки, которые вы укажете в matchLabels.

    Реплики: здесь будет указано количество модулей, которое необходимо развертыванию для продолжения работы через контроллер репликации; например, если вы укажете три реплики и один из модулей умрет, контроллер репликации будет отслеживать спецификацию реплик как желаемое состояние и сообщит планировщику о необходимости запланировать новый модуль, поскольку текущий статус теперь равен 2, так как модуль умер.

    RevisionHistoryLimit: каждый раз, когда вы вносите изменения в развертывание, это изменение сохраняется как ревизия развертывания, которую вы можете позже либо вернуть в предыдущее состояние, либо сохранить запись того, что было изменено. Вы можете просмотреть свою историю с помощью истории развертывания kubectl deploy/<имя развертывания>. С помощью revisionHistoryLimit вы можете установить число, указывающее, сколько записей вы хотите сохранить.

    Стратегия: это позволит вам решить, как вы хотите обрабатывать любое обновление или горизонтальное масштабирование модуля. Чтобы перезаписать значение по умолчанию, которым является rollingUpdate, вам нужно написать ключ type, где вы можете выбрать одно из двух значений: recreate или rollingUpdate.

    Хотя повторное создание — это быстрый способ обновить развертывание, он удалит все модули и заменит их новыми, но это будет означать, что вам придется учитывать, что для этого типа стратегии будет время простоя системы. С другой стороны, rollingUpdate работает плавнее и медленнее и идеально подходит для приложений с отслеживанием состояния, которые могут перебалансировать свои данные. RollingUpdate открывает двери для еще двух полей: maxSurge и maxUnreachable.

    Первым из них будет количество стручков сверх общей суммы, которую вы хотите выполнить при обновлении; например, развертывание со 100 модулями и 20 % maxSurge вырастет до 120 модулей при обновлении. Следующая опция позволит вам выбрать, сколько стручков в процентах вы готовы убить, чтобы заменить их новыми в сценарии со 100 стручками. В случаях, когда 20 % maxUnreachable, только 20 модулей будут уничтожены и заменены новыми, прежде чем продолжить замену остальной части развертывания.

    Шаблон: это просто поле спецификации вложенного модуля, куда вы будете включать все спецификации и метаданные модулей, которыми будет управлять развертывание.

    Мы видели, что при развертывании мы управляем нашими модулями, и они помогают нам поддерживать их в желаемом состоянии. Все эти модули по-прежнему находятся в так называемой кластерной сети, которая представляет собой закрытую сеть, в которой только компоненты кластера Kubernetes могут общаться друг с другом, даже имея собственный набор диапазонов IP-адресов. Как мы разговариваем с нашими модулями извне? Как нам добраться до нашего приложения? Здесь в игру вступают услуги.

    Услуги:

    Служба имен не полностью описывает, что на самом деле делают службы в Kubernetes. Сервисы Kubernetes направляют трафик к нашим модулям. Можно сказать, что сервисы — это то, что связывает стручки вместе.

    Давайте представим, что у нас есть типичный интерфейсный/бэкенд-приложение, в котором наши внешние модули взаимодействуют с нашими внутренними модулями через IP-адреса модулей. Если модуль в бэкэнде умирает, мы теряем связь с нашим бэкендом. Это не только потому, что новый модуль не будет иметь тот же IP-адрес, что и умерший модуль, но теперь нам также нужно перенастроить наше приложение для использования нового IP-адреса. Эта проблема и подобные проблемы решаются с помощью сервисов.

    Служба – это логический объект, который указывает прокси-серверу kube создавать правила iptables на основе того, какие модули находятся за службой. Службы настраивают свои конечные точки, так называются модули, стоящие за сервисом, так же, как развертывания знают, какими модулями управлять, поле селектора и метки модулей.

    На этой диаграмме показано, как сервисы используют ярлыки для управления трафиком:

    Сервисы не только заставят kube-proxy создавать правила для маршрутизации трафика; это также вызовет нечто, называемое kube-dns.

    Kube-dns — это набор модулей с контейнерами SkyDNS, которые работают в кластере, предоставляющем DNS-сервер и сервер пересылки, которые будут создавать записи для служб, а иногда и модули для простоты использования. Всякий раз, когда вы создаете службу, DNS-запись, указывающая на внутренний IP-адрес кластера службы, будет создаваться в форме имя-службы.пространство-имен.svc.cluster.local. Подробнее о спецификациях Kubernetes DNS можно узнать здесь: https://github.com/kubernetes/dns/blob/master/docs/specification.md.

    Возвращаясь к нашему примеру, теперь нам нужно только настроить приложение для связи с полным доменным именем службы (FQDN), чтобы общаться с нашими внутренними модулями. Таким образом, не будет иметь значения, какой IP-адрес имеют модули и сервисы. Если модуль, стоящий за службой, умирает, служба позаботится обо всем, используя запись A, так как мы сможем указать нашему внешнему интерфейсу направлять весь трафик на my-svc. Обо всем остальном позаботится логика сервиса.

    Существует несколько типов сервисов, которые вы можете создавать всякий раз, когда объявляете объект для создания в Kubernetes. Давайте рассмотрим их, чтобы увидеть, какой из них лучше всего подходит для нужного нам типа работы:

    ClusterIP: это служба по умолчанию. Всякий раз, когда вы создаете службу ClusterIP, она создает службу с внутренним IP-адресом кластера, который будет маршрутизироваться только внутри кластера Kubernetes. Этот тип идеально подходит для модулей, которым нужно общаться только друг с другом, а не выходить за пределы кластера.

    NodePort: при создании службы этого типа по умолчанию будет выделен случайный порт от 30000 до 32767 для перенаправления трафика на модули конечных точек службы. Вы можете переопределить это поведение, указав порт узла в массиве портов. Как только это будет определено, вы сможете получить доступ к своим модулям через :. Это полезно для доступа к вашим модулям из-за пределов кластера через IP-адрес узла.

    LoadBalancer: большую часть времени вы будете использовать Kubernetes в облачном провайдере. Тип LoadBalancer идеально подходит для таких ситуаций, так как вы сможете выделять публичные IP-адреса своей службе через API вашего облачного провайдера. Это идеальный сервис, когда вы хотите общаться со своими модулями из-за пределов вашего кластера. С помощью LoadBalancer вы сможете не только выделить общедоступный IP-адрес, но и, используя Azure, выделить частный IP-адрес из вашей виртуальной частной сети. Таким образом, вы можете общаться со своими модулями из Интернета или внутри своей частной подсети.

    Давайте рассмотрим определение сервиса в YAML:

    apiVersion: v1kind: Servicemetadata:   name: my-servicespec: selector:       app: front-end type: NodePort port:   - name: http   port: 80   targetPort: 8080   nodePort: 30024   протокол: TCP

    Службы YAML очень просты, и спецификации будут различаться в зависимости от типа службы, которую вы создаете. Но самое главное, что вы должны принять во внимание, — это определения портов. Давайте посмотрим на них:

    • порт: это порт службы, который открыт
    • targetPort: это порт в модулях, на который служба отправляет трафик.
    • nodePort: это порт, который будет доступен

    Хотя теперь мы понимаем, как мы можем взаимодействовать с модулями в нашем кластере, нам все еще нужно понять, как мы собираемся решать проблему потери наших данных каждый раз, когда модуль завершается. Вот где используются постоянные тома (PV).

    Kubernetes и постоянное хранилище

    Постоянное хранилище в мире контейнеров — серьезная проблема. Единственное хранилище, которое сохраняется при выполнении контейнера, — это слои образа, и они доступны только для чтения. Уровень, на котором работает контейнер, доступен для чтения и записи, но все данные на этом уровне удаляются после остановки контейнера. С подушками то же самое. Когда контейнер умирает, данные, записанные в него, исчезают.

    В Kubernetes есть набор объектов для управления хранилищем между модулями. Первое, что мы обсудим, это объемы.

    Объемы

    Тома решают одну из самых больших проблем, когда речь идет о постоянном хранилище. Во-первых, тома на самом деле не объекты, а определение спецификации подов. Когда вы создаете модуль, вы можете определить том в поле спецификации модуля. Контейнеры в этом модуле смогут монтировать том в своем пространстве имен монтирования, и том будет доступен при перезапуске или сбое контейнера. Однако тома привязаны к модулям, и если модуль будет удален, том также исчезнет. Данные по объему — это отдельная история; сохранение данных будет зависеть от серверной части этого тома.

    Kubernetes поддерживает несколько типов томов или источников томов и то, как они называются в спецификациях API, которые варьируются от карт файловой системы с локального узла, виртуальных дисков облачных провайдеров и томов, поддерживаемых программно-определяемым хранилищем. Монтирование локальной файловой системы является наиболее распространенным, когда речь идет о обычных томах. Важно отметить, что недостатком использования файловой системы локального узла является то, что данные не будут доступны на всех узлах кластера, а только на том узле, где был запланирован pod.

    Давайте посмотрим, как модуль с томом определяется в YAML:

    apiVersion: v1kind: Подметаданные: имя: test-pdspec: containers: - image: k8s.gcr.io/test-webserver   name: test-container   volumeMounts:   - mountPath: /test-pd     name: test-volume Volumes: - name: test-volume   hostPath:     path: /data   type: Directory

    Обратите внимание, что в спецификации есть поле под названием Volumes, а затем еще одно поле VolumeMounts.

    В первом поле (тома) вы определяете том, который хотите создать для этого модуля. В этом поле всегда требуется имя, а затем источник тома. В зависимости от источника требования будут разными. В этом примере источником будет hostPath, который представляет собой локальную файловую систему узла. hostPath поддерживает несколько типов сопоставлений: каталоги, файлы, блочные устройства и даже сокеты Unix.

    Под вторым полем, VolumeMounts, у нас есть mountPath, где вы определяете путь внутри контейнера, к которому вы хотите подключить свой том. Параметр имени – это то, как вы указываете пакету, какой том использовать. Это важно, потому что в томах может быть определено несколько типов томов, и имя будет единственным способом, с помощью которого модуль узнает, какой

    Вы можете узнать больше о различных типах томов здесь https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.11/#volume-v1-core).

    Когда тома умирают вместе с модулями, это не идеально. Нам нужно хранилище, которое сохраняется, и именно так возникла потребность в PV.

    Постоянные тома, заявки на постоянный том и классы хранения

    Основное различие между томами и PV заключается в том, что, в отличие от томов, PV на самом деле являются объектами Kubernetes API, поэтому вы можете управлять ими по отдельности, как отдельными сущностями, и поэтому они сохраняются даже после удаления модуля.

    Вам может быть интересно, почему в этом подразделе смешаны PV, постоянные заявки на объем (PVC) и классы хранилища. Это связано с тем, что все они зависят друг от друга, и очень важно понимать, как они взаимодействуют друг с другом для предоставления хранилища. для наших поддонов.

    Начнем с PV и PVC. Как и у томов, у виртуальных томов есть источник хранения, поэтому здесь применяется тот же механизм, что и у томов. У вас будет либо программно-определяемый кластер хранения, предоставляющий номер логического устройства (LUN), либо облачный провайдер, предоставляющий виртуальные диски, либо даже локальная файловая система для узла Kubernetes, но здесь они называются не источниками томов, а постоянными. типы томов.

    PV очень похожи на LUN в массиве хранения: вы создаете их, но без сопоставления; они просто куча выделенного хранилища, ожидающего использования. PVC подобны сопоставлениям LUN: они поддерживаются или привязываются к PV, а также являются тем, что вы фактически определяете, связываете и делаете доступным для модуля, который он затем может использовать для своих контейнеров.

    То, как вы используете PVC для модулей, точно такое же, как и для обычных томов. У вас есть два поля: одно для указания, какой PVC вы хотите использовать, и другое, чтобы указать модулю, на каком контейнере использовать этот PVC.

    YAML для определения объекта PVC API должен иметь следующий код:

    apiVersion: v1kind: PersistentVolumeClaimmetadata: name: gluster-pvc spec: accessModes: - ReadWriteMany       ресурсы:    запросы:      хранилище: 1Gi

    YAML для модуля должен иметь следующий код:

    kind: PodapiVersion: v1metadata: name: mypodspec: containers:   - name: myfrontend     image: nginx     volumeMounts:     - mountPath: \/mnt/gluster\       name: volume volumes:   - name: volume     PermanentVolumeClaim:      claimName: gluster-pvc

    Когда администратор Kubernetes создает PVC, этот запрос можно удовлетворить двумя способами:

    • Статический: уже создано несколько PV, а затем, когда пользователь создает PVC, любой доступный PV, отвечающий требованиям, будет привязан к этому PVC.
    • Динамический: некоторые типы PV могут создавать PV на основе определений PVC. При создании PVC тип PV динамически создает объект PV и выделяет хранилище в бэкенде; это динамическая подготовка. Суть динамической подготовки заключается в том, что вам требуется третий тип объекта хранилища Kubernetes, который называется классом хранилища.

    Классы хранилища — это своего рода способ разделения хранилища. Вы можете создать класс, который предоставляет медленные тома хранилища, или другой класс со сверхбыстрыми SSD-накопителями. Однако классы хранения немного сложнее, чем просто многоуровневое хранение. Как мы упоминали в двух способах создания PVC, именно классы хранения делают возможным динамическое выделение ресурсов. При работе в облачной среде вам не нужно вручную создавать каждый серверный диск для каждого PV. Классы хранилища установят нечто, называемое поставщиком, который вызывает подключаемый модуль тома, необходимый для взаимодействия с API вашего облачного провайдера. У каждого поставщика есть свои настройки, чтобы он мог общаться с указанным облачным провайдером или поставщиком хранилища.

    Вы можете предоставить классы хранения следующим образом; это пример класса хранилища, использующего Azure-диск в качестве средства подготовки дисков:

    вид: StorageClassapiVersion: storage.k8s.io/v1metadata: name: my-storage-classprovisioner: kubernetes.io/azure-diskparameters: storageaccounttype: Standard_LRS вид: Shared

    У каждого поставщика класса хранилища и типа PV будут разные требования и параметры, а также тома, и у нас уже был общий обзор того, как они работают и для чего мы можем их использовать. Информация о конкретных классах хранения и типах PV будет зависеть от вашей среды; Вы можете узнать больше о каждом из них, перейдя по следующим ссылкам:

    • https://kubernetes.io/docs/concepts/storage/storage-classes/#provisioner
    • https://kubernetes.io/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes

    В этой статье мы узнали о том, что такое Kubernetes, его компоненты и каковы преимущества использования оркестровки. При этом идентификация каждого из объектов API Kubernetes, их назначение и варианты использования должны быть простыми. Теперь вы должны понимать, как главные узлы контролируют кластер и планирование контейнеров в рабочих узлах.

    Если вы нашли эту статью полезной, «Практическое руководство по Linux для архитекторов» должно быть вам полезно. С помощью этой книги вы охватите все, от компонентов и функций Linux до поддержки аппаратного и программного обеспечения, что поможет вам внедрять и настраивать эффективные решения на основе Linux. Вы познакомитесь с методологией проектирования Linux и основными концепциями разработки решения. Если вы системный администратор Linux, инженер службы поддержки Linux, инженер DevOps, консультант Linux или кто-либо, кто хочет учиться или расширять свои знания в области архитектуры, эта книга для вас.