Thiết lập nginx không bị lỗi nếu không tìm thấy máy chủ lưu trữ trong dòng ngược


117

Chúng tôi có một số ứng dụng đường ray trong miền chung trong Docker và chúng tôi sử dụng nginx để chuyển yêu cầu đến các ứng dụng cụ thể.

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

Cấu hình trông như thế này:

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

Nếu một trong những ứng dụng này không được khởi động thì nginx không thành công và dừng lại:

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

Chúng tôi không cần tất cả chúng đều lên nhưng ngược lại thì nginx thất bại. Làm thế nào để làm cho nginx bỏ qua các lần ngược dòng không thành công?


1
Bạn đang liên kết các vùng chứa ứng dụng với vùng chứa Nginx hay chạy chúng tách biệt với nhau? Nếu máy chủ trong upstreamkhối không giải quyết được, trong thời gian chạy, thì Nginx sẽ thoát với lỗi trên ...
Justin

1
Nếu bạn có thể sử dụng một IP thì nó sẽ khởi động tốt. Việc sử dụng resolver( nginx.org/en/docs/http/ngx_http_core_module.html#resolver ) có hiệu quả trong trường hợp của bạn không?
Justin

@Justin chúng tôi có mỗi ứng dụng trong vùng chứa riêng biệt, nginx cũng vậy. Liên kết chúng với docker
Morozov

@Justin Startup order ổn, nginx bắt đầu sau các app khác. Chúng tôi chỉ muốn chạy một số trong số họ :)
Morozov

1
Tôi đã có một thiết lập tương tự (vùng chứa Nginx với (các) vùng chứa ứng dụng) . Chúng tôi đã tạo một hình ảnh Nginx bao gồm một proxy.shtập lệnh đọc các biến môi trường và thêm động upstreamcác mục nhập cho từng biến, sau đó khởi động Nginx. Điều này hoạt động tuyệt vời ở chỗ khi chúng tôi chạy vùng chứa proxy của mình, chúng tôi có thể chuyển các phần ngược dòng cần thiết trong thời gian chạy. Bạn có thể làm điều gì đó tương tự để bật / tắt upstreams nhất định lúc khởi động (hoặc như thiết lập của tôi chỉ cần thêm những cái cần thiết trong thời gian chạy)
Justin

Câu trả lời:


90
  1. Nếu bạn có thể sử dụng IP tĩnh thì chỉ cần sử dụng IP đó, nó sẽ khởi động và chỉ trả về 503nếu nó không phản hồi.

  2. Sử dụng resolverchỉ thị để trỏ đến thứ gì đó có thể giải quyết máy chủ, bất kể nó hiện đang hoạt động hay không.

  3. Giải quyết nó ở locationcấp độ, nếu bạn không thể làm như trên (điều này sẽ cho phép Nginx khởi động / chạy) :

    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
lựa chọn 3 của bạn phù hợp với tôi. Nếu tôi không chỉ định trình phân giải, bạn có biết nginx sẽ lưu vào bộ nhớ cache IP mà nó giải quyết trong bao lâu không?
Riley Lark

14
Cảm ơn! Chỉ cần sử dụng một biến dường như để giữ nginx từ việc thông minh về nó
Blanka

1
Tôi thấy rằng một nhóm thu thập regex cho phép tôi bỏ qua biến:location ~ ^/foo/(.*)$ { proxy_pass http://foo/$1; }
Danny Kirchmeier

2
Điều đó hoạt động như thế nào đối với một proxy TCP? Có vẻ như không có cách nào để thử tùy chọn 3 cho proxy tcp.
krish7919

1
@Charlie những lỗi như vậy trong nginx hầu như luôn liên quan đến việc thiếu ";" ký vào cuối dòng :)
SteveB

18

Đối với tôi, tùy chọn 3 trong số câu trả lời từ @ Justin / @ duskwuff đã giải quyết được vấn đề, nhưng tôi phải thay đổi IP của trình phân giải thành 127.0.0.11 (máy chủ DNS của 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;
}

Nhưng như @ Justin / @ duskwuff đã đề cập, bạn có thể sử dụng bất kỳ máy chủ DNS bên ngoài nào khác.


15

Ưu điểm chính của việc sử dụng upstreamlà xác định một nhóm máy chủ có thể lắng nghe trên các cổng khác nhau và cấu hình cân bằng tải và chuyển đổi dự phòng giữa chúng .

Trong trường hợp của bạn, bạn chỉ xác định 1 máy chủ chính cho mỗi ngược dòng nên nó phải được thiết lập .

Thay vào đó, hãy sử dụng các biến cho proxy_pass(các) của bạn và nhớ xử lý các lỗi có thể xảy ra (404, 503) mà bạn có thể gặp phải khi máy chủ đích gặp sự cố.


1
> Thay vào đó, hãy sử dụng các biến cho (các) proxy_pass của bạn và nhớ xử lý các lỗi có thể xảy ra (404s, 503s) mà bạn có thể gặp phải khi máy chủ đích gặp sự cố. Bạn có thể nói rõ hơn về cách làm điều đó? Nếu tôi làm set $variable http://fooproxy_pass $variablegiữ foo "ngược dòng" (để giữ những lợi thế mà bạn đã đề cập) thì tôi vẫn đang gặp phải vấn đề mà OP đã đề cập.
Tibor Vass

6
Như bạn có thể thấy trong các ví dụ khác, nó sẽ là set $variable fooproxy_pass http://$variable
danielgpm

2
@danielgpm Như bạn đã nêu, việc sử dụng biến cho proxy_pass hoạt động hoàn hảo và giải quyết được vấn đề của tôi. Nó sẽ giúp đỡ người khác nếu bạn có thể cập nhật câu trả lời của bạn và kể rằng làm ví dụ
Nitb

3
Điều gì sẽ xảy ra nếu tôi có nhiều hơn một và tôi muốn bỏ qua những lỗi không thể giải quyết được?
talabes

0

Tôi gặp sự cố "Không tìm thấy máy chủ lưu trữ" tương tự vì một phần máy chủ lưu trữ của tôi đang được ánh xạ bằng cách sử dụng $urithay vì $request_uri:

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

Và khi yêu cầu thay đổi thành truy vấn phụ auth, yêu cầu sẽ $urimất giá trị ban đầu. Thay đổi ánh xạ để sử dụng $request_urithay vì $urigiải quyết vấn đề của tôi:

map $request_uri $kubernetes {
    # ...
}

-8

Bạn không thể sử dụng --linktùy chọn, thay vào đó bạn có thể sử dụng ánh xạ cổng và liên kết nginx với địa chỉ máy chủ.

Ví dụ: Chạy vùng chứa docker đầu tiên của bạn với -p 180:80tùy chọn, vùng chứa thứ hai với -p 280:80tùy chọn.

Chạy nginx và đặt các địa chỉ này cho proxy:

proxy_pass http://192.168.1.20:180/; # first container
proxy_pass http://192.168.1.20:280/; # second container
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.