我有一个无法解决的问题。任务是配置外部 nginx(裸机)以使用 Istio 平衡 OpenShift 的入口网关主机。 我做了一个简单的 nginx 配置:
upstream RobotBalance {
server ingress-robot.apps.gen1.com:443;
}
log_format basic '$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$upstream_addr" '
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
server {
listen 443 ssl http2;
# listen 80;
ssl on;
ssl_certificate /opt/nginx/ssl/cert.crt;
ssl_certificate_key /opt/nginx/ssl/cert.key;
ssl_session_timeout 10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
server_name ingress-robot.apps.gen1.com;
location / {
# return 301 https://$server_name$request_uri; #
proxy_pass https://RobotBalance;
access_log logs/robot_balance.log basic;
error_log logs/robot_balance_error.log debug;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;
add_header X-Upstream $upstream_addr always;
}
}
我正在尝试通过我的 nginx 向在 ingress-robot.apps.gen1.com 运行的应用程序发送一个空请求。但是从 openshift 的 istio 收到一条关于给定路径上应用程序无法访问的消息。
curl --cacert /opt/nginx/ssl/root_ca_united.pem --cert /opt/nginx/ssl/published.pem --key /opt/nginx/ssl/private.key --request POST https://my-ngnix-hostname-here/engine-dream/validate -i --verbose -d '{}'
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 10.55.11.22...
* TCP_NODELAY set
* Connected to my-ngnix-hostname-here (10.55.11.22) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /opt/nginx/ssl/root_ca_united.pem
CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, [no content] (0):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: C=EU; O=MY ORG; OU=99CA; CN=my-ngnix-hostname-here
* start date: Jun 9 07:34:08 2022 GMT
* expire date: Jun 9 07:34:08 2023 GMT
* subjectAltName: host "my-ngnix-hostname-here" matched cert's "my-ngnix-hostname-here"
* issuer: DC=ru; DC=org; DC=gamma; CN=My-Org
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* Using Stream ID: 1 (easy handle 0x56254b3bf690)
* TLSv1.3 (OUT), TLS app data, [no content] (0):
> POST /engine-dream/validate HTTP/2
> Host: my-ngnix-hostname-here
> User-Agent: curl/7.61.1
> Accept: */*
> Content-Length: 2
> Content-Type: application/x-www-form-urlencoded
>
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS app data, [no content] (0):
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* We are completely uploaded and fine
* TLSv1.3 (IN), TLS app data, [no content] (0):
* TLSv1.3 (IN), TLS app data, [no content] (0):
* TLSv1.3 (IN), TLS app data, [no content] (0):
< HTTP/2 503
HTTP/2 503
< server: nginx
server: nginx
< date: Wed, 13 Jul 2022 09:01:33 GMT
date: Wed, 13 Jul 2022 09:01:33 GMT
< content-type: text/html
content-type: text/html
< pragma: no-cache
pragma: no-cache
< cache-control: private, max-age=0, no-cache, no-store
cache-control: private, max-age=0, no-cache, no-store
< x-upstream: 10.55.111.245:443
x-upstream: 10.55.111.245:443
<
<html>
...
<body>
<div>
<h1>Application is not available</h1>
<p>The application is currently not serving requests at this endpoint. It may not have been started or is still starting.</p>
<div class="alert alert-info">
<p class="info">
Possible reasons you are seeing this page:
</p>
<ul>
<li>
<strong>The host doesn't exist.</strong>
Make sure the hostname was typed correctly and that a route matching this hostname exists.
</li>
<li>
<strong>The host exists, but doesn't have a matching path.</strong>
Check if the URL path was typed correctly and that the route was created using the desired path.
</li>
<li>
<strong>Route and path matches, but all pods are down.</strong>
Make sure that the resources exposed by this route (pods, services, deployment configs, etc) have at least one pod running.
</li>
</ul>
</div>
</div>
</body>
...
</html>
* TLSv1.3 (IN), TLS app data, [no content] (0):
* Connection #0 to host my-ngnix-hostname-here left intact
但是当我直接向 ingress 发送请求时,从应用程序中得到了正确的答案。
curl --cacert /opt/nginx/ssl/root_ca_united.pem --cert /opt/nginx/ssl/published.pem --key /opt/nginx/ssl/private.key --request POST https://ingress-robot.apps.gen1.com/engine-dream/validate -i --verbose -d '{}'
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 10.55.111.245...
* TCP_NODELAY set
* Connected to ingress-robot.apps.gen1.com (10.55.111.245) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /opt/nginx/ssl/root_ca_united.pem
CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Request CERT (13):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, [no content] (0):
* TLSv1.3 (OUT), TLS handshake, Certificate (11):
* TLSv1.3 (OUT), TLS handshake, [no content] (0):
* TLSv1.3 (OUT), TLS handshake, CERT verify (15):
* TLSv1.3 (OUT), TLS handshake, [no content] (0):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: C=EU; O=MY ORG; OU=99CA; CN=ingress-robot.apps.gen1.com
* start date: Jun 7 10:32:57 2022 GMT
* expire date: Jun 7 10:32:57 2023 GMT
* subjectAltName: host "ingress-robot.apps.gen1.com" matched cert's "ingress-robot.apps.gen1.com"
* issuer: DC=ru; DC=org; DC=gamma; CN=My-Org
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* Using Stream ID: 1 (easy handle 0x5594f7b31690)
* TLSv1.3 (OUT), TLS app data, [no content] (0):
> POST /dsl-engine-dream/validate HTTP/2
> Host: ingress-robot.apps.gen1.com
> User-Agent: curl/7.61.1
> Accept: */*
> Content-Length: 2
> Content-Type: application/x-www-form-urlencoded
>
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* We are completely uploaded and fine
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS app data, [no content] (0):
* Connection state changed (MAX_CONCURRENT_STREAMS == 2147483647)!
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* TLSv1.3 (IN), TLS app data, [no content] (0):
< HTTP/2 400
HTTP/2 400
< content-type: application/json; charset=utf-8
content-type: application/json; charset=utf-8
< content-length: 100
content-length: 100
< access-control-allow-origin: *
access-control-allow-origin: *
< server: istio-envoy
server: istio-envoy
< date: Wed, 13 Jul 2022 09:02:40 GMT
date: Wed, 13 Jul 2022 09:02:40 GMT
< x-envoy-upstream-service-time: 4
x-envoy-upstream-service-time: 4
<
{
"error": " Hello from robot. Robot.app got the empty request!"
* Connection #0 to host ingress-robot.apps.gen1.com left intact
请帮忙。我的 nginx 配置有什么问题?或者也许有一些功能可以平衡 Istio 的入口?
这“很可能”是因为 Ingress Gateway 正在执行 SNI 路由,即基于 HOST
标头的路由。因此,当您
curl
“https://ingress-robot.apps.gen1.com/engine-dream/validate”时,Ingress Gateway 能够根据“ingress-robot.apps.gen1.com”找到应用程序“ HOST
标题。然而,当您curl
ing“https://my-ngnix-hostname-here/engine-dream/validate”时,您只是通过“my-ngnix-hostname-here”
HOST
头,Ingress Gateway 说:“我没有与该主机名 ́\_(ツ)_/́ 匹配的应用程序”,然后它放弃。我打赌如果你尝试了这个curl
,Ingress 网关就能工作
$ curl -H "Host: ingress-robot.apps.gen1.com" --cacert /opt/nginx/ssl/root_ca_united.pem --cert /opt/nginx/ssl/published.pem --key /opt/nginx/ssl/private.key --request POST https://my-ngnix-hostname-here/engine-dream/validate -i --verbose -d '{}'
(注意我传递的
-H "Host: ingress-robot.apps.gen1.com"
标头)
在我看来,你应该做什么(好吧,实际上,我不认为你应该反向代理另一个反向代理,Ingress Gateway,但无论如何......如果这是你的要求,那就是它是),想出一个新的域名,“apps2.gen1.com”之类的。使用 server_name *.apps2.gen1.com". Then when you expose your applications in OpenShift, you can *pick* the hostname that they get exposed as. So expose your application as "ingress-robot.apps2.gen1.com", and you would still point your Upstream
server` 将 Nginx 设置为“ingress-robot.apps.gen1.com”。
HOST
标头,并且 OpenShift 能够根据 apps2 路由/入口找到应用程序。
上面感觉像是一个更“正确”的解决方案,但是如果您想“破解”它,您可以在 Nginx 配置中硬编码HOST
标头以匹配 Ingress Gateway 期望的
HOST
标头。这感觉有点僵化,难以保持动态,但根据您的要求,它可能“足够好”。