nginx канареечных развертываний с использованием разделенных клиентов и nginx файлов шаблонов - PullRequest
0 голосов
/ 27 мая 2020

Я работаю над внедрением канареечных развертываний для наших сервисов, которые развернуты в среде с несколькими центрами обработки данных. Мы используем nginx .ctmpl для обновления файла nginx .conf. Конфигурация nginx .ctmpl, которую я определил, выглядит следующим образом:

# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {

    upstream servicecanary{
      {{scratch.Set "serviceFound" false}}
        {{ range $tag, $services := service "SERVICENAME" | byTag }}
          {{ if $tag | contains "1.2.3" }}
            {{ range $services }} server  {{ .Address }}:{{ .Port }} max_fails=3 fail_timeout=60 weight=1;
          {{end}}
        {{scratch.Set "serviceFound" true}}
      {{end}}

      {{else}}
        {{range datacenters}}
          {{ range $tag, $services := service "SERVICENAME" | byTag }}
            {{ if $tag | contains "1.2.3" }}
                {{range service (print "SERVICENAME@" .) }}server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60;
            {{end}}
          {{scratch.Set "serviceFound" true}}
          {{end}}
        {{end}}
      {{end}}
      {{end}}

      {{if not (scratch.Get "serviceFound")}}
        server 127.0.0.1:65535; # force a 502
      {{end}}
    }

    upstream servicenoncanary{
      {{scratch.Set "serviceFound" false}}
        {{ range $tag, $services := service "SERVICENAME" | byTag }}
          {{ if $tag | contains "1.2.4"  }}
            {{ range $services }} server  {{ .Address }}:{{ .Port }} max_fails=3 fail_timeout=60 weight=1;
          {{end}}
        {{scratch.Set "serviceFound" true}}
      {{end}}

      {{else}}
        {{range datacenters}}
          {{ range $tag, $services := service "SERVICENAME" | byTag }}
            {{ if $tag | contains "1.2.3" }}
                {{range service (print "SERVICENAME@" .) }}server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60;
              {{end}}
            {{scratch.Set "serviceFound" true}}
          {{end}}
        {{end}}
      {{end}}
      {{end}}

      {{if not (scratch.Get "serviceFound")}}
        server 127.0.0.1:65535; # force a 502
      {{end}}
    }

    split_clients "app${remote_addr}${date_gmt}" $service_variant {
        #The below % is actually getting populated from the chef databags. so my actual configuration will be
        #{{"<%= @service_canary_traffic %>"}} and {{"<%= @service_non_canary_traffic %>"}}. 
        #The values for the variables are populated using chef erb files.
       {{"70%"}} servicenoncanary;
       {{"30%"}} servicecanary;
    }

    map $arg_client $my_service {
       default $service_variant;
    }



    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent $request_time "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for";

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Settings for a TLS enabled server.

    server {
        <SSL Configuration goes here>

        location /servicepathname/ {
          if ($my_service = unknown) {
             return 400;
          }
          proxy_pass https://$my_service;
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
}

Проблема, с которой я столкнулся, заключается в следующем: если служба в сценарии

  • сценария 1: canary service является down или
  • сценарий2: весь canary сервер не работает,

файл nginx .conf обновляется для восходящей службы canary и upstream servicenoncanry блокирует правильно, но split_clients все еще имеют 70% и 30%. Когда я нажимаю ELB, это вызывает 502 ошибки, потому что 30% трафика c идет на канарейку. В обоих сценариях ios мне нужно обновить блок split_client, чтобы он был на 100% не канареечным, а * до канареечного. тогда он работает так, как я ожидал.

Я ищу более динамичный c способ nginx определения, какие службы на каких серверах работают, и обновляю конфигурацию nginx соответственно, включая конфигурацию split_client. Я попробовал одно решение - установить переменные canary traffic c как глобальные в блоке http, что запрещено. Моя мысль состоит в том, чтобы снова установить canary traffic c в этом блоке в восходящем блоке servicecanary, когда я определю, что услуга больше не доступна:

{{if not (scratch.Get "serviceFound")}}
    server 127.0.0.1:65535; # force a 502
    servicenoncanary 100%;
    servicecanary *;
{{end}}

В идеале мне нужно установить% для canary VS noncanary traffic c, когда я форсирую 502. Этот параметр должен заменить значение в блоке split_clients.

Как я могу этого добиться?

...