我在 GCP Kubernetes 上为我们的 golang 服务进行的部署遇到了一个相当奇怪的问题,该服务通过 gRPC 端点以及 HTTP 1.1 调用进行连接。这些配置对于 http 调用工作正常,但是,一旦我使用 gRPC 应用程序点击它,入口就会在访问日志中显示 404 响应,请检查我的 YAML 并告诉我是否缺少任何导致此行为的内容
SA 配置
apiVersion: v1
kind: ServiceAccount
metadata:
name: "service-qa"
namespace: service-qa
labels:
helm.sh/chart: service-0.0.1
app.kubernetes.io/name: service
app.kubernetes.io/instance: release-name
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/managed-by: Helm
服务配置
apiVersion: v1
kind: Service
metadata:
name: "service-qa"
namespace: service-qa
annotations:
cloud.google.com/app-protocols: '{"http2":"HTTP2", "http": "HTTP"}'
cloud.google.com/neg: '{"ingress": true}'
service.alpha.kubernetes.io/app-protocols: '{"http2":"HTTP2", "http": "HTTP"}'
cloud.google.com/backend-config: '{"default": "service-qa"}'
labels:
helm.sh/chart: service-0.0.1
app.kubernetes.io/name: service
app.kubernetes.io/instance: release-name
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/managed-by: Helm
spec:
type: ClusterIP
ports:
- port: 443
targetPort: 8080
protocol: TCP
name: http
selector:
app.kubernetes.io/name: service
app.kubernetes.io/instance: release-name
部署配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: "service-qa"
labels:
helm.sh/chart: service-0.0.1
app.kubernetes.io/name: service
app.kubernetes.io/instance: release-name
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/managed-by: Helm
namespace: service-qa
spec:
replicas: 5
selector:
matchLabels:
app.kubernetes.io/name: service
app.kubernetes.io/instance: release-name
template:
metadata:
labels:
app.kubernetes.io/name: service
app.kubernetes.io/instance: release-name
spec:
securityContext:
{}
containers:
- name: service
securityContext:
{}
image: "REDACTED/service:1.0.0_202310170507"
env:
- name: IS_LIVE
value: "false"
- name: PROFILE
value: "qa"
- name: TOKEN
valueFrom:
secretKeyRef:
key: token
name: service-access-token
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
protocol: TCP
resources:
limits:
cpu: 100m
memory: 200Mi
requests:
cpu: 50m
memory: 100Mi
nodeSelector:
iam.gke.io/gke-metadata-server-enabled: "true"
入口配置
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: "service-qa"
namespace: service-qa
labels:
helm.sh/chart: service-0.0.1
app.kubernetes.io/name: service
app.kubernetes.io/instance: release-name
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/managed-by: Helm
annotations:
ingress.gcp.kubernetes.io/pre-shared-cert: cert
kubernetes.io/ingress.allow-http: "false"
kubernetes.io/ingress.class: gce-internal
kubernetes.io/ingress.regional-static-ip-name: ilb
spec:
tls:
- hosts:
- REDACTED
secretName: cert-qa
rules:
- host: "REDACTED"
http:
paths:
- path: /*
pathType: ImplementationSpecific
backend:
service:
name: service-qa
port:
number: 443
后端配置
apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
name: "service-qa"
namespace: service-qa
spec:
timeoutSec: 400
healthCheck:
checkIntervalSec: 30
port: 8080
type: HTTP
requestPath: /healthcheck
让我还附上我的入口的一些屏幕截图,其中显示了传入的请求,但最终出现了 404,而当我用 Postman 调用击中它时,我得到了正确的响应
我还想指出,关于我调用服务的方式没有拼写错误或任何问题,因为相同的代码在虚拟机上运行良好 - 只是带有 Google 内部负载均衡器的 Kubernetes 无法接听调用转发至服务。
提前致谢,非常感谢您的帮助,因为我已经努力寻找解决方案相当长一段时间了。
据我了解,你有:
Client
|
| HTTP GET/POST Request (Works)
| gRPC Request (Fails)
v
Google Cloud Internal Load Balancer (GCE ILB)
|
| Ingress (service-qa)
v
Kubernetes Cluster (GCP GKE)
|
| (Namespace: service-qa)
v
Service (service-qa)
| Port: 443 TargetPort: 8080
v
Pods (Deployment: service-qa)
|
| Container: service
| Image: REDACTED/service:1.0.0_202310170507
| Ports: ContainerPort: 8080 (Protocol: TCP)
v
gRPC Server / HTTP Server (listening on port 8080)
|
| Response (HTTP: 200 OK)
| (gRPC: 404 Not Found)
v
Back to Client
200 OK
响应。404 Not Found
错误。激活日志:对于 gRPC 日志记录,您可以在服务的部署配置中设置
GRPC_VERBOSITY
和 GRPC_TRACE
环境变量:
env:
- name: GRPC_VERBOSITY
value: DEBUG
- name: GRPC_TRACE
value: all
如果 gRPC 客户端正确配置为连接到端口 443,则流量应根据您的服务配置转发到服务器上的端口 8080。但是,如果 Ingress 或服务配置存在问题,或者 gRPC 客户端错误地尝试使用 HTTP/1.1 而不是 HTTP/2(gRPC 需要)进行通信,则可能会导致您看到的
404 Not Found
错误。
查看 Ingress 控制器的日志,看看是否有任何错误消息或有关 gRPC 调用失败原因的其他信息。
测试您的服务连接入口:您可以执行集群内的 pod,并使用
curl
或 grpcurl
测试与服务的连接:
kubectl run -i --tty --rm debug --image=radial/busyboxplus:curl --restart=Never -- sh
# Then from within the container:
grpcurl -plaintext service-qa.service-qa.svc.cluster.local:8080 list
验证客户端配置涉及确保客户端正确设置为与 gRPC 服务器通信,特别是在所使用的地址、端口和协议方面。根据 gRPC 客户端实现的环境和语言,您可以使用以下几个步骤和命令:
检查创建 gRPC 客户端的代码,确保地址和端口正确设置为您的服务地址和端口
443
。
// In Go, for example, it would look something like this:
conn, err := grpc.Dial("your-service-address:443", grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()