web-dev-qa-db-fra.com

L'installation de nginx ne doit pas planter si l'hôte en amont n'est pas trouvé

Nous avons plusieurs applications Rails dans le domaine commun de Docker et nous utilisons nginx pour diriger les demandes vers des applications spécifiques.

our_dev_server.com/foo # proxies to foo app
our_dev_server.com/bar # proxies to bar

La configuration ressemble à ceci:

upstream foo {
  server foo:3000;
}

upstream bar {
  server bar:3000;
}

# and about 10 more...

server {
  listen *:80 default_server;

  server_name our_dev_server.com;

  location /foo {
      # this is specific to asset management in Rails dev
      rewrite ^/foo/assets(/.*)$ /assets/$1 break;
      rewrite ^/foo(/.*)$ /foo/$1 break;
      proxy_pass http://foo;
  }

  location /bar {
      rewrite ^/bar/assets(/.*)$ /assets/$1 break;
      rewrite ^/bar(/.*)$ /bar/$1 break;
      proxy_pass http://bar;
  }

  # and about 10 more...
}

Si l'une de ces applications n'est pas lancée, nginx échoue et s'arrête:

Host not found in upstream "bar:3000" in /etc/nginx/conf.d/nginx.conf:6

Nous n’avons pas besoin qu’ils soient tous actifs, mais nginx échoue sinon . Comment faire pour que nginx ignore les flux amont échoués?

73
Morozov
  1. Si vous pouvez utiliser une adresse IP statique, utilisez-la simplement, elle démarrera et renverra simplement les 503 si elle ne répond pas. 

  2. Utilisez la directive resolver pour pointer sur un problème susceptible de résoudre l'hôte, qu'il soit opérationnel ou non. 

  3. Résolvez-le au niveau location, si vous ne pouvez pas faire ce qui précède (cela permettra à Nginx de démarrer/exécuter) :

    location /foo {
      resolver 127.0.0.1 valid=30s;
      # or some other DNS (you company/internal DNS server)
      #resolver 8.8.8.8 valid=30s;
      set $upstream_foo foo;
      proxy_pass http://$upstream_foo:80;
    }
    
    location /bar {
      resolver 127.0.0.1 valid=30s;
      # or some other DNS (you company/internal DNS server)
      #resolver 8.8.8.8 valid=30s;
      set $upstream_bar foo;
      proxy_pass http://$upstream_bar:80;
    }
    
62
Justin

Le principal avantage de upstream est de définir un groupe de serveurs pouvant écouter sur différents ports, de configurer l'équilibrage de charge et le basculement entre eux

Dans votre cas, vous êtes définissez uniquement 1 serveur principal par amont, donc il doit être actif.

Au lieu de cela, utilisez des variables pour votre proxy_pass (es) et n'oubliez pas de gérer les erreurs possibles (404, 503) que vous pourriez obtenir lorsqu'un serveur cible est en panne.

9
danielgpm

Pour moi, l'option 3 de la réponse de @ Justin/@ duskwuff a résolu le problème, mais je devais modifier l'IP du résolveur en 127.0.0.11 (serveur DNS de Docker):

location /foo {
  resolver 127.0.0.11 valid=30s;
  set $upstream_foo foo;
  proxy_pass http://$upstream_foo:80;
}

location /bar {
  resolver 127.0.0.11 valid=30s;
  set $upstream_bar foo;
  proxy_pass http://$upstream_bar:80;
}

Toutefois, comme @ Justin/@ duskwuff l’a mentionné, vous pouvez utiliser n’importe quel autre serveur DNS externe.

1
neumann