Введение

В предыдущей статье «Понимание сети подов с помощью одной статьи» мы обсуждали первый уровень сети подов в K8s. С помощью Pod Network все Pod в кластере K8s можно логически рассматривать как плоскую сеть, к которой можно обращаться и обмениваться данными по IP. Однако Pod — это всего лишь абстракция виртуальной машины на облачной платформе K8s. В конечном итоге нам нужно запускать приложения или службы в кластере K8s. Как правило, служба состоит из нескольких модулей, что создает такие проблемы, как обнаружение службы и балансировка нагрузки. Это проблема, которую должен решить второй уровень сервисной сети, и это также проблема, которую я проанализирую в этой статье.

Концептуальная модель сервисной сети

Мы предполагаем, что сеть Pod первого уровня уже существует, и ниже представлена ​​упрощенная концептуальная модель сервисной сети второго уровня K8s:

Предположим, мы развернули приложение Account-App в кластере K8s, который состоит из 4 модулей (виртуальных машин), предоставляющих услуги вместе как кластер, и каждый модуль имеет свой собственный PodIP и порт. Мы также предполагаем, что в кластере развернуты другие приложения, некоторые из которых являются потребителями Account-App. Другими словами, существуют клиентские модули, которым требуется доступ к кластеру модулей Account-App. Тут естественно возникают два вопроса:

  1. Обнаружение службы. Как клиентский модуль может обнаружить и определить IP-адрес модуля в кластере «Учетная запись — приложение»? Кроме того, IP-адрес модуля в кластере Account-App, вероятно, изменится (эфемерно), что включает в себя как ожидаемые изменения, такие как повторный выпуск Account-App, так и неожиданные, например, когда Pod в Account-App Кластер выходит из строя, и K8s выполняет перепланирование развертывания Account-App.
  2. Балансировка нагрузки.Как модуль клиента может получить доступ к различным экземплярам модуля в кластере «Учетная запись-приложение» с помощью определенных стратегий балансировки нагрузки для обеспечения распределения нагрузки и высокой доступности (HA)?

На самом деле Kubernetes решает вышеуказанную проблему, вводя уровень абстракции Account-Service между кластерами Client и Account-App Pod.

  1. Обнаружение службы:Account-Service предоставляет унифицированный ClusterIP для решения проблемы обнаружения службы, поэтому Клиенту нужно только получить доступ к кластеру Pod Account-App через ClusterIP, не беспокоясь о конкретном количестве Pod. и PodIP в кластере, и даже если PodIP изменится, он будет защищен ClusterIP. Обратите внимание, что ClusterIP здесь на самом деле является виртуальным IP-адресом, также известным как виртуальный IP-адрес (VIP).

2. Балансировка нагрузки.Абстрактный уровень Account-Service имеет возможность балансировки нагрузки, которая поддерживает доступ к различным экземплярам Pod в кластере Account-App с различными стратегиями для достижения распределения нагрузки и высокой доступности. Стратегия балансировки нагрузки по умолчанию в K8s — RoundRobin, но можно настроить и другие сложные стратегии.

Зачем вводить абстракцию Service в K8s? Каков основной принцип? Позже я объясню эти вопросы с точки зрения технической эволюции.

Эволюция технологии обнаружения сервисов

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

Внедрить DNS для обнаружения служб в K8s несложно. На самом деле K8s сам поддерживает компонент Kube-DNS. Предполагая, что K8s вводит DNS для обнаружения служб (как показано на рисунке выше), во время выполнения K8s может автоматически регистрировать информацию о кластере модуля (IP + порт и т. д.) Account-App в DNS. Затем клиентское приложение может обнаружить целевой модуль с помощью запроса доменного имени DNS и инициировать вызов. Эта схема не только проста, но и ненавязчива для клиента (в настоящее время почти все операционные системы поставляются с DNS-клиентами). Однако существуют также следующие проблемы с обнаружением службы на основе DNS:

  1. Существуют различия в функциональности разных DNS-клиентов. Некоторые клиенты будут запрашивать службу DNS каждый раз, когда они вызываются, вызывая ненужные накладные расходы, в то время как другие будут кэшировать информацию DNS с более длительным временем ожидания по умолчанию. При изменении целевого PodIP (что является нормальным в облачной среде контейнеров) обновление кеша может быть несвоевременным, что приведет к недействительному доступу к поду.
  2. Стратегия балансировки нагрузки, обычно реализуемая DNS-клиентами, обычно проста, в основном RoundRobin, а некоторые не поддерживают вызовы балансировки нагрузки.

Принимая во внимание различия между различными реализациями DNS-клиентов, которые не входят в сферу контроля K8s, K8s не использует технологию DNS напрямую для обнаружения служб. Обратите внимание, что K8s представляет Kube-DNS для поддержки доступа к службам через доменные имена, но это основано на сети ClusterIP/Service, о которой я расскажу позже.

Еще одна новая технология обнаружения служб — внедрение Service Registry + Client. В нынешнюю эпоху микросервисов это популярный подход. Основные продукты, такие как Eureka + Ribbon с открытым исходным кодом Netflix, Consul с открытым исходным кодом HashiCorp и Nacos с открытым исходным кодом Alibaba, являются типичными представителями этой схемы.

Несложно внедрить Service Registry в K8s для обнаружения сервисов. Сам K8s имеет распределенное хранилище etcd, которое может реализовать Service Registry. Предполагая, что K8s представляет Service Registry для обнаружения служб (как показано на рисунке выше), во время выполнения K8s может автоматически регистрировать информацию о кластере Account-App и Pod (IP + порт и т. д.) в Service Registry, а клиентское приложение может обнаруживать цель. Pod через Service Registry, а затем инициируйте вызов. Эта схема не сложна, и клиент может реализовать гибкие стратегии балансировки нагрузки, но она требует взаимодействия с клиентом и оказывает навязчивое воздействие на клиентское приложение, поэтому K8s не использует эту схему напрямую.

Несмотря на то, что K8s не принял вышеописанную схему напрямую, его реализация сервисной сети представляет собой расширение и эволюцию, основанную на двух технологиях. Он сочетает в себе преимущества вышеперечисленных схем и устраняет недостатки вышеперечисленных схем. В следующем разделе я подробно проанализирую принцип реализации сети K8s Service.

Каков принцип работы сети Kubernetes Service?

Механизм обнаружения сервисов K8s был разработан и эволюционировал из Service Registry + DNS, упомянутых в последнем разделе. На следующем рисунке показан упрощенный принцип обнаружения сервисов K8s:

На каждом рабочем узле платформы K8s развернуты два компонента, один из которых называется Kubelet, а другой — Kube-Proxy. Эти два компонента плюс Мастер являются ключом к реализации регистрации и обнаружения сервисов в K8s. Теперь давайте взглянем на упрощенный процесс регистрации и обнаружения сервисов.

  1. Во-первых, когда экземпляр Service Pod публикуется (соответствует Kind: Deployment в публикации K8s), Kubelet будет отвечать за запуск экземпляра Pod. После завершения запуска Kubelet сообщит список PodIP сервиса Главной ноде.
  2. Во-вторых, через публикацию службы (соответствует виду: служба в публикации K8s) K8s выделяет ClusterIP для службы, и соответствующая информация будет записана на мастере.
  3. В-третьих, на этапе обнаружения службы Kube-Proxy будет прослушивать Мастера и обнаруживать отношения сопоставления ClusterIP службы и списка PodIP, а также изменять локальные правила переадресации Linux iptables, указывая iptables выполнять балансировку нагрузки и пересылку на соответствующий PodIP при получении. запросы на ClusterIP.
  4. Во время работы, когда потребительскому поду требуется доступ к определенному целевому экземпляру службы, он вызывает через ClusterIP, который перехватывается локальным механизмом iptables, а затем перенаправляется в целевой экземпляр службы через балансировку нагрузки.

Фактические потребительские поды не вызывают напрямую ClusterIP службы, а сначала вызывают имя службы, поскольку ClusterIP также может измениться (например, для разных сред, таких как TEST/UAT/PROD, ClusterIP будет другим), только служба имя вообще без изменений. Чтобы защитить изменения ClusterIP, K8s также представила компонент KubeDNS на каждом рабочем узле, который прослушивает Master и обнаруживает связь между именем службы и ClusterIP. Таким образом, потребительские поды могут косвенно обнаруживать ClusterIP службы через KubeDNS.

Обратите внимание, механизм обнаружения сервисов K8s по общему принципу похож на основной механизм обнаружения сервисов (типа Eureka + Ribbon) текущих микросервисов, но есть и существенные отличия (эти отличия в основном проявляются в клиенте):

  1. Прежде всего, оба они используют механизм клиентского прокси (прокси). Как и Ribbon, перенаправление прокси-сервера K8s и балансировка нагрузки также реализованы на стороне клиента, но Ribbon встроен в клиентское приложение в виде библиотеки Lib, которая навязчива для клиентского приложения, в то время как Kube-Proxy K8s независим. На каждом рабочем узле есть один, который не является инвазивным для клиентского приложения. Подход K8s аналогичен подходу sidecar в ServiceMesh.
  2. Во-вторых, прокси-форвардинг Ribbon является проникающим, в то время как прокси-форвардинг в K8s — это форвардинг IPTables. Хотя в K8s есть Kube-Proxy, он отвечает только за обнаружение сервисов и изменение правил IPTables (или IPVS), а фактический запрос не проходит через Kube-Proxy. Обратите внимание, что более ранний прокси-сервер Kube-Proxy в K8s был проникающим, учитывая потерю производительности и проблемы с одной точкой, последующие версии были изменены на отсутствие проникновения.
  3. В-третьих, лента реализует сопоставление имени службы с IP-адресом экземпляра службы, что представляет собой сопоставление только одного уровня. В то время как в K8s есть два уровня сопоставления, Kube-Proxy реализует сопоставление из ClusterIP в PodIP, а Kube-DNS реализует сопоставление из ServiceName в ClusterIP.

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

Краткое содержание

  1. Сеть сервисов Kubernetes построена на сети Pod, ее основная цель — решить проблемы обнаружения сервисов и балансировки нагрузки.
  2. K8s объединяет обнаружение сервисов и балансировку нагрузки через ServiceName+ClusterIP, а базовая технология разрабатывается и развивается на основе DNS+Service Registry.
  3. Обнаружение сервисов K8s и балансировка нагрузки реализованы через переадресацию Kube-Proxy + iptables на стороне клиента, без какого-либо вторжения в приложение, без проникновения в прокси и без дополнительной потери производительности.
  4. K8s Service Discovery Mechanism можно рассматривать как элегантную комбинацию современного механизма обнаружения микросервисов и традиционного механизма ядра Linux.

С абстракцией службы приложения, развернутые в K8s, могут быть адресованы и доступны через абстрактный ClusterIP, и потребителю не нужно заботиться о том, сколько экземпляров Pod находится за этим ClusterIP, каковы их PodIP, будут ли они меняться и как получить доступ. их с балансировкой нагрузки. Однако сеть службы K8s — это только внутренняя сеть, видимая внутри кластера, и она не видна и не доступна напрямую извне кластера. Когда мы развертываем приложения, некоторые из них должны быть доступны извне, чтобы внешние сети или даже общедоступная сеть могли получить к ним доступ, чтобы они могли предоставлять услуги извне. Как K8s выставляет внутренние службы наружу? Это та проблема, которая будет обсуждаться в следующей статье «Доступ к внешней сети Kubernetes», следите за обновлениями.





👋 Если вы считаете это полезным, пожалуйста, несколько раз нажмите кнопку аплодисментов 👏 ниже, чтобы выразить свою поддержку автору 👇

🚀Присоединяйтесь к сообществу разработчиков FAUN и получайте похожие истории в свой почтовый ящик каждую неделю