最近公司产品在适配 openshift 平台,想要弃用掉外部 nginx 的代理,决定使用 redhat 认证过的 serviceMesh 来做代理,也就是将k8s集群外部的流量引入集群内。
istio 的 ServiceEntry
CRD有这个能力,原理与 svc 和 endpoint 是一样的,将外部流量作为 endpoint 引入 ServiceEntry
中,并赋予自定义域名,就像集群内部的 [svc_name].[namespace].svc.cluster.local
一样。
ServiceEntry
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: xxx
namespace: yyy
spec:
hosts:
- test.feiyiblog.com # 这里改为自定义域名
addresses:
- "10.10.26.110/32" # 代表所处网段,这里也可以写10.10.26.0/24
ports:
- number: 5670 # 外部服务的访问端口
name: http # 如果是https就改为https
protocol: HTTP # 如果是HTTPS就改为HTTPS
location: MESH_EXTERNAL # 表示这个域名是从外部引入的
exportTo: # 文件中配置的hosts的生效命名空间
- "*"
resolution: STATIC # 域名解析后的upstream
endpoints:
- address: 10.10.26.110 # 实际外部服务的 IP,支持负载均衡
将上述内容更改为自己所需后,在集群内创建,ServiceEntry
的特点是,创建后,只能是网格内的 pod 才能通过域名访问。
因为我也接触 istio 不多,这里的网格内指的是,创建 pod 时启动了 istio 的 sidecar,sidecar 代理 Envoy 代理,可以将流量拦截在 sidecar 中,再通过 istio 内部处理流量后转发,而外部流量引入网格的功能仅仅是众多功能中的冰山一角。
网格内验证
命名空间需要支持注入 sidecar
oc label ns [namespace] istio-injection=enabled --overwrite
创建一个支持 curl 的 pod 来验证:注意要添加 sidecar.istio.io/inject: 'true'
的 label 才会被注入 sidecar
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-curl
namespace: yyy
spec:
replicas: 1
selector:
matchLabels:
app: test-curl
template:
metadata:
labels:
app: test-curl
sidecar.istio.io/inject: 'true'
spec:
containers:
- name: curl
image: dockerproxy.net/curlimages/curl
command: [ "sleep", "infinity" ]
进入 pod 验证
kubectl exec -it -n [namespace] test-curl-xxxxx-yyyy -- curl http://test.feiyiblog.com:5670
返回正常则识别没问题
Gateway
创建 ServiceEntry
仅仅是集群内部访问,集群外的环境是无法访问的,我的需求是要替代 nginx 代理
Istio 的 Gateway
和 VirtualService
具有暴露服务到外部的功能
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: test-gateway
namespace: yyy
spec:
selector:
istio: ingressgateway # 用来匹配ingressgateway
servers:
- hosts:
- 'test.feiyiblog.com' # 外部访问要使用的域名
port:
number: 80 # 这里使用了ingressgateway的80端口
protocol: HTTP
name: http1
VirtualService
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: external-dbgpt
namespace: yyy
spec:
gateways:
- yyy/test-gateway # 对应gateway的namespace/name,同命名空间可省略namespace
hosts:
- "*"
http:
- route:
- destination:
host: test.feiyiblog.com # 对应ServiceEntry中的hosts域名
port:
number: 5670
集群外部访问:http://test.feiyiblog.com
集群内部访问:http://test.feiyiblog.com:5670
拓展
我这里还有一个服务默认访问 /
会返回404,通过 VirtualService
来做路径重定向,服务本身要访问到 /anything/
会自动跳转到 /angything/#/home
,所以我这只重定向到 /qanything/
http:
- match:
- uri:
exact: /
redirect:
uri: /qanything/ # 当访问 / 时重定向到 /qanything/
- route:
- destination:
host: qanything.feiyiblog.com
port:
number: 8777