使用主机的入口规则
Ingress rule using host
有人可以帮助发现 ingress-2
入口规则的问题吗?为什么 ingress-1
有效而 ingress-2
无效。
我的设置说明,我有两个部署:
第一次部署是 nginx
第二次部署是 httpd
这两个部署都是通过 ClusterIP
服务公开的,分别名为 nginx-svc
和 httpd-svc
。所有 endpoints
都适用于服务。然而,虽然
为这些服务设置入口,我无法使用 host
设置入口(如 ingress-2
中所述)。但是,当我使用 ingress-1
时,一切正常。
//我的名称解析主机文件
grep myapp.com /etc/hosts
127.0.0.1 myapp.com
// 部署细节
kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 3/3 3 3 29m
httpd 3/3 3 3 29m
//服务详情
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 7h48m
nginx-svc ClusterIP 10.152.183.233 <none> 80/TCP 28m
httpd-svc ClusterIP 10.152.183.58 <none> 80/TCP 27m
// 端点详细信息
kubectl get ep
NAME ENDPOINTS AGE
kubernetes 10.0.2.15:16443 7h51m
nginx-svc 10.1.198.86:80,10.1.198.87:80,10.1.198.88:80 31m
httpd-svc 10.1.198.89:80,10.1.198.90:80,10.1.198.91:80 31m
尝试 1:ingress-1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-1
spec:
rules:
- http:
paths:
- path: /nginx
pathType: Prefix
backend:
service:
name: nginx-svc
port:
number: 80
- path: /httpd
pathType: Prefix
backend:
service:
name: httpd-svc
port:
number: 80
// 显示入口路由在使用 ingress-1
时工作正常的示例:
curl myapp.com/nginx
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
curl myapp.com/httpd
<html><body><h1>It works!</h1></body></html>
// 以下入口规则没有像我预期的那样工作
尝试 2:ingress-2
kind: Ingress
metadata:
name: ingress-2
spec:
rules:
- host: "myapp.com"
http:
paths:
- pathType: Prefix
path: "/nginx"
backend:
service:
name: nginx-svc
port:
number: 80
- pathType: Prefix
path: "/httpd"
backend:
service:
name: httpd-svc
port:
number: 80
// 我无法在 ing describe
中发现任何问题
kubectl describe ingress ingress-2
Name: ingress-2
Namespace: default
Address: 127.0.0.1
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
Host Path Backends
---- ---- --------
myapp.com
/nginx nginx-svc:80 (10.1.198.86:80,10.1.198.87:80,10.1.198.88:80)
/httpd httpd-svc:80 (10.1.198.89:80,10.1.198.90:80,10.1.198.91:80)
Annotations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 9m15s (x2 over 10m) nginx-ingress-controller Scheduled for sync
// 显示入口路由的示例不适用于此入口资源
curl myapp.com/nginx
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.21.1</center>
</body>
</html>
curl myapp.com/httpd
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
</body></html>
入口之间的差异
我创建了一个单节点 microk8s
集群 following official documentation 但我无法重现您描述的正确行为。添加了两个 pods 和 mendhak/http-https-echo
图片(强烈推荐:非常方便排除入口问题或了解入口的工作原理)和每个 pods.
的两个服务
两个入口规则的区别是第一个入口规则侦听所有域(HOSTS):
$ mkctl get ing -o wide
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-1 public * 127.0.0.1 80 2m53s
$ curl -I --header "Host: myapp.com" http://127.0.0.1/httpd
HTTP/1.1 200 OK
$ curl -I --header "Host: example.com" http://127.0.0.1/httpd
HTTP/1.1 200 OK
$ curl -I --header "Host: myapp.com" http://127.0.0.1/missing_url
HTTP/1.1 404 Not Found
虽然第二个入口规则将仅服务于 myapp.com
域 (HOST):
$ mkctl get ing
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-2 public myapp.com 127.0.0.1 80 60s
$ curl -I --header "Host: myapp.com" http://127.0.0.1/httpd
HTTP/1.1 200 OK
$ curl -I --header "Host: example.com" http://127.0.0.1/httpd
HTTP/1.1 404 Not Found
到底发生了什么
你问题的最后结果实际上表明入口正在按预期工作。您收到的响应不是来自 kubernetes ingress
,而是来自集群内的 pods。第一个响应是 nginx 1.21.0
的 404
,第二个是 apache
.
的 404
发生这种情况是因为 ingress 向 pods 发送了来自 URL 的相同 path
的请求,但没有进行任何转换。例如(我使用上面提到的图像得到的这个输出):
$ curl myapp.com/httpd
{
"path": "/httpd"
...
虽然 nginx
和 apache
都在 /
投放。
如何解决
Nginx ingress 有很多特性,其中之一是 rewriting,它有助于将 paths
从 ingress 得到的东西转变为 pods 得到的东西。
例如,如果请求转到 http://myapp.com/nginx
,那么它将被定向到具有 /nginx
路径的 nginx
服务,这将导致 nginx
抛出 404
因为这个 path
.
上什么都没有
下面的入口规则通过将 rewrite-target
添加到 /
来修复此问题,我们需要将其传递给 nginx
和 apache
服务:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-2
annotations:
# kubernetes.io/ingress.class: nginx # this should be uncommented if ingress used in "regular" cluster
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myapp.com
http:
paths:
- path: /nginx
pathType: Prefix
backend:
service:
name: service-a
port:
number: 80
- path: /httpd
pathType: Prefix
backend:
service:
name: service-b
port:
number: 80
快速测试它是如何工作的:
$ curl myapp.com/nginx
{
"path": "/",
...
和
$ curl myapp.com/httpd
{
"path": "/",
...
正如您现在看到的 path
是 /
。
将图像切换到 nginx
和:
$ curl myapp.com/nginx
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
...
有用的链接
有人可以帮助发现 ingress-2
入口规则的问题吗?为什么 ingress-1
有效而 ingress-2
无效。
我的设置说明,我有两个部署:
第一次部署是 nginx
第二次部署是 httpd
这两个部署都是通过 ClusterIP
服务公开的,分别名为 nginx-svc
和 httpd-svc
。所有 endpoints
都适用于服务。然而,虽然
为这些服务设置入口,我无法使用 host
设置入口(如 ingress-2
中所述)。但是,当我使用 ingress-1
时,一切正常。
//我的名称解析主机文件
grep myapp.com /etc/hosts
127.0.0.1 myapp.com
// 部署细节
kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 3/3 3 3 29m
httpd 3/3 3 3 29m
//服务详情
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 7h48m
nginx-svc ClusterIP 10.152.183.233 <none> 80/TCP 28m
httpd-svc ClusterIP 10.152.183.58 <none> 80/TCP 27m
// 端点详细信息
kubectl get ep
NAME ENDPOINTS AGE
kubernetes 10.0.2.15:16443 7h51m
nginx-svc 10.1.198.86:80,10.1.198.87:80,10.1.198.88:80 31m
httpd-svc 10.1.198.89:80,10.1.198.90:80,10.1.198.91:80 31m
尝试 1:ingress-1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-1
spec:
rules:
- http:
paths:
- path: /nginx
pathType: Prefix
backend:
service:
name: nginx-svc
port:
number: 80
- path: /httpd
pathType: Prefix
backend:
service:
name: httpd-svc
port:
number: 80
// 显示入口路由在使用 ingress-1
时工作正常的示例:
curl myapp.com/nginx
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
curl myapp.com/httpd
<html><body><h1>It works!</h1></body></html>
// 以下入口规则没有像我预期的那样工作
尝试 2:ingress-2
kind: Ingress
metadata:
name: ingress-2
spec:
rules:
- host: "myapp.com"
http:
paths:
- pathType: Prefix
path: "/nginx"
backend:
service:
name: nginx-svc
port:
number: 80
- pathType: Prefix
path: "/httpd"
backend:
service:
name: httpd-svc
port:
number: 80
// 我无法在 ing describe
中发现任何问题kubectl describe ingress ingress-2
Name: ingress-2
Namespace: default
Address: 127.0.0.1
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
Host Path Backends
---- ---- --------
myapp.com
/nginx nginx-svc:80 (10.1.198.86:80,10.1.198.87:80,10.1.198.88:80)
/httpd httpd-svc:80 (10.1.198.89:80,10.1.198.90:80,10.1.198.91:80)
Annotations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 9m15s (x2 over 10m) nginx-ingress-controller Scheduled for sync
// 显示入口路由的示例不适用于此入口资源
curl myapp.com/nginx
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.21.1</center>
</body>
</html>
curl myapp.com/httpd
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
</body></html>
入口之间的差异
我创建了一个单节点 microk8s
集群 following official documentation 但我无法重现您描述的正确行为。添加了两个 pods 和 mendhak/http-https-echo
图片(强烈推荐:非常方便排除入口问题或了解入口的工作原理)和每个 pods.
两个入口规则的区别是第一个入口规则侦听所有域(HOSTS):
$ mkctl get ing -o wide
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-1 public * 127.0.0.1 80 2m53s
$ curl -I --header "Host: myapp.com" http://127.0.0.1/httpd
HTTP/1.1 200 OK
$ curl -I --header "Host: example.com" http://127.0.0.1/httpd
HTTP/1.1 200 OK
$ curl -I --header "Host: myapp.com" http://127.0.0.1/missing_url
HTTP/1.1 404 Not Found
虽然第二个入口规则将仅服务于 myapp.com
域 (HOST):
$ mkctl get ing
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-2 public myapp.com 127.0.0.1 80 60s
$ curl -I --header "Host: myapp.com" http://127.0.0.1/httpd
HTTP/1.1 200 OK
$ curl -I --header "Host: example.com" http://127.0.0.1/httpd
HTTP/1.1 404 Not Found
到底发生了什么
你问题的最后结果实际上表明入口正在按预期工作。您收到的响应不是来自 kubernetes ingress
,而是来自集群内的 pods。第一个响应是 nginx 1.21.0
的 404
,第二个是 apache
.
404
发生这种情况是因为 ingress 向 pods 发送了来自 URL 的相同 path
的请求,但没有进行任何转换。例如(我使用上面提到的图像得到的这个输出):
$ curl myapp.com/httpd
{
"path": "/httpd"
...
虽然 nginx
和 apache
都在 /
投放。
如何解决
Nginx ingress 有很多特性,其中之一是 rewriting,它有助于将 paths
从 ingress 得到的东西转变为 pods 得到的东西。
例如,如果请求转到 http://myapp.com/nginx
,那么它将被定向到具有 /nginx
路径的 nginx
服务,这将导致 nginx
抛出 404
因为这个 path
.
下面的入口规则通过将 rewrite-target
添加到 /
来修复此问题,我们需要将其传递给 nginx
和 apache
服务:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-2
annotations:
# kubernetes.io/ingress.class: nginx # this should be uncommented if ingress used in "regular" cluster
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myapp.com
http:
paths:
- path: /nginx
pathType: Prefix
backend:
service:
name: service-a
port:
number: 80
- path: /httpd
pathType: Prefix
backend:
service:
name: service-b
port:
number: 80
快速测试它是如何工作的:
$ curl myapp.com/nginx
{
"path": "/",
...
和
$ curl myapp.com/httpd
{
"path": "/",
...
正如您现在看到的 path
是 /
。
将图像切换到 nginx
和:
$ curl myapp.com/nginx
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
...