内容简介:Envoy/Istio 1.1 中有个有趣的新特性:负载均衡提供了接下来首先做一些琐碎的安装工作,这里选择了常见的 GCP 作为测试环境,Istio 版本为 1.1.2。为了方便演示,我们给惯用的 flaskapp 和 sleep 加上
Envoy/Istio 1.1 中有个有趣的新特性:负载均衡提供了 区域感知 的能力。简单说来,就是在分区部署的较大规模的集群,或者公有云上,Istio 负载均衡可以根据节点的区域标签,对调用目标做出就近选择。在跨区部署的应用中,原始的 Kubernetes 负载均衡可能会把来自 A 区的请求发送给远在 B 区的服务,造成高成本的跨区调用。要缩减这种损耗,通常都需要实现更多的逻辑,Istio 的区域感知特性在某种程度上提供了一种解决办法。
准备工作
接下来首先做一些琐碎的安装工作,这里选择了常见的 GCP 作为测试环境,Istio 版本为 1.1.2。
-
在 GCP 的
us-central1
创建一个区域集群:$ gcloud beta container clusters create "standard-cluster-1" \ ... --no-enable-basic-auth \ --cluster-version "1.12.6-gke.10" \ --machine-type "n1-standard-1" --image-type "COS" \ ... --num-nodes "2" \ --no-enable-cloud-logging --no-enable-cloud-monitoring \ ...--no-enable-ip-alias \ --addons HorizontalPodAutoscaling \ --enable-autoupgrade --enable-autorepair
-
获取本地认证,为
kubectl
生成context
:$ gcloud beta container clusters get-credentials \ standard-cluster-1 --region us-central1 \ --project dustise-mesh-lab
-
查看节点标签,这里会看到不同的节点会使用 区域标签 进行标识:
$ kubectl get nodes --show-labels ... failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a ... failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-c ...
-
为 Istio 准备 RBAC:
$ kubectl create clusterrolebinding cluster-admin-binding \ --clusterrole=cluster-admin \ --user=$(gcloud config get-value core/account)
-
初始化 Istio CRD:
$ kubectl create namespace istio-system $ helm template install/kubernetes/helm/istio-init --name istio-init --namespace istio-system | kubectl apply -f - configmap/istio-crd-10 created configmap/istio-crd-11 created serviceaccount/istio-init-service-account created clusterrole.rbac.authorization.k8s.io/istio-init-istio-system created clusterrolebinding.rbac.authorization.k8s.io/istio-init-admin-role-binding-istio-system created job.batch/istio-init-crd-10 created job.batch/istio-init-crd-11 created
-
安装 Isto :
$ helm template install/kubernetes/helm/istio \ --name istio --namespace istio-system \ --values install/kubernetes/helm/istio/values-istio-demo-auth.yaml | kubectl apply -f - ...... handler.config.istio.io/kubernetesenv created rule.config.istio.io/kubeattrgenrulerule created rule.config.istio.io/tcpkubeattrgenrulerule created kubernetes.config.istio.io/attributes created destinationrule.networking.istio.io/istio-policy created destinationrule.networking.istio.io/istio-telemetry created
-
标记
default
命名空间,启动自动注入:
$ kubectl label namespaces default istio-injection=enabled --overwrite kubectl namespace/default labeled
部署应用
为了方便演示,我们给惯用的 flaskapp 和 sleep 加上 NodeSelector
,要求按照版本分布到不同区域的节点上,例如:
nodeSelector: failure-domain.beta.kubernetes.io/zone: us-central1-f
标签内容可以参照上文 kubectl get nodes --show-labels
的显示结果。
修改了部署清单之后,就可以部署了:
$ kubectl apply -f flaskapp/flaskapp.istio.yaml service/flaskapp created deployment.extensions/flaskapp-v1 created deployment.extensions/flaskapp-v2 created $ kubectl apply -f sleep/sleep.istio.yaml service/sleep created deployment.extensions/sleep-v1 created deployment.extensions/sleep-v2 created deployment.extensions/sleep-v3 created
稍候片刻,查看部署结果:
$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE flaskapp-v1-b9644bd75-g82nj 2/2 Running 0 92m 10.40.4.9 gke-standard-cluster-1-default-pool-0570ecb1-lm7q <none> flaskapp-v2-77d648fbd-cvfql 2/2 Running 0 92m 10.40.3.5 gke-standard-cluster-1-default-pool-f2347d89-q79k <none> sleep-v1-84c85c8946-c7bvc 2/2 Running 0 91m 10.40.1.3 gke-standard-cluster-1-default-pool-0570ecb1-1qnq <none> sleep-v2-57cf55db78-vrvtc 2/2 Running 0 92m 10.40.3.7 gke-standard-cluster-1-default-pool-f2347d89-q79k <none>
和上文比较,可以看到,sleep 和 flaskapp 的 v1、v2 两个版本,分别运行在 us-central1-a
和 us-central1-f
中。
验证路由的区域感知功能
接下来分别从网格内部和 Ingress Gateway 来验证这一功能。
服务网格内部请求
$ kubectl exec -it -c sleep sleep-v1-84c85c8946-c7bvc bash # for i in {1..10}; do http --body http://flaskapp/env/version ; done v1 v2 v2 v1 ...
可以看到,请求被随机分配到不同的版本,也就是说,此时的调用是无视分区的。接下来我们设置 Pilot 的环境变量,启用区域感知功能,过程很简单,给它的 Pod 加入环境变量 PILOT_ENABLE_LOCALITY_LOAD_BALANCING
,并任意赋值即可,例如:
- name: PILOT_TRACE_SAMPLING value: "100" ... - name: PILOT_ENABLE_LOCALITY_LOAD_BALANCING value: "1" ...
再次进入 Pod 访问 flaskapp 服务:
$ kubectl exec -it -c sleep sleep-v1-84c85c8946-c7bvc bash # for i in {1..10}; do http --body http://flaskapp/env/version ; done v1 v1 v1 ... # exit $ kubectl exec -it -c sleep sleep-v2-57cf55db78-vrvtc bash # for i in {1..10}; do http --body http://flaskapp/env/version ; done v2 v2 v2 ...
可以看到,果然按照我们预想的情况,不同区域的请求,会交由不同区域的服务来进行响应。如果此时删除同区的目标负载,会发现开始平均访问其它区的服务。
Ingress 网关
Ingress 网关控制器在网格内同样也会分配到不同的节点上,因此也同样会受到区域的影响。例如我们为 flaskapp 创建一个 VirtualService
+ Gateway
的组合,引入外部流量:
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: flaskapp-gateway spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "flaskapp.example.com" --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin spec: hosts: - "flaskapp.example.com" gateways: - flaskapp-gateway http: - route: - destination: port: number: 80 host: flaskapp
提交后,可以在外使用 curl --resolve
来验证:
$ export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}') $ for i in {1..10}; do curl --resolve flaskapp.example.com:80:$INGRESS_HOST http://flaskapp.example.com/env/version ; done v3v3v3v3v3v3v3v3v3v3
可以看到,对 Ingress Gateway 进入的流量,区域感知功能也是同样生效的。
区域间分流
如果只是简单的就近原则,虽然方便,但也难免有些枯燥,例如我的集群中的三个分区之间存在优先次序,或者强行指派一个区的请求需要由指定的其它分区的服务进行处理,又该怎样呢?
istio-system 中有个叫做 istio 的 configmap,其中包含了 Istio 的一些核心配置 ,里面的 LocalityLoadBalancerSetting ,包含了对区域感知负载均衡的一些行为配置。例如我们分配所有分区的流量,都分配到前面两个区域:
localityLbSetting: distribute: - from: us-central1/us-central1-a/* to: us-central1/us-central1-a/*: 90 us-central1/us-central1-b/*: 10 - from: us-central1/us-central1-b/* to: us-central1/us-central1-a/*: 90 us-central1/us-central1-b/*: 10 - from: us-central1/us-central1-f/* to: us-central1/us-central1-a/*: 90 us-central1/us-central1-b/*: 10
应用之后,重启 Galley、Pilot、Injector,并重新注入应用,再次在不同分区的 sleep 容器中进行测试。会发现其中的请求呈现了符合配置要求的分配,并且没有发送到 us-central1-b 区。
事实上本次测试,并没有发现比率生效,仅达到有或无的区别。
结论
目前的分区域分流功能似乎还有些问题,但是不失为一个新的服务亲和思路。 分区是基于 Kubernetes Node 标签完成的,通过对标签的调整(例如机柜、楼层),能够比较方便的在 无侵入 的情况下,实现就近调用,对服务的跨区 HA,有一定的辅助作用。
参考链接
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- WinSrv2019使用DNS构建基于地理位置感知的应用负载均衡
- 庖丁解LevelDB之整体感知
- 态势感知之Malware Callback
- 统计学习方法-感知机笔记
- 感知器:神经网络的主要部分
- 能够自动感知背景主色调的按钮
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。