我按照 AWS EKS 中的示例创建了一个 EKS 集群,并在 kubernetes/nginx 上部署了 nginx 入口控制器,创建了一个指向后端 k8s 服务的入口资源,但是,当我尝试通过curl -kv https://dev01.cricket.com/demo/hello
它进行查询时,它返回永久重定向 308
这是我的 service-nlb.yaml
--- (service-nlb.yaml)
kind: Service
apiVersion: v1
metadata:
name: ingress-nginx
namespace: default
annotations:
**service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http**
service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "3600"
service.beta.kubernetes.io/aws-load-balancer-internal: "0.0.0.0/0"
**service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "arn:aws:acm:us-west-2:xxxxx:certificate/x-037xxxd-4a1e-x-x"**
service.beta.kubernetes.io/aws-load-balancer-ssl-negotiation-policy: ELBSecurityPolicy-TLS-1-2-Ext-2018-06
**service.beta.kubernetes.io/aws-load-balancer-ssl-ports: https**
spec:
ports:
- name: https
port: 443
targetPort: 80
入口文件
```apiVersion: extensions/v1beta1
kind: Ingress
metadata:
labels:
app: jg
env: dev
name: jg-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: nginx
**ingress.kubernetes.io/ssl-redirect: "false"**
spec:
rules:
- host: dev01.cricket.com
http:
paths:
- backend:
serviceName: jg-service
servicePort: 8080
path: /demo
- host: dev02.cricket.com
http:
paths:
- backend:
serviceName: sad-service
servicePort: 8080
path: /sad
tls:
- hosts:
- dev01.cricket.com
secretName: my-tls-secret```
当我curl -kv dev01.cricket.com
这样做时,它返回 308 永久重定向
curl -kv https://dev01.cricket.com/demo/hello
* Trying 10.41.168.92...
* TCP_NODELAY set
* Connected to dev01.cricket.com (10.41.168.92) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=dev01.cricket.com; OU=management:idms.group.140787; O=Cricket Inc.; ST=California; C=US
* start date: Apr 19 08:37:06 2021 GMT
* expire date: May 19 08:37:05 2023 GMT
* issuer: CN=Cricket Corporate Server CA 1; OU=Certification Authority; O=Cricket Inc.; C=US
* 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
* Using Stream ID: 1 (easy handle 0x7ff9eb80d200)
> GET /demo/hello HTTP/2
> Host: dev01.cricket.com
> User-Agent: curl/7.64.1
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 308
< server: Cricket
< date: Tue, 04 May 2021 16:38:38 GMT
< content-type: text/html
< content-length: 171
< location: https://dev01.cricket.com/demo/hello
< strict-transport-security: max-age=31536000; includeSubdomains
< x-frame-options: SAMEORIGIN
< x-content-type-options: nosniff
< x-xss-protection: 1; mode=block
<
<html>
<head><title>308 Permanent Redirect</title></head>
<body>
<center><h1>308 Permanent Redirect</h1></center>
<hr><center>nginx/1.17.8</center>
</body>
</html>
* Connection #0 to host dev01.cricket.com left intact
* Closing connection 0
我不确定为什么 TLS 终止没有发生,并且发生了永久重定向错误,如果我在 http 上执行相同的 curl,它会返回 301
curl -kv http://dev01.cricket.com/demo/hello
* Trying 10.41.162.164...
* TCP_NODELAY set
* Connected to dev01.cricket.com (10.41.162.164) port 80 (#0)
> GET /demo/hello HTTP/1.1
> Host: dev01.cricket.com
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Server: Cricket
< Date: Tue, 04 May 2021 19:17:26 GMT
< Content-Type: text/html
< Content-Length: 162
< Connection: keep-alive
< Location: https://dev01.cricket.com/demo/hello
<
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>Cricket</center>
</body>
</html>
* Connection #0 to host dev01.cricket.com left intact
* Closing connection 0
后端服务.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: jgdeployment
labels:
app: jg
spec:
replicas: 3
selector:
matchLabels:
app: jg
template:
metadata:
labels:
app: jg
spec:
containers:
- name: jg
image: docker.cricket.com/jga:1.0.0
ports:
- containerPort: 8080
livenessProbe:
failureThreshold: 3
httpGet:
path: /demo/hello
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
failureThreshold: 3
httpGet:
path: /demo/hello
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: jg-service
namespace: "default"
spec:
type: ClusterIP
ports:
- port: 8080
targetPort: 8080
selector:
app: jg
不确定我做了什么导致 https 上出现 308 错误。
答案1
这是回答来自 github 的用户 Ariseaz问题Azeez Adeniji 在回答中提到。
在 EKS 上使用 helm ingress-nginx chart
编辑 configmap ingress-nginx-controller
kubectl edit configmap ingress-nginx-controller -n ingress-nginx
添加
data: server-snippet: | listen 8000; if ( $server_port = 80 ) { return 308 https://$host$request_uri; } ssl-redirect: "false"
编辑 service/ingress-nginx-controller,添加
meta.helm.sh/release-namespace: ingress-nginx service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "60" service.beta.kubernetes.io/aws-load-balancer-ssl-cert: <acm arn> service.beta.kubernetes.io/aws-load-balancer-ssl-ports: https service.beta.kubernetes.io/aws-load-balancer-type: nlb
在入口控制器中设置您的端口,使其看起来像下面这样:
NB:特殊端口是您要添加到入口容器端口的端口
:
- 名称:http
端口:80
协议:TCP
目标端口:80 - 名称:https
端口:443
协议:TCP
目标端口:特殊
现在编辑入口控制器部署容器端口
kubectl edit deployment.apps/ingress-nginx-controller -n ingress-nginx
添加:
- 容器端口:8000
名称:特殊
协议:TCP
答案2
我不确定为什么 TLS 终止没有发生,并且发生了永久重定向错误
鉴于您的服务规范:
spec:
ports:
- name: https
port: 443
targetPort: 80
导致以下情况发生:
User -- [Internet] -HTTPS-> :443 [NLB] -HTTPS-> :443 [iptables] -HTTP-> :80 [nginx]
因此,由于 nginx 无法意识到它前面有 TLS,并且在集群内部流量是 HTTP,因此 nginx 认为将请求重定向到其443
端口是有帮助的,从而确保了请求的安全
我还没有用国家法律顾问委员会但理论上,想法是一样的:您需要使用从 NLB 到 nginx 443 端口上的(可能是自签名的)证书的 TLS,因为——在其他条件相同的情况下——AWS LB 不会验证 nginx 证书的有效性。因此,虽然您确实有一个 MITM,但不会有任何从用户浏览器到 nginx 的明文协议通信,这让它很开心,不再是 308
我确实看到了您在 Ingress 上突出显示的注释,但我强烈怀疑您所遇到的机制在到达特定 Ingress 资源之前就发生了,可能是由于 ConfigMap 设置或其他原因。可能可以按照您认为的要求调整 nginx,但我相信“伪端到端 TLS”实际上很容易修复,因此您不需要寻找解决方法
答案3
阅读我对此主题的评论: https://github.com/kubernetes/ingress-nginx/issues/2724
评论来自 Ariseaz
答案4
默认情况下,如果为该 Ingress 启用了 TLS,则控制器会使用 308 永久重定向响应将 HTTP 客户端重定向到 HTTPS 端口 443。
可以使用 NGINX 配置映射全局禁用此功能,或者使用特定资源中的注释ssl-redirect: "false"
为每个 Ingress 禁用此功能。nginx.ingress.kubernetes.io/ssl-redirect: "false"
# kubectl edit cm ingress-nginx-controller -n ingress-nginx
参考: https://kubernetes.github.io/ingress-nginx/user-guide/tls/