Istio - Ingressgateway实践
文章目录
1. 故事背景
这个没背景,用了Istio,就代表了TA接管了整个网络,进进出出就得经过TA,这样你才可以得到好处。但是不是说啥也不干就可以随进随出,嗯,你得告诉TA。
2. 提前准备
- 本次试验是在
CentOS 7.4 64位
系统,root
用户下进行 - Kubernetes(k8s)集群
- istio版本
1.0.2
3. 实践
3.1 简述
参考官网文档:配置请求路由和用 HTTPS 加密 Gateway
在公有云(阿里云)上,service
支持LoadBalancer
,而自建的不支持。当service
指定类型为LoadBalancer
,阿里云会在负载均衡服务里,新增一个实例,同时会提供一个公网IP,通过这个IP就可以访问到对应的service
,而ingressgateway
默认就是这种方式。在这一点上,我的自建集群(用于测试环境)和阿里云K8S集群(用于生产环境)在使用上会有少许差别。
现在我先描述大家共同的部分,也是属于Istio的部分。到最后,再把少许的差别补充上,仅在测试环境需要。
3.2 配置Http
任务:把域名foo.bar.com
指向k8s服务bar
前置条件:
- namespace为foo
- 拥有service,名为bar,端口80
- 假设拥有域名 foo.bar.com
接下来,我们需要配置Gateway
和VirtualService
,如果你用过nginx,我们可以粗略的类比为server
。其中Gateway
相当于配置了server
的基本信息,而VirtualService
相当于配置了location
。前者主要是配置域名端口等,后者配路由规则。
---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bar
namespace: foo
spec:
selector:
istio: ingressgateway # 此配置必须有
servers:
- port:
number: 80
name: http-bar
protocol: HTTP
hosts:
- foo.bar.com
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bar
namespace: foo
spec:
hosts:
- foo.bar.com
gateways:
- bar
http:
- match:
- uri:
prefix: "/"
route:
- destination:
host: bar
port:
number: 80
3.3 配置Https
现在Https基本上已经是标配,这里也少不了,我们需要做三件事:
创建一个Kubernetes sceret对象,用于保存服务器的证书和私钥。具体说来就是使用 kubectl 命令在命名空间 istio-system 中创建一个 secret 对象,命名为
istio-ingressgateway-certs
。Istio 网关会自动载入这个 secret。把证书和私钥放于目录
/etc/istio/ingressgateway-certs
,需要注意的是,这里指的是宿主机器(集群的Master),又或者是你执行kubectl命令的机器,因为我是在Master执行的命令,非本机上没验证过。在
Gateway
上增加对https的配置声明。
第一件事 - 配置Secret
为了服务多个域名,我使用了Opaque
类型,命名规则使用了{domain}.crt
和{domain}.key
。需要注意的是,对应的内容需要使用base64编码!
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: istio-ingressgateway-certs
namespace: istio-system
data:
foo.bar.com.crt: {your-crt-content}
foo.bar.com.key: {your-key-content}
foo2.bar.com.crt: {your-crt-content}
foo2.bar.com.key: {your-key-content}
第二件事 - 放置证书和私钥
把证书和私钥放于目录/etc/istio/ingressgateway-certs
下,命名规则和第一步一致,如下:
# 注意,这里只需要把文件原封不动的放进来,不需要base64编码
.
├── foo.bar.com.crt
├── foo.bar.com.key
├── foo2.bar.com.crt
└── foo2.bar.com.key
第三件事 - 增加配置
以下是修改后的完整配置
---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bar
namespace: foo
spec:
selector:
istio: ingressgateway # 此配置必须有
servers:
- port:
number: 80
name: http-bar
protocol: HTTP
hosts:
- foo.bar.com
# 以下是新增内容
tls:
httpsRedirect: true # 强制跳转至https协议
- port:
number: 443
name: https-bar
protocol: HTTPS
tls:
mode: SIMPLE
serverCertificate: /etc/istio/ingressgateway-certs/foo.bar.com.crt
privateKey: /etc/istio/ingressgateway-certs/foo.bar.com.key
hosts:
- foo.bar.com
# 以上是新增内容
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bar
namespace: foo
spec:
hosts:
- foo.bar.com
gateways:
- bar
http:
- match:
- uri:
prefix: "/"
route:
- destination:
host: bar
port:
number: 80
3.4 少许差别
一般到了这一步,只需要把域名解析指向到负载均衡的IP,就可以生效。(至少在阿里云K8S集群是这样的)。
然而在我自建的集群里,我早前已经使用了另外一个名为traefik
的Ingress,而且自建并不支持LoadBalancer
。所以在还没用Istio前,整条链路是这样的。
域名解析 👉 自行创建的负载均衡实例(公有IP) 👉 Traefik Ingress 👉 Service
当我使用了Istio后,在这个环境下,负载均衡貌似没办法直接到达Istio的Ingressgateway,具体原因我没有深究,就当是的情况,我用了取巧的方式,把traefik
的Ingress再转发给Ingressgateway
,具体如下:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: bar
namespace: istio-system
annotations:
kubernetes.io/ingress.class: traefik
traefik.frontend.passHostHeader: "true"
spec:
rules:
- host: 'foo.bar.com'
http:
paths:
- path: /
backend:
serviceName: istio-ingressgateway
servicePort: 80
所以最终整条链路如下:
域名解析 👉 自行创建的负载均衡实例(公有IP) 👉 Traefik Ingress 👉 Ingressgateway 👉 Service
4. 总结
总的来说,配置还是比较直接简单,至于上面说的少许差距,在日后,有机会可深入再了解一下。这里肯定有更好的更简单的解决方案。
文章作者 xifan
上次更新 2018-12-01