Jak uruchomić Istio przy użyciu Kubernetes w środowisku produkcyjnym. Część 1

Co to jest Podobnie? Jest to tak zwana Service mesh, technologia, która dodaje warstwę abstrakcji w sieci. Przechwytujemy całość lub część ruchu w klastrze i wykonujemy na nim określony zestaw operacji. Który? Na przykład robimy inteligentne trasowanie lub wdrażamy podejście wyłącznika, możemy zorganizować „wdrożenie kanarków”, częściowo przełączając ruch na nową wersję usługi lub możemy ograniczyć interakcje zewnętrzne i kontrolować wszystkie podróże z klastra do sieć zewnętrzna. Możliwe jest ustawienie zasad polityki w celu kontrolowania podróży między różnymi mikrousługami. W końcu możemy uzyskać całą mapę interakcji sieciowych i sprawić, by ujednolicony zbiór metryk był całkowicie przejrzysty dla aplikacji.

O mechanizmie działania można przeczytać m.in oficjalna dokumentacja. Istio to naprawdę potężne narzędzie, które pozwala rozwiązać wiele zadań i problemów. W tym artykule chciałbym odpowiedzieć na główne pytania, które zwykle pojawiają się podczas rozpoczynania pracy z Istio. Pomoże Ci to szybciej sobie z tym poradzić.

Jak uruchomić Istio przy użyciu Kubernetes w środowisku produkcyjnym. Część 1

Zasada działania

Istio składa się z dwóch głównych obszarów - płaszczyzny kontroli i płaszczyzny danych. Płaszczyzna sterowania zawiera główne komponenty, które zapewniają prawidłowe działanie pozostałych. W obecnej wersji (1.0) płaszczyzna kontrolna składa się z trzech głównych elementów: Pilot, Mixer, Citadel. Nie będziemy rozważać Citadel, potrzebne jest wygenerowanie certyfikatów w celu zapewnienia wzajemnego TLS między usługami. Przyjrzyjmy się bliżej urządzeniu i celowi pilota i miksera.

Jak uruchomić Istio przy użyciu Kubernetes w środowisku produkcyjnym. Część 1

Pilot jest głównym komponentem sterującym, który dystrybuuje wszystkie informacje o tym, co mamy w klastrze - usługach, ich punktach końcowych i regułach routingu (na przykład reguły wdrażania Canary lub reguły wyłącznika).

Mikser to opcjonalny składnik płaszczyzny kontrolnej, który zapewnia możliwość zbierania metryk, dzienników i wszelkich informacji o interakcjach sieciowych. Monitoruje również przestrzeganie zasad Polityki oraz przestrzeganie limitów stawek.

Płaszczyzna danych jest implementowana przy użyciu pomocniczych kontenerów proxy. Mocny jest używany domyślnie. pełnomocnik pełnomocnika. Można go zastąpić inną implementacją, taką jak nginx (nginmesh).

Aby Istio działało całkowicie transparentnie dla aplikacji, zastosowano system automatycznego wtrysku. Najnowsza implementacja jest odpowiednia dla wersji Kubernetes 1.9+ (webhook przyjmowania mutacji). Dla wersji Kubernetes 1.7, 1.8 istnieje możliwość użycia Inicjatora.

Kontenery Sidecar są połączone z Pilotem za pomocą protokołu GRPC, co pozwala na optymalizację modelu push pod kątem zmian zachodzących w klastrze. GRPC jest używany w Envoy od wersji 1.6, w Istio jest używany od wersji 0.8 i jest pilotem-agentem - nakładką golanga na emisariusza, która konfiguruje opcje uruchamiania.

Pilot i Mixer są komponentami całkowicie bezstanowymi, wszystkie stany są przechowywane w pamięci. Konfiguracja dla nich jest ustawiona w postaci Kubernetes Custom Resources, które są przechowywane w etcd.
Istio-agent pobiera adres pilota i otwiera do niego strumień GRPC.

Jak powiedziałem, Istio implementuje wszystkie funkcjonalności całkowicie transparentne dla aplikacji. Zobaczmy jak. Algorytm jest taki:

  1. Wdrażanie nowej wersji usługi.
  2. W zależności od podejścia sidecar container injection, kontener istio-init oraz kontener istio-agent (envoy) są dodawane na etapie stosowania konfiguracji lub można je już ręcznie wstawić do opisu encji Kubernetes Pod.
  3. Kontener istio-init to skrypt, który stosuje reguły iptables do poda. Istnieją dwie opcje konfigurowania ruchu w kontenerze istio-agent: użyj reguł przekierowania iptables lub TPROXY. W chwili pisania tego tekstu domyślnym podejściem są reguły przekierowania. W istio-init można skonfigurować, który ruch ma być przechwytywany i wysyłany do istio-agent. Na przykład, aby przechwycić cały ruch przychodzący i wychodzący, musisz ustawić parametry -i и -b w znaczenie *. Możesz określić określone porty do przechwycenia. Aby nie przechwytywać określonej podsieci, możesz określić ją za pomocą flagi -x.
  4. Po wykonaniu kontenerów init uruchamiane są główne, w tym pilot-agent (wysłannik). Łączy się z już wdrożonym Pilotem za pośrednictwem GRPC i otrzymuje informacje o wszystkich istniejących usługach i politykach routingu w klastrze. Na podstawie otrzymanych danych konfiguruje klastry i przypisuje je bezpośrednio do punktów końcowych naszych aplikacji w klastrze Kubernetes. Należy również zwrócić uwagę na ważną kwestię: wysłannik dynamicznie konfiguruje słuchaczy (IP, pary portów), których zaczyna nasłuchiwać. Dlatego, gdy żądania wchodzą do kapsuły i są przekierowywane przy użyciu reguł przekierowania iptables w przyczepie bocznej, wysłannik może już z powodzeniem przetwarzać te połączenia i rozumieć, gdzie dalej przekazywać ruch proxy. Również na tym etapie wysyłane są informacje do Miksera, któremu przyjrzymy się później, oraz wysyłane są rozpiętości śledzenia.

W efekcie otrzymujemy całą sieć serwerów proxy wysłanników, które możemy skonfigurować z jednego punktu (Pilot). Wszystkie żądania przychodzące i wychodzące przechodzą przez wysłannika. Ponadto przechwytywany jest tylko ruch TCP. Oznacza to, że adres IP usługi Kubernetes jest rozpoznawany przy użyciu kube-dns przez UDP bez zmiany. Następnie, po rozwiązaniu, wychodzące żądanie jest przechwytywane i przetwarzane przez wysłannika, który już decyduje, do którego punktu końcowego należy wysłać żądanie (lub nie wysłać, w przypadku polityk dostępu lub wyłącznika algorytmu).

Rozgryźliśmy Pilota, teraz musimy zrozumieć, jak działa Mixer i dlaczego jest potrzebny. Możesz przeczytać oficjalną dokumentację tego tutaj.

Mixer w obecnej postaci składa się z dwóch komponentów: istio-telemetry, istio-policy (przed wersją 0.8 był to jeden komponent istio-mixer). Obaj to miksery, z których każdy odpowiada za swoje własne zadanie. Telemetria Istio otrzymuje informacje o tym, kto idzie gdzie iz jakimi parametrami z sidecar Report kontenerów przez GRPC. Istio-policy akceptuje żądania sprawdzenia, aby sprawdzić, czy zasady Polityki są spełnione. Kontrole zasad nie są oczywiście przeprowadzane dla każdego żądania, ale są przechowywane w pamięci podręcznej klienta (w wózku bocznym) przez określony czas. Kontrole raportów są wysyłane jako żądania wsadowe. Zobaczmy, jak skonfigurować i jakie parametry należy przesłać nieco później.

Mikser ma być komponentem o wysokiej dostępności, zapewniającym nieprzerwaną pracę nad składaniem i przetwarzaniem danych telemetrycznych. Układ uzyskuje się w efekcie jako bufor wielopoziomowy. Początkowo dane są buforowane po stronie sidecar kontenerów, następnie po stronie mixera, a następnie przesyłane do tzw. backendów mixera. W rezultacie, jeśli któryś z elementów systemu ulegnie awarii, bufor powiększa się i jest opróżniany po przywróceniu systemu. Backendy miksera to punkty końcowe do wysyłania danych telemetrycznych: statsd, newrelic itp. Możesz napisać własny backend, to dość proste, a my zobaczymy, jak to zrobić.

Jak uruchomić Istio przy użyciu Kubernetes w środowisku produkcyjnym. Część 1

Podsumowując, schemat pracy z istio-telemetrią jest następujący.

  1. Usługa 1 wysyła żądanie do usługi 2.
  2. Po opuszczeniu usługi 1 żądanie jest pakowane we własny wózek boczny.
  3. Wysłannik Sidecar monitoruje, w jaki sposób żądanie trafia do serwisu 2 i przygotowuje niezbędne informacje.
  4. Następnie wysyła go do istio-telemetry przy użyciu żądania raportu.
  5. Istio-telemetria określa, czy ten Raport powinien zostać wysłany do backendów, do których i jakie dane powinny zostać przesłane.
  6. Telemetria Istio wysyła w razie potrzeby dane raportu do zaplecza.

Zobaczmy teraz, jak wdrożyć Istio w systemie, składającym się tylko z głównych komponentów (Pilot i sidecar envoy).

Najpierw spójrzmy na główną konfigurację (siatkę), którą odczytuje Pilot:

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

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

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

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

    # default конфигурация для envoy sidecar
    defaultConfig:
      # аналогично как rdsRefreshDelay
      discoveryRefreshDelay: 5s

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

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

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

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

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

      # адрес, по которому будут отправляться trace’ы по 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

Wszystkie główne komponenty kontrolne (płaszczyzna kontrolna) będą zlokalizowane w przestrzeni nazw istio-system w Kubernetes.

Jako minimum musimy tylko wdrożyć pilota. Do tego używamy taka konfiguracja.

I ręcznie skonfigurujemy wózek boczny do wstrzykiwania kontenera.

Kontener początkowy:

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

I wózek boczny:

       name: istio-proxy
       args:
         - "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:
         - name: POD_NAME
           valueFrom:
             fieldRef:
               fieldPath: metadata.name
         - name: POD_NAMESPACE
           valueFrom:
             fieldRef:
               fieldPath: metadata.namespace
         - name: INSTANCE_IP
           valueFrom:
             fieldRef:
               fieldPath: status.podIP
         - name: ISTIO_META_POD_NAME
           valueFrom:
             fieldRef:
               fieldPath: metadata.name
         - name: ISTIO_META_INTERCEPTION_MODE
           value: REDIRECT
         image: istio/proxyv2:1.0.0
         imagePullPolicy: IfNotPresent
         resources:
           requests:
             cpu: 100m
             memory: 128Mi
           limits:
             memory: 2048Mi
         securityContext:
           privileged: false
           readOnlyRootFilesystem: true
           runAsUser: 1337
         volumeMounts:
         - mountPath: /etc/istio/proxy
           name: istio-envoy

Aby wszystko ruszyło pomyślnie należy utworzyć ServiceAccount, ClusterRole, ClusterRoleBinding, CRD for Pilot, których opisy można znaleźć tutaj.

W rezultacie usługa, do której wstrzykujemy sidecar z envoy, powinna uruchomić się pomyślnie, otrzymać wszystkie odkrycia od pilota i przetworzyć żądania.

Ważne jest, aby zrozumieć, że wszystkie komponenty płaszczyzny sterowania są aplikacjami bezstanowymi i można je bez problemu skalować w poziomie. Wszystkie dane są przechowywane w etcd w postaci niestandardowych opisów zasobów Kubernetes.

Ponadto Istio (wciąż eksperymentalne) ma możliwość działania poza klastrem oraz możliwość obserwowania i wyszukiwania usług między kilkoma klastrami Kubernetes. Możesz przeczytać więcej na ten temat tutaj.

W przypadku instalacji wieloklastrowej należy pamiętać o następujących ograniczeniach:

  1. CIDR poda i CIDR usługi muszą być unikalne we wszystkich klastrach i nie mogą się nakładać.
  2. Wszystkie kapsuły CIDR muszą być dostępne z dowolnych kapsuł CIDR między klastrami.
  3. Wszystkie serwery Kubernetes API muszą być wzajemnie dostępne.

To są wstępne informacje, które pomogą Ci rozpocząć pracę z Istio. Jednak nadal istnieje wiele pułapek. Na przykład cechy routingu ruchu zewnętrznego (poza klastrem), podejścia do debugowania sidecarów, profilowania, konfigurowania miksera i pisania niestandardowego backendu miksera, ustawiania mechanizmu śledzenia i jego działania za pomocą envoy.
Wszystko to rozważymy w następnych publikacjach. Zadawaj pytania, postaram się je omówić.

Źródło: www.habr.com

Dodaj komentarz