使用外部控制平面安装 Istio

本指南将引导您完成安装外部控制平面, 然后将一个或多个从集群连接到该平面的过程。

外部控制平面部署模型 允许网格操作员在与组成网格的数据平面集群(或多个集群)分开的外部集群上安装和管理控制平面。 这种部署模型可以将网状网络运营商和网状网络管理员明确区分。网格操作员可以安装和管理 Istio 控制平面, 而网格管理员只需配置网格即可。

外部控制平面集群和从集群
外部控制平面集群和从集群

在从集群中运行的 Envoy 代理(Sidecar 和 Gateway)通过 Ingress Gateway 访问外部 Istiod,向外暴露了需要被发现,CA,注入和验证的端点。

虽然外部控制平面的配置和管理是由外部集群中的网格操作员完成的, 但连接到外部控制平面的第一个从集群充当了网格本身的配置集群。除了网状服务本身之外, 网格管理员还将使用配置集群来配置网状资源(Gateway、虚拟服务等)。外部控制平面将从 Kubernetes API Server 远程访问此配置,如上图所示。

准备开始

集群

本指南要求您有任意两个受支持版本的 Kubernetes 集群:1.27, 1.28, 1.29, 1.30。

第一个集群将托管安装在 external-istiod 命名空间中的外部控制平面。 Ingress Gateway 也安装在 istio-system 命名空间中,以提供对外部控制平面的跨集群访问。

第二个集群是将运行网格应用程序工作负载的从集群。 它的 Kubernetes API Server 还提供了外部控制平面(Istiod)用来配置工作负载代理的网状配置。

API Server 访问

外部控制平面集群必须可以访问从集群中的 Kubernetes API Server。 许多云提供商通过网络负载均衡器(NLB)公开访问 API Server。 如果无法直接访问 API Server,则需要修改安装过程以启用访问权限。 例如,在多集群配置中使用的东西向 Gateway 也可以用于启用对 API Server 的访问。

环境变量

以下环境变量将始终用于简化说明:

变量名称描述
CTX_EXTERNAL_CLUSTER默认 Kubernetes 配置文件中的上下文名称,用于访问外部控制平面集群。
CTX_REMOTE_CLUSTER默认 Kubernetes 配置文件中的上下文名称,用于访问从集群。
REMOTE_CLUSTER_NAME从集群的名称。
EXTERNAL_ISTIOD_ADDR外部控制平面集群上的 Ingress Gateway 的主机名。从集群使用它来访问外部控制平面。
SSL_SECRET_NAME拥有外部控制平面集群上 Ingress Gateway 的 TLS 证书的 Secret 名称。

立即设置 CTX_EXTERNAL_CLUSTERCTX_REMOTE_CLUSTERREMOTE_CLUSTER_NAME。稍后将设置其他变量。

  1. $ export CTX_EXTERNAL_CLUSTER=<您的外部集群上下文>
  2. $ export CTX_REMOTE_CLUSTER=<您的从集群上下文>
  3. $ export REMOTE_CLUSTER_NAME=<您的从集群名称>

集群配置

网格操作步骤

网格操作员负责在外部集群上安装和管理外部 Istio 控制平面。 这包括在外部集群上配置 Ingress Gateway,允许从集群访问控制平面,并在从集群上安装所需的 Webhook、ConfigMap 和 Secret,以便使用外部控制平面。

在外部集群中搭建 Gateway

  1. 为 Ingress Gateway 创建 Istio 安装配置,该配置会将外部控制平面端口暴露给其他集群:

    1. $ cat <<EOF > controlplane-gateway.yaml
    2. apiVersion: install.istio.io/v1alpha1
    3. kind: IstioOperator
    4. metadata:
    5. namespace: istio-system
    6. spec:
    7. components:
    8. ingressGateways:
    9. - name: istio-ingressgateway
    10. enabled: true
    11. k8s:
    12. service:
    13. ports:
    14. - port: 15021
    15. targetPort: 15021
    16. name: status-port
    17. - port: 15012
    18. targetPort: 15012
    19. name: tls-xds
    20. - port: 15017
    21. targetPort: 15017
    22. name: tls-webhook
    23. EOF

    然后,将 Gateway 安装在外部集群的 istio-system 命名空间中:

    1. $ istioctl install -f controlplane-gateway.yaml --context="${CTX_EXTERNAL_CLUSTER}"
  2. 运行以下命令来确认 Ingress Gateway 已启动并正在运行:

    1. $ kubectl get po -n istio-system --context="${CTX_EXTERNAL_CLUSTER}"
    2. NAME READY STATUS RESTARTS AGE
    3. istio-ingressgateway-9d4c7f5c7-7qpzz 1/1 Running 0 29s
    4. istiod-68488cd797-mq8dn 1/1 Running 0 38s

    您会注意到在 istio-system 命名空间中也创建了一个 Istiod Deployment。这用于配置 Ingress Gateway,而不是从集群使用的控制平面。

    可以将 Ingress Gateway 配置为在外部集群上的不同命名空间中承载多个外部控制平面, 尽管在本示例中,您将仅在 external-istiod 命名空间中部署一个外部 Istiod。

  3. 使用带有 TLS 的公共主机名配置您的环境来暴露 Istio Ingress Gateway 服务。

    EXTERNAL_ISTIOD_ADDR 环境变量设置为主机名,将 SSL_SECRET_NAME 环境变量设置为包含 TLS 证书的 Secret:

    1. $ export EXTERNAL_ISTIOD_ADDR=<您的外部 istiod 主机>
    2. $ export SSL_SECRET_NAME=<您的外部 istiod secret>

    这些说明假定您使用具有正确签名的 DNS 证书的主机名公开外部集群的 Gateway,因为这是生产环境中推荐的方法。 参阅安全的 Ingress 任务, 了解暴露安全 Gateway 的更多信息。

    您的环境变量应如下所示:

    1. $ echo "$EXTERNAL_ISTIOD_ADDR" "$SSL_SECRET_NAME"
    2. myhost.example.com myhost-example-credential

    如果您没有 DNS 主机名但想在测试环境中试验外部控制平面,您可以使用其外部负载均衡器 IP 地址访问 Gateway:

    1. $ export EXTERNAL_ISTIOD_ADDR=$(kubectl -n istio-system --context="${CTX_EXTERNAL_CLUSTER}" get svc istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    2. $ export SSL_SECRET_NAME=NONE

    这样做还需要对配置进行一些其他更改。请务必按照以下说明中的所有相关步骤进行操作。

设置从集群

  1. 使用 remote 配置文件配置从集群上安装的 Istio。这将安装一个使用外部控制平面注入器的注入 Webhook, 而不是本地部署的注入器。因为这个集群也将作为配置集群,所以安装从集群上所需的 Istio CRD 和其他资源时将 global.configClusterpilot.configMap 设置为 true

    1. $ cat <<EOF > remote-config-cluster.yaml
    2. apiVersion: install.istio.io/v1alpha1
    3. kind: IstioOperator
    4. metadata:
    5. namespace: external-istiod
    6. spec:
    7. profile: remote
    8. values:
    9. global:
    10. istioNamespace: external-istiod
    11. configCluster: true
    12. pilot:
    13. configMap: true
    14. istiodRemote:
    15. injectionURL: https://${EXTERNAL_ISTIOD_ADDR}:15017/inject/cluster/${REMOTE_CLUSTER_NAME}/net/network1
    16. base:
    17. validationURL: https://${EXTERNAL_ISTIOD_ADDR}:15017/validate
    18. EOF

    如果您的集群名称包含/(斜杠)字符,请在 injectionURL 中将其替换为 --slash--, 例如 injectionURL: https://1.2.3.4:15017/inject/cluster/``cluster--slash--1``/net/network1

  2. 如果您使用的是 EXTERNAL_ISTIOD_ADDR 的 IP 地址,而不是正确的 DNS 主机名, 请修改配置以指定发现地址和路径,而不是 URL:

    在生产环境中不推荐这样做。

    1. $ sed -i'.bk' \
    2. -e "s|injectionURL: https://${EXTERNAL_ISTIOD_ADDR}:15017|injectionPath: |" \
    3. -e "/istioNamespace:/a\\
    4. remotePilotAddress: ${EXTERNAL_ISTIOD_ADDR}" \
    5. -e '/base:/,+1d' \
    6. remote-config-cluster.yaml; rm remote-config-cluster.yaml.bk
  3. 在从集群上安装配置:

    1. $ kubectl create namespace external-istiod --context="${CTX_REMOTE_CLUSTER}"
    2. $ istioctl manifest generate -f remote-config-cluster.yaml --set values.defaultRevision=default | kubectl apply --context="${CTX_REMOTE_CLUSTER}" -f -
  4. 确认从集群的注入 Webhook 配置已经安装:

    1. $ kubectl get mutatingwebhookconfiguration --context="${CTX_REMOTE_CLUSTER}"
    2. NAME WEBHOOKS AGE
    3. istio-sidecar-injector-external-istiod 4 6m24s
  5. 确认已安装从集群的验证 Webhook 配置:

    1. $ kubectl get validatingwebhookconfiguration --context="${CTX_REMOTE_CLUSTER}"
    2. NAME WEBHOOKS AGE
    3. istio-validator-external-istiod 1 6m53s
    4. istiod-default-validator 1 6m53s

在外部集群中安装控制平面

  1. 创建 external-istiod 命名空间,该命名空间将用于托管外部控制平面:

    1. $ kubectl create namespace external-istiod --context="${CTX_EXTERNAL_CLUSTER}"
  2. 外部集群中的控制平面需要访问从集群以发现服务、端点和 Pod 属性。创建具有凭据的 Secret,以访问从集群的 kube-apiserver 并将其安装在外部集群中:

    1. $ kubectl create sa istiod-service-account -n external-istiod --context="${CTX_EXTERNAL_CLUSTER}"
    2. $ istioctl create-remote-secret \
    3. --context="${CTX_REMOTE_CLUSTER}" \
    4. --type=config \
    5. --namespace=external-istiod \
    6. --service-account=istiod \
    7. --create-service-account=false | \
    8. kubectl apply -f - --context="${CTX_EXTERNAL_CLUSTER}"
  3. 创建 Istio 配置以在外部集群的 external-istiod 命名空间中安装控制平面。 请注意,istiod 配置为使用本地安装的 istio ConfigMap,并且 SHARED_MESH_CONFIG 环境变量设置为 istio。这指示 istiod 将网格管理员在配置集群的 ConfigMap 中设置的值与网格操作员在本地 ConfigMap 中设置的值合并,如果有任何冲突,这将优先考虑:

    1. $ cat <<EOF > external-istiod.yaml
    2. apiVersion: install.istio.io/v1alpha1
    3. kind: IstioOperator
    4. metadata:
    5. namespace: external-istiod
    6. spec:
    7. profile: empty
    8. meshConfig:
    9. rootNamespace: external-istiod
    10. defaultConfig:
    11. discoveryAddress: $EXTERNAL_ISTIOD_ADDR:15012
    12. proxyMetadata:
    13. XDS_ROOT_CA: /etc/ssl/certs/ca-certificates.crt
    14. CA_ROOT_CA: /etc/ssl/certs/ca-certificates.crt
    15. components:
    16. pilot:
    17. enabled: true
    18. k8s:
    19. overlays:
    20. - kind: Deployment
    21. name: istiod
    22. patches:
    23. - path: spec.template.spec.volumes[100]
    24. value: |-
    25. name: config-volume
    26. configMap:
    27. name: istio
    28. - path: spec.template.spec.volumes[100]
    29. value: |-
    30. name: inject-volume
    31. configMap:
    32. name: istio-sidecar-injector
    33. - path: spec.template.spec.containers[0].volumeMounts[100]
    34. value: |-
    35. name: config-volume
    36. mountPath: /etc/istio/config
    37. - path: spec.template.spec.containers[0].volumeMounts[100]
    38. value: |-
    39. name: inject-volume
    40. mountPath: /var/lib/istio/inject
    41. env:
    42. - name: INJECTION_WEBHOOK_CONFIG_NAME
    43. value: ""
    44. - name: VALIDATION_WEBHOOK_CONFIG_NAME
    45. value: ""
    46. - name: EXTERNAL_ISTIOD
    47. value: "true"
    48. - name: LOCAL_CLUSTER_SECRET_WATCHER
    49. value: "true"
    50. - name: CLUSTER_ID
    51. value: ${REMOTE_CLUSTER_NAME}
    52. - name: SHARED_MESH_CONFIG
    53. value: istio
    54. values:
    55. global:
    56. caAddress: $EXTERNAL_ISTIOD_ADDR:15012
    57. istioNamespace: external-istiod
    58. operatorManageWebhooks: true
    59. configValidation: false
    60. meshID: mesh1
    61. EOF
  4. 如果您使用的是 EXTERNAL_ISTIOD_ADDR 的 IP 地址,而不是合适的 DNS 主机名, 请删除代理元数据并更新配置中的 Webhook 配置环境变量:

    这在生产环境中不推荐。

    1. $ sed -i'.bk' \
    2. -e '/proxyMetadata:/,+2d' \
    3. -e '/INJECTION_WEBHOOK_CONFIG_NAME/{n;s/value: ""/value: istio-sidecar-injector-external-istiod/;}' \
    4. -e '/VALIDATION_WEBHOOK_CONFIG_NAME/{n;s/value: ""/value: istio-validator-external-istiod/;}' \
    5. external-istiod.yaml ; rm external-istiod.yaml.bk
  5. 在外部集群上应用 Istio 配置:

    1. $ istioctl install -f external-istiod.yaml --context="${CTX_EXTERNAL_CLUSTER}"
  6. 确认外部 Istiod 已成功部署:

    1. $ kubectl get po -n external-istiod --context="${CTX_EXTERNAL_CLUSTER}"
    2. NAME READY STATUS RESTARTS AGE
    3. istiod-779bd6fdcf-bd6rg 1/1 Running 0 70s
  7. 创建 Istio GatewayVirtualServiceDestinationRule 配置,将流量从 Ingress Gateway 路由到外部控制平面:

    1. $ cat <<EOF > external-istiod-gw.yaml
    2. apiVersion: networking.istio.io/v1
    3. kind: Gateway
    4. metadata:
    5. name: external-istiod-gw
    6. namespace: external-istiod
    7. spec:
    8. selector:
    9. istio: ingressgateway
    10. servers:
    11. - port:
    12. number: 15012
    13. protocol: https
    14. name: https-XDS
    15. tls:
    16. mode: SIMPLE
    17. credentialName: $SSL_SECRET_NAME
    18. hosts:
    19. - $EXTERNAL_ISTIOD_ADDR
    20. - port:
    21. number: 15017
    22. protocol: https
    23. name: https-WEBHOOK
    24. tls:
    25. mode: SIMPLE
    26. credentialName: $SSL_SECRET_NAME
    27. hosts:
    28. - $EXTERNAL_ISTIOD_ADDR
    29. ---
    30. apiVersion: networking.istio.io/v1
    31. kind: VirtualService
    32. metadata:
    33. name: external-istiod-vs
    34. namespace: external-istiod
    35. spec:
    36. hosts:
    37. - $EXTERNAL_ISTIOD_ADDR
    38. gateways:
    39. - external-istiod-gw
    40. http:
    41. - match:
    42. - port: 15012
    43. route:
    44. - destination:
    45. host: istiod.external-istiod.svc.cluster.local
    46. port:
    47. number: 15012
    48. - match:
    49. - port: 15017
    50. route:
    51. - destination:
    52. host: istiod.external-istiod.svc.cluster.local
    53. port:
    54. number: 443
    55. ---
    56. apiVersion: networking.istio.io/v1
    57. kind: DestinationRule
    58. metadata:
    59. name: external-istiod-dr
    60. namespace: external-istiod
    61. spec:
    62. host: istiod.external-istiod.svc.cluster.local
    63. trafficPolicy:
    64. portLevelSettings:
    65. - port:
    66. number: 15012
    67. tls:
    68. mode: SIMPLE
    69. connectionPool:
    70. http:
    71. h2UpgradePolicy: UPGRADE
    72. - port:
    73. number: 443
    74. tls:
    75. mode: SIMPLE
    76. EOF
  8. 如果您为 EXTERNAL_ISTIOD_ADDR 使用 IP 地址,而不是合适的 DNS 主机名,请修改配置。 删除 DestinationRule,不要在 Gateway 中终止 TLS,在 VirtualService 中使用 TLS 路由:

    在生产环境中不推荐这样做。

    1. $ sed -i'.bk' \
    2. -e '55,$d' \
    3. -e 's/mode: SIMPLE/mode: PASSTHROUGH/' -e '/credentialName:/d' -e "s/${EXTERNAL_ISTIOD_ADDR}/\"*\"/" \
    4. -e 's/http:/tls:/' -e 's/https/tls/' -e '/route:/i\
    5. sniHosts:\
    6. - "*"' \
    7. external-istiod-gw.yaml; rm external-istiod-gw.yaml.bk
  9. 在外部集群上应用配置:

    1. $ kubectl apply -f external-istiod-gw.yaml --context="${CTX_EXTERNAL_CLUSTER}"

网格管理步骤

现在 Istio 已启动并运行,网格管理员只需在网格中部署和配置服务,包括 Gateway(如果需要)。

默认情况下,某些 istioctl CLI 命令在从集群上不起作用,但您可以轻松配置 istioctl 以使其功能齐全。 详情参见 Istioctl-proxy 生态系统项目

部署一个简单应用

  1. 在从集群上创建 sample 命名空间并启用标签注入:

    1. $ kubectl create --context="${CTX_REMOTE_CLUSTER}" namespace sample
    2. $ kubectl label --context="${CTX_REMOTE_CLUSTER}" namespace sample istio-injection=enabled
  2. 部署示例 helloworldv1)和 sleep

    ZipZipZip

    1. $ kubectl apply -f @samples/helloworld/helloworld.yaml@ -l service=helloworld -n sample --context="${CTX_REMOTE_CLUSTER}"
    2. $ kubectl apply -f @samples/helloworld/helloworld.yaml@ -l version=v1 -n sample --context="${CTX_REMOTE_CLUSTER}"
    3. $ kubectl apply -f @samples/sleep/sleep.yaml@ -n sample --context="${CTX_REMOTE_CLUSTER}"
  3. 等几秒钟,Pod helloworldsleep 将以 Sidecar 注入的方式运行:

    1. $ kubectl get pod -n sample --context="${CTX_REMOTE_CLUSTER}"
    2. NAME READY STATUS RESTARTS AGE
    3. helloworld-v1-5b75657f75-ncpc5 2/2 Running 0 10s
    4. sleep-64d7d56698-wqjnm 2/2 Running 0 9s
  4. 从 Pod sleep 向 Pod helloworld 服务发送请求:

    1. $ kubectl exec --context="${CTX_REMOTE_CLUSTER}" -n sample -c sleep \
    2. "$(kubectl get pod --context="${CTX_REMOTE_CLUSTER}" -n sample -l app=sleep -o jsonpath='{.items[0].metadata.name}')" \
    3. -- curl -sS helloworld.sample:5000/hello
    4. Hello version: v1, instance: helloworld-v1-776f57d5f6-s7zfc

启用 Gateway

Istio 支持 Kubernetes Gateway API, 并计划将其作为未来流量管理的默认 API。

如果您使用 Gateway API,则无需安装任何 Gateway 组件。 您可以跳过以下说明,直接进入配置和测试 Ingress Gateway

在从集群上启用 Ingress Gateway:

  1. $ cat <<EOF > istio-ingressgateway.yaml
  2. apiVersion: install.istio.io/v1alpha1
  3. kind: IstioOperator
  4. spec:
  5. profile: empty
  6. components:
  7. ingressGateways:
  8. - namespace: external-istiod
  9. name: istio-ingressgateway
  10. enabled: true
  11. values:
  12. gateways:
  13. istio-ingressgateway:
  14. injectionTemplate: gateway
  15. EOF
  16. $ istioctl install -f istio-ingressgateway.yaml --set values.global.istioNamespace=external-istiod --context="${CTX_REMOTE_CLUSTER}"
  1. $ helm install istio-ingressgateway istio/gateway -n external-istiod --kube-context="${CTX_REMOTE_CLUSTER}"

有关 Gateway 安装的详细文档,请参阅安装 Gateway

在从集群上启用 Egress Gateway 或者其他 Gateway(可选):

  1. $ cat <<EOF > istio-egressgateway.yaml
  2. apiVersion: install.istio.io/v1alpha1
  3. kind: IstioOperator
  4. spec:
  5. profile: empty
  6. components:
  7. egressGateways:
  8. - namespace: external-istiod
  9. name: istio-egressgateway
  10. enabled: true
  11. values:
  12. gateways:
  13. istio-egressgateway:
  14. injectionTemplate: gateway
  15. EOF
  16. $ istioctl install -f istio-egressgateway.yaml --set values.global.istioNamespace=external-istiod --context="${CTX_REMOTE_CLUSTER}"
  1. $ helm install istio-egressgateway istio/gateway -n external-istiod --kube-context="${CTX_REMOTE_CLUSTER}" --set service.type=ClusterIP

有关 Gateway 安装的详细文档,请参阅安装 Gateway

配置和测试 Ingress Gateway

以下说明指导您在网格中配置流量管理时如何选择使用 Gateway API 或 Istio 配置 API。 请按照您的首选项遵循 Gateway APIIstio APIs 页签中的指示说明。

  1. 确保集群已准备好配置 Gateway:

确认 Istio Ingress Gateway 正在运行:

  1. $ kubectl get pod -l app=istio-ingressgateway -n external-istiod --context="${CTX_REMOTE_CLUSTER}"
  2. NAME READY STATUS RESTARTS AGE
  3. istio-ingressgateway-7bcd5c6bbd-kmtl4 1/1 Running 0 8m4s

大多数 Kubernetes 集群默认不会安装 Kubernetes Gateway API CRD,因此请确保在使用 Gateway API 之前安装了它们:

  1. $ kubectl get crd gateways.gateway.networking.k8s.io --context="${CTX_REMOTE_CLUSTER}" || \
  2. { kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.1.0" | kubectl apply -f - --context="${CTX_REMOTE_CLUSTER}"; }
  1. 在 Ingress Gateway 上暴露 helloworld 应用:

Zip

  1. $ kubectl apply -f @samples/helloworld/helloworld-gateway.yaml@ -n sample --context="${CTX_REMOTE_CLUSTER}"

Zip

  1. $ kubectl apply -f @samples/helloworld/gateway-api/helloworld-gateway.yaml@ -n sample --context="${CTX_REMOTE_CLUSTER}"
  1. 设置 GATEWAY_URL 环境变量(有关详细信息,请参阅确定 Ingress 的 IP 和端口):
  1. $ export INGRESS_HOST=$(kubectl -n external-istiod --context="${CTX_REMOTE_CLUSTER}" get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
  2. $ export INGRESS_PORT=$(kubectl -n external-istiod --context="${CTX_REMOTE_CLUSTER}" get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
  3. $ export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
  1. $ kubectl -n sample --context="${CTX_REMOTE_CLUSTER}" wait --for=condition=programmed gtw helloworld-gateway
  2. $ export INGRESS_HOST=$(kubectl -n sample --context="${CTX_REMOTE_CLUSTER}" get gtw helloworld-gateway -o jsonpath='{.status.addresses[0].value}')
  3. $ export GATEWAY_URL=$INGRESS_HOST:80
  1. 确认您可以通过 Ingress Gateway 访问 helloworld 应用:

    1. $ curl -s "http://${GATEWAY_URL}/hello"
    2. Hello version: v1, instance: helloworld-v1-776f57d5f6-s7zfc

将集群添加到网格(可选)

本节介绍如何通过添加另一个从集群将现有的外部控制平面网格扩展到多集群。 这使您可以轻松分发服务并使用位置感知路由和故障转移,以支持应用程序的高可用性。

多从集群的外部控制平面
多从集群的外部控制平面

与第一个从集群不同,添加到同一外部控制平面的第二个以及后续集群不提供网格配置,而仅提供端点配置的来源, 就像主从 Istio 多集群配置中的从集群一样。

要继续的话,您需要另一个 Kubernetes 集群作为网格的第二个从集群。将以下环境变量设置为集群的上下文名称和集群名称:

  1. $ export CTX_SECOND_CLUSTER=<您的第二个从集群上下文>
  2. $ export SECOND_CLUSTER_NAME=<您的第二个从集群名称>

注册新集群

  1. 创建远程 Istio 安装配置,它安装使用外部控制平面注入器的注入 Webhook,而不是本地部署的注入器:

    1. $ cat <<EOF > second-remote-cluster.yaml
    2. apiVersion: install.istio.io/v1alpha1
    3. kind: IstioOperator
    4. metadata:
    5. namespace: external-istiod
    6. spec:
    7. profile: remote
    8. values:
    9. global:
    10. istioNamespace: external-istiod
    11. istiodRemote:
    12. injectionURL: https://${EXTERNAL_ISTIOD_ADDR}:15017/inject/cluster/${SECOND_CLUSTER_NAME}/net/network2
    13. EOF
  2. 如果您使用的是 EXTERNAL_ISTIOD_ADDR 的 IP 地址,而不是合适的 DNS 主机名,请修改配置以指定发现地址和路径,而不是注入 URL:

    在生产环境中不推荐这样做。

    1. $ sed -i'.bk' \
    2. -e "s|injectionURL: https://${EXTERNAL_ISTIOD_ADDR}:15017|injectionPath: |" \
    3. -e "/istioNamespace:/a\\
    4. remotePilotAddress: ${EXTERNAL_ISTIOD_ADDR}" \
    5. second-remote-cluster.yaml; rm second-remote-cluster.yaml.bk
  3. 在从集群上创建系统命名空间并添加注解:

    1. $ kubectl create namespace external-istiod --context="${CTX_SECOND_CLUSTER}"
    2. $ kubectl annotate namespace external-istiod "topology.istio.io/controlPlaneClusters=${REMOTE_CLUSTER_NAME}" --context="${CTX_SECOND_CLUSTER}"

    topology.istio.io/controlPlaneClusters 注解指定了应该管理这个从集群的外部控制平面的集群 ID。 注意这是第一个从(配置)集群的名称,之前在外部集群安装时用于设置外部控制平面的集群 ID。

  4. 在从集群上安装配置:

    1. $ istioctl manifest generate -f second-remote-cluster.yaml | kubectl apply --context="${CTX_SECOND_CLUSTER}" -f -
  5. 确认从集群的注入 Webhook 配置已经安装:

    1. $ kubectl get mutatingwebhookconfiguration --context="${CTX_SECOND_CLUSTER}"
    2. NAME WEBHOOKS AGE
    3. istio-sidecar-injector-external-istiod 4 4m13s
  6. 使用凭据创建一个 Secret,以允许控制平面访问第二个从集群上的端点并安装它:

    1. $ istioctl create-remote-secret \
    2. --context="${CTX_SECOND_CLUSTER}" \
    3. --name="${SECOND_CLUSTER_NAME}" \
    4. --type=remote \
    5. --namespace=external-istiod \
    6. --create-service-account=false | \
    7. kubectl apply -f - --context="${CTX_EXTERNAL_CLUSTER}"

    请注意,与网格的第一个从集群不同,它也用作 config 集群,此时 --type 参数设置为 remote,而不是 config

设置东西向 Gateway

  1. 在两个从集群上部署东西向 Gateway:

    Zip

    1. $ @samples/multicluster/gen-eastwest-gateway.sh@ \
    2. --network network1 > eastwest-gateway-1.yaml
    3. $ istioctl manifest generate -f eastwest-gateway-1.yaml \
    4. --set values.global.istioNamespace=external-istiod | \
    5. kubectl apply --context="${CTX_REMOTE_CLUSTER}" -f -

    Zip

    1. $ @samples/multicluster/gen-eastwest-gateway.sh@ \
    2. --network network2 > eastwest-gateway-2.yaml
    3. $ istioctl manifest generate -f eastwest-gateway-2.yaml \
    4. --set values.global.istioNamespace=external-istiod | \
    5. kubectl apply --context="${CTX_SECOND_CLUSTER}" -f -
  2. 等待东西向 Gateway 分配外部 IP 地址:

    1. $ kubectl --context="${CTX_REMOTE_CLUSTER}" get svc istio-eastwestgateway -n external-istiod
    2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    3. istio-eastwestgateway LoadBalancer 10.0.12.121 34.122.91.98 ... 51s
    1. $ kubectl --context="${CTX_SECOND_CLUSTER}" get svc istio-eastwestgateway -n external-istiod
    2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    3. istio-eastwestgateway LoadBalancer 10.0.12.121 34.122.91.99 ... 51s
  3. 通过东西向 Gateway 公开服务:

    Zip

    1. $ kubectl --context="${CTX_REMOTE_CLUSTER}" apply -n external-istiod -f \
    2. @samples/multicluster/expose-services.yaml@

验证安装

  1. 在从集群上创建 sample 命名空间并启用标签注入:

    1. $ kubectl create --context="${CTX_SECOND_CLUSTER}" namespace sample
    2. $ kubectl label --context="${CTX_SECOND_CLUSTER}" namespace sample istio-injection=enabled
  2. 部署 helloworldv2 版本)和 sleep 的示例:

    ZipZipZip

    1. $ kubectl apply -f @samples/helloworld/helloworld.yaml@ -l service=helloworld -n sample --context="${CTX_SECOND_CLUSTER}"
    2. $ kubectl apply -f @samples/helloworld/helloworld.yaml@ -l version=v2 -n sample --context="${CTX_SECOND_CLUSTER}"
    3. $ kubectl apply -f @samples/sleep/sleep.yaml@ -n sample --context="${CTX_SECOND_CLUSTER}"
  3. 等待几秒钟,让 helloworld 和 Pod sleep 在注入 Sidecar 的情况下运行:

    1. $ kubectl get pod -n sample --context="${CTX_SECOND_CLUSTER}"
    2. NAME READY STATUS RESTARTS AGE
    3. helloworld-v2-54df5f84b-9hxgw 2/2 Running 0 10s
    4. sleep-557747455f-wtdbr 2/2 Running 0 9s
  4. 从 Pod sleephelloworld 服务发送请求:

    1. $ kubectl exec --context="${CTX_SECOND_CLUSTER}" -n sample -c sleep \
    2. "$(kubectl get pod --context="${CTX_SECOND_CLUSTER}" -n sample -l app=sleep -o jsonpath='{.items[0].metadata.name}')" \
    3. -- curl -sS helloworld.sample:5000/hello
    4. Hello version: v2, instance: helloworld-v2-54df5f84b-9hxgw
  5. 确认通过 Ingress Gateway 多次访问 helloworld 应用时,现在调用的是版本 v1v2

    1. $ for i in {1..10}; do curl -s "http://${GATEWAY_URL}/hello"; done
    2. Hello version: v1, instance: helloworld-v1-776f57d5f6-s7zfc
    3. Hello version: v2, instance: helloworld-v2-54df5f84b-9hxgw
    4. Hello version: v1, instance: helloworld-v1-776f57d5f6-s7zfc
    5. Hello version: v2, instance: helloworld-v2-54df5f84b-9hxgw
    6. ...

清理环境

清理外部控制平面集群:

  1. $ kubectl delete -f external-istiod-gw.yaml --context="${CTX_EXTERNAL_CLUSTER}"
  2. $ istioctl uninstall -y --purge --context="${CTX_EXTERNAL_CLUSTER}"
  3. $ kubectl delete ns istio-system external-istiod --context="${CTX_EXTERNAL_CLUSTER}"
  4. $ rm controlplane-gateway.yaml external-istiod.yaml external-istiod-gw.yaml

清理从配置集群:

  1. $ kubectl delete ns sample --context="${CTX_REMOTE_CLUSTER}"
  2. $ istioctl manifest generate -f remote-config-cluster.yaml --set values.defaultRevision=default | kubectl delete --context="${CTX_REMOTE_CLUSTER}" -f -
  3. $ kubectl delete ns external-istiod --context="${CTX_REMOTE_CLUSTER}"
  4. $ rm remote-config-cluster.yaml istio-ingressgateway.yaml
  5. $ rm istio-egressgateway.yaml eastwest-gateway-1.yaml || true

如果安装了可选的第二个从集群,请清理它:

  1. $ kubectl delete ns sample --context="${CTX_SECOND_CLUSTER}"
  2. $ istioctl manifest generate -f second-remote-cluster.yaml | kubectl delete --context="${CTX_SECOND_CLUSTER}" -f -
  3. $ kubectl delete ns external-istiod --context="${CTX_SECOND_CLUSTER}"
  4. $ rm second-remote-cluster.yaml eastwest-gateway-2.yaml