Я работаю над внедрением канареечных развертываний для наших сервисов, которые развернуты в среде с несколькими центрами обработки данных. Мы используем 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.
Как я могу этого добиться?