Как да стартирате Istio, използвайки Kubernetes в production. Част 1

Какво представлява Istio? Это так называемый Service mesh, технология, которая добавляет уровень абстракции над сетью. Мы перехватываем весь или часть трафика в кластере и производим определенный набор операций с ним. Какой именно? Например, делаем умный роутинг, или реализуем подход circuit breaker, можем организовывать «canary deployment», частично переключая трафик на новую версию сервиса, а можем ограничивать внешние взаимодействия и контролировать все походы из кластера во внешнюю сеть. Есть возможность задавать policy правила для контроля походов между разными микросервисами. Наконец, мы можем получить всю карту взаимодействия по сети и сделать унифицированный сбор метрик полностью прозрачно для приложений.

За механизма на работа може да се прочете в официалната документация. Istio е наистина мощен инструмент, който позволява да се решат множество задачи и проблеми. В тази статия бих искал да отговоря на основните въпроси, които обикновено възникват в началото на работата с Istio. Това ще помогне да се запознаете с него по-бързо.

Как да стартирате Istio, използвайки Kubernetes в production. Част 1

Принцип на работа

Istio се състои от две основни зони — control plane и data plane. Control plane съдържа основните компоненти, които осигуряват правилната работа на останалите. В текущата версия (1.0) control plane има три основни компонента: Pilot, Mixer, Citadel. Citadel няма да обсъждаме, той е необходим за генериране на сертификати за осигуряване на mutual TLS между услугите. Нека погледнем по-детайлно устройството и предназначението на Pilot и Mixer.

Как да стартирате Istio, използвайки Kubernetes в production. Част 1

Pilot е главният управляващ компонент, който разпространява цялата информация за това, което имаме в кластера – услуги, техните endpoint’и и правила за routing (например, правила за Canary deployment или правила circuit breaker).

Mixer е опционален компонент на control plane, който предоставя възможност за събиране на метрики, логове и всяка информация за мрежовото взаимодействие. Той също така следи за спазването на Policy правилата и спазването на rate limit’ите.

Data plane се реализира с помощта на sidecar контейнери-прокси. По подразбиране се използва мощният прокси-сървър envoy. Той може да бъде заменен с друга реализация, например nginx (nginmesh).

За да работи Istio напълно прозрачно за приложенията, съществува система за автоматично inject’ване. Последната реализация е подходяща за версии на Kubernetes 1.9+ (mutational admission webhook). За версии на Kubernetes 1.7, 1.8 има възможност за използване на Initializer.

Sidecar контейнерите се свързват с Pilot по протокола GRPC, който позволява оптимизиране на модела за push на измененията, настъпващи в кластера. GRPC започва да се използва в Envoy, започвайки от версия 1.6, в Istio се използва от версия 0.8 и представлява pilot-agent — обвивка на golang над envoy, която конфигурира параметрите на стартиране.

Pilot и Mixer са напълно stateless компоненти, всички състояния се съхраняват в паметта. Конфигурацията за тях се задава под формата на Kubernetes Custom Resources, които се съхраняват в etcd.
Istio-agent получава адреса на Pilot и отваря GRPC stream към него.

Както вече казах, Istio реализира цялата функционалност напълно прозрачно за приложенията. Нека разберем как. Алгоритъмът е такъв:

  1. Деплоим нова версия на услугата.
  2. В зависимост от подхода за инжектиране на sidecar контейнера, се добавят istio-init контейнер и istio-agent контейнер (envoy) по време на прилагане на конфигурацията, или те могат да бъдат вече ръчно добавени в описанието на Pod съществото в Kubernetes.
  3. istio-init контейнерът представлява скрипт, който прилага правила iptables за пода. Има два варианта за конфигуриране на завиването на трафика в istio-agent контейнера: да се използват правила за пренасочване iptables, или TPROXY. Към момента на написване на статията по подразбиране се използва подход с правила за пренасочване. В istio-init има възможност да се настрои какъв точно трафик трябва да бъде прихванат и насочен в istio-agent. Например, за да прихванете целия входящ и целия изходящ трафик, трябва да зададете параметри -i и -b на стойността *. Можете да зададете конкретни портове, които да бъдат прихванати. За да не прихващате определена подсеть, можете да я зададете с помощта на флага -x.
  4. След изпълнението на init контейнерите, се стартират основните, включително pilot-agent (envoy). Той се свързва с вече разгръщания Pilot по GRPC и получава информация за всички съществуващи услуги и routing политики в клъстера. На базата на получените данни, той конфигурира cluster-и и записва директно endpoint-ите на нашите приложения в Kubernetes клъстера. Също така е необходимо да се отбележи важен момент: envoy динамично настройва listeners (попарите IP, port), които започва да слуша. Така, когато заявките влизат в pod, те се пренасочват с помощта на правила за пренасочване iptables в sidecar, envoy вече успешно може да обработва тези връзки и да разбира къде да проксирва трафика. На този етап също така се изпраща информация в Mixer, който ще разгледаме по-късно, и се изпращат tracing span-ове.

В резултат получаваме цяла мрежа от envoy прокси-сървъри, които можем да конфигурираме от една точка (Pilot). Всички входящи и изходящи заявки преминават през envoy. Освен това, се прихваща само TCP трафик. Това означава, че IP на Kubernetes услугата се резолвира с помощта на kube-dns по UDP без промяна. След като е направен резолвът, се извършва прихващане на изходящата заявка и обработка от envoy, който вече решава на кой endpoint трябва да изпрати заявката (или да не я изпрати, в случай на политики за достъп или сработване на алгоритъма за circuit breaker).

С Pilot разбрахме, сега трябва да разберем какво прави Mixer и защо е нужен. Официалната документация за него може да се прочете тук.

Mixer в текущия му вид представлява два компонента: istio-telemetry и istio-policy (до версия 0.8 това беше един компонент istio-mixer). И двата представляват mixer, всеки от които е отговорен за своята задача. Istio telemetry приема по GRPC от sidecar контейнерите Report информация за това, кой къде отива и с какви параметри. Istio-policy приема Check заявки за проверка на спазването на правилата на Policy. Policy check се провеждат, разбира се, не на всяка заявка, а се кешират на клиента (в sidecar) за определено време. Report check-ове се изпращат партидно. Как да настроим и какви точно параметри трябва да се изпращат, ще разгледаме по-късно.

Mixer е проектиран като компонент с висока наличност, който осигурява непрекъсната работа по събиране и обработка на telemetry данни. Системата в крайна сметка представлява многослойен буфер. Първоначално данните се буферират на страната на sidecar контейнерите, след това на страната на mixer и после се изпращат в така наречените mixer backend-ове. В крайна сметка, ако някой от компонентите на системата се провали, буферът нараства и след възстановяване на системата се изпразва. Mixer backend-овете представляват крайните точки за изпращане на данни за телеметрия: statsd, newrelic и т.н. Може да напишете свой собствен backend, това е достатъчно просто, и ние ще разгледаме как да го направим.

Как да стартирате Istio, използвайки Kubernetes в production. Част 1

Ако обобщим, схемата на работа с istio-telemetry е следната.

  1. Сервис 1 изпраща заявка на сервис 2.
  2. При излизане от сервис 1, заявката се обгръща в неговия собствен sidecar.
  3. Sidecar envoy следи как протича заявката към сервис 2 и подготвя необходимата информация.
  4. След това я изпраща в istio-telemetry с помощта на Report заявка.
  5. Istio-telemetry определя дали да изпрати този Report в backend-овете, в кои точно и какви данни да изпрати.
  6. Istio-telemetry изпраща Report данни в backend, ако това е необходимо.

Сега да видим как да разположим в системата Istio, състояща се само от основни компоненти (Pilot и sidecar envoy).

Първо, да погледнем основната конфигурация (mesh), която прочита Pilot:

apiVersion: v1
kind: ConfigMap
metadata:
  name: istio
  namespace: istio-system
  labels:
    app: istio
    service: istio
data:
  mesh: |-

    # Временно отключаем отправку информации о трассировке (Pilot настроит envoy’и так, что отправка не будет происходить)
    enableTracing: false

    # Временно не указываем конечные точки mixer, чтобы контейнеры sidecar не отправляли информацию туда
    #mixerCheckServer: istio-policy.istio-system:15004
    #mixerReportServer: istio-telemetry.istio-system:15004

    # Устанавливаем временной промежуток, с которым будет envoy переспрашивать Pilot (это для старой версии envoy proxy)
    rdsRefreshDelay: 5s

    # Конфигурация по умолчанию для envoy sidecar
    defaultConfig:
      # Аналогично rdsRefreshDelay
      discoveryRefreshDelay: 5s

      # Оставляем по умолчанию (путь к конфигурации и бинарю envoy)
      configPath: "/etc/istio/proxy"
      binaryPath: "/usr/local/bin/envoy"

      # Дефолтное имя запущенного контейнера sidecar (используется, например, в именах сервиса при отправке трассировок)
      serviceCluster: istio-proxy

      # Время, которое будет ждать envoy до принудительного завершения всех установленных соединений
      drainDuration: 45s
      parentShutdownDuration: 1m0s

      # По умолчанию используются правила REDIRECT iptables. Можно изменить на TPROXY.
      #interceptionMode: REDIRECT

      # Порт, на котором будет запущена админ панель каждого контейнера sidecar (envoy)
      proxyAdminPort: 15000

      # Адрес, по которому будут отправляться трассировки по протоколу zipkin (в начале мы отключили саму отправку, поэтому это поле сейчас не будет использоваться)
      zipkinAddress: tracing-collector.tracing:9411

      # statsd адрес для отправки метрик контейнеров envoy (отключаем)
      # statsdUdpAddress: aggregator:8126

      # Отключаем поддержку Mutual TLS
      controlPlaneAuthPolicy: NONE

      # Адрес, на котором будет слушать istio-pilot для того, чтобы сообщать информацию о service discovery всем контейнерам sidecar
      discoveryAddress: istio-pilot.istio-system:15007

Всички основни компоненти за управление (control plane) ще се разположат в namespace istio-system в Kubernetes.

Минимум, от който се нуждаем, е да разположим само Pilot. За това ще използваме такава конфигурация.

И ще настроим ръчно внедряването на контейнера sidecar.

Init контейнер:

initContainers:
 - name: istio-init
   args:
   - -p
   - "15001"
   - -u
   - "1337"
   - -m
   - REDIRECT
   - -i
   - '*'
   - -b
   - '*'
   - -d
   - ""
   image: istio/proxy_init:1.0.0
   imagePullPolicy: IfNotPresent
   resources:
     limits:
       memory: 128Mi
   securityContext:
     capabilities:
       add:
       - NET_ADMIN

И sidecar:

       име: istio-proxy
       аргументи:
         - "bash"
         - "-c"
         - |
           exec /usr/local/bin/pilot-agent proxy sidecar 
           --configPath 
           /etc/istio/proxy 
           --binaryPath 
           /usr/local/bin/envoy 
           --serviceCluster 
           service-name 
           --drainDuration 
           45s 
           --parentShutdownDuration 
           1m0s 
           --discoveryAddress 
           istio-pilot.istio-system:15007 
           --discoveryRefreshDelay 
           1s 
           --connectTimeout 
           10s 
           --proxyAdminPort 
           "15000" 
           --controlPlaneAuthPolicy 
           NONE
         env:
         - име: POD_NAME
           valueFrom:
             fieldRef:
               fieldPath: metadata.name
         - име: POD_NAMESPACE
           valueFrom:
             fieldRef:
               fieldPath: metadata.namespace
         - име: INSTANCE_IP
           valueFrom:
             fieldRef:
               fieldPath: status.podIP
         - име: ISTIO_META_POD_NAME
           valueFrom:
             fieldRef:
               fieldPath: metadata.name
         - име: ISTIO_META_INTERCEPTION_MODE
           value: REDIRECT
         изображение: istio/proxyv2:1.0.0
         imagePullPolicy: IfNotPresent
         ресурси:
           requests:
             cpu: 100m
             памет: 128Mi
           limits:
             памет: 2048Mi
         securityContext:
           privileged: false
           readOnlyRootFilesystem: true
           runAsUser: 1337
         volumeMounts:
         - mountPath: /etc/istio/proxy
           name: istio-envoy

За да стартирате успешно всичко, е необходимо да създадете ServiceAccount, ClusterRole, ClusterRoleBinding и CRD за Pilot, описанията на които можете да намерите. тук.

В резултат на това, услугата, в която инжектираме sidecar с envoy, трябва успешно да стартира, да получи всички discovery от пилота и да обработва заявки.

Важно е да се разбере, че всички компоненти на control plane са stateless приложения и могат лесно да бъдат хоризонтално мащабируеми. Всички данни се съхраняват в etcd под формата на персонализирани описания на ресурсите на Kubernetes.

Също така, в Istio (все още експериментално) има възможност за стартиране извън кластера и възможност за наблюдение и споделяне на service discovery между няколко Kubernetes кластера. Повече информация можете да прочетете. тук.

При мултикластерна инсталация е необходимо да се вземат предвид следните ограничения:

  1. Pod CIDR и Service CIDR трябва да бъдат уникални за всички клъстери и не трябва да се пресичат.
  2. Всички Pod CIDR трябва да бъдат достъпни от всякакви Pod CIDR между клъстерите.
  3. Всички Kubernetes API сървъри трябва да бъдат достъпни един за друг.

Това са основните сведения, които ще ви помогнат да започнете работа с Istio. Обаче има още много подводни камъни. Например, особености на маршрутизацията на външния трафик (навън от клъстера), подходи за отстраняване на грешки в sidecar-ите, профилиране, настройка на mixer и написване на персонализиран mixer backend, настройка на tracing механизъм и неговата работа с envoy.
Всичко това ще разгледаме в следващите публикации. Питайте вашите въпроси, ще се постарая да ги осветя.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster