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.