我有一个“UI”和一个“API”微服务,我正在启用 Istio 的情况下部署在 k8s 默认命名空间上。我的 k8s 环境是一个开发箱,没有外部负载均衡器。
UI的端口配置为80(service port):80(container port in pod)。 API的端口配置为8000(服务端口):80(pod中的容器端口)
我必须为外部流量公开这两个微服务,因为有些人可能会使用“UI”,而有些人可能会直接调用“API”(通过邮递员)来满足他们的请求。
当这些微服务作为没有 k8s 层的简单 docker 容器运行时,用户直接使用
host.example.com
进行 UI 和 host.example.com:8000/api
进行 API 调用(API 调用是 JSON-RPC)。
我为这两个微服务设置了网关和虚拟服务:
对于用户界面:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: ui-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- host.example.com
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ui-vs
spec:
hosts:
- host.example.com
gateways:
- ui-gateway
http:
- route:
- destination:
port:
number: 80
host: ui --> name of k8s svc
对于API:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: api-gateway
spec:
selector:
istio: ingressgateway # use Istio default gateway implementation
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- host.example.com
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: api-vs
spec:
hosts:
- host.example.com
gateways:
- api-gateway
http:
- route:
- destination:
host: api -> name of api service
port:
number: 8000
现在通过 Istio 文档(在浏览器上访问)在浏览器中访问这个 UI,我需要通过
${INGRESS_HOST}:${INGRES_PORT}
访问它。
就我而言:
INGRESS_HOST=host.example.com
INGRESS_PORT=31165
因此访问 http://host.example.com:31165 会加载 UI,我现在如何通过邮递员等在
host.example.com
上从外部访问 API 微服务?无法从外部访问 8000 API 端口。我想这一切都必须通过 31165,但是我需要使用什么路由来直接访问 API?如果有的话,我需要在我的设置中做哪些改变?我刚刚开始使用 Istio,所以我们将不胜感激。
一个选项是添加主机标头。
本地开发人员更简单的方法是使用
*.nip.io
地址。
如果你的入口有一个IP(在
k get svc -n istio-system istio-ingressgateway
的结果中寻找一个外部IP),那么这就是你在url中使用的。
例如
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: grafana-virtualservice
namespace: monitoring
spec:
gateways:
- grafana-gateway
hosts:
- grafana.192.168.87.2.nip.io
http:
- route:
- destination:
host: kube-prometheus-stack-grafana
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: grafana-gateway
namespace: monitoring
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- grafana.192.168.87.2.nip.io
port:
name: http
number: 80
protocol: HTTP
如果您创建证书,HTTPS 重定向也可以工作
例如
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: argocd-gateway
namespace: argocd
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- argocd.192.168.87.2.nip.io
port:
name: http
number: 80
protocol: HTTP
tls:
httpsRedirect: true
- hosts:
- argocd.192.168.87.2.nip.io
port:
name: https
number: 443
protocol: HTTPS
tls:
credentialName: argocd.192.168.87.3.nip.io
mode: SIMPLE
最简单的解决方案是将两者组合成一个
VirtualService
并使用类似路径+重写的东西:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-vs
spec:
hosts:
- host.example.com
gateways:
- my-gateway
http:
- match:
- uri:
prefix: /api
rewrite:
uri: /
route:
- destination:
host: api # -> name of api service
port:
number: 8000
- match:
- uri:
prefix: /ui
rewrite:
uri: /
route:
- destination:
port:
number: 80
host: ui # --> name of k8s svc
如果您查询
host.example.com:<nodePort>/api
,您将最终到达api主机,并使用host.example.com:<nodePort>/ui
ui.
您还可以使用子域(
ui.example.com:<nodePort>
和 api.example.com:<nodePort>
)或基于标题的路由。查看docs以获取更多示例。