我有一个gRPC服务器,可以在本地计算机上正常工作。我可以从python应用发送grpc请求,并获得正确的响应。
我将服务器放入GKE集群(只有一个节点)。我在群集前面有一个普通的TCP负载平衡器。在此设置中,我的本地客户端能够从某些请求中获得正确的响应,而其他请求则没有。我认为是gRPC流式传输无法正常工作。
我认为这是因为流式传输需要HTTP / 2连接,而该连接需要SSL。
我在GKE中获得的标准负载均衡器似乎不支持SSL,因此我遵循文档来设置了一个入口负载均衡器。我正在使用Lets-Encrypt证书。
现在所有gRPC请求都返回
status = StatusCode.UNAVAILABLE
details =“套接字已关闭”
debug_error_string = “ {” created“:” @ 1556172211.931158414“,” description“:”收到错误 同行 ipv4:ip.of.ingress.service:443”,“文件”:“ src / core / lib / surface / call.cc”,“ file_line”:1041,“ grpc_message”:“套接字已关闭”,“ grpc_status”: 14}“
IP地址是我的入口服务的外部IP地址。 入口Yaml看起来像这样:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: rev79-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: "rev79-ip"
ingress.gcp.kubernetes.io/pre-shared-cert: "lets-encrypt-rev79"
kubernetes.io/ingress.allow-http: "false" # disable HTTP
spec:
rules:
- host: sub-domain.domain.app
http:
paths:
- path: /*
backend:
serviceName: sandbox-nodes
servicePort: 60000
我的python应用发出的请求的子域和域与入口规则中的主机匹配。
它连接到如下所示的节点端口:
apiVersion: v1
kind: Service
metadata:
name: sandbox-nodes
spec:
type: NodePort
selector:
app: rev79
environment: sandbox
ports:
- protocol: TCP
port: 60000
targetPort: 9000
节点本身有两个容器,如下所示:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: rev79-sandbox
labels:
app: rev79
environment: sandbox
spec:
replicas: 1
template:
metadata:
labels:
app: rev79
environment: sandbox
spec:
containers:
- name: esp
image: gcr.io/endpoints-release/endpoints-runtime:1.31
args: [
"--http2_port=9000",
"--service=rev79.endpoints.rev79-232812.cloud.goog",
"--rollout_strategy=managed",
"--backend=grpc://0.0.0.0:3011"
]
ports:
- containerPort: 9000
- name: rev79-uac-sandbox
image: gcr.io/rev79-232812/uac:latest
imagePullPolicy: Always
ports:
- containerPort: 3011
env:
- name: RAILS_MASTER_KEY
valueFrom:
secretKeyRef:
name: rev79-secrets
key: rails-master-key
节点端口的目标是ESP容器,该容器连接到部署在云中的gRPC服务,后端是一个实现API后端的Rails应用。该Rails应用程序未运行rails服务器,而是运行grpc_for_rails
gem
Rails应用程序中的grpc_server不会在日志中记录任何操作,因此我认为请求不会那么远。
kubectl get ingress
报告此:
NAME HOSTS ADDRESS PORTS AGE
rev79-ingress sub-domain.domain.app my.static.ip.addr 80 7h
显示端口80,即使它已设置为SSL。那似乎是一个错误。当我用curl -kv https://sub-domain.domain.app
检查时,入口服务器可以很好地处理请求,并使用HTTP / 2。它会重现HTML格式的服务器错误,但我不确定是什么原因导致的。
API需要API密钥,Python客户端会将其插入每个请求的元数据中。
当我转到GCP控制台的终结点页面时,我发现自放入入口负载均衡器以来,该API并未注册任何请求,因此该请求似乎未到达EPS容器。
那我为什么要用gRPC收到“套接字关闭”错误?
答案 0 :(得分:0)
我说过,一旦工作,我会回来并在此处发布答案。看来我没做过。作为我的忠告,我现在将发布对我有用的配置文件。
在部署中,我为ESP容器添加了一个活跃性和就绪性探针。这使部署顺利进行而没有停机:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: rev79-sandbox
labels:
app: rev79
environment: sandbox
spec:
replicas: 3
template:
metadata:
labels:
app: rev79
environment: sandbox
spec:
volumes:
- name: nginx-ssl
secret:
secretName: nginx-ssl
- name: gcs-creds
secret:
secretName: rev79-secrets
items:
- key: gcs-credentials
path: "gcs.json"
containers:
- name: esp
image: gcr.io/endpoints-release/endpoints-runtime:1.45
args: [
"--http_port", "8080",
"--ssl_port", "443",
"--service", "rev79-sandbox.endpoints.rev79-232812.cloud.goog",
"--rollout_strategy", "managed",
"--backend", "grpc://0.0.0.0:3011",
"--cors_preset", "cors_with_regex",
"--cors_allow_origin_regex", ".*",
"-z", " "
]
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
periodSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /healthz
port: 8080
timeoutSeconds: 5
failureThreshold: 1
volumeMounts:
- name: nginx-ssl
mountPath: /etc/nginx/ssl
readOnly: true
ports:
- containerPort: 8080
- containerPort: 443
protocol: TCP
- name: rev79-uac-sandbox
image: gcr.io/rev79-232812/uac:29eff5e
imagePullPolicy: Always
volumeMounts:
- name: gcs-creds
mountPath: "/app/creds"
ports:
- containerPort: 3011
name: end-grpc
- containerPort: 3000
env:
- name: RAILS_MASTER_KEY
valueFrom:
secretKeyRef:
name: rev79-secrets
key: rails-master-key
这是我的服务配置,将部署暴露给负载均衡器:
apiVersion: v1
kind: Service
metadata:
name: rev79-srv-ingress-sandbox
labels:
type: rev79-srv
annotations:
service.alpha.kubernetes.io/app-protocols: '{"rev79":"HTTP2"}'
cloud.google.com/neg: '{"ingress": true}'
spec:
type: NodePort
ports:
- name: rev79
port: 443
protocol: TCP
targetPort: 443
selector:
app: rev79
environment: sandbox
这是我的入口:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: rev79-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: "rev79-global-ip"
spec:
tls:
- secretName: sandbox-api-rev79-app-tls
rules:
- host: sandbox-api.rev79.app
http:
paths:
- backend:
serviceName: rev79-srv-ingress-sandbox
servicePort: 443
我正在使用cert-manager来管理证书。
现在已经很久了。我不记得我还有什么办法解决我遇到的问题