问题描述
我有一个 alpine docker 镜像可以在 apache 服务器 (PHP 7.4) EXPOSE 80
上运行我的原始 PHP 网站。
我想使用入口控制器在 Kubernetes(GKE) 上运行映像。
我正在使用 gcloud 命令将映像推送到 google 容器注册表。
部署和服务都没有错误,成功创建为NodePort。
我部署的ingress来自google tutorials(https://cloud.google.com/community/tutorials/nginx-ingress-gke)
现在在我的入口中有:
- 34.68.78.46.xip.io/
- 34.68.78.46.xip.io/hello
- 34.68.78.46.xip.io/jb(/|$)(.*)
/hello 与教程的配置相同,运行良好。
/jb 与我在下面提到的配置相同,并且总是返回 502 错误。
GCP 控制台中的入口详细信息未显示警告或错误
我已经检查过:
Kubernetes GKE Ingress : 502 Server Error
GKE Ingress: 502 error when downloading file
502 Server Error Google kubernetes
这是部署文件:
apiVersion: apps/v1
kind: Deployment
Metadata:
name: jomlahbazar-deployment
spec:
selector:
matchLabels:
greeting: jomlah
department: bazar
replicas: 1
template:
Metadata:
labels:
greeting: jomlah
department: bazar
spec:
containers:
- name: jomlah
image: "us.gcr.io/third-nature-273904/jb-img-1-0:v1"
ports:
- containerPort: 80
env:
- name: "PORT"
value: "80"
这里是服务文件:
apiVersion: v1
kind: Service
Metadata:
name: jomlahbazar-service
spec:
type: NodePort
selector:
greeting: jomlah
department: bazar
ports:
- protocol: TCP
port: 80
targetPort: 80
在入口文件中:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
Metadata:
name: ingress-resource
annotations:
kubernetes.io/ingress.class: "Nginx"
Nginx.ingress.kubernetes.io/ssl-redirect: "false"
Nginx.ingress.kubernetes.io/rewrite-target: /$2
Nginx.ingress.kubernetes.io/use-regex: "true"
Nginx.ingress.kubernetes.io/add-base-url : "true"
spec:
rules:
- host: 34.68.78.46.xip.io
http:
paths:
- path: /
backend:
serviceName: jomlahbazar-service
servicePort: 80
- path: /hello
backend:
serviceName: hello-app
servicePort: 8080
- path: /jb(/|$)(.*)
backend:
serviceName: jomlahbazar-service
servicePort: 80
这里是入口描述:
Name: ingress-resource
Namespace: default
Address: 34.68.78.46
Default backend: default-http-backend:80 (10.20.1.6:8080)
Rules:
Host Path Backends
---- ---- --------
34.68.78.46.xip.io
/ jomlahbazar-service:80 (<none>)
/hello hello-app:8080 (10.20.2.61:8080)
/jb(/|$)(.*) jomlahbazar-service:80 (<none>)
Annotations:
kubernetes.io/ingress.class: Nginx
Nginx.ingress.kubernetes.io/add-base-url: true
Nginx.ingress.kubernetes.io/rewrite-target: /$2
Nginx.ingress.kubernetes.io/ssl-redirect: false
Nginx.ingress.kubernetes.io/use-regex: true
kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"networking.k8s.io/v1beta1","kind":"Ingress","Metadata":{"annotations":{"kubernetes.io/ingress.class":"Nginx","Nginx.ingress.kubernetes.io/add-base-url":"true","Nginx.ingress.kubernetes.io/rewrite-target":"/$2","Nginx.ingress.kubernetes.io/ssl-redirect":"false","Nginx.ingress.kubernetes.io/use-regex":"true"},"name":"ingress-resource","namespace":"default"},"spec":{"rules":[{"host":"34.68.78.46.xip.io","http":{"paths":[{"backend":{"serviceName":"jomlahbazar-service","servicePort":80},"path":"/"},{"backend":{"serviceName":"hello-app","servicePort":8080},"path":"/hello"},{"backend":{"serviceName":"jomlahbazar-service","path":"/jb(/|$)(.*)"}]}}]}}
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
normal AddedOrUpdated 36m (x6 over 132m) nginx-ingress-controller Configuration for default/ingress-resource was added or updated
kubectl get ing ingress-resource -o yaml 的输出
apiVersion: extensions/v1beta1
kind: Ingress
Metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"networking.k8s.io/v1beta1","path":"/jb(/|$)(.*)"}]}}]}}
kubernetes.io/ingress.class: Nginx
Nginx.ingress.kubernetes.io/add-base-url: "true"
Nginx.ingress.kubernetes.io/rewrite-target: /$2
Nginx.ingress.kubernetes.io/ssl-redirect: "false"
Nginx.ingress.kubernetes.io/use-regex: "true"
creationTimestamp: "2021-02-11T06:00:07Z"
generation: 5
name: ingress-resource
namespace: default
resourceVersion: "2195351"
selfLink: /apis/extensions/v1beta1/namespaces/default/ingresses/ingress-resource
uid: 74dc822f-91cb-4902-991b-1ad298f44ae6
spec:
rules:
- host: 34.68.78.46.xip.io
http:
paths:
- backend:
serviceName: jomlahbazar-service
servicePort: 80
path: /
- backend:
serviceName: hello-app
servicePort: 8080
path: /hello
- backend:
serviceName: jomlahbazar-service
servicePort: 80
path: /jb(/|$)(.*)
status:
loadBalancer:
ingress:
- ip: 34.68.78.46
解决方法
我已经在我的 GKE 集群上运行了一些测试。我已经使用 2 个 hello world 应用程序 v1 和 v2 复制了您的行为。
场景 1
硬件 1
spec:
containers:
- name: hello1
image: gcr.io/google-samples/hello-app:1.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
SVC HW1
spec:
type: NodePort
selector:
key: app
ports:
- port: 80
targetPort: 8080
硬件 2
spec:
containers:
- name: hello2
image: gcr.io/google-samples/hello-app:2.0
env:
- name: "PORT"
value: "80"
SVC HW2
spec:
type: NodePort
ports:
- port: 80
targetPort: 8080
protocol: TCP
selector:
app: hello2
入口
spec:
rules:
- http:
paths:
- path: /hello2
backend:
serviceName: h2
servicePort: 80
- path: /hello
backend:
serviceName: fs
servicePort: 80
输出:
$ curl 34.117.70.75/hello
Hello,world!
Version: 1.0.0
Hostname: fd-c6d79cdf8-7rmmd
$ curl 34.117.70.75/hello2
<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>502 Server Error</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Server Error</h1>
<h2>The server encountered a temporary error and could not complete your request.<p>Please try again in 30 seconds.</h2>
<h2></h2>
</body></html>
在此场景中,部署配置为创建将侦听 port: 80
的 pod。当您跳过在部署中配置 containerPort
时,Kubernetes 会自动使用 containerPort
中与 port
中设置的相同的端口。您可以使用 netstat
命令进行验证。
$ kubectl exec -ti h2-deploy-6dbf5b7899-g7rbj -- bin/sh
/ # netstat -plnt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 :::80 :::* LISTEN 1/hello-app
/ #
在您的服务中设置 containerPort: 8080
,因此服务期望流量通过端口 8080
。由于 pod 仅在 80
上侦听并且流量达到 8080
,因此您会收到 502
错误。
场景 2
将值从“80”更改为“8080”并应用新配置后。
$ curl 34.117.70.75/hello
Hello,world!
Version: 1.0.0
Hostname: fd-c6d79cdf8-7rmmd
$ curl 34.117.70.75/hello2
Hello,world!
Version: 2.0.0
Hostname: h2-deploy-5f5ccfbf9f-fjhrb
网络统计:
$ kubectl exec -ti f2-deploy-5f5ccfbf9f-fjhrb -- bin/sh
/ # netstat -plnt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 :::8080 :::* LISTEN 1/hello-app
解决方案
解决方案 1
您应该将应用程序部署更改为:
env:
- name: "PORT"
value: "8080"
并应用新配置。
解决方案 2
使用containerPort
spec:
containers:
- name: jb
image: "us.gcr.io/third-nature-273904/jb-img-1-0:v3"
ports:
- containerPort: 8080
注意
请注意,如果您创建了自己的映像并在您的 EXPOSE
中使用了 Dockerfile
,则您应该将部署配置为使用此特定端口。
如果您仍有问题,请告诉我。