Kubernetes 是容器的编排工具,可以非常方便的进行大规模的容器调度。通过这种模式,将传统的软件模式改造成微服务模式。这种微服务的架构模式,将复杂系统切分为数十乃至上百个小服务,每个服务负责实现一个独立的业务逻辑。这些小服务易于被小型的软件工程师团队负责,这带来了语言和框架选择灵活性,并可以缩短应用开发上线时间,可根据不同的工作负载和资源要求对服务进行独立缩扩容等优势。但另一方面,当应用被拆分为多个微服务进程后,进程内的方法调用变成了了进程间的远程调用。这就引入了对大量服务的连接、管理和监控的复杂性。
在微服务模式中,如何实现各个进程间的通信,是微服务中一个重要的部分。
Istio 是 CNCF 提出的由 Google、IBM、Lyft 等共同开源的 Service Mesh 框架。是连接 Kubernetes 和 Serverless 架构的重要基础设施层。
一 Istio 简介
1 Istio
Isito 主要实现以下三个功能:
1.监控
2.安全
3.流量管理
其架构图如下:
其中,Citadel 是服务间认证加密的组件,Pilot 是服务间通信策略的控制层面,Galley 负责检查用户的策略配置。
其中 Pilot 是数据层面的控制组件,Proxy 是数据层面的执行组件。
2 流量管理
根据前面的描述,我们知道,在 Istio 中,流量管理通过 Pilot 和 Envoy 实现。Pilot 对 Envoy 通过下面几个组件进行流量策略的控制:
1.Gateway - 是 Istio 的 IngressGateway,流量通过这个 Gateway 进入 VirtualService。
2.VirtualService - 通过
a.HTTP header
b.URIs
c.Ports
d.sourceLables
对流量进行分类,分发到不同的 Service 上。
3.DestinationRule -定义了流量如何分发到 Pod 上,比如负载均衡策略、Session Affinity 等。同时还可以通过 Label 对同一组服务进行更细致的分组,比如 ServiceA-v1、ServiceA-v2。用于流量的 splitting。
本文将介绍在 GKE 上如何实现通过 Isito 实现 service 间流量的控制。
二 环境准备
1 GKE
在 Google Cloud 上创建 GKE Cluster,enable Istio,具体命令行如下:
gcloud beta container clusters create "istiodemo" --zone "us-central1-c" --num-nodes "4" --enable-stackdriver-kubernetes --enable-ip-alias --addons HttpLoadBalancing,Istio
复制代码
通过 Console 界面查看创建的 GKE Cluster:
查看 Istio 相关的 workload:
2 本地安装 Istioctl 工具
本文采用 Istio1.4.3:
export ISTIO_VERSION=1.4.3
curl -L https://git.io/getLatestIstio | ISTIO_VERSION=$ISTIO_VERSION sh -
复制代码
检查 Istio 版本
./istioctl version --short
client version: 1.4.3
control plane version: 04871014b586f671f2ce14646e5061945f75c9c5
data plane version: (1 proxies)
复制代码
查看 istio 状态:
这里采用 Istio 的 Demo profile,可以用下面的命令:
istioctl manifest apply --set profile=demo
复制代码
可以看到各种监控的工具都安装完成:
3 安装 bookinfo
Bookinfo 跟随 Istio 的安装包一起下载到本地目录。Bookinfo 的软件架构如下:
安装过程如下:
kubectl label namespace default istio-injection=enabled
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
复制代码
查看 pod、service 信息:
红框表示出来的,都是 bookinfo 相关的 deployment。
红框表示出来的,都是 bookinfo 相关的 service。
查看应用的状态:
kubectl exec -it $(kubectl get pod -l app=ratings \
-o jsonpath='{.items[0].metadata.name}') \
-c ratings -- curl productpage:9080/productpage \
| grep -o "<title>.*</title>"
复制代码
Simple Bookstore App
三 通过 Istio 进行流量管理
1 配置 Gateway 和 VirtualService 使外部可以访问
配置 Istio Ingress Gateway,使外部可以访问 bookinfo:
kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
复制代码
配置文件如下:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "*"
gateways:
- bookinfo-gateway
http:
- match:
- uri:
exact: /productpage
- uri:
prefix: /static
- uri:
exact: /login
- uri:
exact: /logout
- uri:
prefix: /api/v1/products
route:
- destination:
host: productpage
port:
number: 9080
复制代码
查看 GW 的公网地址:
kubectl get svc -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP
istio-citadel ClusterIP 10.0.12.62 <none>
istio-galley ClusterIP 10.0.5.255 <none>
istio-ingressgateway LoadBalancer 10.0.13.240 35.202.166.31
istio-pilot ClusterIP 10.0.6.138 <none>
istio-policy ClusterIP 10.0.2.42 <none>
istio-sidecar-injector ClusterIP 10.0.0.149 <none>
istio-telemetry ClusterIP 10.0.15.195 <none>
promsd ClusterIP 10.0.5.191 <none>
复制代码
可以看到 istio-ingressgateway 的公网地址是 35.202.166.31。通过这个 IP 地址访问 bookinfo:
curl -s http://$Gateway_URL/productpage | grep -o "<title>.*</title>"
复制代码
Simple Bookstore App
通过 Kiali 界面 istioctl dashboard kiali: admin/admin 可以看到 Micro Service 间拓扑关系:
2 部署 DestinationRule
kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml
复制代码
配置文件内容:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: productpage
spec:
host: productpage
subsets:
- name: v1
labels:
version: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- name: v3
labels:
version: v3
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: ratings
spec:
host: ratings
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- name: v2-mysql
labels:
version: v2-mysql
- name: v2-mysql-vm
labels:
version: v2-mysql-vm
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: details
spec:
host: details
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
---
复制代码
这个 Destination Rule 中包含每个子应用的不同版本。此时在刷新网页时,可以看到 3 个版本的 Review。
通过脚本持续的访问页面:
for i in {1..100};
do curl -o /dev/null -s -w %{http_code} \
http://35.188.64.161/productpage;
sleep 1;
done
复制代码
此时流量是基本均担的:
3 配置 VirtualService 流量导向 v1
kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
复制代码
配置文件内容:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: productpage
spec:
hosts:
- productpage
http:
- route:
- destination:
host: productpage
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- route:
- destination:
host: ratings
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: details
spec:
hosts:
- details
http:
- route:
- destination:
host: details
subset: v1
---
复制代码
可以看到,所有的流量都导向 v1 的 subset。包括 productpage、reviews、ratings、details。此时再刷新页面,都只有相同的内容。
4 配置 VirtualService 通过识别 http header 内容进行控制流量
VirtualService 可以通过 http header 中的内容对流量进行控制。这里采用用户名来进行控制:
kubectl apply \
-f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml
复制代码
配置文件内容:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
复制代码
可以看到,如果用户是 jason,流量将导向 v2,否则导向 v1.
使用 jason 登录,可以看到 review 的页面是下面黑色的星星。是 v2 的 subset。
退出登录,或用随意的名字登录,都是没有星星的 v1 版本:
5 配置 VirtualService 流量导向 v1 和 v3 各一半
清除上面实验的配置:
kubectl delete \
-f samples/bookinfo/networking/virtual-service-all-v1.yaml
复制代码
此时流量会在 3 个版本间轮训。
下面的配置会只导向 v1:
kubectl apply \
-f samples/bookinfo/networking/virtual-service-all-v1.yaml
复制代码
采用下面的配置,把流量在 v1 和 v3 间各 50%分流:
kubectl apply \
-f samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml
复制代码
配置的具体内容:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 50
- destination:
host: reviews
subset: v3
weight: 50
复制代码
此时可以看到流量在 v1 和 v3 间轮询:
6 配置 VirtualService 流量导向 v3
应用如下配置:
kubectl apply \
-f samples/bookinfo/networking/virtual-service-reviews-v3.yaml
复制代码
配置的具体内容如下:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v3
复制代码
这样流量都导向 v3:
7 配置 VirtualService 流量导向 v1 和 v2,比例 9:1
应用如下配置:
kubectl apply \
-f samples/bookinfo/networking/virtual-service-reviews-90-10.yaml
复制代码
配置的具体内容如下:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 90
- destination:
host: reviews
subset: v2
weight: 10
复制代码
此时 90%流量导向 v1,10%的流量导向 v2。可以通过多刷页面看到 v2 的黑色星星页面。
四 总结
通过在 GKE 上的 Istio 的 Gateway/VirtualService/DestinationRule 可以非常方便的控制各个微服务间的流量调度。
评论