接上文《使用 k3s 搭建 cilium + istio 实验环境》
除了支持 Kubernetes Ingress,Istio还提供了另一种配置模式,Istio Gateway。与Ingress
相比,Gateway
提供了更广泛的自定义和灵活性,并允许将 Istio 功能(例如监控和路由规则)应用于进入集群的流量。
下面介绍如何使用 IstioGateway
来将服务暴露至服务网格之外。
一、开始之前
1. 安装 Istio 环境
上文已经使用 demo 配置安装了 Istio 环境,包含 istio-ingressgateway 组件
2. 安装 LoadBalancer 服务
每个Gateway
由类型为 LoadBalancer 的服务支撑,该服务的外部负载均衡器 IP 和端口用于访问 Gateway。k3s 安装的时候禁用了默认的 servicelb 服务,需要手动安装其他 LB 服务,这里安装MetalLB。
使用一下命令安装 MetalLB (native模式)
1
|
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.10/config/manifests/metallb-native.yaml
|
配置 MetalLB 地址池:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
cat <<EOF > IPAddressPool.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
# 可分配的 IP 地址,可以指定多个,包括 ipv4、ipv6
- 192.168.10.0/24
EOF
kubectl apply -f IPAddressPool.yaml
|
3. 部署示例应用
启动 httpbin 样例,用作用口流量的目标服务:
1
|
kubectl apply -f istio-1.18.2/samples/httpbin/httpbin.yaml
|
本文旨在展示如何使用网关控制到“Kubernetes 集群”中的入口流量,无论是否启用 Sidecar 注入都可以启动httpbin
服务(即目标服务可以在 Istio 网格内,也可以在 Istio 网格外)。
二、使用网关配置 Ingress
IngressGateway
描述在网格边界运作的负载均衡器,用于接收传入的 HTTP/TCP 连接。 它会配置暴露的端口、协议等,但与Kubernetes Ingress 资源不同,不会包括任何流量路由配置。 转而使用路由规则来配置入口流量的流量路由,这与内部服务请求所用的方式相同。
使用以下步骤为 HTTP 流量在 80 端口上配置Gateway
(Istio APIS为例)
创建Istio Gateway:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: httpbin-gateway
spec:
selector:
istio: ingressgateway # use Istio default gateway implementation
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "httpbin.example.com"
EOF
|
通过Gateway
为进入的流量配置路由:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- "httpbin.example.com"
gateways:
- httpbin-gateway
http:
- match:
- uri:
prefix: /status
- uri:
prefix: /delay
route:
- destination:
port:
number: 8000
host: httpbin
EOF
|
已为httpbin
服务创建了虚拟服务配置,包含两个路由规则,允许流量流向路径/status
和/delay
。
三、确定 Ingress IP 和端口
每个Gateway
由类型为 LoadBalancer 的服务支撑。 该服务的外部负载均衡器 IP 和端口用于访问 Gateway。
设置INGRESS_HOST
和INGRESS_PORT
环境变量:
1
2
|
export INGRESS_NAME=istio-ingressgateway
export INGRESS_NS=istio-system
|
执行如下指令,确定您的 Kubernetes 集群是否运行在支持外部负载均衡器的环境中:
1
2
3
|
kubectl get svc "$INGRESS_NAME" -n "$INGRESS_NS"
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.43.184.198 192.168.10.0 15021:30789/TCP,80:30472/TCP,443:32302/TCP,31400:32312/TCP,15443:31676/TCP 27h
|
四、访问 Ingress 服务
- 使用 curl 访问 httpbin 服务:
1
2
3
4
5
6
7
8
9
|
# curl -s -I -HHost:httpbin.example.com "http://192.168.10.0:80/status/200"
HTTP/1.1 200 OK
server: istio-envoy
date: Wed, 16 Aug 2023 06:43:17 GMT
content-type: text/html; charset=utf-8
access-control-allow-origin: *
access-control-allow-credentials: true
content-length: 0
x-envoy-upstream-service-time: 20
|
注意上文命令使用-H
标识将 HTTP 头部参数 Host 设置为 “httpbin.example.com”。 该操作是必需的,因为 IngressGateway
已被配置用来处理 “httpbin.example.com” 的服务请求, 而在测试环境中并没有为该主机绑定 DNS,而是简单直接地向 Ingress IP 发送请求。
- 访问其他没有被显式暴露的 URL 时,将看到 HTTP 404 错误:
1
2
3
4
5
|
curl -s -I -HHost:httpbin.example.com "http://192.168.10.0:80/headers"
HTTP/1.1 404 Not Found
date: Wed, 16 Aug 2023 06:45:01 GMT
server: istio-envoy
transfer-encoding: chunked
|
五、使用 Ingress Gateway 服务的 Node Port
如果您的环境不支持外部负载均衡器,则您仍然可以使用istio-ingressgateway
服务的Node Port来实验某些 Istio 特性。
1
2
3
4
5
6
7
8
9
|
# curl -s -I -HHost:httpbin.example.com "http://10.0.0.214:30472/status/200"
HTTP/1.1 200 OK
server: istio-envoy
date: Wed, 16 Aug 2023 07:25:41 GMT
content-type: text/html; charset=utf-8
access-control-allow-origin: *
access-control-allow-credentials: true
content-length: 0
x-envoy-upstream-service-time: 4
|
其中:10.0.0.214 是本机的业务地址,30472 是 istio-ingressgateway 80 的 nodeport 端口
六、通过浏览器访问 Ingress 服务
因为服务运行在 oracle cloud,负载均衡的地址本地无法 web 访问,所以使用本地使用 公网IP:nodeport 进行web 访问
浏览器访问httpbin.example.com→ vps 公网ip:nodeport → istio-ingressgateway 80
首先 vps 安全组放行 istio-ingressgateway 80 的 nodeport 端口: 30472
然后本地 hosts 添加如下内容:
1
2
|
# istio
VPS公网IP httpbin.example.com
|
在浏览器中输入httpbin
服务的 URL 不能获得有效的响应,因为无法像curl
那样,将请求头部参数 Host 传给浏览器。 可以在简单的测试和演示中按下述方法绕过这个问题:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
# 在 Gateway 和 VirtualService 配置中使用通配符 *。例如如下修改 Ingress 配置:
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: httpbin-gateway
spec:
selector:
istio: ingressgateway # use Istio default gateway implementation
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- "*"
gateways:
- httpbin-gateway
http:
- match:
- uri:
prefix: /headers
route:
- destination:
port:
number: 8000
host: httpbin
EOF
|
此时,便可以在浏览器中输入输入http://$VPS公网ip:$nodeport/headers
,将显示浏览器发送的所有 Header 信息。
清除
删除 Gateway
和 VirtualService
配置,并关闭 httpbin 服务:
1
2
3
|
kubectl delete gateway httpbin-gateway
kubectl delete virtualservice httpbin
kubectl delete --ignore-not-found=true -f istio-1.18.2/samples/httpbin/httpbin.yaml
|