在共享控制平面部署模型下,多个Kubernetes远程集群连接到在主集群中运行的共享Istio控制平面。远程群集可以与主群集位于同一网络中,也可以位于不同网络中。连接一个或多个远程集群后,主集群的控制平面将管理所有服务端点上的服务网格。

Istio网格跨越多个Kubernetes集群,可通过VPN直接访问远程Pod

先决条件

  • 两个或更多运行受支持的Kubernetes版本(1.16、1.17、1.18)的集群。
  • 所有Kubernetes控制平面API服务器必须可相互路由。
  • 同一网络上的群集必须是RFC1918网络,VPN或满足以下要求的替代的更高级的网络技术:
  • 各个集群Pod CIDR范围和服务CIDR范围在整个网络中必须是唯一的,并且不能重叠。
  • 同一网络中的所有Pod CIDR必须彼此可路由。
  • 不同网络上的集群必须具有istio-ingressgateway服务,该服务可从其他每个集群访问,最好使用L4网络负载平衡器(NLB)。并非所有的云提供商都支持NLB,并且某些云提供商需要使用特殊的注释才能使用它们。

准备

CA

从组织的根CA为每个集群的CA生成中间CA证书。共享的根CA允许跨不同集群的相互TLS通信。为便于说明,以下说明将Istio示例目录中的证书用于两个集群。
在网格中的每个集群上运行以下命令以安装证书。有关配置外部CA的更多详细信息,请参阅证书颁发机构(CA)证书。

$ 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
samples中的根证书和中间证书已广泛分发并广为人知。不要在生产中使用这些证书,因为这样集群将容易受到安全漏洞和危害。

跨集群控制平面访问

确定如何向远程集群公开主集群的Istiod发现服务。选择以下两个选项之一:

  • Option (1) - 使用与数据流量共享的istio-ingressgateway网关。.
  • Option (2) - 在Istiod服务上使用云提供商的内部负载平衡器。有关在群集之间使用内部负载均衡器时可能适用的其他要求和限制,请参阅Kubernetes内部负载均衡器文档和您的云提供商的文档。

集群和网络命名

确定网格中集群和网络的名称。这些名称将在mesh网络配置中以及配置mesh网络的服务注册表时使用。为每个集群分配一个唯一的名称。该名称必须是DNS标签名称。在下面的示例中,主集群称为main0,而远程群集为remote0

$ export MAIN_CLUSTER_NAME=main0
$ export REMOTE_CLUSTER_NAME=remote0

如果集群位于不同的网络上,请为每个网络分配一个唯一的网络名称。

$ export MAIN_CLUSTER_NETWORK=network1
$ export REMOTE_CLUSTER_NETWORK=network2

如果集群在同一网络上,则这些集群使用相同的网络名称。

$ export MAIN_CLUSTER_NETWORK=network1
$ export REMOTE_CLUSTER_NETWORK=network1

部署

主集群

创建主集群的配置。选择跨集群控制平面访问的两个选项之一。
如果是选择istio-ingressgateway , 则:

cat <<EOF> istio-main-cluster.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  values:
    global:
      multiCluster:
        clusterName: ${MAIN_CLUSTER_NAME}
      network: ${MAIN_CLUSTER_NETWORK}

      # Mesh network configuration. This is optional and may be omitted if
      # all clusters are on the same network.
      meshNetworks:
        ${MAIN_CLUSTER_NETWORK}:
          endpoints:
          - fromRegistry: ${MAIN_CLUSTER_NAME}
          gateways:
          - registry_service_name: istio-ingressgateway.istio-system.svc.cluster.local
            port: 443

        ${REMOTE_CLUSTER_NETWORK}:
          endpoints:
          - fromRegistry: ${REMOTE_CLUSTER_NAME}
          gateways:
          - registry_service_name: istio-ingressgateway.istio-system.svc.cluster.local
            port: 443

      # Use the existing istio-ingressgateway.
      meshExpansion:
        enabled: true
EOF

如果是选择内部负载均衡器,则:

cat <<EOF> istio-main-cluster.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  values:
    global:
      multiCluster:
        clusterName: ${MAIN_CLUSTER_NAME}
      network: ${MAIN_CLUSTER_NETWORK}

      # Mesh network configuration. This is optional and may be omitted if
      # all clusters are on the same network.
      meshNetworks:
        ${MAIN_CLUSTER_NETWORK}:
          endpoints:
          - fromRegistry: ${MAIN_CLUSTER_NAME}
          gateways:
          - registry_service_name: istio-ingressgateway.istio-system.svc.cluster.local
            port: 443

        ${REMOTE_CLUSTER_NETWORK}:
          endpoints:
          - fromRegistry: ${REMOTE_CLUSTER_NAME}
          gateways:
          - registry_service_name: istio-ingressgateway.istio-system.svc.cluster.local
            port: 443

  # Change the Istio service `type=LoadBalancer` and add the cloud provider specific annotations. See
  # https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer for more
  # information. The example below shows the configuration for GCP/GKE.
  # If the GCP/GKE version is less than 1.16, add `network.gke.io/internal-load-balancer-allow-global-access: "true"` to the `service_annotations`.
  # See https://stackoverflow.com/questions/59680679/gcp-internal-load-balancer-global-access-beta-annotation-does-not-work?answertab=active#tab-top.
  components:
    pilot:
      k8s:
        service:
          type: LoadBalancer
        service_annotations:
          cloud.google.com/load-balancer-type: Internal
EOF

应用主集群的配置。

istioctl install -f istio-main-cluster.yaml --context=${MAIN_CLUSTER_CTX}

等待控制平面准备就绪,然后再继续。

kubectl get pod -n istio-system --context=${MAIN_CLUSTER_CTX}

NAME                                    READY   STATUS    RESTARTS   AGE
istio-ingressgateway-7c8dd65766-lv9ck   1/1     Running   0          136m
istiod-f756bbfc4-thkmk                  1/1     Running   0          136m

根据之前选择的远程控制平面配置选项设置ISTIOD_REMOTE_EP环境变量。

如果选择的是istio-ingressgateway,则:

$ export ISTIOD_REMOTE_EP=$(kubectl get svc -n istio-system --context=${MAIN_CLUSTER_CTX} istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
$ echo "ISTIOD_REMOTE_EP is ${ISTIOD_REMOTE_EP}"

如果选择的是内部负载均衡器,则:

$ export ISTIOD_REMOTE_EP=$(kubectl get svc -n istio-system --context=${MAIN_CLUSTER_CTX} istiod -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
$ echo "ISTIOD_REMOTE_EP is ${ISTIOD_REMOTE_EP}"

远程集群

创建远程集群的配置。

cat <<EOF> istio-remote0-cluster.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  values:
    global:
      # The remote cluster's name and network name must match the values specified in the
      # mesh network configuration of the primary cluster.
      multiCluster:
        clusterName: ${REMOTE_CLUSTER_NAME}
      network: ${REMOTE_CLUSTER_NETWORK}

      # Replace ISTIOD_REMOTE_EP with the the value of ISTIOD_REMOTE_EP set earlier.
      remotePilotAddress: ${ISTIOD_REMOTE_EP}

  ## The istio-ingressgateway is not required in the remote cluster if both clusters are on
  ## the same network. To disable the istio-ingressgateway component, uncomment the lines below.
  #
  # components:
  #  ingressGateways:
  #  - name: istio-ingressgateway
  #    enabled: false
EOF

应用远程集群配置。

$ istioctl install -f istio-remote0-cluster.yaml --context ${REMOTE_CLUSTER_CTX}

等待远程集群准备就绪。

$ kubectl get pod -n istio-system --context=${REMOTE_CLUSTER_CTX}
NAME                                    READY   STATUS    RESTARTS   AGE
istio-ingressgateway-55f784779d-s5hwl   1/1     Running   0          91m
istiod-7b4bfd7b4f-fwmks                 1/1     Running   0          91m
在远程集群中运行的istiod部署为远程集群的pod提供自动sidecar注入和CA服务。这些服务以前由Sidecar注入器和Citadel部署提供,而Istiod中不包含这服务。远程集群的Pod正在从主集群的Istiod获取配置以进行服务发现。

跨集群负载均衡

配置 ingress gateway

如果两个集群都在同一网络上,请跳过此步骤并继续配置服务注册表。

跨网络流量通过每个目标集群的ingress gateway安全地路由。当网格中的集群位于不同的网络上时,您需要在入口网关上配置端口443,以将传入流量传递到请求的SNI标头中指定的目标服务,以获取本地顶级域(即Kubernetes)的SNI值。 DNS域)。相互TLS连接将从源到目的地一直使用。

将以下配置应用于每个集群。

cat <<EOF> cluster-aware-gateway.yaml
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

$ kubectl apply -f cluster-aware-gateway.yaml --context=${MAIN_CLUSTER_CTX}
$ kubectl apply -f cluster-aware-gateway.yaml --context=${REMOTE_CLUSTER_CTX}

配置跨集群服务注册

为了实现跨集群的负载平衡,Istio控制平面要求访问网格中的所有集群以发现服务,端点和Pod属性。要配置访问权限,请为每个具有凭据的远程集群创建一个秘钥,以访问远程集群的kube-apiserver并将其安装在主集群中。此秘钥使用远程集群中istio-reader-service-account的凭据。 --name指定远程集群的名称。它必须与主集群的IstioOperator配置中的集群名称匹配。

$ istioctl x create-remote-secret --name ${REMOTE_CLUSTER_NAME} --context=${REMOTE_CLUSTER_CTX} | 
    kubectl apply -f - --context=${MAIN_CLUSTER_CTX}
不要为运行Istio控制平面的本地群集创建远程秘钥。 Istio始终知道本地集群的Kubernetes凭据。

其他

Automatic injection

每个集群中的Istiod服务都会为其自身集群中的代理提供自动Sidecar注入。必须按照自动Sidecar注入指南在每个集群中标记名称空间。

访问来自不同集群的服务

Kubernetes会基于集群解析DNS。由于DNS解析与集群相关,因此无论服务端点的位置如何,您都必须在运行客户端的每个集群中定义服务对象。为确保这种情况,请使用kubectl将服务对象复制到每个集群。复制可确保Kubernetes可以解析任何集群中的服务名称。由于服务对象是在名称空间中定义的,因此您必须定义该名称空间(如果该名称不存在),并将其包含在所有集群的服务定义中。

安全

每个集群中的Istiod服务向其自己集群中的代理提供CA功能。早期的CA设置可确保网格中集群之间的代理具有相同的信任根。


iyacontrol
1.4k 声望2.7k 粉丝

专注kubernetes,devops,aiops,service mesh。