如果您的服務採用分布式架構,您可以使用gRPC協議提升用戶端與伺服器端的通訊效率。將使用gRPC協議的服務部署在Nginx Ingress Controller的後端時,您需要對Ingress資源進行特殊的配置。
背景資訊
gRPC(Google Remote Procedure Call)是一個基於HTTP/2協議標準和ProtoBuf(Protocol Buffers)序列化協議設計的遠端程序呼叫(RPC)架構。它由Google開源,支援在多語言開發的平台上使用。其因其高效、靈活和跨語言的特性,gRPC適用於分布式系統和微服務架構情境,例如微服務間調用、物聯網裝置間通訊、使用複雜資料結構的遠程API服務等。
定義如下gRPC服務,用戶端可調用helloworld.Greeter服務的SayHello介面。
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
package helloworld;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
更多gRPC服務樣本,請參見grpc-go。
步驟一:將SSL認證儲存到叢集Secret資源中
使用Nginx Ingress Controller時,gRPC服務只運行在HTTPS連接埠(預設443)上,因此需要使用SSL認證。認證需要以Secret資源的方式儲存在叢集中。
如果您暫未擁有認證,您可參照下方的步驟產生自我簽署憑證,樣本中使用grpc.example.com
作為認證的網域名稱。
重要
由於缺乏可靠的CA認證,自我簽署憑證在瀏覽器和用戶端中預設不受信任,通常會導致客戶訪問時收到安全警告。本文中產生的自我簽署憑證僅作為樣本,請勿在生產環境中使用。
建立並拷貝以下內容至/tmp/openssl.cnf檔案中。
[ req ]
#default_bits = 2048
#default_md = sha256
#default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
req_extensions = v3_req
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
0.organizationName = Organization Name (eg, company)
organizationalUnitName = Organizational Unit Name (eg, section)
commonName = Common Name (eg, fully qualified host name)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
[v3_req]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = grpc.example.com
執行以下命令簽署認證請求。
openssl req -new -nodes -keyout grpc.key -out grpc.csr -config /tmp/openssl.cnf -subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=AlibabaCloud/OU=ContainerService/CN=grpc.example.com"
執行以下命令簽署認證。
openssl x509 -req -days 3650 -in grpc.csr -signkey grpc.key -out grpc.crt -extensions v3_req -extfile /tmp/openssl.cnf
命令執行成功後,可得到認證grpc.crt與私密金鑰檔案grpc.key。
執行以下命令,將認證通過grpc-secret
添加到叢集中。
kubectl create secret tls grpc-secret --key grpc.key --cert grpc.crt
步驟二:建立gRPC服務
建立並將以下內容拷貝到grpc.yaml檔案中。
apiVersion: apps/v1
kind: Deployment
metadata:
name: grpc-service
spec:
replicas: 1
selector:
matchLabels:
run: grpc-service
template:
metadata:
labels:
run: grpc-service
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/acs-sample/grpc-server:latest
imagePullPolicy: Always
name: grpc-service
ports:
- containerPort: 50051
protocol: TCP
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: grpc-service
spec:
ports:
- port: 50051
protocol: TCP
targetPort: 50051
selector:
run: grpc-service
sessionAffinity: None
type: NodePort
執行以下命令建立gRPC服務。
kubectl apply -f grpc.yaml
預期輸出:
deployment.apps/grpc-service created
service/grpc-service created
步驟三:建立Ingress
建立並拷貝以下內容到grpc-ingress.yaml檔案中。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: grpc-ingress
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
spec:
tls:
- hosts:
- grpc.example.com
secretName: grpc-secret
rules:
- host: grpc.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: grpc-service
port:
number: 50051
重要
由於Nginx grpc_pass的限制,目前對於gRPC服務,暫不支援service-weight的配置。
執行以下命令建立Ingress。
kubectl apply -f grpc-ingress.yaml
預期輸出:
ingress.networking.k8s.io/grpc-ingress created
步驟四:效果驗證
執行以下命令,查看Ingress資訊。
預期輸出:
NAME CLASS HOSTS ADDRESS PORTS AGE
grpc-ingress nginx grpc.example.com 139.196.***** 80, 443 3m51s
記錄ADDRESS
對應的IP地址。
使用grpcurl串連服務。
grpcurl -insecure -authority grpc.example.com <IP_ADDRESS>:443 list
輸出如下,表明流量被Ingress成功轉寄到後端gRPC服務:
grpc.reflection.v1alpha.ServerReflection
helloworld.Greeter