Yukarı akışta ana bilgisayar bulunmazsa nginx'i çökmeyecek şekilde kurun


117

Docker'da ortak alan adı altında birkaç rails uygulamamız var ve istekleri belirli uygulamalara yönlendirmek için nginx kullanıyoruz.

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

Config şuna benzer:

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...
}

Bu uygulamalardan biri başlatılmazsa, nginx başarısız olur ve durur:

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

Hepsinin yükselmesine ihtiyacımız yok ama nginx aksi halde başarısız olur. Nginx'in başarısız olan yukarı akışları görmezden gelmesini nasıl sağlayabilirim?


1
Uygulama kaplarını Nginx kapsayıcılarına mı bağlıyorsunuz yoksa birbirinden ayrı mı çalıştırıyorsunuz? upstreamBlok içindeki ana bilgisayar çalışma zamanında çözülmezse, Nginx yukarıdaki hatayla çıkacaktır ...
Justin

1
Bir IP kullanabiliyorsanız, o zaman iyi bir şekilde başlayacaktır. Kullanarak misiniz resolver( nginx.org/en/docs/http/ngx_http_core_module.html#resolver senin durumunda) çalışır?
Justin

@Justin, her bir uygulamaya ayrı bir kapsayıcıda sahibiz, nginx de. Onları liman işçisine bağlayın
Morozov

@Justin Başlangıç ​​sırası iyi, nginx diğer uygulamalardan sonra başlıyor. Sadece bazılarını çalıştırmak istiyoruz :)
Morozov

1
Benzer bir kurulumum var (uygulama kapsayıcıları ile Nginx kapsayıcısı) . proxy.shOrtam değişkenlerini okuyan ve upstreamher biri için dinamik olarak girişler ekleyen ve ardından Nginx'i başlatan bir komut dosyası içeren bir Nginx görüntüsü oluşturduk . Bu, proxy kapsayıcımızı çalıştırdığımızda, çalışma zamanında gerekli üst akışları geçirebileceğimiz için harika çalışıyor. Başlatma sırasında belirli yukarı akışları etkinleştirmek / devre dışı bırakmak için benzer bir şey yapabilirsiniz (veya kurulumum gibi, çalışma zamanında gerekli olanları ekleyin)
Justin,

Yanıtlar:


90
  1. Statik bir IP kullanabiliyorsanız, sadece onu kullanın, başlatılır ve 503yanıt vermezse 's' i döndürür .

  2. resolverŞu anda çalışır durumda olup olmadığına bakılmaksızın, ana bilgisayarı çözebilecek bir şeyi işaret etmek için yönergeyi kullanın .

  3. locationYukarıdakileri yapamazsanız, bunu seviyede çözün (bu, Nginx'in başlamasına / çalışmasına izin verecektir) :

    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;
    }
    

1
3. seçeneğiniz benim için harika çalışıyor. Bir çözümleyici belirtmezsem, nginx'in çözdüğü IP'yi ne kadar süreyle önbelleğe alacağını biliyor musunuz?
Riley Lark

14
Teşekkürler! Sadece bir değişken kullanmak, nginx'in bu konuda akıllı davranmasını engelliyor gibi görünüyor
Blanka

1
Bir normal ifade yakalama grubunun değişkeni atlamama izin verdiğini buldum:location ~ ^/foo/(.*)$ { proxy_pass http://foo/$1; }
Danny Kirchmeier

2
Bu bir TCP proxy'si için nasıl çalışır? Tcp proxy'si için 3. seçeneği denemenin bir yolu yok gibi görünüyor.
krish7919

1
@Charlie nginx'teki bu tür hatalar neredeyse her zaman eksiklikle ilgilidir ";" satırın sonunda imzala :)
SteveB

18

Benim için @ Justin / @ duskwuff'tan gelen yanıtın 3. seçeneği sorunu çözdü, ancak çözümleyici IP'sini 127.0.0.11 (Docker DNS sunucusu) olarak değiştirmek zorunda kaldım :

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;
}

Ancak @ Justin / @ duskwuff'ın bahsettiği gibi, başka herhangi bir harici DNS sunucusunu kullanabilirsiniz.


15

Kullanmanın temel avantajı, farklı bağlantı noktalarında dinleyebilen ve bunlar arasında yük dengeleme ve yük devretmeyi yapılandırabilen bir sunucu grubuupstream tanımlamaktır .

Sizin durumunuzda, yukarı akış başına yalnızca 1 birincil sunucu tanımlıyorsunuz, bu nedenle yukarıda olması gerekir .

Bunun yerine, proxy_pass(ler) iniz için değişkenler kullanın ve bir hedef sunucu çalışmadığında alabileceğiniz olası hataları (404s, 503s) işlemeyi unutmayın.


1
> Bunun yerine, proxy_pass (ler) iniz için değişkenler kullanın ve bir hedef sunucu çalışmadığında alabileceğiniz olası hataları (404s, 503s) işlemeyi unutmayın. Bunun nasıl yapılacağını açıklar mısınız? Ben yaparsanız set $variable http://foove proxy_pass $variableve "yukarı" foo tutmak sonra hala OP tarafından bahsedilen sorunu vuruyorum (Bahsettiğiniz avantaj tutmak için).
Tibor Vass

6
Diğer örneklerde görebileceğiniz gibi, bu olacak set $variable fooveproxy_pass http://$variable
danielgpm

2
@danielgpm belirttiğiniz gibi proxy_pass değişkenini kullanmak mükemmel çalışıyor ve sorunumu çözdü. Cevabınızı güncelleyip örnek olarak belirtmeniz başkalarına yardımcı olur
Nitb

3
Ya birden fazla varsa ve çözülemeyenleri görmezden gelmek istersem?
talabes

0

Aynı "Ana bilgisayar bulunamadı" sorununu yaşadım çünkü ana bilgisayarımın bir kısmı aşağıdakiler $uriyerine kullanılarak eşleniyordu $request_uri:

proxy_pass http://one-api-service.$kubernetes:8091/auth;

Ve istek, kimlik doğrulama alt isteğine dönüştüğünde $uri, başlangıç ​​değerini kaybetti. Eşlemeyi değiştirmek $request_uriyerine kullanmak $urisorunumu çözdü:

map $request_uri $kubernetes {
    # ...
}

-8

--linkSeçeneği kullanamazsınız , bunun yerine bağlantı noktası eşleştirmeyi kullanabilir ve nginx'i ana bilgisayar adresine bağlayabilirsiniz.

Örnek: İlk docker container'ınızı -p 180:80seçenekle, ikinci kapsayıcıyı -p 280:80seçenekle çalıştırın.

Nginx'i çalıştırın ve şu adresleri proxy için ayarlayın:

proxy_pass http://192.168.1.20:180/; # first container
proxy_pass http://192.168.1.20:280/; # second container
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.