istio gateway 试玩
Gateway描述在网格边缘运行的负载均衡器,用于接收传入或传出的 HTTP/TCP 连接。该规范描述了应公开的一组端口、要使用的协议类型、负载均衡器的 SNI 配置等。
实验性功能不玩,例如Ingress Sidecar TLS 终止
k8s v1.30.2
client version: 1.23.2
control plane version: 1.23.2
data plane version: 1.23.2 (9 proxies)
gateway一般和vistualService配合使用。gateway定义了服务从外面怎样访问;vs定义了匹配到内部的服务怎么流转。
1、配置示例
1.1、gw多端口、https
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: my-gateway
namespace: some-config-namespace
spec:
selector:
app: my-gateway-controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- uk.bookinfo.com
- eu.bookinfo.com
tls:
httpsRedirect: true # sends 301 redirect for http requests
- port:
number: 443
name: https-443
protocol: HTTPS
hosts:
- uk.bookinfo.com
- eu.bookinfo.com
tls:
mode: SIMPLE # enables HTTPS on this port
serverCertificate: /etc/certs/servercert.pem
privateKey: /etc/certs/privatekey.pem
- port:
number: 9443
name: https-9443
protocol: HTTPS
hosts:
- "bookinfo-namespace/*.bookinfo.com"
tls:
mode: SIMPLE # enables HTTPS on this port
credentialName: bookinfo-secret # fetches certs from Kubernetes secret
- port:
number: 9080
name: http-wildcard
protocol: HTTP
hosts:
- "*"
- port:
number: 2379 # to expose internal service via external port 2379
name: mongo
protocol: MONGO
hosts:
- "*"
1.2、vs默认网关和外部流量网关
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: bookinfo-rule
namespace: bookinfo-namespace
spec:
hosts:
- reviews.prod.svc.cluster.local
- uk.bookinfo.com
- eu.bookinfo.com
gateways:
- some-config-namespace/my-gateway
- mesh # applies to all the sidecars in the mesh
http:
- match:
- headers:
cookie:
exact: "user=dev-123"
route:
- destination:
port:
number: 7777
host: reviews.qa.svc.cluster.local
- match:
- uri:
prefix: /reviews/
route:
- destination:
port:
number: 9080 # can be omitted if it's the only port for reviews
host: reviews.prod.svc.cluster.local
weight: 80
- destination:
host: reviews.qa.svc.cluster.local
weight: 20
1.3、vs只可以外部流量网关
将到达(外部)端口27017的流量转发到端口5555的内部Mongo服务器。此规则在mesh内部不适用,因为网关列表省略了保留名称mesh。
The following VirtualService forwards traffic arriving at (external) port 27017 to internal Mongo server on port 5555. This rule is not applicable internally in the mesh as the gateway list omits the reserved name mesh.
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: bookinfo-mongo
namespace: bookinfo-namespace
spec:
hosts:
- mongosvr.prod.svc.cluster.local # name of internal Mongo service
gateways:
- some-config-namespace/my-gateway # can omit the namespace if gateway is in same namespace as virtual service.
tcp:
- match:
- port: 27017
route:
- destination:
host: mongo.prod.svc.cluster.local
port:
number: 5555
1.4、gw限制命名空间的hosts
以下网关允许 ns1 命名空间中的任何虚拟服务绑定到它,同时仅限制 ns2 命名空间中具有 foo.bar.com 主机的虚拟服务绑定到它。
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: my-gateway
namespace: some-config-namespace
spec:
selector:
app: my-gateway-controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "ns1/*"
- "ns2/foo.bar.com"
2、mesh gateway 规则流量变化
2.1、基础环境
主要是为了测试mesh内部网关是否可以正常应用vs的规则,就是下面的话。
来自网格中其他服务的内部请求不受这些规则的约束,而是默认采用循环路由。要将这些规则也应用于内部调用,您可以将特殊值添加mesh到 列表中gateways。由于服务的内部主机名可能与外部主机名不同(例如httpbin.default.svc.cluster.local),您还需要将其添加到hosts列表中。
2.2、配置
2.2.1、gateway
接收外部流量
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: my-service-gw
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "myservice-a.com"
2.2.2、路由规则
gateways.mesh 需要打开和关闭
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: main-service
spec:
hosts:
- "myservice-a.com"
- "service-a"
gateways:
- my-service-gw
- mesh
http:
- match:
- uri:
prefix: "/api/v1/testA"
route:
- destination:
host: service-a
port:
number: 8000
fault:
delay:
percentage:
value: 10
fixedDelay: 5s
- match:
- uri:
prefix: "/api/v1/testB"
route:
- destination:
host: service-b
port:
number: 9000
- match:
- uri:
prefix: "/api/v1/testC"
route:
- destination:
host: service-c
port:
number: 9000
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: service-a-destination
spec:
host: service-a
subsets:
- name: v1
labels:
version: v1
2.2.3、没有配置mesh
2.2.3.1、 外部流量请求
vv@localhost istio-example % for i in $(seq 1 100); do curl "http://myservice-a.com/api/v1/testA/"; echo `date`;done
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 11:21:21 CST 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 11:21:21 CST 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 11:21:22 CST 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 11:21:22 CST 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 11:21:22 CST 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 11:21:22 CST 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 11:21:22 CST 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 11:21:27 CST 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 11:21:27 CST 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 11:21:27 CST 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 11:21:32 CST 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 11:21:32 CST 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 11:21:32 CST 2024
2.2.3.2、 内部流量请求
default@reviews-v2-6f85cb9b7c-g8r42:/$ for i in $(seq 1 100); do curl http://service-a:8000/api/v1/testA/ ; echo `date`;done
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:26:47 AM UTC 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:26:47 AM UTC 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:26:47 AM UTC 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:26:47 AM UTC 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:26:47 AM UTC 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:26:47 AM UTC 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:26:48 AM UTC 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:26:48 AM UTC 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:26:48 AM UTC 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:26:48 AM UTC 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:26:48 AM UTC 2024
内部流量请求就没有匹配上路由规则,延迟没有起作用,并且请求是从reviews-v2发起
2.2.4、配置了mesh之后
2.2.4.1、外部流量请求
没有什么变化。
2.2.4.2、内部流量请求
是不是可以很明显的看出输出时间有5秒的间隔。
default@reviews-v2-6f85cb9b7c-g8r42:/$ for i in $(seq 1 100); do curl http://service-a:8000/api/v1/testA/ ; echo `date`;done
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:37:11 AM UTC 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:37:11 AM UTC 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:37:16 AM UTC 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:37:22 AM UTC 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:37:22 AM UTC 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:37:27 AM UTC 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:37:27 AM UTC 2024
"b'\"{\\\\\"message\\\\\":\\\\\"i am service c, come from service b or a.\\\\\"}\"' and b'{\"message\":\"i am service c, come from service b or a.\"}'"Thu Oct 31 03:37:27 AM UTC 2024
下图当外部流量停止后,通过kiali可以很明显的看出流量的走势。
3、单向认证
生产环境还是单向tls用的比较多。
3.1、自签证书
3.1.1、生成一个自签名的根证书和私钥
mkdir example_certs1
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=vv Inc./CN=localserver.com' -keyout example_certs1/localserver.com.key -out example_certs1/localserver.com.crt
3.1.2、为具体的服务(如 service-a.localserver.com)生成一个证书签名请求和私钥
openssl req -out example_certs1/service-a.localserver.com.csr -newkey rsa:2048 -nodes -keyout example_certs1/service-a.localserver.com.key -subj "/CN=service-a.localserver.com/O=httpbin organization"
3.1.3、使用根证书和私钥来对该服务的证书请求进行签名,生成最终的服务证书
openssl x509 -req -sha256 -days 365 -CA example_certs1/localserver.com.crt -CAkey example_certs1/localserver.com.key -set_serial 0 -in example_certs1/service-a.localserver.com.csr -out example_certs1/service-a.localserver.com.crt
3.2、创建tls secret
kubectl create -n istio-system secret tls localserver-credential \
--key=example_certs1/service-a.localserver.com.key \
--cert=example_certs1/service-a.localserver.com.crt
3.3、gateway配置
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: my-service-gw
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "service-a.localserver.com"
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: localserver-credential # must be the same as secret
hosts:
- service-a.localserver.com
3.4、测试
curl -v --cacert example_certs1/localserver.com.crt "https://service-a.localserver.com/api/v1/testA/"
4、双向认证
4.1、客户端证书
openssl req -out example_certs1/client.localserver.com.csr -newkey rsa:2048 -nodes -keyout example_certs1/client.localserver.com.key -subj "/CN=client.localserver.com/O=client organization"
openssl x509 -req -sha256 -days 365 -CA example_certs1/localserver.com.crt -CAkey example_certs1/localserver.com.key -set_serial 1 -in example_certs1/client.localserver.com.csr -out example_certs1/client.localserver.com.crt
4.2、服务器使用 CA 证书来验证其客户端,我们必须使用密钥ca.crt来保存 CA 证书
kubectl create -n istio-system secret generic localserver-credential \
--from-file=tls.key=example_certs1/service-a.localserver.com.key \
--from-file=tls.crt=example_certs1/service-a.localserver.com.crt \
--from-file=ca.crt=example_certs1/localserver.com.crt
4.3、gateway配置
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: my-service-gw
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "service-a.localserver.com"
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: MUTUAL
credentialName: localserver-credential # must be the same as secret
hosts:
- service-a.localserver.com
4.4、请求
curl --cacert example_certs1/localserver.com.crt --cert example_certs1/client.localserver.com.crt --key example_certs1/client.localserver.com.key \
"https://service-a.localserver.com/api/v1/testA/"
5、Ingress Gateway without TLS Termination
5.1、概念和场景
TLS Termination: TLS Termination 是指在 Ingress Gateway 上处理 TLS(Transport Layer Security)加密流量的过程。 当启用 TLS 终止时,Ingress Gateway 解密 HTTPS 流量,然后以明文形式将请求转发给后端服务。
Without TLS Termination: 无 TLS 终止 意味着 Ingress Gateway 不会解密流量,而是将加密流量直接传递给后端服务。 后端服务需要能够处理 HTTPS 流量,也就是说,后端服务也需要配置自己的证书和私钥来进行 TLS 解密。
SSL/TLS 终止也称为“SSL/TLS 卸载”。
参考:what-is-ssl-tls-termination
理想情况下,这发生在负载均衡器上,以避免后端服务器因协商 TLS 会话密钥而负担过重——这是一个相当耗费 CPU 的过程。在服务器上运行终止可能会降低性能,从而对 Web 应用程序处理客户端请求的方式产生负面影响。
5.2、官方案例
6、egress出口网关部署
6.1、安装egressGateway
方式一:
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: mesh-default-2
namespace: istio-system
spec:
components:
egressGateways:
- name: istio-egressgateway
enabled: true
否则,在部署istio时安装
istioctl install <flags-you-used-to-install-Istio> \
--set "components.egressGateways[0].name=istio-egressgateway" \
--set "components.egressGateways[0].enabled=true"
6.2、http流量的egress网关
6.2.1、创建ServiceEntry
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
name: cnn
spec:
hosts:
- edition.cnn.com
ports:
- number: 80
name: http-port
protocol: HTTP
- number: 443
name: https
protocol: HTTPS
resolution: DNS
EOF
6.2.2、访问
kubectl exec pod/sleep-5577c64d7c-8zln9 -c sleep -- curl -sSL -o /dev/null -D - http://edition.cnn.com/politics|grep HTTP
HTTP/1.1 301 Moved Permanently
HTTP/2 200
6.2.3、为到edition.cnn.com端口 80 的出站流量创建一个Gateway。
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: istio-egressgateway
spec:
selector:
istio: egressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- edition.cnn.com
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: egressgateway-for-cnn
spec:
host: istio-egressgateway.istio-system.svc.cluster.local
subsets:
- name: cnn
EOF
6.2.4、配置路由规则
将流量从 Sidecar 引导至 Egress 网关,并从 Egress 网关引导至外部服务
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: direct-cnn-through-egress-gateway
spec:
hosts:
- edition.cnn.com
gateways:
- istio-egressgateway
- mesh
http:
- match:
- gateways:
- mesh
port: 80
route:
- destination:
host: istio-egressgateway.istio-system.svc.cluster.local
subset: cnn
port:
number: 80
weight: 100
- match:
- gateways:
- istio-egressgateway
port: 80
route:
- destination:
host: edition.cnn.com
port:
number: 80
weight: 100
EOF
6.2.5、访问
kubectl exec pod/sleep-5577c64d7c-8zln9 -c sleep -- curl -sSL -o /dev/null -D - http://edition.cnn.com/politics
Vs规则匹配
1、请求发起
从istio服务网格内运行的pod中发起,Istio Sidecar 负责拦截所有出站流量,并根据配置决定如何路由该流量。
2、流量经过sidecar
请求的目标是外部 URL(edition.cnn.com),Sidecar 会查找相关的 VirtualService 和 DestinationRule 配置(前提是有相关配置),确定如何将流量路由到外部服务。
3、流量通过mesh网关
因为请求从服务网格内部发起,所以请求edition.cnn.com时会先走mesh的网关。
该规则中指定了 subset: cnn,但是由于 cnn 子集并没有标签,流量将默认路由到 istio-egressgateway 的默认实例
4、流量通过egress网关
请求到达istio-egressgateway网关后,转发到外部edition.cnn.com。
Egress 网关将流量转发到 edition.cnn.com,并将原始请求路径 /politics 保持不变。
[destination](https://istio.io/latest/docs/reference/config/networking/virtual-service/#Destination)
5、请求到达外部服务
最终,流量到达外部服务 edition.cnn.com,并且请求的路径是 /politics,因此 edition.cnn.com/politics 页面会被返回。
出口网关代理日志,请注意,您仅通过出口网关重定向了来自端口 80 的 HTTP 流量。到端口 443 的 HTTPS 流量直接流向edition.cnn.com。
kubectl logs -l istio=egressgateway -c istio-proxy -n istio-system | tail
[2024-11-06T02:36:14.324Z] "GET /politics HTTP/2" 301 - via_upstream - "-" 0 0 229 228 "10.1.3.132" "curl/8.10.1" "f0a7355f-efad-901b-a119-5c013f1db5e4" "edition.cnn.com" "151.101.131.5:80" outbound|80||edition.cnn.com 10.1.3.125:39758 10.1.3.125:8080 10.1.3.132:37030 - -
7、egress 发起的tls
与sidercar发起tls不同,这个是egress直接与外部建立https连接。
7.1、sidecar发起和egress发起的区别
7.1.1、sidecar发起的tls
-
概念:在 Sidecar 发起 TLS 时,应用中的 Pod 直接通过其 Sidecar 代理(Envoy)与外部服务建立 TLS 连接。这个过程中,应用 Pod 和外部服务之间的连接是加密的。
-
应用场景:适合那些无需经过 Egress 网关的服务,或者对安全性要求较高、希望端到端 TLS 的情况。这样,数据从应用到外部服务全程都是加密的。
-
配置方式:在这种模式下,通常需要在 ServiceEntry 和 DestinationRule 中配置相应的 TLS 设置,告诉 Sidecar 代理与目标服务直接建立 TLS。
-
数据流流程:1、应用 Pod 发送请求,Sidecar 代理拦截请求。 2、Sidecar 使用指定的 TLS 配置与目标服务直接建立 TLS 连接。 3、流量经过 Sidecar 加密后,直接流向外部服务。
-
优点:简单直接,减少了一层网关代理的开销,适合简单的服务流量需求。
-
缺点:缺乏集中管理,无法利用 Egress 网关的流量监控和访问控制等功能。
7.1.2、egress发起的tls
-
概念:当 Egress 网关发起 TLS 时,应用 Pod 先通过 Sidecar 将请求发送到 Egress 网关,Egress 网关再负责与外部服务建立 TLS 连接。应用到 Egress 网关之间的流量可以是明文 HTTP,也可以是 Istio 内部的 mTLS。
-
应用场景:适合需要集中控制的场景,例如需要对外部流量进行监控、审计,或者需要遵循统一的访问策略和访问控制。Egress 网关作为出口流量的统一出口,可以让企业更好地控制和管理流量。
-
配置方式:在这种模式下,通常在 VirtualService 中将流量路由到 Egress 网关,然后在 Egress 网关的 DestinationRule 中配置 TLS 设置,使其与外部服务建立 TLS 连接。
-
数据流流程:1、应用 Pod 发出请求,Sidecar 拦截并将流量路由到 Egress 网关(根据 VirtualService 和 ServiceEntry 的配置)。 2、Egress 网关根据配置的 TLS 规则,与目标外部服务建立 TLS 连接。 3、Egress 网关到外部服务的流量是加密的。
-
优点:便于集中管理,适合对外部流量有严格的访问控制和审计要求的环境。
-
缺点:Egress 网关增加了一层代理,可能引入一些延迟和资源开销。
7.1.3、区别和选择
特性 | Sidecar 发起 TLS | Egress 网关发起 TLS |
---|---|---|
加密位置 | Sidecar 直接与外部服务加密 | Egress 网关与外部服务加密 |
适用场景 | 简单流量需求,端到端加密 | 集中管理、流量审计和控制 |
配置难度 | 配置较简单 | 配置较复杂 |
流量控制和管理 | 缺乏集中控制 | 便于集中流量管理 |
性能 | 较高性能,少一层代理 | 稍有性能开销,但增强了流量管理能力 |
7.2、官网案例
7.2.1、创建se
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
name: cnn
spec:
hosts:
- edition.cnn.com
ports:
- number: 80
name: http
protocol: HTTP
- number: 443
name: https
protocol: HTTPS
resolution: DNS
EOF
7.2.2、创建gw和dr
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: istio-egressgateway
spec:
selector:
istio: egressgateway
servers:
- port:
number: 80 #The Port on which the proxy should listen for incoming connections.
name: https-port-for-tls-origination
protocol: HTTPS #端口上暴露的协议。
hosts:
- edition.cnn.com
tls:
mode: ISTIO_MUTUAL #Istio 内部启用双向 TLS
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: egressgateway-for-cnn
spec:
host: istio-egressgateway.istio-system.svc.cluster.local
subsets:
- name: cnn
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
portLevelSettings:
- port:
number: 80 #指定应用此策略的目标服务上的端口号。
tls: #TLS related settings for connections to the upstream service.
mode: ISTIO_MUTUAL
sni: edition.cnn.com #在 TLS 握手期间向服务器显示的 SNI 字符串。如果未指定,则将根据 SIMPLE 和 MUTUAL TLS 模式的下游 HTTP 主机/授权标头自动设置 SNI。
EOF
7.2.3、创建vs
负载到egress gateway和egress gateway到edition.cnn.com的vs
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: direct-cnn-through-egress-gateway
spec:
hosts:
- edition.cnn.com
gateways:
- istio-egressgateway
- mesh
http:
- match:
- gateways:
- mesh
port: 80
route:
- destination:
host: istio-egressgateway.istio-system.svc.cluster.local
subset: cnn
port:
number: 80
weight: 100
- match:
- gateways:
- istio-egressgateway
port: 80
route:
- destination:
host: edition.cnn.com
port:
number: 443
weight: 100
EOF
7.2.4、创建请求edition.cnn.com的dr
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: originate-tls-for-edition-cnn-com
spec:
host: edition.cnn.com
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
portLevelSettings:
- port:
number: 443
tls:
mode: SIMPLE # initiates HTTPS for connections to edition.cnn.com
EOF
7.2.5、规则生效顺序
- VirtualService 的第一条规则:工作负载到 egress gateway 的路由。
-
DestinationRule 中的 egressgateway-for-cnn:工作负载到 egress gateway 的双向 TLS。
-
VirtualService 的第二条规则:egress gateway 到外部服务的路由。
- DestinationRule 中的 originate-tls-for-edition-cnn-com:egress gateway 到外部服务的 HTTPS 加密。
7.2.6、数据流顺序
- 工作负载 ➔ mesh 网关 ➔ 匹配 VirtualService 的第一条规则,将请求转发到istio-egressgateway。
- 工作负载 ➔ istio-egressgateway(使用 ISTIO_MUTUAL 实现内部双向 TLS)。
- istio-egressgateway ➔ 匹配 VirtualService 的第二条规则,将请求转发到外部的 edition.cnn.com。
- istio-egressgateway ➔ edition.cnn.com(使用 DestinationRule 中的 tls.mode: SIMPLE,通过单向 TLS 进行 HTTPS 加密)。
8、egress 访问通配符host
当所有通配符主机由单个服务器服务时,对通配符主机的基于出口网关的访问的配置与任何主机的配置非常相似,只有一个例外:配置的路由目的地将与配置的主机不同,即通配符。相反,它将被配置为一组域的单个服务器的主机。
9、典型应用
从云原生服务网格istio:原理、实践、架构与源码解析中获取,部分配置与最新版已经发生偏差,理性复制。
9.1、将网格内http服务发布为http外部服务
9.2、将网格内https服务发布为https外部服务
gw只透传应用程序提供的https内容。本示例中,frontend入口服务自身是https类型的服务,tls需要的服务端证书、秘钥等都是由frontend服务自己维护的。
istio提供了通道和机制,这里的https是应用程序的https,不是istio的gw提供的https。对于自己的服务已经是https的应用,istio支持通过这种方式吧服务发布成外部可访问。
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: istio-gateway
namespace: istio-system
spec:
selector:
app: ingress-gateway
servers:
- port:
name: https
number: 443
protocol: HTTPS
hosts:
- weather.com
tls:
mode: PASSTHROUGH
9.3、将网格内的http服务发布为https外部访问
外部通过https访问,内部服务是http服务。与前一种场景的入口服务自身为https不同,这里的tls模式是simple,表示gw提供标准的单向tls认证。这种方式又被称为终结的https,在gw外是https,从gw往里的服务间访问还是http。
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: istio-gateway
namespace: istio-system
spec:
selector:
app: ingress-gateway
servers:
- port:
name: https
number: 443
protocol: HTTPS
hosts:
- weather.com
tls:
mode: SIMPLE
serverCertificate: /etc/server.pem
privateKey: /etc/privatekey.pem
9.4、将网格内的http服务发布为双向https外部访问
对于大多数场景,使用9.3的方式就可以满足需求,但是在某些场景下,比如调用入口服务的是另一个服务,在服务端需要对客户端进行身份校验,这就需要tls的双向认证。
双向认证和单向认证的区别在于,gw上的模式设置为mutual时标识双向认证。
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: istio-gateway
namespace: istio-system
spec:
selector:
app: ingress-gateway
servers:
- port:
name: https
number: 443
protocol: HTTPS
hosts:
- weather.com
tls:
mode: MUTUAL
serverCertificate: /etc/server.pem
privateKey: /etc/privatekey.pem
caCertificates: /etc/ca.cert.pem
9.5、将网格内的http服务发布为https外部访问和https内部访问
istio可以透明地给网格内的服务启用双向tls,并且自动维护证书和秘钥。
-
frontend服务自身还是http,不涉及证书秘钥的事情。
-
gw作为frontend服务的入口代理,对外提供https的访问。外部访问到的是在gw上发布的https服务,使用gw上的配置提供的服务端证书和秘钥。
-
gw作为外部服务访问frontend服务的客户端代理,对frontend服务发起另一个https请求,使用的是citadel分发和维护的客户端证书和秘钥,与frontend服务的服务端证书和秘钥进行双向tls认证和通信。
入口服务通过gw发布成https,结合istio提供的透明双向tls,在入口的envoy上是两套证书秘钥,一套是gw对外发布https服务使用的,另一套是istio提供的网格内双向tls认证,两者没有任何关系。