marion 47f8f7a8a1 init há 4 anos atrás
..
client 47f8f7a8a1 init há 4 anos atrás
clientImpl 47f8f7a8a1 init há 4 anos atrás
constants 47f8f7a8a1 init há 4 anos atrás
deploy 47f8f7a8a1 init há 4 anos atrás
example 47f8f7a8a1 init há 4 anos atrás
py-example 47f8f7a8a1 init há 4 anos atrás
server 47f8f7a8a1 init há 4 anos atrás
serverImpl 47f8f7a8a1 init há 4 anos atrás
tls 47f8f7a8a1 init há 4 anos atrás
README.md 47f8f7a8a1 init há 4 anos atrás

README.md

gRPC原生负载均衡原型

目录example中是proto定义

目录server中是服务实现

目录client中是客户端实现

目录deploy中是k8s相关部署文件

目录py-example中是一个python的示例gRPC服务

测试结论

gRPC原生库负载均衡实现

  1. gRPC原生库在客户端用resolver支持负载均衡,验证通过,代码灵活可配置,但需要有额外的机制维护服务端暴露的动态gRPC节点列表

不使用resolver相关代码库,尝试k8s原生环境的负载均衡实现

  1. 基于NodePort、ClusterIP的Service,可以访问通,但无负载均衡效果

  2. 基于LoadBalance的Service和相应4层负载均衡,或手工创建的4层负载均衡,可以访问通,但无负载均衡效果

  3. 腾讯云容器环境TKE默认的gcloud类型的ingress和相应7层负载均衡,无法访问通

  4. TKE需另外安装nginx controller,安装方法下面有说明,443 tls连接能访问通,但不是必须做证书验证,且正确实现负载均衡(目前推荐使用此方式,相关更改都是部署层面的,代码几乎没有修改)

使用服务中间件的负载均衡实现

  1. Ambassador边缘网关中间件,安装方法下面有说明,http 1.1请求能正常转发,gRPC未调通

  2. Istio服务网格,每个Pod前端都加了网格代理,gRPC负载均衡自动能够实现,无需做其它额外配置

grpcurl连接测试工具:https://github.com/fullstorydev/grpcurl

nginx ingress方式访问gRPC

nginx ingress安装

先新建命名空间 ingress-nginx

ingress-nginx项目网站 找到最新的mandatory.yaml文件的源文件下载安装即可

kubectl apply -f mandatory.yaml

时间可能较久,耐心等待,安装成功后会在ingress-nginx命名空间下新增nginx controller的pod

建立一个指向此pod的service以便访问,注意一定同时映射80和443端口(nginx controller的gRPC支持实际在443上),且type推荐为ClusterIP以便最小化可访问范围和路由长度,参考ingress-nginx-service.yaml

客户端访问nginx controller会按照域名分发请求,所以需要给上述pod或service配置域名解析,到外部dns服务里去配置,推荐指向上述service内网ip

另外,经测试,在客户端pod的yaml文件中配置本地hosts的方式无效,而在kube-dns的configmap配置文件中添加配置可能导致整个集群dns失效

nginx ingress使用

创建nginx类型的ingress即可,可参考本项目中的ingress.yaml

ingress创建或更新后,会自动同步更新nginx controller中的配置,可以进入nginx controller pod查看nginx.conf

kubectl exec -n ingress-nginx -it cat nginx.conf

关于k8s证书创建

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ex_tls.key -out ex_tls.crt -subj "/CN=example.wanpinghui.com/O=example.wanpinghui.com"

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout gw_tls.key -out gw_tls.crt -subj "/CN=gw.wanpinghui.com/O=gw.wanpinghui.com"

其中两个example.wanpinghui.com或gw.wanpinghui.com之类是证书对应域名

kubectl create secret tls ex-wph-secret --key ex_tls.key --cert ex_tls.crt

kubectl create secret tls gw-wph-secret --key gw_tls.key --cert gw_tls.crt

将刚刚生成的证书加入k8s的secret

如果具体某个nginx ingress不放在ingress-nginx命名空间,那么最好ingress-nginx命名空间和nginx ingress所在命名空间中都加一下secret

Ambassador网关方式访问gRPC(gRPC重定向未通)

Ambassador安装

下载edgectl

edgectl是必备的

https://www.getambassador.io/reference/edgectl-download/

但尝试用推荐的edgectl install命令安装未完全成功且运行不稳定,改用次选的Helm应用管理器方式安装

通过Helm安装

先在k8s集群上安装helm,腾讯云到集群管理后台打开即可

下载Helm客户端

curl -O https://storage.googleapis.com/kubernetes-helm/helm-v2.10.0-linux-amd64.tar.gz
tar xzvf helm-v2.10.0-linux-amd64.tar.gz
sudo cp linux-amd64/helm /usr/local/bin/helm
helm init --client-only

如果是在k8s集群中的节点机上,可以直接使用,推荐直接使用

否则再执行如下操作

以下是针对腾讯云环境,配置Helm客户端访问集群

将helm对应的tiller service转换为内网负载均衡模式

kubectl patch svc $(kubectl get svc -l app=helm,name=tiller -n kube-system -o=jsonpath={.items[0].metadata.name}) -n kube-system -p '{"metadata":{"annotations":{"service.kubernetes.io/qcloud-loadbalancer-internal-subnetid":"subnet-88888888"}},"spec":{"type":"LoadBalancer"}}'

等待负载均衡配置完成后,获取ip和端口信息

kubectl get svc -l app=helm,name=tiller -n kube-system -o=jsonpath={.items[0].status.loadBalancer.ingress[0].ip}

kubectl get svc -l app=helm,name=tiller -n kube-system -o=jsonpath={.items[0].spec.ports[0].port}

以后,在helm客户端所在机器,即可执行如下命令导入环境变量,以切换连接指定集群

可以将这个语句存成一个脚本,以便使用

export HELM_HOST=$EXTERNALIP:$PORT

安装Ambassador

helm repo add datawire https://www.getambassador.io

kubectl create namespace ambassador

helm install --name ambassador --namespace ambassador datawire/ambassador

安装完毕后会在ambassador命名空间中创建一堆crds,以及deployment、service以及service相应的4层公网负载均衡

经测试,手工创建http 7层负载均衡指向node port无效,且公网访问仅用于管理,内网访问用service的内网ip即可,也并不仅限于http协议请求处理,所以,保留自动建立的负载均衡

获取Community Edition License

  1. 新建一个域名指向ambassador service的公网ip(后续如更换域名,需要重复执行下面2、3步)

  2. 命令行工具登录

edgectl login --namespace=ambassador <访问域名>

可能会提示缺少xdg-open,如果在CentOS上,通过以下命令安装

yum install -y xdg-utils

  1. 访问命令输出的admin网址

  2. 该网站首页中会有一个获取授权的豆腐块,在其中输入一个邮箱然后点击sign up

  3. 邮箱会收到邮件,根据邮件中的提示,执行edgectl命令行工具应用授权即可

随后即可正常使用Ambassador,几个主要网址:

/edge_stack/admin/ 或首页点击空白处即可进入 管理端,提供服务监控及Mapping等的图形化配置

/docs/ 本地文档,这个网址就是通过Mapping配置的请求转发,关于用yaml配置Mapping做普通的http转发的示例,可见Ambassador官网Get Start

Istio服务网格

参照Istio官网Get Start https://istio.io/docs/setup/getting-started/

下载istioctl客户端后,kubectl切换到目标集群,执行一下命令即可安装Istio

istioctl manifest apply --set profile=demo

对希望开启自动istio sidecar代理注入的k8s命名空间,执行一下命令

kubectl label namespace <命名空间名称> istio-injection=enabled

然后,正常部署gRPC服务,正常访问即可,代码无需做任何改动,即可实现gGPC负载均衡

其它Istio标签配置,路由配置,TLS证书,请求头处理,服务跟踪,金丝雀发布等,参考本项目中deloy中相关内容即可

更多内容参考Istio文档

相关资源清理语句

# ambassador相关
kubectl delete service ambassador ambassador-admin ambassador-redis -n ambassador
kubectl delete deployment ambassador ambassador-redis -n ambassador
kubectl delete crds authservices.getambassador.io consulresolvers.getambassador.io filterpolicies.getambassador.io filters.getambassador.io hosts.getambassador.io kubernetesendpointresolvers.getambassador.io kubernetesserviceresolvers.getambassador.io logservices.getambassador.io mappings.getambassador.io ratelimits.getambassador.io ratelimitservices.getambassador.io tcpmappings.getambassador.io tlscontexts.getambassador.io tracingservices.getambassador.io modules.getambassador.io -n ambassador
kubectl delete secret ambassador-edge-stack ambassador-internal -n ambassador
kubectl delete namespace ambassador

# 后端服务
kubectl delete service grpc-example py-grpc-example quote -n prd
kubectl delete deployment grpc-example py-grpc-example quote -n prd

# helm相关
kubectl delete service helm-api tiller-deploy -n kube-system
kubectl delete deployment tiller-deploy -n kube-system

# ingress-nginx相关
kubectl delete secret ex-wph-secret gw-wph-secret -n prd
kubectl delete secret ex-wph-secret gw-wph-secret -n ingress-nginx
kubectl delete ingress py-grpc-example grpc-example -n prd
kubectl delete deployment nginx-ingress-controller -n ingress-nginx
kubectl delete service ingress-nginx-service -n ingress-nginx
kubectl delete namespace ingress-nginx