使用外部控制平面安装 Istio

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

    外部控制平面集群和远程集群

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

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

    本指南要求您有任意两个受支持版本的 Kubernetes 集群:1.21, 1.22, 1.23, 1.24。

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

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

    API Server 访问

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

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

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

    网格操作步骤

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

    在外部集群中搭建网关

    1. 为 Ingress 网关创建 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

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

      1. $ istioctl install -f controlplane-gateway.yaml --context="${CTX_EXTERNAL_CLUSTER}"
      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 部署。 这用于配置 Ingress 网关,而不是远程集群使用的控制平面。

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

    2. 使用带有 TLS 的公共主机名配置您的环境来暴露 Istio Ingress 网关服务。 将 EXTERNAL_ISTIOD_ADDR 环境变量设置为主机名,将 SSL_SECRET_NAME 环境变量设置为包含 TLS 证书的密钥:

      1. $ export EXTERNAL_ISTIOD_ADDR=<your external istiod host>
      2. $ export SSL_SECRET_NAME=<your external istiod secret>

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

    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 x create-remote-secret \
      3. --context="${CTX_REMOTE_CLUSTER}" \
      4. --type=config \
      5. --namespace=external-istiod | \
      6. kubectl apply -f - --context="${CTX_EXTERNAL_CLUSTER}"
    3. 创建 Istio 配置以将控制平面安装在外部集群的 external-istiod 命名空间中:

      1. $ cat <<EOF > external-istiod.yaml
      2. apiVersion: install.istio.io/v1alpha1
      3. kind: IstioOperator
      4. metadata:
      5. namespace: external-istiod
      6. spec:
      7. meshConfig:
      8. rootNamespace: external-istiod
      9. defaultConfig:
      10. discoveryAddress: $EXTERNAL_ISTIOD_ADDR:15012
      11. proxyMetadata:
      12. XDS_ROOT_CA: /etc/ssl/certs/ca-certificates.crt
      13. CA_ROOT_CA: /etc/ssl/certs/ca-certificates.crt
      14. components:
      15. base:
      16. enabled: false
      17. ingressGateways:
      18. - name: istio-ingressgateway
      19. enabled: false
      20. values:
      21. global:
      22. caAddress: $EXTERNAL_ISTIOD_ADDR:15012
      23. istioNamespace: external-istiod
      24. operatorManageWebhooks: true
      25. meshID: mesh1
      26. multiCluster:
      27. clusterName: $REMOTE_CLUSTER_NAME
      28. pilot:
      29. env:
      30. INJECTION_WEBHOOK_CONFIG_NAME: ""
      31. VALIDATION_WEBHOOK_CONFIG_NAME: ""
      32. EOF

      然后,在外部集群上应用 Istio 配置:

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

    5. 创建 Istio GatewayVirtualServiceDestinationRule 配置,将流量从 Ingress 网关路由到外部控制平面:

      1. $ cat <<EOF > external-istiod-gw.yaml
      2. apiVersion: networking.istio.io/v1beta1
      3. name: external-istiod-gw
      4. namespace: external-istiod
      5. spec:
      6. selector:
      7. istio: ingressgateway
      8. servers:
      9. - port:
      10. number: 15012
      11. protocol: https
      12. name: https-XDS
      13. tls:
      14. mode: SIMPLE
      15. credentialName: $SSL_SECRET_NAME
      16. hosts:
      17. - $EXTERNAL_ISTIOD_ADDR
      18. - port:
      19. number: 15017
      20. protocol: https
      21. name: https-WEBHOOK
      22. tls:
      23. mode: SIMPLE
      24. credentialName: $SSL_SECRET_NAME
      25. hosts:
      26. - $EXTERNAL_ISTIOD_ADDR
      27. ---
      28. apiVersion: networking.istio.io/v1beta1
      29. kind: VirtualService
      30. metadata:
      31. name: external-istiod-vs
      32. namespace: external-istiod
      33. spec:
      34. hosts:
      35. - $EXTERNAL_ISTIOD_ADDR
      36. gateways:
      37. - external-istiod-gw
      38. http:
      39. - match:
      40. - port: 15012
      41. route:
      42. - destination:
      43. host: istiod.external-istiod.svc.cluster.local
      44. port:
      45. number: 15012
      46. - match:
      47. - port: 15017
      48. route:
      49. - destination:
      50. host: istiod.external-istiod.svc.cluster.local
      51. port:
      52. number: 443
      53. ---
      54. apiVersion: networking.istio.io/v1alpha3
      55. kind: DestinationRule
      56. metadata:
      57. name: external-istiod-dr
      58. namespace: external-istiod
      59. spec:
      60. host: istiod.external-istiod.svc.cluster.local
      61. trafficPolicy:
      62. portLevelSettings:
      63. - port:
      64. number: 15012
      65. tls:
      66. mode: SIMPLE
      67. connectionPool:
      68. http:
      69. h2UpgradePolicy: UPGRADE
      70. - port:
      71. number: 443
      72. tls:
      73. mode: SIMPLE
      74. EOF

      然后,在外部集群上应用配置:

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

    设置远程集群

    1. 创建远程 Istio 安装配置,使用外部控制平面而不是在本地部署控制平面来安装 Webhook,Configmap 和 Secret:

      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. 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: false
      18. ingressGateways:
      19. - name: istio-ingressgateway
      20. enabled: true
      21. values:
      22. global:
      23. caAddress: $EXTERNAL_ISTIOD_ADDR:15012
      24. istioNamespace: external-istiod
      25. meshID: mesh1
      26. multiCluster:
      27. clusterName: $REMOTE_CLUSTER_NAME
      28. istiodRemote:
      29. injectionURL: https://$EXTERNAL_ISTIOD_ADDR:15017/inject
      30. base:
      31. validationURL: https://$EXTERNAL_ISTIOD_ADDR:15017/validate
      32. EOF

      然后,在远程集群上安装配置:

      1. $ istioctl manifest generate -f remote-config-cluster.yaml | kubectl apply --context="${CTX_REMOTE_CLUSTER}" -f -
    2. 确认远程集群已安装 Webhook,Secret 和 Configmap:

      1. $ kubectl get mutatingwebhookconfiguration -n external-istiod --context="${CTX_REMOTE_CLUSTER}"
      2. NAME WEBHOOKS AGE
      3. istio-sidecar-injector-external-istiod 4 6m24s
      1. $ kubectl get validatingwebhookconfiguration -n external-istiod --context="${CTX_REMOTE_CLUSTER}"
      2. NAME WEBHOOKS AGE
      3. istiod-external-istiod 1 6m32s
      1. $ kubectl get configmaps -n external-istiod --context="${CTX_REMOTE_CLUSTER}"
      2. NAME DATA AGE
      3. istio 2 2m1s
      4. istio-ca-root-cert 1 2m9s
      5. istio-leader 0 2m9s
      6. istio-namespace-controller-election 0 2m11s
      7. istio-sidecar-injector 2 2m1s
      8. istio-validation-controller-election 0 2m9s
      1. $ kubectl get secrets -n external-istiod --context="${CTX_REMOTE_CLUSTER}"
      2. NAME TYPE DATA AGE
      3. default-token-m9nnj kubernetes.io/service-account-token 3 2m37s
      4. istio-ca-secret istio.io/ca-root 5 18s
      5. istio-reader-service-account-token-prnvv kubernetes.io/service-account-token 3 2m31s
      6. istiod-service-account-token-z2cvz kubernetes.io/service-account-token 3 2m30s

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

    部署一个简单应用

    1. 部署示例 helloworldv1)和 sleep

      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}"
    2. 等几秒钟,helloworldsleep Pod 将以 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
    3. sleep Pod 向 helloworld Pod 服务发送请求:

      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-5b75657f75-ncpc5

    启用网关

    1. 在远程集群上启用 Ingress 网关:

      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 --context="${CTX_REMOTE_CLUSTER}"
    2. 在远程集群上启用 Egress 网关或者其他网关(可选):

      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 --context="${CTX_REMOTE_CLUSTER}"
    3. 确认 Istio Ingress 网关正在运行:

      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
    4. 在 Ingress 网关上暴露 helloworld 应用:

      1. $ kubectl apply -f samples/helloworld/helloworld-gateway.yaml -n sample --context="${CTX_REMOTE_CLUSTER}"
    5. 设置 GATEWAY_URL 环境变量(有关详细信息,请参阅):

      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}')
    6. 确认您可以通过 Ingress 网关访问 helloworld 应用:

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

    多远程集群的外部控制平面

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

    网格操作员说明

    未完待续