Статьи

Отслеживание трафика с помощью Istio: снижение риска выпуска кода

Мы недавно говорили об Istio и сервисной сетке ( следите за @christianposta для последней), но один аспект Istio может быть скрыт. Одним из наиболее важных аспектов Istio.io является его способность контролировать маршрутизацию трафика между сервисами . Благодаря этому детальному управлению трафиком на уровне приложений мы можем выполнять интересные операции по обеспечению устойчивости, такие как маршрутизация при сбоях, маршрутизация в различные зоны доступности при необходимости и т. Д. ИМХО, что более важно, мы также можем контролировать поток трафика для наших развертываний, поэтому мы может снизить риск изменения системы.

С помощью сервисной архитектуры наша цель состоит в том, чтобы увеличить нашу способность работать быстрее, поэтому мы делаем такие вещи, как внедрение микросервисов, автоматическое тестирование конвейеров, CI / CD и т. Д. Но что хорошего в этом, если у нас есть узкие места при внесении изменений в наш код в производство? В процессе производства мы понимаем, оказывают ли наши изменения какое-либо положительное влияние на наши KPI, поэтому мы должны сократить количество узких мест при вводе кода в производство.

У типичных корпоративных клиентов, которых я регулярно посещаю (финансовые услуги, страхование, розничная торговля, энергетика и т. Д.), Риск является такой большой частью уравнения. Риск используется в качестве причины, по которой изменения в производстве блокируются. Большая часть этого риска заключается в том, что «развертывание» кода — это все или ничего в этих средах. Я имею в виду, что не существует разделения на развертывание и выпуск . Это такое чрезвычайно важное различие.

Развертывание против выпуска

Развертывание приносит новый код в производство, но не требует рабочего трафика . Оказавшись в производственной среде, сервисные бригады могут проводить тесты дыма, интеграционные тесты и т. Д., Не оказывая влияния на пользователей. Сервисная команда должна свободно развертываться так часто, как она пожелает.

Релиз приносит живой трафик для развертывания, но может потребовать подтверждения со стороны «заинтересованных сторон бизнеса». В идеале перенос трафика в развертывание может осуществляться контролируемым образом для снижения риска. Например, мы можем сначала направить внутренний трафик на развертывание. Или мы можем захотеть привнести небольшую долю, скажем, 1% трафика в развертывание. Если какая-либо из этих стратегий выпуска релизов (внутренняя, неоплачиваемая, трафик 1% и т. Д.) Демонстрирует нежелательное поведение (следовательно, потребность в сильной наблюдаемости), то мы можем выполнить откат.

Пожалуйста, прочитайте серию из двух частей под названием «Deploy! = Release» от хороших ребят из Turbine.io labs, чтобы глубже изучить эту тему.

Темный трафик

Одна из стратегий, которую мы можем использовать для снижения риска для наших выпусков, прежде чем мы даже представим их любому пользователю, заключается в том, чтобы скрывать трафик от живого трафика до нашего развертывания. С затенением трафика мы можем взять часть трафика и направить его в наше новое развертывание и наблюдать за его поведением. Мы можем делать такие вещи, как тестирование на исключения, производительность и четность результатов. Такие проекты, как Twitter Diffy, можно использовать для сравнения различных выпущенных версий и неизданных версий.

С помощью Istio мы можем осуществлять такой контроль трафика, отражая трафик от одного сервиса к другому. Давайте посмотрим на пример.

Зеркальное отображение трафика с Istio

С выпуском Istio 0.5.0 у нас есть возможность зеркалировать трафик от одного сервиса к другому или от одной версии к более новой версии.

Мы начнем с создания двух развертываний службы httpbin .

1
$  cat httpbin-v1.yaml
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  labels:
    app: httpbin
spec:
  ports:
  - name: http
    port: 8080
  selector:
    app: httpbin
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: httpbin-v1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
    spec:
      containers:
      - image: docker.io/kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:8080", "httpbin:app"]
        ports:
        - containerPort: 8080

Мы вставим коляску kube-inject с помощью kube-inject следующим образом:

1
$  kubectl create -f <(istioctl kube-inject -f httpbin-v1.yaml)

Версия 2 службы httpbin аналогична, за исключением того, что она имеет метки, обозначающие ее версию 2:

1
$  cat httpbin-v2.yaml
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: httpbin-v2
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: httpbin
        version: v2
    spec:
      containers:
      - image: docker.io/kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:8080", "httpbin:app"]
        ports:
        - containerPort: 8080

Давайте также развернем httpbin-v2:

1
$  kubectl create -f <(istioctl kube-inject -f httpbin-v2.yaml)

Наконец, давайте развернем демо sleep из примеров Istio, чтобы мы могли легко вызвать наш сервис httpbin :

1
$  kubectl create -f <(istioctl kube-inject -f sleep.yaml)

Вы должны увидеть три таких модуля:

1
$  kubectl get pod NAME                          READY     STATUS    RESTARTS   AGE httpbin-v1-2113278084-98whj   2/2       Running   0          1d httpbin-v2-2839546783-2dvhq   2/2       Running   0          1d sleep-1512692991-txrfn        2/2       Running   0          1d

Если мы начнем отправлять трафик в службу httpbin , мы увидим поведение Kubernetes по умолчанию для балансировки нагрузки как в v1 и в v2 поскольку оба модуля будут соответствовать селектору для службы httpbin Kubernetes . Давайте посмотрим на правило маршрута Istio по умолчанию для маршрутизации всего трафика до v1 нашего сервиса:

01
02
03
04
05
06
07
08
09
10
11
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
  name: httpbin-default-v1
spec:
  destination:
    name: httpbin
  precedence: 5
  route:
  - labels:
      version: v1

Давайте создадим этот routerule :

1
$  istioctl create -f routerules/all-httpbin-v1.yaml

Если мы начнем отправлять трафик в нашу службу httpbin , мы должны видеть только трафик для развертывания httpbin-v1 :

1
export SLEEP_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) kubectl exec -it $SLEEP_POD -c sleep -- sh -c 'curl  http://httpbin:8080/headers' {   "headers": {     "Accept": "*/*",     "Content-Length": "0",     "Host": "httpbin:8080",     "User-Agent": "curl/7.35.0",     "X-B3-Sampled": "1",     "X-B3-Spanid": "eca3d7ed8f2e6a0a",     "X-B3-Traceid": "eca3d7ed8f2e6a0a",     "X-Ot-Span-Context": "eca3d7ed8f2e6a0a;eca3d7ed8f2e6a0a;0000000000000000"   } }

Если мы проверим журналы доступа для httpbin-v1 , мы должны увидеть один оператор доступа:

1
$  kubectl logs -f httpbin-v1-2113278084-98whj -c httpbin 127.0.0.1 - - [07/Feb/2018:00:07:39 +0000] "GET /headers HTTP/1.1" 200 349 "-" "curl/7.35.0"

Если мы проверим журналы для httpbin-v2 , мы должны увидеть НЕТ операторов журнала доступа.

Давайте отразим трафик от v1 до v2 . Вот правило маршрута Istio, которое мы будем использовать:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
  name: mirror-traffic-to-httbin-v2
spec:
  destination:
    name: httpbin
  precedence: 11
  route:
  - labels:
      version: v1
    weight: 100
  - labels:
      version: v2
    weight: 0
  mirror:
    name: httpbin
    labels:
      version: v2

Несколько вещей, на которые стоит обратить внимание:

  • Мы явно просим Istio взвесить трафик между v1 (100%) и v2 (0%)
  • Мы используем метки, чтобы указать, какую версию службы httpbin, на которую мы хотим зеркалировать

Давайте создадим этот routerule

1
$  istioctl create -f routerules/mirror/mirror-traffic-to-httbin-v2.yaml

Мы должны увидеть роутеры вот так:

1
$  istioctl get routerules $  istioctl get routerules NAME                    KIND                                    NAMESPACE httpbin-default-v1      RouteRule.v1alpha2.config.istio.io      tutorial httpbin-mirror-v2       RouteRule.v1alpha2.config.istio.io      tutorial

Теперь, если мы начнем отправлять трафик, мы увидим, что запросы идут к v1 а запросы скрываются к v2 .

Видео демо

Вот видео, показывающее это:

Istio Mirroring Демо из христианской посты на Vimeo .

Пожалуйста, ознакомьтесь с официальными документами istio для получения более подробной информации!

Смотрите оригинальную статью здесь: Отслеживание трафика с помощью Istio: снижение риска выпуска кода

Мнения, высказанные участниками Java Code Geeks, являются их собственными.