zh-translation: Cleaning up obsolete files in multicluster install (#8708)

This commit is contained in:
zhiguo-lu 2020-12-28 10:22:16 +08:00 committed by GitHub
parent 6c6a5baa95
commit ea886bb43d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 0 additions and 1529 deletions

View File

@ -1,509 +0,0 @@
---
title: 控制平面副本集
description: 通过控制平面副本集实例,在多个 Kubernetes 集群上安装 Istio 网格。
weight: 2
aliases:
- /zh/docs/setup/kubernetes/multicluster-install/gateways/
- /zh/docs/examples/multicluster/gateways/
- /zh/docs/tasks/multicluster/gateways/
- /zh/docs/setup/kubernetes/install/multicluster/gateways/
keywords: [kubernetes,multicluster,gateway]
---
请参照本指南安装具有副本集[控制平面](/zh/docs/ops/deployment/deployment-models/#multiple-clusters)实例的
Istio [多集群部署](/zh/docs/ops/deployment/deployment-models/#control-plane-models),并在每个群集中使用 gateway 来提供跨集群连接服务。
在此配置中,每个集群都使用它自己的 Istio 控制平面来完成安装,并管理自己的 endpoint
而不是使用共享的 Istio 控制平面来管理网格。
出于以下目的,所有群集都在共同的管理控制下,执行策略与安全行为
通过共享服务副本及命名空间,并在所有群集中使用公共的根证书,可以在群集中实现一个 Istio 服务网格。
跨集群通信基于各个集群的 Istio gateway。
{{< image width="80%" link="./multicluster-with-gateways.svg" caption="使用 Istio Gateway 跨越多个基于 Kubernetes 集群的 Istio 网格并最终到达远端 pod" >}}
## 前提条件{#prerequisites}
* 两个以上 Kubernetes 集群,且版本为:{{< supported_kubernetes_versions >}}。
* 有权限在 **每个** Kubernetes 集群上,[部署 Istio 控制平面](/zh/docs/setup/install/istioctl/)。
* 每个集群 `istio-ingressgateway` 服务的 IP 地址,必须允许其它集群访问,最好使用 4 层负载均衡NLB
有些云服务商不支持负载均衡或者需要特别注明才能使用。所以,请查阅您的云服务商的文档,为负载均衡类型的服务对象启用 NLB。
在不支持负载均衡的平台上部署时,可能需要修改健康检查,使得负载均衡对象可以注册为 ingress gateway。
* 一个 **根 CA**。跨集群的服务通信必须使用双向 TLS 连接。
为了在集群之间使用双向 TLS 通信,每个集群的 Citadel 都将由共享的根 CA 生成中间 CA 凭据。
为方便演示,您在安装 Istio 时,可以使用 `samples/certs` 目录下的一个根 CA 证书样本。
## 在每个集群中部署 Istio 控制平面{#deploy-the-Istio-control-plane-in-each-cluster}
1. 从组织的根 CA 为每个集群的 Citadel 生成中间 CA 证书。
共享的根 CA 支持跨集群的双向 TLS 通信。
为方便演示,后面两个集群的演示都将使用 Istio 样本目录下的证书。
在实际部署中,一般会使用一个公共根 CA 为每个集群签发不同的 CA 证书。
1. 想要在 **每个集群** 上部署相同的 Istio 控制平面,请运行下面的命令:
{{< tip >}}
请确保当前用户拥有集群的管理员(`cluster-admin`)权限。
如果没有权限,请授权给它。例如,在 GKE 平台下,可以使用以下命令授权:
{{< text bash >}}
$ kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user="$(gcloud config get-value core/account)"
{{< /text >}}
{{< /tip >}}
* 使用类似于下面的命令,为生成的 CA 证书创建 Kubernetes secret。了解详情请参见 [CA 证书](/zh/docs/tasks/security/plugin-ca-cert/#plugging-in-the-existing-certificate-and-key)。
{{< warning >}}
示例目录中的根证书和中间证书已被广泛分发和知道。
**千万不要** 在生成环境中使用这些证书,这样集群就容易受到安全漏洞的威胁和破坏。
{{< /warning >}}
{{< text bash >}}
$ kubectl create namespace istio-system
$ kubectl create secret generic cacerts -n istio-system \
--from-file=@samples/certs/ca-cert.pem@ \
--from-file=@samples/certs/ca-key.pem@ \
--from-file=@samples/certs/root-cert.pem@ \
--from-file=@samples/certs/cert-chain.pem@
{{< /text >}}
* 安装 Istio:
{{< text bash >}}
$ istioctl manifest apply \
-f install/kubernetes/operator/examples/multicluster/values-istio-multicluster-gateways.yaml
{{< /text >}}
想了解更多细节和自定义选项,请参考[使用 Istioctl 安装](/zh/docs/setup/install/istioctl/)。
## 配置 DNS{#setup-DNS}
应用一般需要通过他们的 DNS 解析服务名然后访问返回的 IP为远端集群中的服务提供 DNS 解析,将允许已有的应用不做修改就可以正常运行。
Istio 本身不会为两个服务之间的请求使用 DNS。集群本地的服务共用一个通用的 DNS 后缀(例如,`svc.cluster.local`。Kubernetes DNS 为这些服务提供了 DNS 解析。
要为远端集群的服务提供类似的配置,远端集群内的服务需要以 `<name>.<namespace>.global` 的格式命名。
Istio 还附带了一个名为 CoreDNS 的服务,它可以为这些服务提供 DNS 解析。
想要使用 CoreDNSKubernetes DNS 的 `.global` 必须配置为 `stub a domain`
{{< warning >}}
一些云提供商的 Kubernetes 服务可能有不同的、特殊的 `DNS domain stub` 程序和功能。
请参考云提供商的文档,以确定如何为不同环境的 `stub DNS domains`
这个 bash 的目的是为 `53` 端口上的 `.global` 存根域引用或代理 Istio 的 service namespace 中的 `istiocoredns` 服务。
{{< /warning >}}
在每个要调用远端集群中服务的集群中(通常是所有集群),
选择并创建下面这些 ConfigMaps 中的一个,或直接使用现有的做修改。
{{< tabset category-name="platform" >}}
{{< tab name="KubeDNS" category-value="kube-dns" >}}
{{< text bash >}}
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: kube-dns
namespace: kube-system
data:
stubDomains: |
{"global": ["$(kubectl get svc -n istio-system istiocoredns -o jsonpath={.spec.clusterIP})"]}
EOF
{{< /text >}}
{{< /tab >}}
{{< tab name="CoreDNS (< 1.4.0)" category-value="coredns-prev-1.4.0" >}}
{{< text bash >}}
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
upstream
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
proxy . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
global:53 {
errors
cache 30
forward . $(kubectl get svc -n istio-system istiocoredns -o jsonpath={.spec.clusterIP}):53
}
EOF
{{< /text >}}
{{< /tab >}}
{{< tab name="CoreDNS (>= 1.4.0)" cookie-value="coredns-after-1.4.0" >}}
{{< text bash >}}
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
upstream
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
global:53 {
errors
cache 30
forward . $(kubectl get svc -n istio-system istiocoredns -o jsonpath={.spec.clusterIP}):53
}
EOF
{{< /text >}}
{{< /tab >}}
{{< tab name="CoreDNS (== 1.4.0)" cookie-value="coredns-1.4.0" >}}
{{< text bash >}}
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
upstream
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
global:53 {
errors
cache 30
forward . $(kubectl get svc -n istio-system istiocoredns -o jsonpath={.spec.clusterIP})
}
EOF
{{< /text >}}
{{< /tab >}}
{{< /tabset >}}
## 应用服务的配置{#configure-application-services}
一个集群中所有需要被其它远端集群访问的服务,都需要在远端集群中配置 `ServiceEntry`
service entry 使用的 host 应该采用如下格式:`<name>.<namespace>.global`。
其中 name 和 namespace 分别对应服务名和命名空间。
为了演示跨集群访问,需要配置:
在第一个集群中运行的 [sleep service]({{<github_tree>}}/samples/sleep) 并调用
在第二个集群中运行的 [httpbin service]({{<github_tree>}}/samples/httpbin)。
开始之前:
* 选择两个 Istio 集群,分别称之为 `cluster1``cluster2`
{{< boilerplate kubectl-multicluster-contexts >}}
### 示例服务的配置{#configure-the-example-services}
1. 在 `cluster1` 上部署 `sleep` 服务。
{{< text bash >}}
$ kubectl create --context=$CTX_CLUSTER1 namespace foo
$ kubectl label --context=$CTX_CLUSTER1 namespace foo istio-injection=enabled
$ kubectl apply --context=$CTX_CLUSTER1 -n foo -f @samples/sleep/sleep.yaml@
$ export SLEEP_POD=$(kubectl get --context=$CTX_CLUSTER1 -n foo pod -l app=sleep -o jsonpath={.items..metadata.name})
{{< /text >}}
1. 在 `cluster2` 上部署 `httpbin` 服务。
{{< text bash >}}
$ kubectl create --context=$CTX_CLUSTER2 namespace bar
$ kubectl label --context=$CTX_CLUSTER2 namespace bar istio-injection=enabled
$ kubectl apply --context=$CTX_CLUSTER2 -n bar -f @samples/httpbin/httpbin.yaml@
{{< /text >}}
1. 暴露 `cluster2` 的 gateway 地址:
{{< text bash >}}
$ export CLUSTER2_GW_ADDR=$(kubectl get --context=$CTX_CLUSTER2 svc --selector=app=istio-ingressgateway \
-n istio-system -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}')
{{< /text >}}
该命令使用了 gateway 的公网 IP如果您有域名的话您也可以直接使用域名。
{{< tip >}}
如果 `cluster2` 运行在一个不支持对外负载均衡的环境下,您需要使用 nodePort 访问 gateway。
有关获取使用 IP 的说明,请参见教程:[控制 Ingress 流量](/zh/docs/tasks/traffic-management/ingress/ingress-control/#determining-the-ingress-i-p-and-ports)。
在后面的步骤中,您还需要将 service entry 的 endpoint 的端口从 15443 修改为其对应的 nodePort
(例如,`kubectl --context=$CTX_CLUSTER2 get svc -n istio-system istio-ingressgateway -o=jsonpath='{.spec.ports [?(@.port==15443)].nodePort}'`)。
{{< /tip >}}
1. 在 `cluster1` 中为 `httpbin` 服务创建一个 service entry。
为了让 `cluster1` 中的 `sleep` 访问 `cluster2` 中的 `httpbin`,我们需要在 `cluster1` 中为 `httpbin` 服务创建一个 service entry。
service entry 的 host 命名应采用 `<name>.<namespace>.global` 的格式。
其中 name 和 namespace 分别与远端服务的 name 和 namespace 对应。
为了让 DNS 解析 `*.global` 域下的服务,您需要给这些服务分配一个 IP 地址。
{{< tip >}}
每个(`.global` 域下的)服务都必须有一个在其所属集群内唯一的 IP 地址。
{{< /tip >}}
如果 global service 需要使用虚拟 IP您可以使用但除此之外我们建议使用范围在 `240.0.0.0/4` 的 E 类 IP 地址。
使用这类 IP 地址的应用的流量将被 sidecar 捕获,并路由至适当的远程服务。
{{< warning >}}
组播地址 (224.0.0.0 ~ 239.255.255.255) 不应该被使用,因为这些地址默认不会被路由。
环路地址 (127.0.0.0/8) 不应该被使用,因为 sidecar 可能会将其重定向至 sidecar 的某个监听端口。
{{< /warning >}}
{{< text bash >}}
$ kubectl apply --context=$CTX_CLUSTER1 -n foo -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: httpbin-bar
spec:
hosts:
# must be of form name.namespace.global
- httpbin.bar.global
# Treat remote cluster services as part of the service mesh
# as all clusters in the service mesh share the same root of trust.
location: MESH_INTERNAL
ports:
- name: http1
number: 8000
protocol: http
resolution: DNS
addresses:
# the IP address to which httpbin.bar.global will resolve to
# must be unique for each remote service, within a given cluster.
# This address need not be routable. Traffic for this IP will be captured
# by the sidecar and routed appropriately.
- 240.0.0.2
endpoints:
# This is the routable address of the ingress gateway in cluster2 that
# sits in front of sleep.foo service. Traffic from the sidecar will be
# routed to this address.
- address: ${CLUSTER2_GW_ADDR}
ports:
http1: 15443 # Do not change this port value
EOF
{{< /text >}}
上面的配置会基于双向 TLS 连接,将 `cluster1` 中对 `httpbin.bar.global`*任意端口* 的访问,路由至 `<IPofCluster2IngressGateway>:15443` endpoint。
gateway 的 15443 端口是一个特殊的 SNI-aware Envoy当您在集群中部署 Istio 控制平面时,它会自动安装。
进入 15443 端口的流量会为目标集群内适当的服务的 pods 提供负载均衡(在这个例子中是,`cluster2` 集群中的 `httpbin.bar` 服务)。
{{< warning >}}
不要手动创建一个使用 15443 端口的 `Gateway`
{{< /warning >}}
1. 验证 `sleep` 是否可以访问 `httpbin`
{{< text bash >}}
$ kubectl exec --context=$CTX_CLUSTER1 $SLEEP_POD -n foo -c sleep -- curl -I httpbin.bar.global:8000/headers
{{< /text >}}
### 通过 egress gateway 发送远程流量{#send-remote-traffic-via-an-egress-gateway}
如果您想在 `cluster1` 中通过一个专用的 egress gateway 路由流量,而不是从 sidecars 直连。
使用下面的 service entry 替换前面一节对 `httpbin.bar` 使用的配置。
{{< tip >}}
该配置中使用的 egress gateway 依然不能处理其它的、非 inter-cluster 的 egress 流量。
{{< /tip >}}
如果 `$CLUSTER2_GW_ADDR` 是 IP 地址,请使用 `$CLUSTER2_GW_ADDR - IP address` 选项。如果 `$CLUSTER2_GW_ADDR` 是域名,请使用 `$CLUSTER2_GW_ADDR - hostname` 选项。
{{< tabset category-name="profile" >}}
{{< tab name="$CLUSTER2_GW_ADDR - IP address" category-value="option1" >}}
* 暴露 `cluster1` egress gateway 地址:
{{< text bash >}}
$ export CLUSTER1_EGW_ADDR=$(kubectl get --context=$CTX_CLUSTER1 svc --selector=app=istio-egressgateway \
-n istio-system -o yaml -o jsonpath='{.items[0].spec.clusterIP}')
{{< /text >}}
* 使 httpbin-bar 服务的 entry 生效:
{{< text bash >}}
$ kubectl apply --context=$CTX_CLUSTER1 -n foo -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: httpbin-bar
spec:
hosts:
# must be of form name.namespace.global
- httpbin.bar.global
location: MESH_INTERNAL
ports:
- name: http1
number: 8000
protocol: http
resolution: STATIC
addresses:
- 240.0.0.2
endpoints:
- address: ${CLUSTER2_GW_ADDR}
network: external
ports:
http1: 15443 # Do not change this port value
- address: ${CLUSTER1_EGW_ADDR}
ports:
http1: 15443
EOF
{{< /text >}}
{{< /tab >}}
{{< tab name="$CLUSTER2_GW_ADDR - hostname" category-value="option2" >}}
如果 `${CLUSTER2_GW_ADDR}` 是域名,您也可以使用 `resolution: DNS` 实现 endpoint 解析。
{{< text bash >}}
$ kubectl apply --context=$CTX_CLUSTER1 -n foo -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: httpbin-bar
spec:
hosts:
# must be of form name.namespace.global
- httpbin.bar.global
location: MESH_INTERNAL
ports:
- name: http1
number: 8000
protocol: http
resolution: DNS
addresses:
- 240.0.0.2
endpoints:
- address: ${CLUSTER2_GW_ADDR}
network: external
ports:
http1: 15443 # Do not change this port value
- address: istio-egressgateway.istio-system.svc.cluster.local
ports:
http1: 15443
EOF
{{< /text >}}
{{< /tab >}}
{{< /tabset >}}
### 示例的清理{#cleanup-the-example}
运行下面的命令清理示例中的服务。
* 清理 `cluster1`
{{< text bash >}}
$ kubectl delete --context=$CTX_CLUSTER1 -n foo -f @samples/sleep/sleep.yaml@
$ kubectl delete --context=$CTX_CLUSTER1 -n foo serviceentry httpbin-bar
$ kubectl delete --context=$CTX_CLUSTER1 ns foo
{{< /text >}}
* 清理 `cluster2`
{{< text bash >}}
$ kubectl delete --context=$CTX_CLUSTER2 -n bar -f @samples/httpbin/httpbin.yaml@
$ kubectl delete --context=$CTX_CLUSTER2 ns bar
{{< /text >}}
## Version-aware 路由到远端服务{#version-aware-routing-to-remote-services}
如果远端服务有多个版本,您可以为 service entry endpoint 添加标签。比如:
{{< text bash >}}
$ kubectl apply --context=$CTX_CLUSTER1 -n foo -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: httpbin-bar
spec:
hosts:
# must be of form name.namespace.global
- httpbin.bar.global
location: MESH_INTERNAL
ports:
- name: http1
number: 8000
protocol: http
resolution: DNS
addresses:
# the IP address to which httpbin.bar.global will resolve to
# must be unique for each service.
- 240.0.0.2
endpoints:
- address: ${CLUSTER2_GW_ADDR}
labels:
cluster: cluster2
ports:
http1: 15443 # Do not change this port value
EOF
{{< /text >}}
然后您就可以使用适当的 gateway 标签选择器,创建虚拟服务和目标规则去定义 `httpbin.bar.global` 的子集。
这些指令与路由到本地服务使用的指令相同。
完整的例子,请参考 [multicluster version routing](/zh/blog/2019/multicluster-version-routing/)。
## 卸载{#uninstalling}
若要卸载 Istio请在 **每个集群** 上执行下面的命令:
{{< text bash >}}
$ kubectl delete -f $HOME/istio.yaml
$ kubectl delete ns istio-system
{{< /text >}}
## 总结{#summary}
使用 Istio gateway、公共的根 CA 和 service entry您可以配置一个跨多个 Kubernetes 集群的单 Istio 服务网格。
经过这种方式配置后,应用无需任何修改,即可将流量路由到远端的集群内。
尽管此方法需要手动配置一些访问远端服务的选项,但 service entry 的创建过程可以自动化。

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 250 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 116 KiB

View File

@ -1,433 +0,0 @@
---
title: 共享的控制平面(多网络)
description: 跨多个 Kubernetes 集群安装一个 Istio 网格,使互不联通的集群网络共享同一个控制平面。
weight: 85
keywords: [kubernetes,multicluster]
aliases:
- /zh/docs/examples/multicluster/split-horizon-eds/
- /zh/docs/tasks/multicluster/split-horizon-eds/
- /zh/docs/setup/kubernetes/install/multicluster/shared-gateways/
---
遵循本指南配置一个多集群网格,使用共享的
[控制平面](/zh/docs/ops/deployment/deployment-models/#control-plane-models),并通过网关连通彼此网络隔离的集群。
Istio 位置感知的服务路由特性,可以根据请求源所在的位置将请求路由至不同的 endpoints。
遵循本指南中的说明,将安装一个两集群网格,如下图所示:
{{< image width="80%"
link="./diagram.svg"
caption="Shared Istio control plane topology spanning multiple Kubernetes clusters using gateways" >}}
主集群 `cluster1` 运行全部的 Istio 控制平面组件集,而 `cluster2` 只运行 Istio Citadel、Sidecar 注入器以及 Ingress 网关。
不同集群的工作负载之间既不要求 VPN 连接也不要求直接网络访问。
## 前提条件{#prerequisites}
* 两个或多个 Kubernetes 集群,版本为:{{< supported_kubernetes_versions >}}。
* 有权限[部署 Istio 控制平面](/zh/docs/setup/install/istioctl/)
* 两个 Kubernetes 集群(称为 `cluster1``cluster2`)。
{{< warning >}}
为了运行本配置,`cluster1` 必须能够访问 `cluster2` 的 Kubernetes API server。
{{< /warning >}}
{{< boilerplate kubectl-multicluster-contexts >}}
## 安装多集群网格{#setup-the-multicluster-mesh}
在本配置中,安装 Istio 时同时开启控制平面和应用 pods 的双向 TLS。
对于共享的根 CA使用 Istio 示例目录下相同的 Istio 证书,在 `cluster1``cluster2` 中都创建相同的 `cacerts` secret。
下文命令安装 `cluster2` 时,创建一个无 selector 的服务,并为 `istio-pilot.istio-system` 创建一个 endpoint其地址为 `cluster1` 的 Istio ingress gateway。
它们用于通过 ingress gateway 安全地访问 `cluster1` 中的 pilot无需双向 TLS 终端。
### 安装集群 1主集群{#setup-cluster-1-primary}
1. 在 `cluster1` 中部署 Istio
{{< warning >}}
当启用多集群所需的附加组件时Istio 控制平面的资源占用量可能会增长,甚至超过 Kubernetes 集群安装[平台安装](/zh/docs/setup/platform-setup/)步骤中的默认容量。
如果因 CPU 或内存资源不足导致 Istio 服务无法调度,可以考虑在集群中添加更多节点,或按需升级为更大内存容量的实例。
{{< /warning >}}
{{< text bash >}}
$ kubectl create --context=$CTX_CLUSTER1 ns istio-system
$ kubectl create --context=$CTX_CLUSTER1 secret generic cacerts -n istio-system --from-file=samples/certs/ca-cert.pem --from-file=samples/certs/ca-key.pem --from-file=samples/certs/root-cert.pem --from-file=samples/certs/cert-chain.pem
$ istioctl manifest apply --context=$CTX_CLUSTER1 \
-f install/kubernetes/operator/examples/multicluster/values-istio-multicluster-primary.yaml
{{< /text >}}
{{< warning >}}
注意网关地址设置为 `0.0.0.0`。这些是临时的占位值,在下文章节集群部署后,将被更新为 `cluster1``cluster2` 的网关公网 IP。
{{< /warning >}}
等待 `cluster1` 中的 Istio pods 就绪:
{{< text bash >}}
$ kubectl get pods --context=$CTX_CLUSTER1 -n istio-system
NAME READY STATUS RESTARTS AGE
istio-citadel-55d8b59798-6hnx4 1/1 Running 0 83s
istio-galley-c74b77787-lrtr5 2/2 Running 0 82s
istio-ingressgateway-684f5df677-shzhm 1/1 Running 0 83s
istio-pilot-5495bc8885-2rgmf 2/2 Running 0 82s
istio-policy-69cdf5db4c-x4sct 2/2 Running 2 83s
istio-sidecar-injector-5749cf7cfc-pgd95 1/1 Running 0 82s
istio-telemetry-646db5ddbd-gvp6l 2/2 Running 1 83s
prometheus-685585888b-4tvf7 1/1 Running 0 83s
{{< /text >}}
1. 创建一个 ingress 网关访问 `cluster2` 中的服务:
{{< text bash >}}
$ kubectl apply --context=$CTX_CLUSTER1 -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: cluster-aware-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: tls
protocol: TLS
tls:
mode: AUTO_PASSTHROUGH
hosts:
- "*.local"
EOF
{{< /text >}}
本例 `Gateway` 配置 443 端口来将流经的入口流量导向请求 SNI 头中指明的目标服务,其中 SNI 的顶级域名为 _local_(譬如:[Kubernetes DNS 域名](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/))。
从源至目标 sidecar始终使用双向 TLS 连接。
尽管应用于 `cluster1`,该网关实例也会影响 `cluster2`,因为两个集群通过同一个 Pilot 通信。
1. 确定 `cluster1` 的 ingress IP 和端口。
1. 设置 `kubectl` 的当前上下文为 `CTX_CLUSTER1`
{{< text bash >}}
$ export ORIGINAL_CONTEXT=$(kubectl config current-context)
$ kubectl config use-context $CTX_CLUSTER1
{{< /text >}}
1. 按照[确定 ingress IP 和端口](/zh/docs/tasks/traffic-management/ingress/ingress-control/#determining-the-ingress-i-p-and-ports)中的说明,设置环境变量 `INGRESS_HOST``SECURE_INGRESS_PORT`
1. 恢复之前的 `kubectl` 上下文:
{{< text bash >}}
$ kubectl config use-context $ORIGINAL_CONTEXT
$ unset ORIGINAL_CONTEXT
{{< /text >}}
1. 打印 `INGRESS_HOST``SECURE_INGRESS_PORT`
{{< text bash >}}
$ echo The ingress gateway of cluster1: address=$INGRESS_HOST, port=$SECURE_INGRESS_PORT
{{< /text >}}
1. 更新网格网络配置中的网关地址。编辑 `istio` `ConfigMap`
{{< text bash >}}
$ kubectl edit cm -n istio-system --context=$CTX_CLUSTER1 istio
{{< /text >}}
将网关地址和 `network1` 的端口分别更新为 `cluster1` 的 ingress 主机和端口,然后保存并退出。注意该地址在配置文件中出现两次,第二次位于 `values.yaml:` 下方。
一旦保存Pilot 将自动读取更新后的网络配置。
### 安装集群 2{#setup-cluster-2}
1. 输出 `cluster1` 的网关地址:
{{< text bash >}}
$ export LOCAL_GW_ADDR=$(kubectl get --context=$CTX_CLUSTER1 svc --selector=app=istio-ingressgateway \
-n istio-system -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') && echo ${LOCAL_GW_ADDR}
{{< /text >}}
该命令将网关地址设置为网关的公共 IP 并显示。
{{< warning >}}
若负载均衡配置没有设置 IP 地址命令将执行失败。DNS 域名支持尚未实现,亟待解决。
{{< /warning >}}
1. 在 `cluster2` 中部署 Istio
{{< text bash >}}
$ kubectl create --context=$CTX_CLUSTER2 ns istio-system
$ kubectl create --context=$CTX_CLUSTER2 secret generic cacerts -n istio-system --from-file=samples/certs/ca-cert.pem --from-file=samples/certs/ca-key.pem --from-file=samples/certs/root-cert.pem --from-file=samples/certs/cert-chain.pem
$ CLUSTER_NAME=$(kubectl --context=$CTX_CLUSTER2 config view --minify=true -o jsonpath='{.clusters[].name}')
$ istioctl manifest apply --context=$CTX_CLUSTER2 \
--set profile=remote \
--set values.global.mtls.enabled=true \
--set values.gateways.enabled=true \
--set values.security.selfSigned=false \
--set values.global.createRemoteSvcEndpoints=true \
--set values.global.remotePilotCreateSvcEndpoint=true \
--set values.global.remotePilotAddress=${LOCAL_GW_ADDR} \
--set values.global.remotePolicyAddress=${LOCAL_GW_ADDR} \
--set values.global.remoteTelemetryAddress=${LOCAL_GW_ADDR} \
--set values.gateways.istio-ingressgateway.env.ISTIO_META_NETWORK="network2" \
--set values.global.network="network2" \
--set values.global.multiCluster.clusterName=${CLUSTER_NAME} \
--set autoInjection.enabled=true
{{< /text >}}
等待 `cluster2` 中的 Istio pods 就绪,`istio-ingressgateway` 除外。
{{< text bash >}}
$ kubectl get pods --context=$CTX_CLUSTER2 -n istio-system -l istio!=ingressgateway
NAME READY STATUS RESTARTS AGE
istio-citadel-55d8b59798-nlk2z 1/1 Running 0 26s
istio-sidecar-injector-5749cf7cfc-s6r7p 1/1 Running 0 25s
{{< /text >}}
{{< warning >}}
`istio-ingressgateway` 无法就绪,直到在 `cluster1` 的 Istio 控制面板中配置好 watch `cluster2`。下一节执行该操作。
{{< /warning >}}
1. 确定 `cluster2` 的 ingress IP 和口。
1. 设置 `kubectl` 的当前上下文为 `CTX_CLUSTER2`
{{< text bash >}}
$ export ORIGINAL_CONTEXT=$(kubectl config current-context)
$ kubectl config use-context $CTX_CLUSTER2
{{< /text >}}
1. 按照[确定 ingress IP 和端口](/zh/docs/tasks/traffic-management/ingress/ingress-control/#determining-the-ingress-i-p-and-ports)中的说明,设置环境变量 `INGRESS_HOST``SECURE_INGRESS_PORT`
1. 恢复之前的 `kubectl` 上下文:
{{< text bash >}}
$ kubectl config use-context $ORIGINAL_CONTEXT
$ unset ORIGINAL_CONTEXT
{{< /text >}}
1. 打印 `INGRESS_HOST``SECURE_INGRESS_PORT`
{{< text bash >}}
$ echo The ingress gateway of cluster2: address=$INGRESS_HOST, port=$SECURE_INGRESS_PORT
{{< /text >}}
1. 更新网格网络配置中的网关地址。编辑 `istio` `ConfigMap`
{{< text bash >}}
$ kubectl edit cm -n istio-system --context=$CTX_CLUSTER1 istio
{{< /text >}}
`network2` 的网关地址和端口分别更新为 `cluster2` 的 ingress 主机和端口,然后保存并退出。注意该地址在配置文件中出现两次,第二次位于 `values.yaml:` 下方。
一旦保存Pilot 将自动读取更新后的网络配置。
1. 准备环境变量,构建服务账户 `istio-reader-service-account` 的配置文件 `n2-k8s-config`
{{< text bash >}}
$ CLUSTER_NAME=$(kubectl --context=$CTX_CLUSTER2 config view --minify=true -o jsonpath='{.clusters[].name}')
$ SERVER=$(kubectl --context=$CTX_CLUSTER2 config view --minify=true -o jsonpath='{.clusters[].cluster.server}')
$ SECRET_NAME=$(kubectl --context=$CTX_CLUSTER2 get sa istio-reader-service-account -n istio-system -o jsonpath='{.secrets[].name}')
$ CA_DATA=$(kubectl get --context=$CTX_CLUSTER2 secret ${SECRET_NAME} -n istio-system -o jsonpath="{.data['ca\.crt']}")
$ TOKEN=$(kubectl get --context=$CTX_CLUSTER2 secret ${SECRET_NAME} -n istio-system -o jsonpath="{.data['token']}" | base64 --decode)
{{< /text >}}
{{< idea >}}
在许多系统中,`base64 --decode` 可以替换为 `openssl enc -d -base64 -A`
{{< /idea >}}
1. 在工作目录中创建文件 `n2-k8s-config`
{{< text bash >}}
$ cat <<EOF > n2-k8s-config
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority-data: ${CA_DATA}
server: ${SERVER}
name: ${CLUSTER_NAME}
contexts:
- context:
cluster: ${CLUSTER_NAME}
user: ${CLUSTER_NAME}
name: ${CLUSTER_NAME}
current-context: ${CLUSTER_NAME}
users:
- name: ${CLUSTER_NAME}
user:
token: ${TOKEN}
EOF
{{< /text >}}
### 启动 watching 集群 2{start-watching-cluster-2}
1. 执行下面命令,添加并标记 Kubernetes `cluster2` 的 secret。
执行完这些命令,`cluster1` 中的 Istio Pilot 将开始 watching `cluster2` 的服务和实例,如同对待 `cluster1` 一样。
{{< text bash >}}
$ kubectl create --context=$CTX_CLUSTER1 secret generic n2-k8s-secret --from-file n2-k8s-config -n istio-system
$ kubectl label --context=$CTX_CLUSTER1 secret n2-k8s-secret istio/multiCluster=true -n istio-system
{{< /text >}}
1. 等待 `istio-ingressgateway` 就绪:
{{< text bash >}}
$ kubectl get pods --context=$CTX_CLUSTER2 -n istio-system -l istio=ingressgateway
NAME READY STATUS RESTARTS AGE
istio-ingressgateway-5c667f4f84-bscff 1/1 Running 0 16m
{{< /text >}}
现在,`cluster1` 和 `cluster2` 均已安装完成,可以部署一个案例服务。
## 部署案例服务{#deploy-example-service}
如上图所示,部署两个 `helloworld` 服务,一个运行在 `cluster1` 中,另一个运行在 `cluster2` 中。
二者的区别是 `helloworld` 镜像的版本不同。
### 在集群 2 中部署 helloworld v2{#deploy-helloworld-v2-in-cluster-2}
1. 创建一个 `sample` 命名空间,用 label 标识开启 sidecar 自动注入:
{{< text bash >}}
$ kubectl create --context=$CTX_CLUSTER2 ns sample
$ kubectl label --context=$CTX_CLUSTER2 namespace sample istio-injection=enabled
{{< /text >}}
1. 部署 `helloworld v2`
{{< text bash >}}
$ kubectl create --context=$CTX_CLUSTER2 -f @samples/helloworld/helloworld.yaml@ -l app=helloworld -n sample
$ kubectl create --context=$CTX_CLUSTER2 -f @samples/helloworld/helloworld.yaml@ -l version=v2 -n sample
{{< /text >}}
1. 确认 `helloworld v2` 正在运行:
{{< text bash >}}
$ kubectl get po --context=$CTX_CLUSTER2 -n sample
NAME READY STATUS RESTARTS AGE
helloworld-v2-7dd57c44c4-f56gq 2/2 Running 0 35s
{{< /text >}}
### 在集群 1 中部署 helloworld v1{#deploy-helloworld-v1-in-cluster-1}
1. 创建一个 `sample` 命名空间,用 label 标识开启 sidecar 自动注入:
{{< text bash >}}
$ kubectl create --context=$CTX_CLUSTER1 ns sample
$ kubectl label --context=$CTX_CLUSTER1 namespace sample istio-injection=enabled
{{< /text >}}
1. 部署 `helloworld v1`
{{< text bash >}}
$ kubectl create --context=$CTX_CLUSTER1 -f @samples/helloworld/helloworld.yaml@ -l app=helloworld -n sample
$ kubectl create --context=$CTX_CLUSTER1 -f @samples/helloworld/helloworld.yaml@ -l version=v1 -n sample
{{< /text >}}
1. 确认 `helloworld v1` 正在运行:
{{< text bash >}}
$ kubectl get po --context=$CTX_CLUSTER1 -n sample
NAME READY STATUS RESTARTS AGE
helloworld-v1-d4557d97b-pv2hr 2/2 Running 0 40s
{{< /text >}}
### 跨集群路由实践{#cross-cluster-routing-in-action}
为了演示访问 `helloworld` 服务的流量如何跨两个集群进行分发,我们从网格内的另一个 `sleep` 服务请求 `helloworld` 服务。
1. 在两个集群中均部署 `sleep` 服务:
{{< text bash >}}
$ kubectl apply --context=$CTX_CLUSTER1 -f @samples/sleep/sleep.yaml@ -n sample
$ kubectl apply --context=$CTX_CLUSTER2 -f @samples/sleep/sleep.yaml@ -n sample
{{< /text >}}
1. 等待 `sleep` 服务启动:
{{< text bash >}}
$ kubectl get po --context=$CTX_CLUSTER1 -n sample -l app=sleep
sleep-754684654f-n6bzf 2/2 Running 0 5s
{{< /text >}}
{{< text bash >}}
$ kubectl get po --context=$CTX_CLUSTER2 -n sample -l app=sleep
sleep-754684654f-dzl9j 2/2 Running 0 5s
{{< /text >}}
1. 从 `cluster1` 请求 `helloworld.sample` 服务若干次:
{{< text bash >}}
$ kubectl exec --context=$CTX_CLUSTER1 -it -n sample -c sleep $(kubectl get pod --context=$CTX_CLUSTER1 -n sample -l app=sleep -o jsonpath='{.items[0].metadata.name}') -- curl helloworld.sample:5000/hello
{{< /text >}}
1. 从 `cluster2` 请求 `helloworld.sample` 服务若干次:
{{< text bash >}}
$ kubectl exec --context=$CTX_CLUSTER2 -it -n sample -c sleep $(kubectl get pod --context=$CTX_CLUSTER2 -n sample -l app=sleep -o jsonpath='{.items[0].metadata.name}') -- curl helloworld.sample:5000/hello
{{< /text >}}
如果设置正确,访问 `helloworld.sample` 的流量将在 `cluster1``cluster2` 之间分发,返回的响应结果或者为 `v1` 或者为 `v2`
{{< text plain >}}
Hello version: v2, instance: helloworld-v2-758dd55874-6x4t8
Hello version: v1, instance: helloworld-v1-86f77cd7bd-cpxhv
{{< /text >}}
也可以通过打印 sleep 的 `istio-proxy` 容器日志,验证访问 endpoints 的 IP 地址。
{{< text bash >}}
$ kubectl logs --context=$CTX_CLUSTER1 -n sample $(kubectl get pod --context=$CTX_CLUSTER1 -n sample -l app=sleep -o jsonpath='{.items[0].metadata.name}') istio-proxy
[2018-11-25T12:37:52.077Z] "GET /hello HTTP/1.1" 200 - 0 60 190 189 "-" "curl/7.60.0" "6e096efe-f550-4dfa-8c8c-ba164baf4679" "helloworld.sample:5000" "192.23.120.32:15443" outbound|5000||helloworld.sample.svc.cluster.local - 10.20.194.146:5000 10.10.0.89:59496 -
[2018-11-25T12:38:06.745Z] "GET /hello HTTP/1.1" 200 - 0 60 171 170 "-" "curl/7.60.0" "6f93c9cc-d32a-4878-b56a-086a740045d2" "helloworld.sample:5000" "10.10.0.90:5000" outbound|5000||helloworld.sample.svc.cluster.local - 10.20.194.146:5000 10.10.0.89:59646 -
{{< /text >}}
`cluster1` 中,当请求分发给 v2 时,`cluster2` 的网关 IP`192.23.120.32:15443`)被记录,当请求分发给 v1 时,`cluster1` 的实例 IP`10.10.0.90:5000`)被记录。
{{< text bash >}}
$ kubectl logs --context=$CTX_CLUSTER2 -n sample $(kubectl get pod --context=$CTX_CLUSTER2 -n sample -l app=sleep -o jsonpath='{.items[0].metadata.name}') istio-proxy
[2019-05-25T08:06:11.468Z] "GET /hello HTTP/1.1" 200 - "-" 0 60 177 176 "-" "curl/7.60.0" "58cfb92b-b217-4602-af67-7de8f63543d8" "helloworld.sample:5000" "192.168.1.246:15443" outbound|5000||helloworld.sample.svc.cluster.local - 10.107.117.235:5000 10.32.0.10:36840 -
[2019-05-25T08:06:12.834Z] "GET /hello HTTP/1.1" 200 - "-" 0 60 181 180 "-" "curl/7.60.0" "ce480b56-fafd-468b-9996-9fea5257cb1e" "helloworld.sample:5000" "10.32.0.9:5000" outbound|5000||helloworld.sample.svc.cluster.local - 10.107.117.235:5000 10.32.0.10:36886 -
{{< /text >}}
`cluster2` 中,当请求分发给 v1 时,`cluster1` 的网关 IP `192.168.1.246:15443`)被记录,当请求分发给 v2 时,`cluster2` 的网关 IP`10.32.0.9:5000`)被记录。
## 清除{#cleanup}
执行如下命令清除示例服务__以及__ Istio 组件。
清除集群 `cluster2`
{{< text bash >}}
$ istioctl manifest generate --context=$CTX_CLUSTER2 \
--set profile=remote \
--set values.global.mtls.enabled=true \
--set values.gateways.enabled=true \
--set values.security.selfSigned=false \
--set values.global.createRemoteSvcEndpoints=true \
--set values.global.remotePilotCreateSvcEndpoint=true \
--set values.global.remotePilotAddress=${LOCAL_GW_ADDR} \
--set values.global.remotePolicyAddress=${LOCAL_GW_ADDR} \
--set values.global.remoteTelemetryAddress=${LOCAL_GW_ADDR} \
--set values.gateways.istio-ingressgateway.env.ISTIO_META_NETWORK="network2" \
--set values.global.network="network2" \
--set autoInjection.enabled=true | kubectl --context=$CTX_CLUSTER2 delete -f -
$ kubectl delete --context=$CTX_CLUSTER2 ns sample
$ rm n2-k8s-config
$ unset CTX_CLUSTER2 CLUSTER_NAME SERVER SECRET_NAME CA_DATA TOKEN INGRESS_HOST SECURE_INGRESS_PORT INGRESS_PORT LOCAL_GW_ADDR
{{< /text >}}
清除集群 `cluster1`
{{< text bash >}}
$ istioctl manifest generate --context=$CTX_CLUSTER1 \
-f install/kubernetes/operator/examples/multicluster/values-istio-multicluster-primary.yaml | kubectl --context=$CTX_CLUSTER1 delete -f -
$ kubectl delete --context=$CTX_CLUSTER1 ns sample
$ unset CTX_CLUSTER1
$ rm n2-k8s-config
{{< /text >}}

View File

@ -1,431 +0,0 @@
---
title: 共享控制平面(单一网络)
description: 安装一个跨多个 Kubernetes 集群的 Istio 网格,多集群共享控制平面,并且集群间通过 VPN 互连。
weight: 5
keywords: [kubernetes,multicluster,federation,vpn]
aliases:
- /zh/docs/setup/kubernetes/multicluster-install/vpn/
- /zh/docs/setup/kubernetes/install/multicluster/vpn/
- /zh/docs/setup/kubernetes/install/multicluster/shared-vpn/
---
按照该指南安装一个 Istio [多集群服务网格](/zh/docs/ops/deployment/deployment-models/#multiple-clusters)以让每个 Kubernetes 集群的服务和应用能够将他们的内部 Kubernetes 网络暴露至其它集群。
在这个配置中,多个 Kubernetes 集群运行一份可以连接到一个共享 Istio [控制平面](/zh/docs/ops/deployment/deployment-models/#control-plane-models)的远程配置。
一旦一个或多个远程 Kubernetes 集群连接到该 Istio 控制平面Envoy 就会形成一个跨多集群的网格网络。
{{< image width="80%" link="./multicluster-with-vpn.svg" caption="跨多 Kubernetes 集群的 Istio 网格可通过 VPN 直接访问远程 Pod" >}}
## 前提条件{#prerequisites}
* 两个或更多运行受支持的 Kubernetes 版本({{< supported_kubernetes_versions >}})的集群。
* 能够在多集群中的**一个**上[部署 Istio 控制平面](/zh/docs/setup/install/istioctl/)。
* 满足下列要求的 RFC1918 网络、VPN、或其它更高级的网络技术
* 各集群的 Pod CIDR 范围和服务 CIDR 范围在多群集环境中必须唯一,并且不能重叠。
* 每个集群中的所有 pod CIDRs 必须互相可路由。
* 所有 Kubernetes 控制平面 API 服务必须互相可路由。
本指南介绍如何使用 Istio 提供的远程配置文件安装多群集 Istio 拓扑。
## 部署本地控制平面{#deploy-the-local-control-plane}
在 Kubernetes 集群**之一**上[安装 Istio 控制平面](/zh/docs/setup/install/istioctl/)。
### 设置环境变量{#environment-var}
在执行本节中的步骤之前,请等待 Istio 控制平面完成初始化。
您必须在 Istio 控制平面集群上执行这些操作,以获取 Istio 控制平面服务端点例如Pilot 和 Policy Pod IP 端点。
运行以下命令设置环境变量:
{{< text bash >}}
$ export PILOT_POD_IP=$(kubectl -n istio-system get pod -l istio=pilot -o jsonpath='{.items[0].status.podIP}')
$ export POLICY_POD_IP=$(kubectl -n istio-system get pod -l istio-mixer-type=policy -o jsonpath='{.items[0].status.podIP}')
$ export TELEMETRY_POD_IP=$(kubectl -n istio-system get pod -l istio-mixer-type=telemetry -o jsonpath='{.items[0].status.podIP}')
{{< /text >}}
通常,在远程集群上自动 sidecar 注入已经启用。
要执行手动 sidecar 注入,请参考[手动 sidecar 示例](#manual-sidecar)。
## 安装 Istio 远程组件{#install-the-Istio-remote}
您必须在每个远程 Kubernetes 集群上都部署 `istio-remote` 组件。
您可以用下面两种方式之一来安装该组件:
1. 在远程集群上使用下列命令来安装 Istio 控制平面服务端点:
{{< text bash >}}
$ istioctl manifest apply \
--set profile=remote \
--set values.global.controlPlaneSecurityEnabled=false \
--set values.global.createRemoteSvcEndpoints=true \
--set values.global.remotePilotCreateSvcEndpoint=true \
--set values.global.remotePilotAddress=${PILOT_POD_IP} \
--set values.global.remotePolicyAddress=${POLICY_POD_IP} \
--set values.global.remoteTelemetryAddress=${TELEMETRY_POD_IP} \
--set gateways.enabled=false \
--set autoInjection.enabled=true
{{< /text >}}
{{< tip >}}
所有集群的 Istio 组件都必须具有相同的命名空间。
只要所有集群中所有 Istio 组件的命名空间都相同,就可以在主集群上覆盖 `istio-system` 名称。
{{< /tip >}}
1. 下列命令示例标记了 `default` 命名空间。使用类似的命令标记所有需要自动进行 sidecar 注入的远程集群的命名空间。
{{< text bash >}}
$ kubectl label namespace default istio-injection=enabled
{{< /text >}}
为所有需要设置自动 sidecar 注入的 Kubernetes 命名空间重复以上命令。
### 安装配置参数{#installation-configuration-parameters}
你必须配置远程集群的 sidecar 与 Istio 控制平面交互,包括在 `istio-remote` 配置文件中的以下端点:`pilot`、`policy`、`telemetry`和跟踪服务。
该配置文件默认在远程集群中启用自动 sidecar 注入。
您可以通过单独的设置禁用自动 sidecar 注入。
下列表格展示了 `istioctl` 针对远程集群的配置值:
| 安装设置 | 可选值 | 默认 | 值作用 |
| --- | --- | --- | --- |
| `values.global.remotePilotAddress` | 有效的 IP 地址或主机名 | None | 指定 Istio 控制平面的 pilot Pod IP 地址或远程集群 DNS 可解析的主机名 |
| `values.global.remotePolicyAddress` | 有效的 IP 地址或主机名 | None | 指定 Istio 控制平面的 policy Pod IP 地址或远程集群 DNS 可解析的主机名 |
| `values.global.remoteTelemetryAddress` | 有效的 IP 地址或主机名 | None | 指定 Istio 控制平面的 telemetry Pod IP 地址或远程集群 DNS 可解析的主机名 |
| `values.sidecarInjectorWebhook.enabled` | true, false | true | 指定是否在远程集群上启用自动 sidecar 注入 |
| `values.global.remotePilotCreateSvcEndpoint` | true, false | false | 如果设置,将使用 `remotePilotAddress` IP 创建用于 `istio-pilot` 的无选择器的服务和端点,以确保 `istio-pilot.<namespace>` 在远程集群上可通过 DNS 解析。 |
| `values.global.createRemoteSvcEndpoints` | true, false | false | 如果设置,`istio-pilot`、`istio-telemetry` 和 `istio-policy` 的 selector-less 服务和端点将用相应的远程 IP`remotePilotAddress`、`remoteTelmetryAddress` 和 `remotePolicyAddress` 分别创建,这样确保在远程集群中服务名可以通过 DNS 解析。 |
## 为远程集群创建配置文件{#kubeconfig}
Istio 控制平面需要访问网格中的所有集群以发现服务、端点和 pod 属性。
下列步骤描述了如何通过远程集群为 Istio 控制平面创建 `kubeconfig` 配置文件。
在每个远程集群上执行这些步骤以将集群加入服务网格。这些步骤需要具有远程集群的 `cluster-admin` 用户访问权限。
1. 用以下命令设置为 `istio-reader-service-account` 服务账号构建 `kubeconfig` 文件所需的环境变量:
{{< text bash >}}
$ export WORK_DIR=$(pwd)
$ CLUSTER_NAME=$(kubectl config view --minify=true -o jsonpath='{.clusters[].name}')
$ export KUBECFG_FILE=${WORK_DIR}/${CLUSTER_NAME}
$ SERVER=$(kubectl config view --minify=true -o jsonpath='{.clusters[].cluster.server}')
$ NAMESPACE=istio-system
$ SERVICE_ACCOUNT=istio-reader-service-account
$ SECRET_NAME=$(kubectl get sa ${SERVICE_ACCOUNT} -n ${NAMESPACE} -o jsonpath='{.secrets[].name}')
$ CA_DATA=$(kubectl get secret ${SECRET_NAME} -n ${NAMESPACE} -o jsonpath="{.data['ca\.crt']}")
$ TOKEN=$(kubectl get secret ${SECRET_NAME} -n ${NAMESPACE} -o jsonpath="{.data['token']}" | base64 --decode)
{{< /text >}}
{{< tip >}}
在许多系统上,`openssl enc -d -base64 -A` 可以替代 `base64 --decode`
{{< /tip >}}
1. 在工作目录中,用以下命令创建 `istio-reader-service-account` 服务账号对应的 `kubeconfig` 文件:
{{< text bash >}}
$ cat <<EOF > ${KUBECFG_FILE}
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: ${CA_DATA}
server: ${SERVER}
name: ${CLUSTER_NAME}
contexts:
- context:
cluster: ${CLUSTER_NAME}
user: ${CLUSTER_NAME}
name: ${CLUSTER_NAME}
current-context: ${CLUSTER_NAME}
kind: Config
preferences: {}
users:
- name: ${CLUSTER_NAME}
user:
token: ${TOKEN}
EOF
{{< /text >}}
1. _可选_ 创建环境变量文件以创建远程集群的 secret
{{< text bash >}}
$ cat <<EOF > remote_cluster_env_vars
export CLUSTER_NAME=${CLUSTER_NAME}
export KUBECFG_FILE=${KUBECFG_FILE}
export NAMESPACE=${NAMESPACE}
EOF
{{< /text >}}
至此,您已在当前目录中创建了远程集群的 `kubeconfig` 文件。
`kubeconfig` 文件的文件名与原始集群名称相同。
## 实例化凭证{#credentials}
在运行 Istio 控制平面的集群上执行这一步骤。
该步骤使用了来自[上一节](#kubeconfig)的 `WORK_DIR`、`CLUSTER_NAME` 和 `NAMESPACE` 环境变量以及为远程集群的 secret 创建的文件。
如果您已经为远程集群的 secret 创建了环境变量文件,运行以下命令加载该文件:
{{< text bash >}}
$ source remote_cluster_env_vars
{{< /text >}}
您可以将 Istio 安装到不同的命名空间。
本步骤使用了 `istio-system` 命名空间。
{{< warning >}}
不要为运行 Istio 控制平面的本地集群存储和标记 secrets。
Istio 始终可以感知到本地集群的 Kubernetes 凭据。
{{< /warning >}}
创建一个 secret 并为每个远程集群正确标记:
{{< text bash >}}
$ kubectl create secret generic ${CLUSTER_NAME} --from-file ${KUBECFG_FILE} -n ${NAMESPACE}
$ kubectl label secret ${CLUSTER_NAME} istio/multiCluster=true -n ${NAMESPACE}
{{< /text >}}
{{< warning >}}
Kubernetes secret 数据密钥必须符合 `DNS-1123 subdomain` [格式](https://tools.ietf.org/html/rfc1123#page-13)。
例如,文件名不能含有下划线。
只需更改文件名使其符合格式,即可解决文件名的任何问题。
{{< /warning >}}
## 卸载远程集群{#uninstalling-the-remote-cluster}
运行下列命令以卸载远程集群:
{{< text bash >}}
$ istioctl manifest generate \
--set profile=remote \
--set values.global.controlPlaneSecurityEnabled=false \
--set values.global.createRemoteSvcEndpoints=true \
--set values.global.remotePilotCreateSvcEndpoint=true \
--set values.global.remotePilotAddress=${PILOT_POD_IP} \
--set values.global.remotePolicyAddress=${POLICY_POD_IP} \
--set values.global.remoteTelemetryAddress=${TELEMETRY_POD_IP} \
--set gateways.enabled=false \
--set autoInjection.enabled=true | kubectl delete -f -
{{< /text >}}
## 手动 sidecar 注入示例 {#manual-sidecar}
下列例子展示了如何使用 `istioctl manifest` 命令来为禁用自动 sidecar 注入的远程集群生成清单。
另外,这个例子还展示了如何通过 [`istioctl kube-inject`](/zh/docs/reference/commands/istioctl/#istioctl-kube-inject) 命令使用远程集群的 `configmaps` 来为远程集群生成任意应用的清单。
对远程集群执行下列步骤。
在开始之前,请按照[设置环境变量部分](#environment-var)中的说明设置端点 IP 环境变量。
1. 安装 Istio 远程配置文件:
{{< text bash >}}
$ istioctl manifest apply \
--set profile=remote \
--set values.global.controlPlaneSecurityEnabled=false \
--set values.global.createRemoteSvcEndpoints=true \
--set values.global.remotePilotCreateSvcEndpoint=true \
--set values.global.remotePilotAddress=${PILOT_POD_IP} \
--set values.global.remotePolicyAddress=${POLICY_POD_IP} \
--set values.global.remoteTelemetryAddress=${TELEMETRY_POD_IP} \
--set gateways.enabled=false \
--set autoInjection.enabled=false
{{< /text >}}
1. 为每个远程集群[生成](#kubeconfig) `kubeconfig` 配置文件。
1. 为每个远程集群[实例化凭证](#credentials)。
### 手动将 sidecars 注入到应用程序清单{#manually-inject-the-sidecars-into-the-application-manifests}
以下示例 `istioctl` 命令将 sidecar 注入到应用程序清单中。
在为远程集群设置了 `kubeconfig` 上下文的 shell 中运行以下命令。
{{< text bash >}}
$ ORIGINAL_SVC_MANIFEST=mysvc-v1.yaml
$ istioctl kube-inject --injectConfigMapName istio-sidecar-injector --meshConfigMapName istio -f ${ORIGINAL_SVC_MANIFEST} | kubectl apply -f -
{{< /text >}}
## 从不同的集群中访问服务{#access-services-from-different-clusters}
Kubernetes 基于集群解析 DNS。
由于 DNS 解析与集群有关,因此无论服务端点的位置在哪,您都必须在运行客户端的每个集群中定义服务对象。
为确保这种情况,请使用 `kubectl` 将服务对象复制到每个集群。
复制可确保 Kubernetes 可以解析任何集群中的服务名称。
由于服务对象是在命名空间中定义的,如果该命名空间不存在,您必须定义它,并将其包含在所有集群的服务定义中。
## 部署注意事项{#deployment-considerations}
前面的步骤提供了一个简单且按部就班的部署多集群环境的指导。
一个生产环境需要更多的步骤或更复杂的部署选项。
本节收集 Istio 服务的端点 IPs 并使用它们来调用 `istioctl`
这个过程会在远程集群上创建 Istio 服务。
作为在远程集群中创建那些服务和端口的一部分Kubernetes 会往 `kube-dns` 配置对象中添加 DNS 条目。
这让远程集群上的 `kube-dns` 配置对象可以为那些远程集群中的所有 Envoy sidecars 解析 Istio 服务名。
因为 Kubernetes pods 没有固定的 IPs控制平面中的任意 Istio 服务 pod 的重启都会导致它的端点变化。
因此,任何从远程集群到那个端点的连接都会断开。
这个行为记录在 [Istio 问题 #4822](https://github.com/istio/istio/issues/4822)。
有几个选项可以避免或解决这个情况。本节概述了这些选项:
* 更新 DNS 条目
* 使用负载均衡服务类型
* 通过网关暴露这些 Istio 服务
### 更新 DNS 条目{#update-the-DNS-entries}
本地 Istio 控制平面发生任何故障或重新启动时,必须使用 Istio 服务的正确端点映射更新远程集群上的 `kube-dns`
有许多方法可以做到这一点。
最明显的是在控制平面集群上的 Istio 服务重新启动后,在远程集群中重新运行 `istioctl` 命令。
### 使用负载均衡服务类型{#use-load-balance-service-type}
在 Kubernetes 中,您可以声明一个服务的服务类型为 `LoadBalancer`
更多信息请参考 Kubernetes 文档的[服务类型](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types)。
Pod 重启问题的一个简单的解决方案就是为 Istio 服务使用负载均衡器。
然后,您可以使用负载均衡器的 IPs 作为 Istio 服务的端点 IPs 来配置远程集群。
您可能需要下列 Istio 服务的负载均衡器 IPs
* `istio-pilot`
* `istio-telemetry`
* `istio-policy`
目前Istio 安装没有提供用于为 Istio 服务指定服务类型的选项。
您可以在 Istio 清单中手动指定服务类型。
### 通过网关暴露这些 Istio 服务{#expose-the-Istio-services-via-a-gateway}
这个方法使用了 Istio ingress 网关功能。
远程集群需要 `istio-pilot`、`istio-telemetry` 和 `istio-policy` 服务指向 Istio ingress 网关的负载均衡器 IP。
然后,所有的服务指向相同的 IP。
您必须接着创建 destination rules 以在 ingress 网关的主集群中访问到对应的 Istio 服务。
此方法提供了两种选择:
* 重用提供的清单所创建的默认 Istio ingress 网关。您只需要添加正确的 destination rules。
* 为多集群创建另外一个 Istio ingress 网关。
## 安全性{#security}
Istio 支持在控制平面组件之间以及注入到应用的 pods 的 sidecar 之间部署双向 TLS。
### 控制平面安全性{#control-plane-security}
按照这些步骤启用控制平面安全性:
1. 部署 Istio 控制平面集群需要:
* 启用控制平面安全性。
* 禁用 `citadel` 证书自签名。
* Istio 控制平面命名空间中具有[证书颁发机构CA证书](/zh/docs/tasks/security/plugin-ca-cert/#plugging-in-the-existing-certificate-and-key)的名为 `cacerts` 的 secret。
1. 部署 Istio 远程集群需要:
* 启用控制平面安全性。
* 禁用 `citadel` 证书自签名。
* Istio 控制平面命名空间中具有 [CA 证书](/zh/docs/tasks/security/plugin-ca-cert/#plugging-in-the-existing-certificate-and-key)的名为 `cacerts` 的 secret。
主集群的证书颁发机构CA或根 CA 必须也为远程集群签名 CA 证书。
* Istio pilot 服务主机名可被 DNS 解析。
DNS 解析是必需的,因为 Istio 将 sidecar 配置为使用 `istio-pilot.<namespace>` 主题名称格式来验证证书主题名称。
* 设置控制平面 IPs 或可解析的主机名。
### 应用 pods 间的双向 TLS{#mutual-TLS-between-application-pods}
按照这些步骤以为所有应用 pods 启用双向 TLS
1. 部署 Istio 控制平面集群需要:
* 启用全局双向 TLS。
* 禁用 Citadel 证书自签名。
* Istio 控制平面命名空间中具有 [CA 证书](/zh/docs/tasks/security/plugin-ca-cert/#plugging-in-the-existing-certificate-and-key)的名为 `cacerts` 的 secret。
1. 部署 Istio 远程集群需要:
* 启用全局双向 TLS。
* 禁用 Citadel 证书自签名。
* Istio 控制平面命名空间中具有 [CA 证书](/zh/docs/tasks/security/plugin-ca-cert/#plugging-in-the-existing-certificate-and-key)的名为 `cacerts` 的 secret。
主集群的 CA 或根 CA 必须也为远程集群签名 CA 证书。
{{< tip >}}
对于控制平面安全性和应用 pod 安全性步骤CA 证书的步骤相同。
{{< /tip >}}
### 部署示例{#example-deployment}
这个示例过程将在同时启用控制平面双向 TLS 和应用 pod 双向 TLS 的情况下安装 Istio。
该过程用无选择器的服务和端点来设置远程集群。
Istio Pilot 用该服务和端点以让远程 sidecars 可以通过 Istio 的本地 Kubernetes DNS 解析 `istio-pilot.istio-system` 主机名。
#### 主集群:部署控制平面集群{#primary-cluster-deploy-the-control-plane-cluster}
1. 使用 `istio-system` 命名空间中的 Istio 证书示例创建 `cacerts` secret
{{< text bash >}}
$ kubectl create ns istio-system
$ kubectl create secret generic cacerts -n istio-system --from-file=samples/certs/ca-cert.pem --from-file=samples/certs/ca-key.pem --from-file=samples/certs/root-cert.pem --from-file=samples/certs/cert-chain.pem
{{< /text >}}
1. 部署 Istio 控制平面,并为控制平面和应用程序容器启用安全性:
{{< text bash >}}
$ istioctl manifest apply \
--set values.global.mtls.enabled=true \
--set values.security.selfSigned=false
{{< /text >}}
#### 远程集群:部署 Istio 组件{#remote-cluster-deploy-Istio-components}
1. 使用 `istio-system` 命名空间中的 Istio 证书示例创建 `cacerts` secret
{{< text bash >}}
$ kubectl create ns istio-system
$ kubectl create secret generic cacerts -n istio-system --from-file=samples/certs/ca-cert.pem --from-file=samples/certs/ca-key.pem --from-file=samples/certs/root-cert.pem --from-file=samples/certs/cert-chain.pem
{{< /text >}}
1. 按照[设置环境变量部分](#environment-var)中的说明设置端点 IP 环境变量。
1. 以下命令部署远程集群的组件,并为控制平面和应用程序 pod 启用安全性,并启用 Istio Pilot 无选择器服务和端点的创建,以在远程集群中获取 DNS 条目。
{{< text bash >}}
$ istioctl manifest apply \
--set profile=remote \
--set values.global.mtls.enabled=true \
--set values.security.selfSigned=false \
--set values.global.createRemoteSvcEndpoints=true \
--set values.global.remotePilotCreateSvcEndpoint=true \
--set values.global.remotePilotAddress=${PILOT_POD_IP} \
--set values.global.remotePolicyAddress=${POLICY_POD_IP} \
--set values.global.remoteTelemetryAddress=${TELEMETRY_POD_IP} \
--set gateways.enabled=false \
--set autoInjection.enabled=true
{{< /text >}}
1. 要为远程集群生成 `kubeconfig` 配置文件,请遵循 [Kubernetes 配置部分](#kubeconfig)中的步骤。
### 主集群:实例化凭证{#primary-cluster-instantiate-credentials}
您必须为每个远程集群都实例化凭证。请按照[实例化凭证过程](#credentials)完成部署。
### 恭喜{#congratulations}
您已将所有群集中的所有 Istio 组件都配置为在应用 sidecars、控制平面组件和其他应用 sidecars 之间使用双向 TLS。

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 152 KiB

View File

@ -1,153 +0,0 @@
---
title: 简化地多集群安装[实验性]
description: 配置一个跨多个 Kubernetes 集群的 Istio 网格。
weight: 1
keywords: [kubernetes,multicluster]
---
{{< boilerplate experimental-feature-warning >}}
本指南描述了如何使用一种简化的实验性方式来配置一个跨多个 Kubernetes 集群的 Istio 网格。
我们希望在将来的版本中继续开发这项功能,因此非常期待您对这个流程进行反馈。
在此我们集中讨论如何连接多集群网格的细节,有关其它背景信息,请参考[多集群部署模型](/zh/docs/ops/deployment/deployment-models/#multiple-clusters)。
我们将展示如何将同一网络上的两个集群与另一个网络上的第三个集群连接起来。
使用本指南中展示的方法会导致 Istio 控制平面的实例部署在网格中的每个集群中。
尽管这是一种常见配置,但其他更复杂的拓扑也是可能的,只是需要使用一些手动的过程来完成,此处不再赘述。
## 开始之前{#before-you-begin}
此处我们描述的过程主要针对相对干净的未部署过 Istio 的集群。
我们在将来能将支持扩展到现有集群。
为了便于说明,本指南假定您已经创建了三个 Kubernetes 集群:
- 一个在 `network-east` 网络上的名为 `cluster-east-1` 的集群。
- 一个在 `network-east` 网络上的名为 `cluster-east-2` 的集群。
- 一个在 `network-west` 网络上的名为 `cluster-west-1` 的集群。
这些集群应当尚未安装 Istio。前两个集群在同一个网络并可直连而第三个集群在另一个网络。
请查看[平台设置说明](/zh/docs/setup/platform-setup),以了解针对您的特定环境的任何特殊说明。
## 初步准备{#initial-preparations}
您需要执行一些一次性步骤才能设置多集群网格:
1. 确保您的所有集群都被包含在您的 [Kubernetes 配置文件](https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/#define-clusters-users-and-contexts)中,并为它们创建了上下文配置。完成后,您的配置文件应该包含类似如下内容:
{{< text syntax="yaml" downloadas="kubeconfig.yaml" >}}
kind: Config
apiVersion: v1
clusters:
- cluster:
name: cluster-east-1
- cluster:
name: cluster-east-2
- cluster:
name: cluster-west-1
contexts:
- context:
cluster: cluster-east-1
name: context-east-1
- context:
cluster: cluster-east-2
name: context-east-2
- context:
cluster: cluster-west-1
name: context-west-1
{{< /text >}}
1. 决定您的多集群网格的名字。推荐使用一些短小好记的:
{{< text bash >}}
$ export MESH_ID=mymeshname
{{< /text >}}
1. 决定组织名以用于创建用来让集群互相通信的根证书和中间证书。这通常可以从您的组织的 DNS 名中得来:
{{< text bash >}}
$ export ORG_NAME=mymeshname.mycompanyname.com
{{< /text >}}
1. 创建一个工作目录,用于存储在集群启动过程中产生的若干文件:
{{< text bash >}}
$ export WORKDIR=mydir
$ mkdir -p ${WORKDIR}
$ cd ${WORKDIR}
{{< /text >}}
1. 下载[设置脚本]({{<github_file>}}/samples/multicluster/setup-mesh.sh)到您的工作目录。
该脚本负责创建必要的证书以启用跨集群通信,它为您准备了默认配置文件,并将在每个集群中部署和配置 Istio。
1. 最后,运行下载的脚本以准备网格。这会创建一个将用于保护网格中群集之间的通信安全的根密钥和证书,以及用于控制所有群集上部署的 Istio 的配置的 `base.yaml` 文件:
{{< text bash >}}
$ ./setup-mesh.sh prep-mesh
{{< /text >}}
请注意此步骤不会对集群产生任何影响,它只是在您的工作目录里创建了若干文件。
## 定制 Istio{#customizing-Istio}
上面的网格准备工作在您的工作目录里创建了一个名为 `base.yaml` 的文件。
这个文件定义了基本的 [`IstioControlPlane`](/zh/docs/reference/config/istio.operator.v1alpha12.pb/#IstioControlPlane) 配置,它用于将 Istio 部署到您的集群中(下面就会提到)。
您可以[定制 `base.yaml`](/zh/docs/setup/install/istioctl/#configure-the-feature-or-component-settings) 文件,以精确控制 Istio 将被如何部署到所有的集群中。
只有这些值不应该被修改:
{{< text plain >}}
values.gateway.istio-ingressgateway.env.ISTIO_MESH_NETWORK
values.global.controlPlaneSecurityEnabled
values.global.multiCluster.clusterName
values.global.network
values.global.meshNetworks
values.pilot.meshNetworks=
{{< /text >}}
这些值是通过以下步骤自动设置的,任何手动设置都会导致数据丢失。
## 创建网格{#creating-the-mesh}
通过编辑在您的工作目录中的 `topology.yaml` 文件来指定哪些集群将被包含在网格中。
为这三个集群都添加一个条目,使文件如下所示:
{{< text yaml >}}
mesh_id: mymeshname
contexts:
context-east-1:
network: network-east
context-east-2:
network: network-east
context-west-1:
network: network-west
{{< /text >}}
该拓扑文件保存了网格的名字,以及网络的上下文映射。当文件保存后,您就可以开始创建网格了。
这将部署 Istio 到每个集群,并配置每个势力以互相安全通信:
{{< text bash >}}
$ ./setup-mesh.sh apply
{{< /text >}}
想要往网格中添加或删除集群,只需要对应地更新该拓扑文件并重新应用这些更改。
{{< warning >}}
每当您使用 `setup-mesh.sh apply` 时,都会在您的工作目录中创建一些 secret 文件,尤其是与不同证书关联的一些私钥。
您应该存储并保护好这些 secrets。需要保护的这些文件是
{{< text plain >}}
certs/root-key.pem - 根私钥
certs/intermediate-*/ca-key.pem - 中间私钥
{{< /text >}}
{{< /warning >}}
## 清理{#clean-up}
您可以使用以下命令从所有的已知集群中删除 Istio
{{< text bash >}}
$ ./setup-mesh.sh teardown
{{< /text >}}