Использование Istio Multicluster для «Burst» Рабочие нагрузки между кластерами

1. Добро пожаловать

Спасибо, что присоединились к нам в лаборатории кода Istio Multi Cloud Burst от Google. Для этой лаборатории кода требуется начальный практический опыт работы с Kubernetes, Node и Go.

Что вам понадобится

  • Учетная запись Google Cloud Platform (используйте существующие или мы предоставим бесплатные учетные записи)
  • Ваш ноутбук (установите «kubectl», «gcloud» и т. д.) или вы можете использовать Google Cloud Shell.

Что вы узнаете

  • Как создать кластер Kubernetes на GKE
  • Как установить Istio в кластере Kubernetes с помощью Helm
  • Как установить Istio Multicluster с Helm
  • Развертывание веб-приложения из исходного кода в Kubernetes
  • Написание и применение правил маршрутизации трафика в Istio
  • Метрики Прометея
  • Создавайте и отправляйте образы контейнеров внутри кластера Kubernetes.

2. Приступаем к настройке

Вы можете следить за этой кодовой лабораторией либо:

  • Google Cloud Shell (рекомендуется) : оболочка в браузере, поставляется с установленными инструментами.
  • ваш ноутбук (следуйте инструкциям ниже)

Начните с облачной платформы Google

  1. Если у вас нет учетной записи GCP, возьмите у преподавателя бесплатную карту учетной записи пользователя.
  2. Перейдите в Google Cloud Console и нажмите «Выбрать проект»: 5c2d9bf74c78f7e4.png
  3. Запишите где-нибудь «ID» проекта, затем нажмите на проект, чтобы выбрать его: ecc5e8e97bfa6559.png

Cloud Shell предоставляет оболочку командной строки внутри вашего браузера с необходимыми инструментами, установленными и автоматически аутентифицируемыми в вашей учетной записи Google Cloud Platform. (Если вы не хотите выполнять это упражнение в Cloud Shell, перейдите к следующему разделу.)

Перейдите в Cloud Console и нажмите «Активировать Cloud Shell» на верхней правой панели инструментов:

68a17b036ce24ccb.png

Добавьте инструменты в Cloud Shell

  1. Установите kubectx ****: загрузив отсюда сценарии bash в папку $PATH.
  2. Установите helm ****: следуя данной инструкции .

Альтернативно запустите эти команды, чтобы установить оба файла в ~/.bin и добавить их в $PATH:

mkdir -p ~/.bin && \
cd ~/.bin && \
curl -LO https://raw.githubusercontent.com/ahmetb/kubectx/master/kubectx && \
chmod +x kubectx && \
curl -LO https://raw.githubusercontent.com/ahmetb/kubectx/master/kubens && \
chmod +x kubens && \
curl -LO  https://storage.googleapis.com/kubernetes-helm/helm-v2.12.0-linux-amd64.tar.gz && \
tar xzf helm-v2.12.0-linux-amd64.tar.gz && \
rm helm-v2.12.0-linux-amd64.tar.gz && \
mv linux-amd64/helm ./helm && \
rm -r linux-amd64 && \
export PATH=${HOME}/.bin:${PATH}

Несколько простых советов , которые помогут упростить использование Cloud Shell:

1. Отсоедините оболочку в новом окне:

2. Использование редактора файлов: щелкните значок карандаша в правом верхнем углу, чтобы запустить редактор файлов в браузере. Вы найдете это полезным, поскольку мы будем копировать фрагменты кода в файлы.

3. Откройте новые вкладки: если вам нужно несколько подсказок терминала.

4. Увеличьте текст. Размер шрифта по умолчанию в Cloud Shell может быть слишком маленьким для чтения.

Ctrl-+ в Linux/Windows⌘-+ в macOS.

Если вам удобнее использовать собственную среду рабочей станции, чем Cloud Shell, настройте следующие инструменты:

  1. Установите gcloud: (предварительно установлен в Cloud Shell.) Следуйте инструкциям , чтобы установить gcloud на вашу платформу. Мы будем использовать это для создания кластера Kubernetes.
  2. Установите kubectl: (предварительно установлен в Cloud Shell). Для установки выполните следующую команду:
gcloud components install kubectl

Выполните следующую команду для аутентификации gcloud. Он попросит вас войти в свою учетную запись Google. Затем выберите предварительно созданный проект (см. выше) в качестве проекта по умолчанию. (Вы можете пропустить настройку вычислительной зоны):

gcloud init
  1. Установить curl: предустановлен в большинстве систем Linux/macOS. Вероятно, оно у вас уже есть. В противном случае поищите в Интернете, как его установить.
  2. Установите kubectx ****: загрузив отсюда скрипты bash в папку $PATH.
  3. Установите helm ****: следуя данной инструкции .

3. Настройка проекта GCP

Включите API GKE (Google Kubernetes Engine), GCR (Google Container Registry) и GCB (Google Cloud Build) в своем проекте:

gcloud services enable \
  cloudapis.googleapis.com \
  container.googleapis.com \
  containerregistry.googleapis.com \
  cloudbuild.googleapis.com

Настройка переменных среды

Во время установки мы будем активно работать с нашим проектом Google Cloud. Давайте установим переменную среды для быстрого ознакомления.

export GCLOUD_PROJECT=$(gcloud config get-value project)

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

mkdir -p src/istio-burst && \
cd src/istio-burst && \
export proj=$(pwd)

4. Создайте «основной» кластер Kubernetes.

Вы можете легко создать управляемый кластер Kubernetes с помощью Google Kubernetes Engine (GKE) .

Следующая команда создаст кластер Kubernetes:

  • названный «первичным»,
  • в зоне us-west1-a,
  • Доступна последняя версия Kubernetes.
  • с 4 начальными узлами
export cluster=primary
export zone=us-west1-a
gcloud container clusters create $cluster --zone $zone --username "admin" \
--cluster-version latest --machine-type "n1-standard-2" \
--image-type "COS" --disk-size "100" \
--scopes "https://www.googleapis.com/auth/compute",\
"https://www.googleapis.com/auth/devstorage.read_only",\
"https://www.googleapis.com/auth/logging.write",\
"https://www.googleapis.com/auth/monitoring",\
"https://www.googleapis.com/auth/servicecontrol",\
"https://www.googleapis.com/auth/service.management.readonly",\
"https://www.googleapis.com/auth/trace.append" \
--num-nodes "4" --network "default" \
--enable-cloud-logging --enable-cloud-monitoring --enable-ip-alias

(Это может занять около 5 минут. Вы можете наблюдать за созданием кластера в Cloud Console .)

После создания кластера Kubernetes gcloud настраивает kubectl с учетными данными, указывающими на кластер.

gcloud container clusters get-credentials $cluster --zone=$zone

Теперь вы сможете использовать kubectl с новым кластером.

Выполните следующую команду, чтобы получить список узлов Kubernetes вашего кластера (они должны иметь статус «Готово»):

kubectl get nodes

Измените имена Kubeconfig для удобства использования.

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

Эта команда переименует только что созданную запись kubeconfig в primary

kubectx ${cluster}=gke_${GCLOUD_PROJECT}_${zone}_${cluster}

Установите разрешения:

Для развертывания Istio необходимо быть администратором кластера. Эта команда установит адрес электронной почты, связанный с вашей учетной записью Google Cloud, в качестве администратора кластера.

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole=cluster-admin \
    --user=$(gcloud config get-value core/account)

5. Создайте «взрывной» кластер

Следующая команда создаст кластер Kubernetes:

  • названный «взрыв»,
  • в зоне us-west1-a,
  • Доступна последняя версия Kubernetes.
  • С 1 начальным узлом
  • Автомасштабирование включено до 5 узлов
export cluster=burst
export zone=us-west1-a
gcloud container clusters create $cluster --zone $zone --username "admin" \
--cluster-version latest --machine-type "n1-standard-2" \
--image-type "COS" --disk-size "100" \
--scopes "https://www.googleapis.com/auth/compute",\
"https://www.googleapis.com/auth/devstorage.read_only",\
"https://www.googleapis.com/auth/logging.write",\
"https://www.googleapis.com/auth/monitoring",\
"https://www.googleapis.com/auth/servicecontrol",\
"https://www.googleapis.com/auth/service.management.readonly",\
"https://www.googleapis.com/auth/trace.append" \
--num-nodes "1" --enable-autoscaling --min-nodes=1 --max-nodes=5 \
--network "default" \
--enable-cloud-logging --enable-cloud-monitoring --enable-ip-alias

(Это может занять около 5 минут. Вы можете наблюдать за созданием кластера в Cloud Console .)

После создания кластера Kubernetes gcloud настраивает kubectl с учетными данными, указывающими на кластер.

gcloud container clusters get-credentials $cluster --zone=$zone

Теперь вы сможете использовать kubectl с новым кластером.

Выполните следующую команду, чтобы получить список узлов Kubernetes вашего кластера (они должны иметь статус «Готово»):

kubectl get nodes

Измените имена Kubeconfig для удобства использования.

Эта команда изменит запись kubeconfig, которую вы только что сделали, чтобы burst

kubectx ${cluster}=gke_${GCLOUD_PROJECT}_${zone}_${cluster}

Установите разрешения:

Для развертывания Istio Remote вам необходимо быть администратором кластера. Эта команда установит адрес электронной почты, связанный с вашей учетной записью Google Cloud, в качестве администратора кластера.

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole=cluster-admin \
    --user=$(gcloud config get-value core/account)

6. Примените правила брандмауэра

Чтобы наши два кластера могли взаимодействовать друг с другом, нам нужно создать правило брандмауэра.

Выполните следующие команды, чтобы создать правило брандмауэра в Google Cloud Platform, которое позволит нашим кластерам взаимодействовать.

function join_by { local IFS="$1"; shift; echo "$*"; }
ALL_CLUSTER_CIDRS=$(gcloud container clusters list \
--filter="(name=burst OR name=primary) AND zone=$zone" \
--format='value(clusterIpv4Cidr)' | sort | uniq)
ALL_CLUSTER_CIDRS=$(join_by , $(echo "${ALL_CLUSTER_CIDRS}"))
ALL_CLUSTER_NETTAGS=$(gcloud compute instances list \
--filter="(metadata.cluster-name=burst OR metadata.cluster-name=primary) AND metadata.cluster-location=us-west1-a" \
--format='value(tags.items.[0])' | sort | uniq)
ALL_CLUSTER_NETTAGS=$(join_by , $(echo "${ALL_CLUSTER_NETTAGS}"))
gcloud compute firewall-rules create istio-multicluster-test-pods \
  --allow=tcp,udp,icmp,esp,ah,sctp \
  --direction=INGRESS \
  --priority=900 \
  --source-ranges="${ALL_CLUSTER_CIDRS}" \
  --target-tags="${ALL_CLUSTER_NETTAGS}" --quiet

Оба наших кластера настроены и готовы к развертыванию на них нашего приложения и Istio!

7. Знакомство с Istio

Что такое Истио?

Istio — это плоскость управления сервисной сеткой, целью которой является «подключение, защита, контроль и наблюдение за услугами». Это делается разными способами, но в первую очередь путем подключения прокси-контейнера ( Envoy ) к каждому из развернутых модулей Kubernetes. Прокси-контейнер контролирует всю сетевую связь между микросервисами совместно с политикой общего назначения и концентратором телеметрии ( Mixer ).

a25613cd581825da.png

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

Некоторые функции управления трафиком, поддерживаемые Istio:

  • Автоматические выключатели
  • Процентное разделение трафика
  • перезапись URL-адресов
  • Прекращение TLS
  • Проверка здоровья
  • Балансировка нагрузки

В рамках этого семинара мы сосредоточимся на процентном разделении трафика.

Условия Istio, с которыми мы будем работать

виртуальныйсервис

VirtualService определяет набор правил маршрутизации трафика, которые применяются при обращении к хосту.

шлюз

Шлюз — это балансировщик нагрузки, работающий на границе сети, принимающий входящие или исходящие соединения HTTP/TCP. Шлюзы могут указывать порты, конфигурации SNI и т. д.

Правило назначения

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

Истио Мультикластер

Возможно, вы заметили, когда мы создавали два кластера, что наш primary кластер состоял из 4 узлов без автомасштабирования, а burst кластер — из 1 узла с автомасштабированием до 5 узлов.

Есть две причины для такой конфигурации.

Во-первых, мы хотим смоделировать сценарий «локального» перехода в облако. В локальной среде у вас нет доступа к кластерам автоматического масштабирования, поскольку у вас есть фиксированная инфраструктура.

Во-вторых, установка из 4 узлов (как определено выше) — это минимальные требования для запуска Istio. Возникает вопрос: если для Istio требуется минимум 4 узла, как наш burst кластер сможет запускать Istio с 1 узлом? Ответ заключается в том, что Istio Multicluster устанавливает гораздо меньший набор служб Istio и взаимодействует с установкой Istio в основном кластере для получения правил политики и публикации информации телеметрии.

8. Обзор архитектуры приложения

Обзор компонентов

Мы будем развертывать трехуровневое приложение с использованием NodeJS и Redis .

Рабочий

Рабочее приложение написано на NodeJS и будет прослушивать входящие HTTP-запросы POST, выполнять над ними операцию хеширования и, если определена переменная среды с именем PREFIX , оно добавит к хешу это значение. После расчета хеша приложение отправляет результат по каналу « calculation » на указанный сервер Redis.

Позже мы будем использовать переменную среды PREFIX , чтобы продемонстрировать функциональность мультикластера.

Для справки: это пакеты, которые использует приложение.

  • body-parser: позволяет нам анализировать наши http-запросы.
  • cors: позволяет использовать совместное использование ресурсов между источниками.
  • dotenv: простой анализ переменных среды.
  • express: простой хостинг веб-сайтов
  • ioredis: клиентская библиотека для связи с базами данных Redis.
  • morgan: Обеспечивает хороший структурированный журнал.

Внешний интерфейс

Наш интерфейс также представляет собой приложение NodeJS , в котором размещается веб-страница с использованием express . Он принимает введенную пользователем частоту и отправляет запросы нашему worker приложению с этой частотой. Это приложение также подписывается на сообщения на канале Redis под названием « calculation » и отображает результаты на веб-странице.

Приложение использует следующие зависимости.

  • body-parser: позволяет нам анализировать наши http-запросы.
  • dotenv: простой анализ переменных среды.
  • express: простой хостинг веб-сайтов
  • ioredis: клиентская библиотека для связи с базами данных Redis.
  • morgan: предоставляет хорошие структурированные журналы.
  • request: позволяет делать HTTP-запросы.
  • socket.io: обеспечивает двустороннюю связь с веб-страницы на сервер.

Эта веб-страница использует Bootstrap для стилизации и при запуске выглядит следующим образом.

e5e3b9cbede4cac4.png

Схема архитектуры

7ae4bc22a58f80a6.png

Схема развертывания

Мы будем развертывать наше окончательное приложение в двух созданных нами кластерах. primary кластере будут развернуты все компоненты ( frontend , worker и Redis), но в burst кластере будет развернуто только worker приложение.

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

561db37c510944bd.png

Обратите внимание, что в burst кластере по-прежнему развернута служба Redis, хотя в кластере нет развертывания Redis. Нам необходимо иметь эту службу в кластере, чтобы Kubernetes DNS мог разрешить запрос, но когда запрос действительно будет сделан, прокси-сервер Istio перенаправит запрос на развертывание Redis в primary кластере.

В конечном приложении будет выполняться дополнительное развертывание в primary кластере с именем istiowatcher. Это то, что позволит нам динамически перенаправлять трафик в burst автоматически, когда наш трафик превысит определенный порог.

8f6183bdfc3f813c.png

9. Создайте файлы развертывания приложения.

Нам нужно создать набор манифестов Kubernetes для развертывания нашего приложения.

Перейдите в корневой каталог проекта и создайте новую папку с именем kubernetes

mkdir ${proj}/kubernetes && cd ${proj}/kubernetes

Напишите frontend.yaml

Это создаст как развертывание Kubernetes, так и службу для доступа к нашему внешнему образу.

Вставьте следующее в frontend.yaml .

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: frontend-deployment
  labels:
    app: frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - name: frontend
        image: gcr.io/istio-burst-workshop/frontend
        ports:
        - containerPort: 8080
        readinessProbe:
            initialDelaySeconds: 10
            httpGet:
              path: "/_healthz"
              port: 8080
              httpHeaders:
              - name: "Cookie"
                value: "istio_session-id=x-readiness-probe"
        livenessProbe:
          initialDelaySeconds: 10
          httpGet:
            path: "/"
            port: 8080
            httpHeaders:
            - name: "Cookie"
              value: "istio_session-id=x-liveness-probe"
        env:
        - name: PORT
          value: "8080"
        - name: PROCESSOR_URL
          value: "http://worker-service"
        - name: REDIS_URL
          value: "redis-cache-service:6379"
---
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
spec:
  type: ClusterIP
  selector:
    app: frontend
  ports:
  - name: http
    port: 80
    targetPort: 8080

Ключевые моменты, на которые следует обратить внимание при Deployment

  • Мы указали порт, на котором будет работать приложение, — 8080
  • Мы установили адрес работника « http://worker-service » и будем использовать встроенную функцию DNS Kubernetes для разрешения полученного сервиса.
  • Мы установили адрес для нашего REDIS_URL как « redis-cache-service:6379 » и будем использовать встроенную функцию DNS Kubernetes для разрешения полученных IP-адресов.
  • Мы также установили для контейнера проверки liveness и readiness , чтобы информировать Kubernetes о том, что контейнер запущен и работает.

Напишите worker-service.yaml

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

Вставьте следующее в worker-service.yaml

apiVersion: v1
kind: Service
metadata:
 name: worker-service
spec:
 type: ClusterIP
 selector:
   app: worker
 ports:
 - name: http
   port: 80
   targetPort: 8081

Напишите файл worker-primary.yaml.

Это будет развертывание worker , который мы отправим в основной кластер.

Вставьте следующее в worker-primary.yaml .

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: worker-deployment
 labels:
   app: worker
spec:
 replicas: 1
 selector:
   matchLabels:
     app: worker
 template:
   metadata:
     labels:
       app: worker
       cluster-type: primary-cluster
   spec:
     containers:
     - name: worker
       image: gcr.io/istio-burst-workshop/worker
       imagePullPolicy: Always
       ports:
       - containerPort: 8081
       readinessProbe:
           initialDelaySeconds: 10
           httpGet:
             path: "/_healthz"
             port: 8081
             httpHeaders:
             - name: "Cookie"
               value: "istio_session-id=x-readiness-probe"
       livenessProbe:
         initialDelaySeconds: 10
         httpGet:
           path: "/"
           port: 8081
           httpHeaders:
           - name: "Cookie"
             value: "istio_session-id=x-liveness-probe"
       env:
       - name: PORT
         value: "8081"
       - name: REDIS_URL
         value: "redis-cache-service:6379"

Обратите внимание, что при этом мы следуем той же схеме предоставления тестов liveness и readiness , а также указания переменных среды PORT и REDIS_URL для использования нашим приложением.

Еще одна вещь, на которую следует обратить внимание в этом развертывании, — это отсутствие переменной среды PREFIX . Это означает, что результаты наших вычислений будут представлять собой необработанные хеши (без префиксов).

Последним ключевым моментом этого развертывания является метка cluster-type: primary-cluster . Мы будем использовать это позже, когда будем выполнять маршрутизацию трафика в Istio Multicluster.

Напишите redis.yaml

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

Вставьте следующее в redis.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: redis-cache
spec:
 template:
   metadata:
     labels:
       app: redis-cache
   spec:
     containers:
     - name: redis
       image: redis:alpine
       ports:
       - containerPort: 6379
       readinessProbe:
         periodSeconds: 5
         tcpSocket:
           port: 6379
       livenessProbe:
         periodSeconds: 5
         tcpSocket:
           port: 6379
       volumeMounts:
       - mountPath: /data
         name: redis-data
       resources:
         limits:
           memory: 256Mi
           cpu: 125m
         requests:
           cpu: 70m
           memory: 200Mi
     volumes:
     - name: redis-data
       emptyDir: {}

Это полустандартное развертывание приложения Redis. Он поддерживает контейнер на основе образа redis:alpine , предоставляет соответствующие порты и устанавливает разумные ограничения ресурсов.

Напишите redis-service.yaml

Нам нужна служба Kubernetes для связи с нашим приложением Redis.

Вставьте следующее в redis-service.yaml

apiVersion: v1
kind: Service
metadata:
 name: redis-cache-service
spec:
 type: ClusterIP
 selector:
   app: redis-cache
 ports:
 - port: 6379
   targetPort: 6379

Это предоставляет службу с именем redis-cache-service для доступа к нашему развертыванию Redis.

10. Развертывание приложения

Когда наши образы отправлены в GCR и написаны манифесты Kubernetes, это хороший момент для развертывания нашего приложения и просмотра того, как оно работает!

Выполните следующие команды для развертывания приложения

  1. Убедитесь, что мы находимся в правильном кластере
kubectx primary
  1. Развертывание кэша Redis
kubectl apply -f redis.yaml
  1. Развертывание службы Redis
kubectl apply -f redis-service.yaml
  1. Развертывание интерфейса
kubectl apply -f frontend.yaml
  1. Развернуть работника
kubectl apply -f worker-primary.yaml
  1. Развертывание рабочей службы
kubectl apply -f worker-service.yaml

Мы развернули наше приложение в GKE. Поздравляю!

Тест

Подождите, пока капсулы появятся в сети.

kubectl get pods -w

Как только все модули будут запущены, нажмите Ctrl + C.

NAME                                   READY     STATUS    RESTARTS   AGE
frontend-deployment-695d95fbf7-76sd8   1/1       Running   0          2m
redis-cache-7475999bf5-nxj8x           1/1       Running   0          2m
worker-deployment-5b9cf9956d-g975p     1/1       Running   0          2m

Вы заметите, что мы не предоставили доступ к нашему интерфейсу через LoadBalancer. Это потому, что позже мы будем получать доступ к приложению через Istio. Чтобы проверить, что все работает, мы воспользуемся kubectl port-forward. Выполните следующую команду, чтобы перенаправить порт 8080 на локальном компьютере (или компьютере Cloud Shell) на порт 8080, на котором выполняется frontend развертывание.

kubectl port-forward \
$(kubectl get pods -l app=frontend -o jsonpath='{.items[0].metadata.name}') \
8080:8080

Если вы работаете локально : откройте веб-браузер и перейдите по адресу http://localhost:8080.

Если вы работаете в Cloud Shell: нажмите кнопку «Предварительный просмотр в Интернете» и выберите «Предварительный просмотр на порту 8080».

bdb5dc75f415be11.png

Вы должны видеть интерфейс! И если вы введете число в поле «частота», вы увидите, как начнут появляться хеши.

1caafaffab26897a.png

Поздравляю; все в порядке!

Нажмите Ctrl+C , чтобы остановить переадресацию порта.

11. Очистка развернутого приложения

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

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

  1. Удалить redis-cache-service
kubectl delete -f redis-service.yaml
  1. Удалить redis
kubectl delete -f redis.yaml
  1. Удалить frontend
kubectl delete -f frontend.yaml
  1. Удалить worker
kubectl delete -f worker-primary.yaml
  1. Удалить worker-service
kubectl delete -f worker-service.yaml

12. Установите Istio в основной кластер.

Получить Истио

Релизы Istio размещаются на GitHub. Следующие команды загрузят версию istio 1.0.0 и распакуют ее.

  1. Перейдите в корень вашего проекта
cd ${proj}
  1. Скачать архив
curl -LO https://github.com/istio/istio/releases/download/1.0.0/istio-1.0.0-linux.tar.gz
  1. Распакуйте и удалите архив
tar xzf istio-1.0.0-linux.tar.gz && rm istio-1.0.0-linux.tar.gz

Создать шаблон Istio

Выполнение следующей команды Helm создаст шаблон для установки Istio в ваш кластер.

helm template istio-1.0.0/install/kubernetes/helm/istio \
--name istio --namespace istio-system \
--set prometheus.enabled=true \
--set servicegraph.enabled=true  > istio-primary.yaml

В результате в вашем текущем каталоге будет создан файл с именем istio-primary.yaml , содержащий все определения и спецификации, необходимые для развертывания и запуска Istio.

Обратите внимание на два параметра --set . Они добавляют поддержку Prometheus и ServiceGraph в систему Istio. Позже в лабораторной работе мы будем использовать сервис Prometheus.

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

Чтобы развернуть istio, нам сначала нужно создать пространство имен под названием istio-system , в котором могут работать развертывания и службы Istio.

kubectl create namespace istio-system

И, наконец, примените файл istio-primary.yaml , который мы создали с помощью Helm.

kubectl apply -f istio-primary.yaml

Метка пространства имен по умолчанию

Istio работает путем внедрения дополнительной прокси-службы в каждое из ваших развертываний. Это делается по согласию, поэтому нам нужно пометить наше пространство имен default с помощью istio-injection=enabled чтобы Istio мог автоматически внедрить для нас сайдкар.

kubectl label namespace default istio-injection=enabled

Поздравляю! У нас есть работающий кластер с Istio, готовый к развертыванию нашего приложения!

13. Разверните наше приложение с помощью Istio Traffic Management.

Создание файлов конфигурации управления трафиком Istio

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

Создайте каталог с именем istio-manifests и перейдите в него.

mkdir ${proj}/istio-manifests && cd ${proj}/istio-manifests

Напишите frontend-gateway.yaml

Этот файл предоставит доступ к нашему кластеру Kubernetes аналогично GKE LoadBalancer и направит весь входящий трафик в нашу интерфейсную службу.

Создайте файл с именем frontend-gateway.yaml и вставьте следующее.

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
 name: frontend-gateway
spec:
 selector:
   istio: ingressgateway # use Istio default gateway implementation
 servers:
 - port:
     number: 80
     name: http
     protocol: HTTP
   hosts:
   - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: frontend-ingress-virtual-service
spec:
 hosts:
 - "*"
 gateways:
 - frontend-gateway
 http:
 - route:
   - destination:
       host: frontend-service
       port:
         number: 80

Напишите redis-virtualservice.yaml.

Создайте файл с именем redis-virtualservice.yaml и вставьте следующее

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: redis-virtual-service
spec:
 hosts:
 - redis-cache-service
 gateways:
 - mesh
 tcp:
 - route:
   - destination:
       host: redis-cache-service.default.svc.cluster.local

Напишите файл worker-virtualservice.yaml.

Создайте файл с именем worker-virtualservice.yaml и вставьте следующее

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: worker-virtual-service
spec:
 hosts:
 - worker-service
 gateways:
 - mesh
 http:
 - route:
   - destination:
       host: worker-service.default.svc.cluster.local   
       port:
         number: 80

Развертывание политик управления трафиком Istio

Развертывание политик Istio выполняется так же, как и других ресурсов Kubernetes, с kubectl apply

  1. Примените наш шлюз
kubectl apply -f frontend-gateway.yaml
  1. Примените наш Redis VirtualService
kubectl apply -f redis-virtualservice.yaml
  1. Примените наш Worker VirtualService
kubectl apply -f worker-virtualservice.yaml

Развернуть приложение

  1. Вернитесь в наш каталог kubernetes .
cd ${proj}/kubernetes
  1. Развертывание кэша Redis
kubectl apply -f redis.yaml
  1. Развертывание службы Redis
kubectl apply -f redis-service.yaml
  1. Развертывание внешнего интерфейса
kubectl apply -f frontend.yaml
  1. Развернуть работника
kubectl apply -f worker-primary.yaml
  1. Развертывание рабочей службы
kubectl apply -f worker-service.yaml

Проверять

На этом этапе мы повторно развернули наше приложение в кластере с помощью Istio и политик управления трафиком.

Давайте подождем, пока все наши рабочие нагрузки будут переведены в онлайн.

Как только они все будут подключены к сети, получите IngressGateway, который мы настроили в frontend-ingressgateway.yaml

$ kubectl -n istio-system get svc istio-ingressgateway
NAME                   TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)                                                                                                     AGE
istio-ingressgateway   LoadBalancer   10.36.3.112   35.199.158.10   80:31380/TCP,

Либо перейдите по адресу <EXTERNAL-IP>, либо сверните его, и вы должны увидеть интерфейс!

$ curl 35.199.158.10
<!doctype html>
<html>

<head>
    <title>String Hashr</title>
    <!-- Bootstrap -->
...

14. Установите Istio на «взрывной» кластер.

Мы потратили много времени на настройку и развертывание нашего primary кластера, но нам нужно развернуть целый другой кластер!

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

Создайте удаленный манифест Istio.

Как и в случае с развертыванием Istio в primary кластере, мы собираемся использовать Helm для шаблонирования развертывания удаленного istio в burst кластере. Однако прежде чем мы сможем это сделать, нам нужно получить некоторую информацию о нашем primary кластере.

Сбор первичной информации о кластере

Перейти на primary кластер

kubectx primary

Следующие команды получают IP-адреса различных модулей в основном кластере. Они используются Istio Remote для обратной связи с основным кластером.

export PILOT_POD_IP=$(kubectl -n istio-system get pod -l istio=pilot -o jsonpath='{.items[0].status.podIP}')
export POLICY_POD_IP=$(kubectl -n istio-system get pod -l istio-mixer-type=policy -o jsonpath='{.items[0].status.podIP}')
export STATSD_POD_IP=$(kubectl -n istio-system get pod -l istio=statsd-prom-bridge -o jsonpath='{.items[0].status.podIP}')
export TELEMETRY_POD_IP=$(kubectl -n istio-system get pod -l istio-mixer-type=telemetry -o jsonpath='{.items[0].status.podIP}')
export ZIPKIN_POD_IP=$(kubectl -n istio-system get pod -l app=jaeger -o jsonpath='{range .items[*]}{.status.podIP}{end}')

Создать удаленный шаблон

Теперь мы воспользуемся helm для создания файла с именем istio-remote-burst.yaml который затем можно будет развернуть в burst кластере.

Перейти в корень проекта

cd $proj
helm template istio-1.0.0/install/kubernetes/helm/istio-remote --namespace istio-system \
--name istio-remote \
--set global.remotePilotAddress=${PILOT_POD_IP} \
--set global.remotePolicyAddress=${POLICY_POD_IP} \
--set global.remoteTelemetryAddress=${TELEMETRY_POD_IP} \
--set global.proxy.envoyStatsd.enabled=true \
--set global.proxy.envoyStatsd.host=${STATSD_POD_IP} \
--set global.remoteZipkinAddress=${ZIPKIN_POD_IP} > istio-remote-burst.yaml

Установите Istio Remote в кластере Burst

Чтобы установить Istio в нашем burst кластере, нам нужно выполнить те же действия, что и при установке в primary кластере, но вместо этого нам нужно использовать файл istio-remote-burst.yaml .

Измените kubecontext на взрыв

kubectx burst

Создать пространство имен isio-system

kubectl create ns istio-system

Примените istio-burst.yaml

kubectl apply -f istio-remote-burst.yaml

Метка пространства имен по умолчанию

Еще раз нам нужно пометить пространство имен default , чтобы прокси можно было автоматически внедрить.

kubectl label namespace default istio-injection=enabled

Поздравляю! На этом этапе мы настроили Istio Remote в burst кластере. Однако на данный момент кластеры все еще не могут обмениваться данными. Нам нужно создать файл kubeconfig для burst кластера, который мы можем развернуть в primary кластере, чтобы связать их вместе.

Создайте kubeconfig для «пакетного» кластера.

Переход на пакетный кластер

kubectx burst

Настройка среды

Нам нужно собрать некоторую информацию о кластере, чтобы создать для него файл kubeconfig .

  1. Получить имя кластера
CLUSTER_NAME=$(kubectl config view --minify=true -o "jsonpath={.clusters[].name}")
  1. Получить имя сервера кластера
SERVER=$(kubectl config view --minify=true -o "jsonpath={.clusters[].cluster.server}")
  1. Получите имя секрета для центра сертификации учетной записи службы istio-multi
SECRET_NAME=$(kubectl get sa istio-multi -n istio-system -o jsonpath='{.secrets[].name}')
  1. Получите данные центра сертификации, хранящиеся в предыдущем секрете.
CA_DATA=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['ca\.crt']}")
  1. Получите токен, хранящийся в предыдущем секрете
TOKEN=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['token']}" | base64 --decode)

Создать файл кубеконфигурации

Установив все эти переменные среды, нам нужно создать файл kubeconfig.

cat <<EOF > burst-kubeconfig
apiVersion: v1
clusters:
   - cluster:
       certificate-authority-data: ${CA_DATA}
       server: ${SERVER}
     name: ${CLUSTER_NAME}
contexts:
   - context:
       cluster: ${CLUSTER_NAME}
       user: ${CLUSTER_NAME}
     name: ${CLUSTER_NAME}
current-context: ${CLUSTER_NAME}
kind: Config
preferences: {}
users:
   - name: ${CLUSTER_NAME}
     user:
       token: ${TOKEN}
EOF

В результате в вашем текущем каталоге появится новый файл с именем burst-kubeconfig который может использоваться primary кластером для аутентификации и управления burst кластером.

Вернитесь к основному кластеру

kubectx primary

Примените kubeconfig для «burst», создав секрет и пометив его.

kubectl create secret generic burst-kubeconfig --from-file burst-kubeconfig -n istio-system

Пометьте секрет, чтобы Istio мог использовать его для мультикластерной аутентификации.

kubectl label secret burst-kubeconfig istio/multiCluster=true -n istio-system

Поздравляю! У нас есть оба кластера, аутентифицированные и взаимодействующие друг с другом через Istio Multicluster. Давайте развернем наше приложение Cross-Cluster.

15. Развертывание межкластерного приложения

Создание развертываний

Перейдите в каталог kubernetes .

cd ${proj}/kubernetes

Создайте рабочее развертывание для «пакетного» кластера: worker-burst.yaml.

Создайте файл с именем worker-burst.yaml и вставьте в него следующее:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: worker-deployment
  labels:
    app: worker
spec:
  replicas: 1
  selector:
    matchLabels:
      app: worker
  template:
    metadata:
      labels:
        app: worker
        cluster-type: burst-cluster
    spec:
      containers:
      - name: worker
        image: gcr.io/istio-burst-workshop/worker
        imagePullPolicy: Always
        ports:
        - containerPort: 8081
        readinessProbe:
            initialDelaySeconds: 10
            httpGet:
              path: "/_healthz"
              port: 8081
              httpHeaders:
              - name: "Cookie"
                value: "istio_session-id=x-readiness-probe"
        livenessProbe:
          initialDelaySeconds: 10
          httpGet:
            path: "/"
            port: 8081
            httpHeaders:
            - name: "Cookie"
              value: "istio_session-id=x-liveness-probe"
        env:
        - name: PORT
          value: "8081"
        - name: REDIS_URL
          value: "redis-cache-service:6379"
        - name: PREFIX
          value: "bursty-"

Обратите внимание, что он почти идентичен файлу worker-primary.yaml, который мы создали ранее. Есть два ключевых различия.

Первое ключевое отличие заключается в том, что мы добавили переменную среды PREFIX со значением " bursty- ".

env:
- name: PORT
  value: "8081"
- name: REDIS_URL
  value: "redis-cache-service:6379"
- name: PREFIX
  value: "bursty-"

Это означает, что наш исполнитель в burst кластере будет префиксом всех отправляемых хэшей « bursty- ». Мы можем использовать это, чтобы знать, что наше приложение действительно является межкластерным.

Второе ключевое отличие заключается в том, что мы изменили метку cluster-type в этом развертывании с primary-cluster на burst-cluster

labels:
  app: worker
  cluster-type: burst-cluster

Мы будем использовать эту метку позже, когда будем обновлять наш VirtualService.

Изменить службы Istio

В настоящее время наши службы Istio не используют преимущества обоих наших развертываний. 100% нашего трафика направляется в «основной» кластер. Давайте изменим это.

Перейдите в наш каталог istio-manifests

cd ${proj}/istio-manifests

Отредактируйте файл worker-virtualservice.yaml, включив в него DestinationRules.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: worker-virtual-service
spec:
  hosts:
  - worker-service
  gateways:
  - mesh
  http:
  - route:
    - destination:
        host: worker-service.default.svc.cluster.local    
        subset: primary
        port:
          number: 80        
      weight: 50
    - destination:
        host: worker-service.default.svc.cluster.local     
        subset: burst  
        port:
          number: 80        
      weight: 50
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: worker-destination-rule
spec:
  host: worker-service
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
  subsets:
  - name: primary
    labels:
      cluster-type: primary-cluster
  - name: burst
    labels:
     cluster-type: burst-cluster

Как видите, мы добавили второй пункт назначения в наш VirtualService. Он по-прежнему ссылается на тот же хост ( worker-service.default.svc.cluster.local) , но 50 % трафика направляется в primary подмножество, а остальные 50 % — в burst подмножество.

Мы определили primary подмножество как развертывания с меткой cluster-type: primary-cluster , а burst подмножество — это развертывания с меткой cluster-type: burst-cluster .

Это эффективно разделяет наш трафик 50/50 между двумя кластерами.

Развертывание в кластере

Развертывание redis-service.yaml для развертывания кластера

Переход на burst kubeconfig

kubectx burst

Перейдите в корень нашего проекта

cd ${proj}

Затем разверните

Разверните redis-service.yaml в пакетном кластере.

kubectl apply -f kubernetes/redis-service.yaml

Разверните файл worker-burst.yaml в пакетном кластере.

kubectl apply -f kubernetes/worker-burst.yaml

Разверните файл worker-service.yaml в пакетном кластере.

kubectl apply -f kubernetes/worker-service.yaml

Применить Istio VirtualServices

Перейти к primary kubeconfig

kubectx primary

Затем разверните

kubectl apply -f istio-manifests/worker-virtualservice.yaml

Убедитесь, что это работает

Чтобы убедиться, что это работает, перейдите к своей точке входа Istio и обратите внимание, что около 50% хэшей имеют префикс «burst-».

78fb6e235e9f4a07.png

Это означает, что мы успешно говорим о перекрестном кластере! Попробуйте изменить веса различных сервисов и применить файл worker-virtualservice.yaml . Это отличный способ сбалансировать трафик между кластерами, но что, если мы сможем делать это автоматически?

16. Использование метрик Prometheus

Введение в Прометей

Prometheus — это набор инструментов для мониторинга и оповещения систем с открытым исходным кодом, изначально созданный в SoundCloud. Он поддерживает многомерную модель данных с данными временных рядов, идентифицируемыми по имени метрики и парам ключ/значение.

Для справки, вот диаграмма архитектуры Prometheus:

601e1155a825e0c2.png

Istio при развертывании с Prometheus автоматически передает различные показатели на сервер Prometheus. Мы можем использовать эти метрики для оперативного управления нашими кластерами.

Изучение наших показателей Prometheus

Для начала нам нужно раскрыть развертывание Prometheus.

Перейдите на вкладку «Рабочие нагрузки» в GKE и перейдите к рабочей нагрузке «Прометей».

b4a7a3cd67db05b3.png

Просмотрев сведения о развертывании, перейдите в «Действия» -> «Выставить».

c04a482e55bdfd41.png

Выберите переадресацию на порт 9090 и введите «Балансировщик нагрузки».

d5af3ba22a7a6ebb.png

И выберите «Разоблачить»

Это создаст Сервис на общедоступном IP-адресе, который мы сможем использовать для изучения наших показателей Prometheus.

Подождите, пока конечная точка станет работоспособной, и после этого щелкните IP-адрес рядом с «Внешние конечные точки». b1e40ad90851da29.png

Теперь вы должны увидеть пользовательский интерфейс Prometheus.

ed273552270337ec.png

Prometheus предоставляет достаточно метрик, чтобы стать его собственной мастерской. Однако сейчас мы начнем с изучения метрики istio_requests_total .

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

Запросы, в которых целевой службой является worker-service.default.svc.cluster.local , а источником является frontend-deployment ограниченный последними 15 секундами.

Этот запрос выглядит так:

istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s]

И дает нам гораздо более управляемый набор данных для работы.

19d551fd5eac3785.png

Но все равно немного густоват. Мы хотим знать количество запросов в секунду, а не все запросы.

Чтобы получить это, мы можем использовать встроенную функцию rate

rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])

dbb9dc063a18da9b.png

Это приближает нас, но нам нужно еще немного свести эти показатели в логическую группу.

Для этого мы можем использовать sum и by слова для группировки и суммирования наших результатов.

sum(rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])) by (source_workload,
source_app, destination_service)

898519966930ec56.png

Идеальный! Мы можем получить от Prometheus точные метрики, которые нам нужны.

Наш последний запрос к Прометею

После всего, что мы узнали, последний вопрос, который нам нужно задать Прометею:

sum(rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])) by (source_workload,
source_app, destination_service)

Теперь мы можем использовать их HTTP API для получения метрики.

Мы можем запросить их API с помощью нашего запроса, выполнив такой HTTP-запрос GET. Замените <прометей-ip-здесь>

curl http://<prometheus-ip-here>/api/v1/query?query=sum\(rate\(istio_requests_total%7Breporter%3D%22destination%22%2C%0Adestination_service%3D%22worker-service.default.svc.cluster.local%22%2C%0Asource_workload%3D%22frontend-deployment%22%7D%5B15s%5D\)\)%20by%20\(source_workload%2C%0Asource_app%2C%20destination_service\)

Вот пример ответа:

{
    "status": "success",
    "data": {
        "resultType": "vector",
        "result": [
            {
                "metric": {
                    "destination_service": "worker-service.default.svc.cluster.local",
                    "source_app": "frontend",
                    "source_workload": "frontend-deployment"
                },
                "value": [
                    1544404907.503,
                    "18.892886390062788"
                ]
            }
        ]
    }
}

Теперь мы можем извлечь значение нашей метрики из JSON.

Очистка

Нам нужно удалить Службу, которую мы только что использовали, чтобы разоблачить Прометея. В Google Cloud Console перейдите в верхнюю часть только что созданного сервиса и нажмите «Удалить».

d58cb51b4c922751.png

Следующие шаги:

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

17. Создайте перекрестный кластерный всплеск

Настраивать

Установите весь трафик для рабочей службы в основной кластер.

Мы будем считать, что весь трафик, предназначенный для worker-service , направляемый в primary кластер, является состоянием «по умолчанию» нашего приложения.

Отредактируйте файл $proj/istio-manifests/worker-virtualservice.yaml чтобы он выглядел следующим образом.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: worker-virtual-service
spec:
  hosts:
  - worker-service
  gateways:
  - mesh
  http:
  - route:
    - destination:
        host: worker-service.default.svc.cluster.local    
        subset: primary
        port:
          number: 80        
      weight: 100
    - destination:
        host: worker-service.default.svc.cluster.local     
        subset: burst  
        port:
          number: 80        
      weight: 0
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: worker-destination-rule
spec:
  host: worker-service
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
  subsets:
  - name: primary
    labels:
      cluster-type: primary-cluster
  - name: burst
    labels:
     cluster-type: burst-cluster

Убедитесь, что вы подключены к primary кластеру.

kubectx primary

Примените istio-manifests/worker-virtualservice.yaml.

kubectl apply -f istio-manifests/worker-virtualservice.yaml

Написать демон istiowatcher

Для написания этого сервиса мы будем использовать Go из-за его скорости и портативности. Общий поток работы приложения будет заключаться в запуске и ежесекундном запросе Prometheus,

Создайте новый каталог в src с именем istiowatcher.

mkdir -p ${proj}/src/istiowatcher && cd ${proj}/src/istiowatcher

Мы будем вызывать istioctl из нашего контейнера, чтобы управлять плоскостью управления Istio изнутри кластера.

Напишите istiowatcher.go

Создайте в этом каталоге файл с именем istiowatcher.go и вставьте в него следующее:

package main

import (
        "github.com/tidwall/gjson"
        "io/ioutil"
        "log"
        "net/http"
        "os/exec"
        "time"
)

func main() {
        //These are in requests per second
        var targetLow float64 = 10
        var targetHigh float64 = 15
        // This is for the ticker in milliseconds
        ticker := time.NewTicker(1000 * time.Millisecond)

        isBurst := false

        // Our prometheus query
        reqQuery := `/api/v1/query?query=sum(rate(istio_requests_total{reporter="destination",destination_service="worker-service.default.svc.cluster.local",source_workload="frontend-deployment"}[15s]))by(source_workload,source_app,destination_service)`

        for t := range ticker.C {
                log.Printf("Checking Prometheus at %v", t)

                // Check prometheus
                // Note that b/c we are querying over the past 5 minutes, we are getting a very SLOW ramp of our reqs/second
                // If we wanted this to be a little "snappier" we can scale it down to say 30s
                resp, err := http.Get("http://prometheus.istio-system.svc.cluster.local:9090" + reqQuery)
                if err != nil {
                        log.Printf("Error: %v", err)
                        continue
                }
                defer resp.Body.Close()
                body, _ := ioutil.ReadAll(resp.Body)

                val := gjson.Get(string(body), "data.result.0.value.1")
                log.Printf("Value: %v", val)

                currentReqPerSecond := val.Float()
                log.Printf("Reqs per second %f", currentReqPerSecond)

                if currentReqPerSecond > targetHigh && !isBurst {
                        applyIstio("burst.yaml")
                        log.Println("Entering burst mode")
                        isBurst = true
                } else if currentReqPerSecond < targetLow && isBurst {
                        applyIstio("natural.yaml")
                        log.Println("Returning to natural state.")
                        isBurst = false
                }
        }
}

func applyIstio(filename string) {
        cmd := exec.Command("istioctl", "replace", "-f", filename)
        if err := cmd.Run(); err != nil {
                log.Printf("Error hit applying istio manifests: %v", err)
        }
}

Написать Docker-файл

Создайте новый файл с именем Dockerfile и вставьте в него следующее.

FROM golang:1.11.2-stretch as base

FROM base as builder

WORKDIR /workdir
RUN curl -LO https://github.com/istio/istio/releases/download/1.0.0/istio-1.0.0-linux.tar.gz
RUN tar xzf istio-1.0.0-linux.tar.gz
RUN cp istio-1.0.0/bin/istioctl ./istioctl

FROM base 

WORKDIR /go/src/istiowatcher
COPY . .
COPY --from=builder /workdir/istioctl /usr/local/bin/istioctl

RUN go get -d -v ./...
RUN go install -v ./...

CMD ["istiowatcher"]

Этот многоэтапный файл Dockerfile на первом этапе загружает и извлекает версию Istio 1.0.0. На втором этапе копируется все из нашего каталога в образ, затем копируется istioctl со стадии сборки в /usr/local/bin (чтобы его могло вызывать наше приложение), получает зависимости, компилирует код и устанавливает CMD как " istiowatcher "

Напишите взрыв.yaml

Это файл, который istiowatcher будет применять, когда количество запросов в секунду к worker из frontend превышает 15.

Создайте новый файл с именем burst.yaml и вставьте в него следующее.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: worker-virtual-service
spec:
 hosts:
 - worker-service
 gateways:
 - mesh
 http:
 - route:
   - destination:
       host: worker-service.default.svc.cluster.local   
       subset: primary
       port:
         number: 80       
     weight: 0
   - destination:
       host: worker-service.default.svc.cluster.local    
       subset: burst 
       port:
         number: 80       
     weight:  100

Напишите natural.yaml

Мы будем считать это «естественным» состоянием, в которое мы возвращаемся, когда количество запросов в секунду от frontend к worker падает ниже 10. В этом состоянии 100% трафика направляется в primary кластер.

Создайте новый файл с именем natural.yaml и вставьте в него следующее:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: worker-virtual-service
spec:
 hosts:
 - worker-service
 gateways:
 - mesh
 http:
 - route:
   - destination:
       host: worker-service.default.svc.cluster.local   
       subset: primary
       port:
         number: 80       
     weight: 100
   - destination:
       host: worker-service.default.svc.cluster.local    
       subset: burst 
       port:
         number: 80       
     weight: 0

Сборка и публикация istiowatcher

Выполните следующую команду, чтобы отправить текущий каталог в Google Could Build (GCB), который создаст изображение и пометит его в GCR.

gcloud builds submit -t gcr.io/${GCLOUD_PROJECT}/istiowatcher

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

Перейдите в наш каталог kubernetes .

cd ${proj}/kubernetes/

Напишите файл развертывания: istiowatcher.yaml.

Создайте файл с именем istiowatcher.yaml и вставьте следующее (замените <your-project-id>).

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: istiowatcher-deployment
  labels:
    app: istiowatcher
spec:
  replicas: 1
  selector:
    matchLabels:
      app: istiowatcher
  template:
    metadata:
      labels:
        app: istiowatcher
    spec:
      serviceAccountName: istio-pilot-service-account
      automountServiceAccountToken: true
      containers:
      - name: istiowatcher
        image: gcr.io/<your-project-id>/istiowatcher
        imagePullPolicy: Always

Развертывать

Убедитесь, что мы работаем в основном кластере

kubectx primary

Разверните istiowatcher.yaml в пространстве имен istio-system .

kubectl apply -n istio-system -f istiowatcher.yaml

Важно отметить директивы serviceAccountName и automountServiceAccountToken в файле yaml. Это дает нам учетные данные, необходимые для запуска istioctl из кластера.

Нам также необходимо развернуть это в пространстве имен istio-system чтобы гарантировать, что у нас есть учетные данные для istio-pilot-service-account . (его не существует в пространстве имен default ).

Наблюдайте за автоматическим переключением трафика!

А теперь волшебный момент! Давайте перейдем к нашему интерфейсу и увеличим требование в секунду до 20.

Обратите внимание, что это занимает несколько секунд, но потом оно увеличивается, и все наши хэши имеют префикс «bursty-»!

Это связано с тем, что мы отбираем данные Prometheus в диапазоне 15s , из-за чего время отклика немного запаздывает. Если бы мы хотели более узкую полосу, мы могли бы изменить наш запрос на Прометей, чтобы он был 5s.

18. Что дальше?

Очистка

Вам не нужно выполнять очистку, если вы используете временную учетную запись, предоставленную для этого семинара.

Вы можете удалить кластеры Kubernetes, правило брандмауэра и образы в GCR.

gcloud container clusters delete primary --zone=us-west1-a
gcloud container clusters delete burst --zone=us-west1-a
gcloud compute firewall-rules delete istio-multicluster-test-pods 
gcloud container images delete gcr.io/$GCLOUD_PROJECT/istiowatcher

Идем вперед