VPN 连接
这是一个关于当每个集群中的 pod 可以直连访问其他集群中的 pod 时,可以跨多个集群安装 Istio 网格的说明。
在此配置中,运行远程配置的多个 Kubernetes 控制平面将连接到单个 Istio 控制平面。一旦一个或多个远程 Kubernetes 集群连接到 Istio 控制平面,Envoy 就可以与单个控制平面通信并形成跨多个集群的服务网格。
先决条件
两个以上运行 Kubernetes 1.9 或更高版本的集群。
能够在其中一个集群上部署 Istio 控制平面的能力。
RFC1918 网络、VPN或是满足以下可选条件的更高级的网络技术:
单集群 Pod 和服务的 CIDR 范围在多集群环境中必须唯一,最好不要重叠。
每个集群中的所有 Pod CIDR 必须的相互可达的。
所有 Kubernetes 控制平面 API 服务必须是相互可达的。
Helm 2.7.2 或更高版本。 也可选择使用 Tiller 。
本指南将介绍如何使用 Istio 仓库中提供的清单和 Helm charts 安装一个多集群的 Istio 拓扑。
部署本地控制平面
在一个 Kubernetes 集群中安装 Istio 控制平面。
安装 Istio 远程组件
你必须将 istio-remote
组件部署到每一个远程 Kubernetes集群中。 你可以通过以下两种方式之一安装组件:
设置环境变量
等待 Istio 控制平面完成初始化,然后再执行本节中的步骤。
你必须在 Istio 控制平面上运行这些操作以捕获 Istio 控制平面服务端点,如:Pilot、Policy 端点。
如果你在每个远程组件上使用 Helm 和 Tiller,你必须将环境变量复制到每个节点,然后再使用 Helm 将远程集群连接到 Istio 控制平面。
通过以下命令设置环境变量:
$ 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}')
$ export ZIPKIN_POD_IP=$(kubectl -n istio-system get pod -l app=jaeger -o jsonpath='{range .items[*]}{.status.podIP}{end}')
接着,你必须将远程集群与本地集群连接。
继续你先前的选项:
通常,需要启动远程 sidecar 注入。如果需要执行手动 sidecar 注入,请参阅手动 sidecar 注入示例。
安装并管理远程集群
通过 Helm 和 kubectl
- 通过以下
helm template
命令在远程集群中指定 Istio 控制平面服务端点:
$ helm template install/kubernetes/helm/istio-remote --namespace istio-system \
--name istio-remote \
--set global.remotePilotAddress=${PILOT_POD_IP} \
--set global.remotePolicyAddress=${POLICY_POD_IP} \
--set global.remoteTelemetryAddress=${TELEMETRY_POD_IP} \
--set global.remoteZipkinAddress=${ZIPKIN_POD_IP} > $HOME/istio-remote.yaml
- 通过以下命令给远程 Istio 创建一个
istio-system
命名空间:
$ kubectl create ns istio-system
所有集群必须有相同的 Istio 组件命名空间。只要命名空间对有所有集群中的 Istio 组件都相同,就可以覆盖住集群上的 istio-system
名称。
- 通过以下命令实例化远程集群与 Istio 控制平面的连接:
$ kubectl apply -f $HOME/istio-remote.yaml
- 使用以下示例命令标记
default
命名空间。使用相似命令标记所有需要自动 sidecar 注入的远程集群命名空间。
$ kubectl label namespace default istio-injection=enabled
对需要设置 sidecar 注入的所有 Kubernetes 命名空间需要重复此操作。
通过 Helm 和 Tiller
- 如果你尚未给 Helm 设置一个 service account ,请使用以下命令安装一个:
$ kubectl apply -f install/kubernetes/helm/helm-service-account.yaml
- 通过以下命令初始化 Helm:
$ helm init --service-account tiller
- 通过以下命令来为
istio-remote
安装 Helm chart:
$ helm install install/kubernetes/helm/istio-remote --name istio-remote --namespace istio-system --set global.remotePilotAddress=${PILOT_POD_IP} --set global.remotePolicyAddress=${POLICY_POD_IP} --set global.remoteTelemetryAddress=${TELEMETRY_POD_IP} --set global.remoteZipkinAddress=${ZIPKIN_POD_IP}
Helm chart 配置参数
你必须配置远程集群的 sidecar 与 Istio 控制平面的交互,包括 istio-remote
的 Helm chart:pilot
, policy
, telemetry
, statsd
和 追踪服务。
该 chart 默认启动自动 sidecar 注入。你可以通过 chart 变量来禁用该功能。
下表显示了已通过的 istio-remote
Helm chart 配置变量:
Helm 变量 | 可选值 | 默认 | 用途 |
---|---|---|---|
global.remotePilotAddress | 一个合法的 IP 地址或主机名 | None | 指定 Istio 控制平面的 pilot Pod IP 地址或远程集群 DNS 可解析的主机名。 |
global.remotePolicyAddress | 一个合法的 IP 地址或主机名 | None | 指定 Istio 控制平面的 policy Pod IP 地址或远程集群 DNS 可解析的主机名。 |
global.remoteTelemetryAddress | 一个合法的 IP 地址或主机名 | None | 指定 Istio 控制平面的 telemetry Pod IP 地址或远程集群 DNS 可解析的主机名。 |
global.remoteZipkinAddress | 一个合法的 IP 地址或主机名 | None | 指定 Istio 控制平面追踪应用的 Pod IP 地址或远程集群 DNS 可解析的主机名。例如:zipkin 或 jaeger 。 |
sidecarInjectorWebhook.enabled | true, false | true | 指定是否在远程集群中启用了自动 sidecar 注入 |
global.remotePilotCreateSvcEndpoint | true, false | false | 如果设置该项,一个无选择器服务和端点将以remotePilotAddress IP的形式被创建给 istio-pilot.<namespace> 是远程集群 DNS 可解析的。 |
为远程集群生成配置文件
Istio 控制平面需要服务所有集群中的网格来发现服务、端点和 pod 属性。
以下步骤描述了如何生成一个 kubeconfig
配置文件给 Istio 控制面板以使用远程集群。
istio-remote
Helm chart 在远程集群中创建了一个叫 istio-multi
的 Kubernetes service account 用于最小化 RBAC 访问请求。此过程通过使用先前所述的 istio-multi
service account 凭证生成了一个远程集群的 kubeconfig
配置文件。
每个远程集群上执行此过程以将集群添加到服务网格。此过程需要 cluster-admin
用户访问远程集群的权限。
- 通过以下命令为
istio-multi
service account 设置所需环境变量构建kubeconfig
文件:
$ 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-multi
$ 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)
许多系统对 base64 —decode
都有 openssl enc -d -base64 -A
这样的替代方案。
- 通过以下命令为
istio-multi
service account 在工作目录创建一个kubeconfig
文件:
$ 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
- (可选) 使用环境变量创建文件以创建远程集群的密钥:
$ cat <<EOF > remote_cluster_env_vars
export CLUSTER_NAME=${CLUSTER_NAME}
export KUBECFG_FILE=${KUBECFG_FILE}
export NAMESPACE=${NAMESPACE}
EOF
此时,你在当前目录创建了远程集群的 kubeconfig
文件。
文件名为 kubeconfig
的文件与原始集群名称相同。
实例化凭据
在运行了 Istio 控制平面的机器上执行以下过程。该过程使用的 WORK_DIR
、CLUSTER_NAME
和 NAMESPACE
环境变量都存在于上一节为远程集群创建的配置文件中。如果你为远程集群的 secret 创建了环境变量文件,请通过以下命令获取该文件:
$ source remote_cluster_env_vars
你可以在不同的命名空间中安装 Istio。该过程需要使用 istio-system
命名空间。
为每个集群创建一个正确的 secret 和 标记:
$ kubectl create secret generic ${CLUSTER_NAME} —from-file ${KUBECFG_FILE} -n ${NAMESPACE}
$ kubectl label secret ${CLUSTER_NAME} istio/multiCluster=true -n ${NAMESPACE}
卸载远程集群
你必须使用与他们安装相同的方法卸载远程集群。
通过 kubectl + Helm
或 Tiller + Helm
合理卸载他们。
通过 kubectl
要卸载集群,你必须移除 istio-remote.yaml
文件进行的配置。通过以下命令卸载:
$ kubectl delete -f $HOME/istio-remote.yaml
通过 Tiller
要卸载集群,你必须移除 istio-remote.yaml
文件进行的配置。通过以下命令卸载:
$ helm delete --purge istio-remote
手动 sidecar 注入示例
以下示例将展示如何使用 helm template
命令生成清单以禁用集群的自动 sidecar 注入。此外,示例将展示如何使用远程集群的 configmaps
,通过 istioctl kube-inject
命令为远程集群生成任何应用的清单。
对远程集群执行以下过程:
在开始之前,请按照设置环境变量部分设置端点 IP 环境变量
- 在远程集群使用
helm template
命令指定 Istio控制平面的 service 端点:
$ helm template install/kubernetes/helm/istio-remote --namespace istio-system --name istio-remote --set global.remotePilotAddress=${PILOT_POD_IP} --set global.remotePolicyAddress=${POLICY_POD_IP} --set global.remoteTelemetryAddress=${TELEMETRY_POD_IP} --set global.remoteZipkinAddress=${ZIPKIN_POD_IP} --set sidecarInjectorWebhook.enabled=false > $HOME/istio-remote_noautoinj.yaml
- 为远程 Istio 创建
istio-system
命名空间:
$ kubectl create ns istio-system
- 实例化远程集群与 Istio 控制平面的连接:
$ kubectl apply -f $HOME/istio-remote_noautoinj.yaml
手动将 sidecars 注入到应用清单中
以下示例通过 istioctl
命令将 sidecar 注入到应用清单。
在终端中运行以下命令,通过 kubeconfig
为远程集群设置上下文。
$ ORIGINAL_SVC_MANIFEST=mysvc-v1.yaml
$ istioctl kube-inject --injectConfigMapName istio-sidecar-injector --meshConfigMapName istio -f ${ORIGINAL_SVC_MANIFEST} | kubectl apply -f -
访问来自不同集群的服务
Kubernetes 在集群的基础上解析 DNS。由于 DNS解析与集群相关联,因此无论服务端点的位置如何,你都必须在每个运行客户端的集群中定义服务对象。
为了确保这种情况,在每个集群中使用 kubectl
复制服务对象。副本确保了 Kubernetes 可以解析任何集群中的服务名称。由于服务对象被定义在命名空间中,你必须自己定义命名空间(如果命名空间不存在)并且将其囊括在所有集群的服务定义中。
部署注意事项
前面的过程提供了部署多集群环境的简单分步指南。生产环境可能需要其他步骤或更复杂的部署选项。该过程收集 Istio 服务端点的 IP 地址并用他们来调用 Helm。这个过程在远程集群创建了 Istio 服务。作为在远程集群创建这些服务和端点的一部分,Kubernetes 将 DNS 条目加入到了 kube-dns
配置对象中。这将允许在远程集群中 kube-dns
配置对象将解析 Istio 服务名给所有 Envoy sidecar。由于 Kubernetes pods 没有固定的 IP 地址,在控制平面中重启任何 Istio 服务 pod 都会导致它端点的改变。因此,任何从远程集群到任何端点的连接都会中断。Istio issue #4822详细记录了该问题。
要避免或解决此问题,有多个选项可供选择。本节提供了以下选项的高级概述:
- 更新 DNS 条目
- 切换负载均衡服务类型
- 通过网关暴露 Istio 服务
更新 DNS 条目
在发生任何故障或 pod 重启时,在远程集群重启 kube-dns
可以为 Istio 服务正确更新端点的映射关系。有很多方法可以做到这点。常规做法是在远程节点重新运行 Helm 安装,之后 Istio 服务便会在控制平面上重启。
切换负载均衡类型
在 Kubernetes 中,你可以以 LoadBalancer
类型声明服务。更多内容详见 Kubernetes 的服务类型。
pod 重启的一个简单的解决方案是给 Istio 服务使用负载均衡器。
接着,你可以使用负载均衡器的 IP 地址作为 Istio 服务端点的 IP 地址以配置远程集群。你或许需要这些 Istio 服务的负载均衡器:
istio-pilot
istio-telemetry
istio-policy
zipkin
目前,Istio 安装不提供为 Istio 服务指定服务类型的选项。 您可以在 Istio Helm chart 或 Istio 清单中手动指定服务类型。
通过网关暴露 Istio 服务
此方法使用了 Istio ingress 网关的功能。远程集群有 istio-pilot
、istio-telemetry
、 istio-policy
、和 zipkin
服务,它们指向了 Istio ingress 网关的负载均衡 IP 地址。然后,所有的服务均指向相同的 IP 地址。你必须创建目标规则以在主集群的 ingress 网关中获得正确的 Istio 服务。
以下两种方案可供选择:
重新使用清单或 Helm charts 提供安装的默认 Istio ingress 网关。您只需添加正确的目标规则。
专门为集群创建另一个 Istio ingress 网关。
安装
Istio 支持在控制平面组件之间以及在 sidecar 注入的应用 pod 之间部署双向 TLS。
控制平面安全
要启用控制平面安全性,请遵循以下常规步骤:
部署 Istio 控制平面集群:
控制平面安全已启用。
该
citadel
证书自签署禁用。cacerts
的 secret 通过证书颁发机构 (CA) 证书下发在Istio 控制平面命名空间中。
部署 Istio 远程集群:
控制平面安全已启用。
该
citadel
证书自签署禁用。cacerts
的 secret 通过(CA) 证书下发在Istio 控制平面命名空间中。
主集群的证书颁发机构(CA)或根 CA 也必须为远程群集签署 CA 证书。
Istio pilot 服务主机名必须通过DNS解析。DNS解析是必需的,因为Istio 需要配置 sidecar 以使用
istio-pilot.<namespace>
主题名称格式验证证书主题名称。设置控制平面IP或可解析的主机名。
应用 Pod 之间的双向 TLS
为了确保应用 Pod 之间的双向 TLS,请按照以下常规步骤操作:
部署Istio控制平面集群:
全局启用了相互TLS。
Citadel 证书自签名禁用。
cacerts
的 secret 通过(CA) 证书下发在Istio 控制平面命名空间中。
部署Istio远程集群:
全局启用了相互TLS。
Citadel 证书自签名禁用。
cacerts
的 secret 通过(CA) 证书下发在Istio 控制平面命名空间中。主集群的 CA 或根 CA 也必须为远程集群签署CA证书。
对于控制平面安全性和应用 pod 安全性步骤,CA 证书步骤是相同的。
部署示例
此示例为安装 Istio 的过程,同时启用控制平面双向 TLS 和 应用 pod 双向 TLS。该过程使用无选择器服务和端点设置远程集群。Istio Pilot 使用服务和端点允许远程 sidecar 通过 Istio 的本地 Kubernetes DNS 解析主机名。
主集群: 部署控制平面集群
- 通过在
istio-system
命名空间中的 Istio 证书示例创建cacerts
secret:
$ 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
- 部署 Istio 控制平面,并为控制平面和应用 pod 启用安全:
$ helm template --namespace=istio-system \
--values install/kubernetes/helm/istio/values.yaml \
--set global.mtls.enabled=true \
--set security.selfSigned=false \
--set global.controlPlaneSecurityEnabled=true \
install/kubernetes/helm/istio > ${HOME}/istio-auth.yaml
$ kubectl apply -f ${HOME}/istio-auth.yaml
远程群集:部署 Istio 组件
- 通过在
istio-system
命名空间中的Istio 证书示例创建cacerts
secret:
$ 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
按照设置环境变量的说明为 pod 的 IP 地址设置环境变量。
通过以下命令为部署远程集群的组件并为控制平面和应用 pod 启用安全,同时启用创建 Istio Pilot 无选择器服务和端点以在远程集群中获取 DNS 条目。
$ helm template install/kubernetes/helm/istio-remote \
--name istio-remote \
--namespace=istio-system \
--set global.mtls.enabled=true \
--set security.selfSigned=false \
--set global.controlPlaneSecurityEnabled=true \
--set global.remotePilotCreateSvcEndpoint=true \
--set global.remotePilotAddress=${PILOT_POD_IP} \
--set global.remotePolicyAddress=${POLICY_POD_IP} \
--set global.remoteTelemetryAddress=${TELEMETRY_POD_IP} > ${HOME}/istio-remote-auth.yaml
$ kubectl apply -f ${HOME}/istio-remote-auth.yaml
- 要为远程集群生成
kubeconfig
配置文件,请按照Kubernetes 配置部分的步骤操作。
主集群:实例化凭据
你必须为每个远程群集实例化凭据。请按照实例化凭据工程完成部署。
恭喜!
你已经在两个集群中配置了所有 Istio 组件以及在应用 sidecar、控制平面组件和其他应用 sidecar 之间开启了双向TLS。