zh-translation: /docs/tasks/traffic-management/egress/wildcard-egress-hosts/index.md (#9748)

This commit is contained in:
youhonglian 2021-05-15 11:26:05 +08:00 committed by GitHub
parent 7d4a2da1ca
commit 62a65e3d23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 154 additions and 202 deletions

View File

@ -15,17 +15,56 @@ test: yes
假定您想要为 Istio 中所有语种的 `wikipedia.org` 站点开启 egress 流量。每个语种的 `wikipedia.org` 站点均有自己的主机名,譬如:英语和德语对应的主机分别为 `en.wikipedia.org``de.rikipedia.org`。您希望通过通用配置项开启所有 Wikipedia 站点的 egress 流量,无需单独配置每个语种的站点。 假定您想要为 Istio 中所有语种的 `wikipedia.org` 站点开启 egress 流量。每个语种的 `wikipedia.org` 站点均有自己的主机名,譬如:英语和德语对应的主机分别为 `en.wikipedia.org``de.rikipedia.org`。您希望通过通用配置项开启所有 Wikipedia 站点的 egress 流量,无需单独配置每个语种的站点。
{{< boilerplate before-you-begin-egress >}} ## 开始之前(before-you-begin)
* [部署 Istio egress 网关](/zh/docs/tasks/traffic-management/egress/egress-gateway/#deploy-Istio-egress-gateway)。 * 使用 `demo` [配置文件](/zh/docs/setup/additional-setup/config-profiles/)安装 Istio 以及默认阻止出站流量策略:
* [开启 Envoy 的访问日志](/zh/docs/tasks/observability/logs/access-log/#enable-envoy-s-access-logging) {{< text bash >}}
$ istioctl install --set profile=demo --set meshConfig.outboundTrafficPolicy.mode=REGISTRY_ONLY
{{< /text >}}
{{< tip >}}
您可以在 `demo` 配置文件以外的 Istio 配置上运行此任务,只要您确保 [部署 Istio egress 网关](/zh/docs/tasks/traffic-management/egress/egress-gateway/#deploy-Istio-egress-gateway)。
[开启 Envoy 的访问日志](/zh/docs/tasks/observability/logs/access-log/#enable-envoy-s-access-logging)和
[应用默认阻止出站流量策略](/zh/docs/tasks/traffic-management/egress/egress-control/#change-to-the-blocking-by-default-policy)
在您的安装步骤中。您还需要使用自己的 `IstioOperator` CR 代替[使用SNI代理设置出口网关](#setup-egress-gateway-with-sni-proxy)中显示。
{{< /tip >}}
* 部署[sleep]({{< github_tree >}}/samples/sleep)示例应用程序,以用作发送请求的测试源。如果您开启了 [自动 sidecar 注入](/zh/docs/setup/additional-setup/sidecar-injection/#automatic-sidecar-injection),运行以下命令以部署示例应用程序:
{{< text bash >}}
$ kubectl apply -f @samples/sleep/sleep.yaml@
{{< /text >}}
否则,在使用以下命令部署 `sleep` 应用程序之前,手动注入 sidecar
{{< text bash >}}
$ kubectl apply -f <(istioctl kube-inject -f @samples/sleep/sleep.yaml@)
{{< /text >}}
{{< tip >}}
您可以在任意 pod 上使用 `curl` 作为测试源。
{{< /tip >}}
* 将 `SOURCE_POD` 环境变量设置为您的源 Pod 的名称:
{{< text bash >}}
$ export SOURCE_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
{{< /text >}}
## 引导流量流向 Wildcard 主机{#configure-direct-traffic-to-a-wildcard-host} ## 引导流量流向 Wildcard 主机{#configure-direct-traffic-to-a-wildcard-host}
访问通用域中一组主机的第一个也是最简单的方法,是使用一个 wildcard 主机配置一个简单的 `ServiceEntry`,直接从 sidecar 调用服务。 访问通用域中一组主机的第一个也是最简单的方法,是使用一个 wildcard 主机配置一个简单的 `ServiceEntry`,直接从 sidecar 调用服务。
当直接调用服务时(譬如:不是通过一个 egress 网关),一个 wildcard 主机的配置与任何其他主机(如:全域名主机)没有什么不同,只是当通用域中有许多台主机时,这样比较方便。 当直接调用服务时(譬如:不是通过一个 egress 网关),一个 wildcard 主机的配置与任何其他主机(如:全域名主机)没有什么不同,只是当通用域中有许多台主机时,这样比较方便。
{{< warning >}}
请注意,恶意应用程序很容易绕过以下配置。为了实现安全的出口流量控制,可以通过出口网关引导流量。
{{< /warning >}}
{{< warning >}}
请注意,`DNS` 解析不能用于通配符主机。这就是为什么`NONE`分辨率(因为它是默认)用于以下服务条目。
{{< /warning >}}
1. 为 `*.wikipedia.org` 定义一个 `ServiceEntry` 以及相应的 `VirtualSevice` 1. 为 `*.wikipedia.org` 定义一个 `ServiceEntry` 以及相应的 `VirtualSevice`
{{< text bash >}} {{< text bash >}}
@ -39,26 +78,8 @@ test: yes
- "*.wikipedia.org" - "*.wikipedia.org"
ports: ports:
- number: 443 - number: 443
name: tls name: https
protocol: TLS protocol: HTTPS
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: wikipedia
spec:
hosts:
- "*.wikipedia.org"
tls:
- match:
- port: 443
sni_hosts:
- "*.wikipedia.org"
route:
- destination:
host: "*.wikipedia.org"
port:
number: 443
EOF EOF
{{< /text >}} {{< /text >}}
@ -75,7 +96,6 @@ test: yes
{{< text bash >}} {{< text bash >}}
$ kubectl delete serviceentry wikipedia $ kubectl delete serviceentry wikipedia
$ kubectl delete virtualservice wikipedia
{{< /text >}} {{< /text >}}
## 配置访问 wildcard 主机的 egress 网关{#configure-egress-gateway-traffic-to-a-wildcard-host} ## 配置访问 wildcard 主机的 egress 网关{#configure-egress-gateway-traffic-to-a-wildcard-host}
@ -103,8 +123,8 @@ $ kubectl delete virtualservice wikipedia
servers: servers:
- port: - port:
number: 443 number: 443
name: tls name: https
protocol: TLS protocol: HTTPS
hosts: hosts:
- "*.wikipedia.org" - "*.wikipedia.org"
tls: tls:
@ -134,7 +154,7 @@ $ kubectl delete virtualservice wikipedia
- gateways: - gateways:
- mesh - mesh
port: 443 port: 443
sni_hosts: sniHosts:
- "*.wikipedia.org" - "*.wikipedia.org"
route: route:
- destination: - destination:
@ -147,7 +167,7 @@ $ kubectl delete virtualservice wikipedia
- gateways: - gateways:
- istio-egressgateway - istio-egressgateway
port: 443 port: 443
sni_hosts: sniHosts:
- "*.wikipedia.org" - "*.wikipedia.org"
route: route:
- destination: - destination:
@ -229,7 +249,8 @@ SNI 代理将监听在端口 `8443` 上您可以绑定任意其它端口eg
{{< text bash >}} {{< text bash >}}
$ cat <<EOF > ./sni-proxy.conf $ cat <<EOF > ./sni-proxy.conf
user www-data; # 设置不需要根访问权限的自定义路径
pid /tmp/nginx.pid;
events { events {
} }
@ -241,7 +262,7 @@ SNI 代理将监听在端口 `8443` 上您可以绑定任意其它端口eg
access_log /var/log/nginx/access.log log_stream; access_log /var/log/nginx/access.log log_stream;
error_log /var/log/nginx/error.log; error_log /var/log/nginx/error.log;
# tcp forward proxy by SNI # SNI 的 TCP 转发代理
server { server {
resolver 8.8.8.8 ipv6=off; resolver 8.8.8.8 ipv6=off;
listen 127.0.0.1:8443; listen 127.0.0.1:8443;
@ -259,61 +280,58 @@ SNI 代理将监听在端口 `8443` 上您可以绑定任意其它端口eg
$ kubectl create configmap egress-sni-proxy-configmap -n istio-system --from-file=nginx.conf=./sni-proxy.conf $ kubectl create configmap egress-sni-proxy-configmap -n istio-system --from-file=nginx.conf=./sni-proxy.conf
{{< /text >}} {{< /text >}}
1. 下面的命令将生成 `istio-egressgateway-with-sni-proxy.yaml`,您可以选择性编辑该配置文件然后部署。 1. 创建一个 `IstioOperator` CR以使用SNI代理添加新的出口网关
{{< text bash >}} {{< text bash >}}
$ cat <<EOF | istioctl manifest generate --set values.global.istioNamespace=istio-system -f - > ./istio-egressgateway-with-sni-proxy.yaml $ istioctl manifest generate -f - <<EOF > ./egressgateway-with-sni-proxy.yaml
gateways: apiVersion: install.istio.io/v1alpha1
enabled: true kind: IstioOperator
istio-ingressgateway: spec:
enabled: false # Only generate a gateway component defined below.
istio-egressgateway: # Using this with "istioctl install" will reconcile and remove existing control-plane components.
enabled: false # Instead use "istioctl manifest generate" or "kubectl create" if using the istio operator.
istio-egressgateway-with-sni-proxy: profile: empty
enabled: true components:
labels: egressGateways:
app: istio-egressgateway-with-sni-proxy - name: istio-egressgateway-with-sni-proxy
istio: egressgateway-with-sni-proxy enabled: true
replicaCount: 1 label:
autoscaleMin: 1 app: istio-egressgateway-with-sni-proxy
autoscaleMax: 5 istio: egressgateway-with-sni-proxy
cpu: k8s:
targetAverageUtilization: 80 service:
serviceAnnotations: {} ports:
type: ClusterIP - port: 443
ports: targetPort: 8443
- port: 443 name: https
name: https overlays:
secretVolumes: - kind: Deployment
- name: egressgateway-certs name: istio-egressgateway-with-sni-proxy
secretName: istio-egressgateway-certs patches:
mountPath: /etc/istio/egressgateway-certs - path: spec.template.spec.containers[-1]
- name: egressgateway-ca-certs value: |
secretName: istio-egressgateway-ca-certs name: sni-proxy
mountPath: /etc/istio/egressgateway-ca-certs image: nginx
configVolumes: volumeMounts:
- name: sni-proxy-config - name: sni-proxy-config
configMapName: egress-sni-proxy-configmap mountPath: /etc/nginx
additionalContainers: readOnly: true
- name: sni-proxy securityContext:
image: nginx runAsNonRoot: true
volumeMounts: runAsUser: 101
- name: sni-proxy-config - path: spec.template.spec.volumes[-1]
mountPath: /etc/nginx value: |
readOnly: true name: sni-proxy-config
configMap:
name: egress-sni-proxy-configmap
defaultMode: 292 # 0444
EOF EOF
{{< /text >}} {{< /text >}}
1. 部署新的 egress 网关: 1. 部署新的 egress 网关:
{{< text bash >}} {{< text bash >}}
$ kubectl apply -f ./istio-egressgateway-with-sni-proxy.yaml $ kubectl apply -f ./egressgateway-with-sni-proxy.yaml
serviceaccount "istio-egressgateway-with-sni-proxy-service-account" created
role "istio-egressgateway-with-sni-proxy-istio-system" created
rolebinding "istio-egressgateway-with-sni-proxy-istio-system" created
service "istio-egressgateway-with-sni-proxy" created
deployment "istio-egressgateway-with-sni-proxy" created
horizontalpodautoscaler "istio-egressgateway-with-sni-proxy" created
{{< /text >}} {{< /text >}}
1. 验证新的 egress 网关正在运行。注意 pod 有两个容器(一个是 Envoy 代理,另一个是 SNI 代理)。 1. 验证新的 egress 网关正在运行。注意 pod 有两个容器(一个是 Envoy 代理,另一个是 SNI 代理)。
@ -378,17 +396,6 @@ SNI 代理将监听在端口 `8443` 上您可以绑定任意其它端口eg
1. 为 _*.wikipedia.org_ 创建一个 egress `Gateway`,端口 443协议 TLS以及一个虚拟服务负责引导目标为 _*.wikipedia.org_ 的流量流经网关。 1. 为 _*.wikipedia.org_ 创建一个 egress `Gateway`,端口 443协议 TLS以及一个虚拟服务负责引导目标为 _*.wikipedia.org_ 的流量流经网关。
根据您是否希望在源 pod 与 egress 网关之间开启
[双向 TLS 认证](/zh/docs/tasks/security/authentication/authn-policy/#auto-mutual-TLS),选择指令。
{{< idea >}}
您可能希望开启双向 TLS 以使得 egress 网关得以监控源 pods 的身份标识并基于身份标识信息启用 Mixer 的强制策略。
{{< /idea >}}
{{< tabset category-name="mtls" >}}
{{< tab name="mutual TLS enabled" category-value="enabled" >}}
{{< text bash >}} {{< text bash >}}
$ kubectl apply -f - <<EOF $ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3 apiVersion: networking.istio.io/v1alpha3
@ -406,10 +413,7 @@ SNI 代理将监听在端口 `8443` 上您可以绑定任意其它端口eg
hosts: hosts:
- "*.wikipedia.org" - "*.wikipedia.org"
tls: tls:
mode: MUTUAL mode: ISTIO_MUTUAL
serverCertificate: /etc/certs/cert-chain.pem
privateKey: /etc/certs/key.pem
caCertificates: /etc/certs/root-cert.pem
--- ---
apiVersion: networking.istio.io/v1alpha3 apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule kind: DestinationRule
@ -443,7 +447,7 @@ SNI 代理将监听在端口 `8443` 上您可以绑定任意其它端口eg
- gateways: - gateways:
- mesh - mesh
port: 443 port: 443
sni_hosts: sniHosts:
- "*.wikipedia.org" - "*.wikipedia.org"
route: route:
- destination: - destination:
@ -461,118 +465,68 @@ SNI 代理将监听在端口 `8443` 上您可以绑定任意其它端口eg
- destination: - destination:
host: sni-proxy.local host: sni-proxy.local
port: port:
number: 8443 number: 18443
weight: 100 weight: 100
--- ---
# 下面的 filter 用于将最初的 SNI (应用发送的)转换为双向 TLS 连接的 SNI。 # 下面的 filter 用于将最初的 SNI (应用发送的)转换为双向 TLS 连接的 SNI。
# 双向 TLS 连接。
# 转换后的 SNI 将被报告给 Mixer以基于初始 SNI 的值强制实施策略。 # 转换后的 SNI 将被报告给 Mixer以基于初始 SNI 的值强制实施策略。
apiVersion: networking.istio.io/v1alpha3 apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter kind: EnvoyFilter
metadata: metadata:
name: forward-downstream-sni name: forward-downstream-sni
spec: spec:
filters: configPatches:
- listenerMatch: - applyTo: NETWORK_FILTER
portNumber: 443 match:
listenerType: SIDECAR_OUTBOUND context: SIDECAR_OUTBOUND
filterName: forward_downstream_sni listener:
filterType: NETWORK portNumber: 443
filterConfig: {} filterChain:
--- filter:
# 下面的 filter 验证双向 TLS 连接的 SNI (报告至 Mixer 的 SNI与应用发起的初始 SNISNI 代理进实施路由的 SNI相同。 name: istio.stats
# Filter 阻止 Mixer 被恶意应用欺骗:路由至一个 SNI而报告其他的 SNI 值。如果初始 SNI 与双向 TLS 连接的 SNI 不匹配filter 将截断发往外部服务的连接。 patch:
operation: INSERT_BEFORE
value:
name: forward_downstream_sni
config: {}
EOF
{{< /text >}}
1. Add an `EnvoyFilter` to the gateway, to prevent it from being deceived.
{{< text bash >}}
$ kubectl apply -n istio-system -f - <<EOF
# The following filter verifies that the SNI of the mutual TLS connection is
# identical to the original SNI issued by the client (the SNI used for routing by the SNI proxy).
# The filter prevents the gateway from being deceived by a malicious client: routing to one SNI while
# reporting some other value of SNI. If the original SNI does not match the SNI of the mutual TLS connection,
# the filter will block the connection to the external service.
apiVersion: networking.istio.io/v1alpha3 apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter kind: EnvoyFilter
metadata: metadata:
name: egress-gateway-sni-verifier name: egress-gateway-sni-verifier
spec: spec:
workloadLabels: workloadSelector:
app: istio-egressgateway-with-sni-proxy labels:
filters: app: istio-egressgateway-with-sni-proxy
- listenerMatch: configPatches:
portNumber: 443 - applyTo: NETWORK_FILTER
listenerType: GATEWAY match:
filterName: sni_verifier context: GATEWAY
filterType: NETWORK listener:
filterConfig: {} portNumber: 443
filterChain:
filter:
name: istio.stats
patch:
operation: INSERT_BEFORE
value:
name: sni_verifier
config: {}
EOF EOF
{{< /text >}} {{< /text >}}
{{< /tab >}}
{{< tab name="mutual TLS disabled" category-value="disabled" >}}
{{< text bash >}}
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: istio-egressgateway-with-sni-proxy
spec:
selector:
istio: egressgateway-with-sni-proxy
servers:
- port:
number: 443
name: tls
protocol: TLS
hosts:
- "*.wikipedia.org"
tls:
mode: PASSTHROUGH
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: egressgateway-for-wikipedia
spec:
host: istio-egressgateway-with-sni-proxy.istio-system.svc.cluster.local
subsets:
- name: wikipedia
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: direct-wikipedia-through-egress-gateway
spec:
hosts:
- "*.wikipedia.org"
gateways:
- mesh
- istio-egressgateway-with-sni-proxy
tls:
- match:
- gateways:
- mesh
port: 443
sni_hosts:
- "*.wikipedia.org"
route:
- destination:
host: istio-egressgateway-with-sni-proxy.istio-system.svc.cluster.local
subset: wikipedia
port:
number: 443
weight: 100
- match:
- gateways:
- istio-egressgateway-with-sni-proxy
port: 443
sni_hosts:
- "*.wikipedia.org"
route:
- destination:
host: sni-proxy.local
port:
number: 8443
weight: 100
EOF
{{< /text >}}
{{< /tab >}}
{{< /tabset >}}
1. 发送 HTTPS 请求至 1. 发送 HTTPS 请求至
[https://en.wikipedia.org](https://en.wikipedia.org) and [https://de.wikipedia.org](https://de.wikipedia.org): [https://en.wikipedia.org](https://en.wikipedia.org) and [https://de.wikipedia.org](https://de.wikipedia.org):
@ -603,15 +557,6 @@ SNI 代理将监听在端口 `8443` 上您可以绑定任意其它端口eg
127.0.0.1 [01/Aug/2018:15:32:03 +0000] TCP [de.wikipedia.org]200 67745 291 0.659 127.0.0.1 [01/Aug/2018:15:32:03 +0000] TCP [de.wikipedia.org]200 67745 291 0.659
{{< /text >}} {{< /text >}}
1. 检查 mixer 日志。如果 Istio 部署在 `istio-system` 命名空间中,打印日志的命令为:
{{< text bash >}}
$ kubectl -n istio-system logs -l istio-mixer-type=telemetry -c mixer | grep '"connectionEvent":"open"' | grep '"sourceName":"istio-egressgateway' | grep 'wikipedia.org'
{"level":"info","time":"2018-08-26T16:16:34.784571Z","instance":"tcpaccesslog.logentry.istio-system","connectionDuration":"0s","connectionEvent":"open","connection_security_policy":"unknown","destinationApp":"","destinationIp":"127.0.0.1","destinationName":"unknown","destinationNamespace":"default","destinationOwner":"unknown","destinationPrincipal":"cluster.local/ns/istio-system/sa/istio-egressgateway-with-sni-proxy-service-account","destinationServiceHost":"","destinationWorkload":"unknown","protocol":"tcp","receivedBytes":298,"reporter":"source","requestedServerName":"en.wikipedia.org","sentBytes":0,"sourceApp":"istio-egressgateway-with-sni-proxy","sourceIp":"172.30.146.88","sourceName":"istio-egressgateway-with-sni-proxy-7c4f7868fb-rc8pr","sourceNamespace":"istio-system","sourceOwner":"kubernetes://apis/extensions/v1beta1/namespaces/istio-system/deployments/istio-egressgateway-with-sni-proxy","sourcePrincipal":"cluster.local/ns/sleep/sa/default","sourceWorkload":"istio-egressgateway-with-sni-proxy","totalReceivedBytes":298,"totalSentBytes":0}
{{< /text >}}
注意属性 `requestedServerName`
#### 清除任意域的 wildcard 配置{#cleanup-wildcard-configuration-for-arbitrary-domains} #### 清除任意域的 wildcard 配置{#cleanup-wildcard-configuration-for-arbitrary-domains}
1. 删除 _*.wikipedia.org_ 的配置项: 1. 删除 _*.wikipedia.org_ 的配置项:
@ -621,7 +566,8 @@ SNI 代理将监听在端口 `8443` 上您可以绑定任意其它端口eg
$ kubectl delete gateway istio-egressgateway-with-sni-proxy $ kubectl delete gateway istio-egressgateway-with-sni-proxy
$ kubectl delete virtualservice direct-wikipedia-through-egress-gateway $ kubectl delete virtualservice direct-wikipedia-through-egress-gateway
$ kubectl delete destinationrule egressgateway-for-wikipedia $ kubectl delete destinationrule egressgateway-for-wikipedia
$ kubectl delete --ignore-not-found=true envoyfilter forward-downstream-sni egress-gateway-sni-verifier $ kubectl delete --ignore-not-found=true envoyfilter forward-downstream-sni
$ kubectl delete --ignore-not-found=true envoyfilter -n istio-system egress-gateway-sni-verifier
{{< /text >}} {{< /text >}}
1. 删除部署 `egressgateway-with-sni-proxy` 的配置项: 1. 删除部署 `egressgateway-with-sni-proxy` 的配置项:
@ -629,21 +575,27 @@ SNI 代理将监听在端口 `8443` 上您可以绑定任意其它端口eg
{{< text bash >}} {{< text bash >}}
$ kubectl delete serviceentry sni-proxy $ kubectl delete serviceentry sni-proxy
$ kubectl delete destinationrule disable-mtls-for-sni-proxy $ kubectl delete destinationrule disable-mtls-for-sni-proxy
$ kubectl delete -f ./istio-egressgateway-with-sni-proxy.yaml
$ kubectl delete configmap egress-sni-proxy-configmap -n istio-system $ kubectl delete configmap egress-sni-proxy-configmap -n istio-system
$ kubectl delete -f ./egressgateway-with-sni-proxy.yaml
{{< /text >}} {{< /text >}}
1. 删除您创建的配置文件: 1. 删除您创建的配置文件:
{{< text bash >}} {{< text bash >}}
$ rm ./istio-egressgateway-with-sni-proxy.yaml $ rm ./sni-proxy.conf ./egressgateway-with-sni-proxy.yaml
$ rm ./sni-proxy.conf
{{< /text >}} {{< /text >}}
## 清除{#cleanup} ## 清除{#cleanup}
关闭服务 [sleep]({{< github_tree >}}/samples/sleep) * 关闭服务 [sleep]({{< github_tree >}}/samples/sleep)
{{< text bash >}} {{< text bash >}}
$ kubectl delete -f @samples/sleep/sleep.yaml@ $ kubectl delete -f @samples/sleep/sleep.yaml@
{{< /text >}} {{< /text >}}
* 从您的集群中卸载 Istio:
{{< text bash >}}
$ istioctl x uninstall --purge
{{< /text >}}