И снова здравствуйте! Я – Евгений Симигин, занимаюсь внедрением DevOps-практик в Центре компетенций по разработке облачных и интернет-решений МТС Digital. Как я и обещал – это вторая часть нашего обзора Argo Rollouts, из которой вы узнаете о том, как в процессе выкатки нового релиза организовать еще и тестирование. Первая часть статьи – по ссылке.

Рассмотренные в первой половине статьи механизмы послужат нам существенным подспорьем, однако итоговое решение – прошло все успешно или нет – принимается на основе звонков от разгневанных пользователей алертов от системы мониторинга. Тут на помощь нам спешат analysis и experiments.Они позволят вклиниться в шаги выкатки и выставить критерии для принятия решения: идем мы дальше или откатываем ревизию.
Прежде всего мы задаем «правила игры» – то, что мы будем анализировать и критерии «что такое хорошо, что такое плохо». Для этого служат AnalysisTemplate ClusterAnalysisTemplate
apiVersion: argoproj.io/v1alpha1 kind: AnalysisTemplate metadata: name: error-rate spec: args: - name: service-name - name: api-token valueFrom: secretKeyRef: name: token-secret key: apiToken - name: api-url value: http://example/measure - name: host metrics: - name: error-rate interval: 5m successCondition: result[0] <= 0.95 failureLimit: 3 provider: prometheus: address: http://prometheus.example.com:9090 query: | sum(irate( istio_requests_total{reporter="source",destination_service=~"{{args.service-name}}",response_code=~"5.*"}[5m] )) / sum(irate( istio_requests_total{reporter="source",destination_service=~"{{args.service-name}}"}[5m] )) - name: webmetric successCondition: result == 'true' provider: web: # placeholders are resolved when an AnalysisRun is created url: "{{ args.api-url }}?service={{ args.service-name }}" headers: - key: Authorization value: "Bearer {{ args.api-token }}" jsonPath: "{$.results.ok}" - name: http-benchmark failureLimit: 100 interval: 5s provider: job: spec: template: spec: containers: - name: load-tester image: argoproj/load-tester:latest command: [sh, -xec] args: - | wrk -t1 -c1 -d5 -s report.lua http://{{args.host}}/color jq -e '.errors_ratio <= 0.05' report.json restartPolicy: Never backoffLimit: 0
Прошу прощения за огромный шаблон (его пришлось склеить из трех), но это сделано для максимальной наглядности.
-
args:– можно задать переменные для шаблона и при запуске экземпляра анализа их можно переопределить. Значения можно взять из секретов -
metrics:– массив тестов. Метрики поддерживают разные провайдеры. В примере показаны istio, web и job. -
Если что-то не прошло нашу проверку – откатываем изменения (поведение можно менять)
-
Для метрики
http-benchmarkзапускается отдельный контейнер (по ссылке вы можете посмотреть файл report.lua, который формирует структуру отчета). Провайдерjobпозволяет нам подпихнуть любой контейнер с нашими автотестами и прогнать их без переключение реального трафика (для этого используется experiment). -
Шаблонизация очень удобна, если ваши сервисы поставляются разными командами: так вы задаете единые критерии для всех. Особенно это помогает с теми, у кого нет времени на написание автотестов.
Подключаем шаблон к Rollout. Сначала рассмотрим поведение при canary-стратегии:
strategy: canary: analysis: templates: - templateName: error-rate # имя шаблона - templateName: Mytemplate # можно подключать несколько шаблонов сразу clusterScope: true #это служит для подключения ClusterAnalysisTemplate startingStep: 2 # Ждём когда rollout дойдёт до 2 шага (40%) и стартуем args: - name: service-name value: guestbook-svc.default.svc.cluster.local steps: - setWeight: 20 - pause: {duration: 10m} - setWeight: 40 - pause: {duration: 10m} - setWeight: 60 - pause: {duration: 10m} - setWeight: 80 - pause: {duration: 10m}
В данном манифесте показан пример анализа в фоне: Rollout потихоньку подменяет поды, а инстанс анализа делает своё дело до тех пор, пока не завершится накат новой ревизии или же возникнет ошибка и тогда нас ждёт Rollback. Есть другой вариант применения – Inline Analysis. Он позволяет нам вклиниться в steps, анализироваться столько сколько хочется и только потом переходить на другие шаги.
steps: - setWeight: 20 - pause: {duration: 5m} - analysis: templates: - templateName: success-rate args: - name: service-name value: guestbook-svc.default.svc.cluster.local
Тут будет необходим тюнинг шаблона анализа, без interval и count ваш тест выполнится один раз
metrics: - name: success-rate successCondition: result[0] >= 0.95 interval: 60s count: 5 provider: prometheus: address: http://prometheus.example.com:9090 query: ...
Тут уже в зависимости от количества новых подов, мы можем выбрать различные наборы и продолжительность наших тестов. А теперь рассмотрим BlueGreen – стратегию: в данном случае мы можем проводить проверку до переключения трафика и после:
strategy: blueGreen: activeService: active-svc previewService: preview-svc prePromotionAnalysis: # прогоняем тесты и переключем templates: - templateName: smoke-tests #...или... scaleDownDelaySeconds: 600 # сколько живёт текущая реплика после переключения postPromotionAnalysis: # прогоняем тесты после переключения templates: - templateName: smoke-tests
В первом случае контроллер просто не переключит трафик, во втором будет производиться откат, поэтому рекомендуется увеличить (в разумных пределах) scaleDownDelaySeconds, чтобы контроллер не уничтожал сразу предыдущую реплику. В случае проблем он быстро перекинет лейблы и мы не будем ожидать старта контейнеров.
Как всегда есть исключения из правил: метрика вроде бы есть, но если не выполняется – давайте не будем из-за нее останавливать релиз. Для этого служит механизм dry-run: можно пометить метрики и выкатка не зафейлится, если все плохо.
Пример dry-run метрик
#В манифесте AnalysisTemplate ... dryRun: - metricName: .* metrics: - name: total-5xx-errors # в манифестах rollout ... steps: - analysis: templates: - templateName: random-fail - templateName: always-pass dryRun: - metricName: .*
Еще есть состояние inconclusive или, говоря по-русски, «нипанятна» – состояние, когда заданы success и failed границы, но мы не попали. В таком случае Rollout встает на паузу и ждет ручного вмешательства. На мой взгляд, лучше не допускать дырки в диапазонах и однозначно задавать критерии.
metrics: - name: success-rate successCondition: result[0] >= 0.90 failureCondition: result[0] < 0.50
Мы рассмотрели Analysis, который позволял нам подстелить соломку в случае плохого релиза, а теперь пора перейти к целому «стогу» – experiments. Согласно документации, в первом случае мы переключаем реальный клиентский трафик (хотя в случае BlueGreen prePromotionAnalysis ничего не переключается). Experiments позволяет нам развернуть произвольное количество replicaset в с разными контейнерами, прогнать по ним тесты, сравнить и принять решение о судьбе релиза.
длинная портянка из документации
apiVersion: argoproj.io/v1alpha1 kind: Experiment metadata: name: example-experiment spec: # Duration of the experiment, beginning from when all ReplicaSets became healthy (optional) # If omitted, will run indefinitely until terminated, or until all analyses which were marked # `requiredForCompletion` have completed. duration: 20m # Deadline in seconds in which a ReplicaSet should make progress towards becoming available. # If exceeded, the Experiment will fail. progressDeadlineSeconds: 30 # List of pod template specs to run in the experiment as ReplicaSets templates: - name: purple # Number of replicas to run (optional). If omitted, will run a single replica replicas: 1 selector: matchLabels: app: canary-demo color: purple template: metadata: labels: app: canary-demo color: purple spec: containers: - name: rollouts-demo image: argoproj/rollouts-demo:purple imagePullPolicy: Always ports: - name: http containerPort: 8080 protocol: TCP - name: orange replicas: 1 minReadySeconds: 10 selector: matchLabels: app: canary-demo color: orange template: metadata: labels: app: canary-demo color: orange spec: containers: - name: rollouts-demo image: argoproj/rollouts-demo:orange imagePullPolicy: Always ports: - name: http containerPort: 8080 protocol: TCP # List of AnalysisTemplate references to perform during the experiment analyses: - name: purple templateName: http-benchmark args: - name: host value: purple - name: orange templateName: http-benchmark args: - name: host value: orange - name: compare-results templateName: compare # If requiredForCompletion is true for an analysis reference, the Experiment will not complete # until this analysis has completed. requiredForCompletion: true args: - name: host value: purple
Также можно запускать автономные эксперименты не привязанных к процессу выкатки. Это может быть востребовано у тестировщиков – запустил/забыл/вспомнил/сравнил. Вот так можно подглядывать за экспериментом:

Способ подключения из rollout похож на AnalysisTemplate:
strategy: canary: steps: - experiment: duration: 1h templates: - name: baseline specRef: stable - name: canary specRef: canary analyses: - name : mann-whitney templateName: mann-whitney args: - name: baseline-hash value: "{{templates.baseline.podTemplateHash}}" - name: canary-hash value: "{{templates.canary.podTemplateHash}}"
Можно сделать еще интереснее: развернуть N-экспериментальных replicaset, переключить какой-то процент боевого трафика на них и посмотреть, что из этого получится (работает только на SMI, ALB, Istio):
steps: - experiment: duration: 1h templates: - name: experiment-baseline specRef: stable weight: 5 - name: experiment-canary specRef: canary weight: 5
Есть еще удобная функция – не писать весь spec в манифесте rollout, а прицепиться к существующему deployment:
# манифест rollout spec: replicas: 5 selector: matchLabels: app: rollout-ref-deployment workloadRef: apiVersion: apps/v1 kind: Deployment name: rollout-ref-deployment strategy: #...
Обратите внимание, что rollout не управляет количеством реплик deployment. После наката, у вас будет задвоение (но это позволяет избежать простоя) и если все прошло успешно, вы уменьшаете число реплик у deployment до нуля. С этого момента deployment служит по сути шаблоном spec: все дальнейшие изменения вы делаете в нем (но число реплик всегда должно быть 0), а rollout контроллер отслеживает изменения и порождает replicaset.
Я собрал для вас основные выдержки из документации, которые интересны для специалистов по автоматизации и они помогут вам быстро вникнуть в решение и начать применять его на практике. Примеры из документации можете посмотреть здесь и здесь (тут встречаются старые апи), есть гайд по миграции.
Если у вас есть замечания, благодарности, или вы хотите поделиться опытом – добро пожаловать в комментарии.
Всем удачных релизов!
ссылка на оригинал статьи https://habr.com/ru/company/ru_mts/blog/695744/
Добавить комментарий