istio入门玩家笔记
最近需要用 istio-ingress 做一些事情, 所以先在测试环境部署一下 istio 玩一下.
部署 istio
部署 istio 选择了 Helm 来生成部署文件, 关于 Helm 可以见 Helm入门笔记 因为暂时只需要 istio-ingress 的功能,所以裁剪了许多不需要的组件, 最终的 Helm template 如下:
helm template /opt/istio-0.8.0/install/kubernetes/helm/istio \
--name istio \
--namespace istio-system \
--set sidecarInjectorWebhook.enabled=false \
--set galley.enabled=false \
--set mixer.enabled=false > ~/istio-min.yaml
这里还要注意的是, helm 并不会帮你写创建 --namespace istio-system
的配置,所以在apply前要记得先把 namespace 创建好. 在正确apply以后可以看到 istio-system 这个 namespace 下的服务有:
- istio-citadel
- istio-cleanup
- istio-egressgateway
- istio-ingress
- istio-ingressgateway
- istio-pilot
- prometheus
因为没有启用 mixer 所以按这个方式去启动 istio 以后 envoy 会报错
[libprotobuf ERROR src/istio/mixerclient/report_batch.cc:83] Mixer Report failed with: UNAVAILABLE:Cluster not available
在之前产生的安装yaml里找到
# To disable the mixer completely (including metrics), comment out
# the following lines
mixerCheckServer: istio-policy.istio-system.svc.cluster.local:15004
mixerReportServer: istio-telemetry.istio-system.svc.cluster.local:15004
注释这两行, 但是很奇怪的是 mixerCheckServer 和 mixerReportServer 提交数据给名叫 istio-policy 和 istio-telemetry 的服务,还不清楚具体的数据流是怎么传输的.
在折腾 istio-ingress 前多嘴一句, 既然安装了 istio 要体验它自动给 pods 加上 sidecar 的话, 可以参考 https://istio.io/docs/setup/kubernetes/sidecar-injection/#automatic-sidecar-injection 在新建 namespace 的时候加入 istio-injection=enabled
就可以了~
$ kubectl label namespace <namespace> istio-injection=enabled
$ kubectl create -n <namespace> -f <your-app-spec>.yaml
准备好测试服务
之前用gin写了一个非常简单的http api, 根据发的版本 v1
和 v2
,调用 /test/release
可以获得当前发布的版本和对应的容器名称,例如对 test-service-a
这个域名:
curl -HHost:test-service-a.deploy.com http://10.7.3.194:31380
返回
{
"hostname":"tapi-5c745dbdf8-v44ws",
"message":"service available",
"release_version":"v1.0",
"status":200
}
返回的版本号是v1.0, 对 test-service-b
这个域名:
curl -HHost:test-service-b.deploy.com http://10.7.3.194:31380
返回
{
"hostname":"tapi-v2-7976fddd8-tzd9m",
"message":"service available",
"release_version":"v2.0",
"status":200
}
版本号为v2.0.
在正常部署服务pod和service后,暴露两个 ClusterIP 供 istio-ingress 调用, kubectl -n test-deploy get service
的结果如下:
test-deploy tapi-service-only-v1 ClusterIP 172.21.138.249 80/TCP app=tapi-service,deployVersion=v1.0
test-deploy tapi-service-only-v2 ClusterIP 172.21.57.248 80/TCP app=tapi-service,deployVersion=v2.0
首先在 istio-ingress 里部署一个 Gateway, istio 的 Gateway 作为一个负载均衡器工作在ingress的位置监听端口,接收HTTP/TCP请求并转发给后端. 一个简单的 Gateway 配置如下:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: tapi-gateway
namespace: test-deploy
spec:
selector:
istio: ingressgateway # 用Istio默认的gateway,在service里selector为istio=ingressgateway
servers:
- port:
number: 80 # 80端口
name: http
protocol: HTTP # 可以是HTTP\HTTP2等见文档
hosts:
- "*" # 允许的域名
在定义好负载均衡器后,还要定义具体的后端转发流程, 在 istio 里的 VirtualService 用来定义请求的转发规则和对应的后端服务, 下面的例子里定义了2个 VirtualService ,后端服务分别为同一个服务的 v1 和 v2 版, 同时定义了 Gateway 为前面创建的 tapi-gateway.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: test-virtualservice-v1
namespace: test-deploy
spec:
hosts:
- "test-service-a.deploy.com" # 监听的域名, 可以有多个
gateways:
- tapi-gateway # 对应使用的gateway, 可以有多个
http:
- match: # 对应uri的转发策略
- uri:
prefix: /
route:
- destination: # 后端的服务
port:
number: 80
host: tapi-service-only-v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: test-virtualservice-v2
namespace: test-deploy
spec:
hosts:
- "test-service-b.deploy.com"
- "tapi-*.deploy.com"
gateways:
- tapi-gateway
http:
- match:
- uri:
prefix: /
route:
- destination:
port:
number: 80
host: tapi-service-only-v2
其中 match 可以支持非常多的匹配形式, 例如 uri 前缀, header, cookie 等, 详情见 https://istio.io/docs/reference/config/istio.networking.v1alpha3/#Gateway
destination 可以配置多个后端, 并支持权重配置 https://istio.io/docs/reference/config/istio.networking.v1alpha3/#DestinationWeight
最终可以见到在不同 Host 请求 test-service-a.deploy.com
和 test-service-b.deploy.com
时得到不同的后端服务.
Gateway 和 VirtualService 姿势说明
- 对不同的服务 使用不同的
namespace
和 Gateway, VirtualService 隔离; - 尽量不要在 Gateway 的 host 里写
*
匹配以免发生一些自己都不知道结果是怎么样的事情; - 当前 Gateway 的 TLS 配置存在时必须保证正确否则会把整个 Gateway 带挂起不来;
- 要配置多张 TLS 证书, 参考 https://github.com/istio/istio/issues/7658
- host 匹配重复域名时必然会发生错误, istio并不会替你检查, 要避免这一点