假如你正在一家典型的企业里工作, 需要与多个团队一起工作, 并为客户提供一个独立的软件, 组成一个应用程序. 你的团队遵循微服务架构, 并拥有由多个 Kubernetes 集群组成的广泛基础设施.
由于微服务分布在多个集群中, 你需要设计一个解决方案来集中管理所有微服务. 幸运的是, 你正在使用 Istio, 提供这个解决方案只不过是另一个配置的变化.
像 Istio 这样的服务网格技术可以帮助你安全地发现和连接分布在多个集群和环境中的微服务. 今天我们来讨论一下使用 Istio 管理托管在多个 Kubernetes 集群中的微服务.
架构说明
Istio 使用以下组件提供跨集群服务发现:
Istio CoreDNS: 每个 Istio 控制平面都有一个 CoreDNS.Istio 使用它来发现全局范围上定义的服务. 例如, 如果一个托管在集群 1 上的微服务需要连接到另一个托管在集群 2 上的微服务, 你需要为运行在集群 2 上的微服务在 Istio CoreDNS 上做一个全局条目.
Root CA: 由于 Istio 需要在不同集群上运行的服务之间建立 mTLS 连接, 因此需要使用共享的 Root CA 为两个集群生成中间 CA 证书. 这就在不同集群上运行的微服务之间建立了信任, 因为中间 CA 共享同一个 Root CA.
Istio Ingress 网关: 集群间的通信通过 Ingress 网关进行, 服务之间没有直接连接. 因此, 你要确保 Ingress 网关是可发现的, 并且所有集群都可以连接到它.
服务发现
Istio 使用以下步骤来促进服务发现:
集群上都有相同的控制平面, 以促进高可用性.
Kube DNS 与 Istio CoreDNS 为支点, 以提供全局服务发现.
用户通过 Istio CoreDNS 中的 ServiceEntries 定义远程服务的路由, 格式为 name.namespace.global.
源 sidecar 使用全局 CoreDNS 条目将流量路由到目标 Istio Ingress 网关.
目标 Istio Ingress 网关将流量路由到正确的微服务 pod.
前期准备
本文假设你已经对 Kubernetes 以及 Istio 的工作原理有一个基本的了解. 如果你想了解 Istio 1.5 和 1.6 的详细内容, 点击此处即可查看相关视频 https://www.bilibili.com/video/BV1uz4y1R7WB . 为了能够跟上我们接下来的演示, 请确保:
你有至少两个 Kubernetes 集群, Kubernetes 的版本为 1.14,1.15 或 1.16
你拥有在集群内安装和配置 Istio 的权限
你在两个 Kubernetes 集群上都有集群管理权限.
Ingress 网关可通过网络负载均衡器或类似配置连接到其他集群. 扁平网络是不必要的.
安装 Istio
在两个集群上, 使用以下命令安装 Istio 1.6.1:
- curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.6.1 sh -
- cd istio-1.6.1
- export PATH=$PWD/bin:$PATH
由于我们需要用共享的根证书生成的中间证书来启动我们的 Istio 服务网格, 所以使用中间证书创建一个 secret.
在这个例子中, 我们使用提供的样本证书. 但是, 我不建议你在生产中使用这些证书, 因为它们一般都是可轻松获取的, 而且是众所周知的. 最好是使用你的组织的 Root 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
- secret/cacerts created
由于我们需要安装 Istio 进行多集群设置, 所以在两个集群上使用提供的 Istio 多集群网关 manifest 文件.
- $ istioctl manifest apply -f install/kubernetes/operator/examples/multicluster/values-istio-multicluster-gateways.YAML
- - Applying manifest for component Base...
- Finished applying manifest for component Base.
- - Applying manifest for component Pilot...
- Finished applying manifest for component Pilot.
- Waiting for resources to become ready...
- - Applying manifest for component AddonComponents...
- - Applying manifest for component IngressGateways...
- - Applying manifest for component EgressGateways...
- Finished applying manifest for component EgressGateways.
- Finished applying manifest for component IngressGateways.
- Finished applying manifest for component AddonComponents.
- Installation complete
配置 KubeDNS
下一步是将 DNS 解析从 Kube DNS 联邦到 Istio CoreDNS. 让我们通过为 kube-dns 定义一个 ConfigMap 来配置一个存根域. 在两个集群上应用以下 manifest:
- $ 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
- configmap/kube-dns configured
设置上下文 (context)
由于我们需要为不同得活动连接两个集群, 因此获取上下文并将其存储在环境变量中会很有意义. 有了这些, 我们只要在 kubectl 命令中加入上下文, 就可以在我们选择得集群中运行 kubectl 命令.
获取上下文:
- $ kubectl config get-contexts
- CURRENT NAME CLUSTER AUTHINFO NAMESPACE
- cluster-1 cluster-1 cluster-1
- * cluster-2 cluster-2 cluster-2
设置环境变量以使用上下文:
- $ export CTX_CLUSTER1=$(kubectl config view -o jsonpath='{.contexts[0].name}')
- $ export CTX_CLUSTER2=$(kubectl config view -o jsonpath='{.contexts[1].name}')
- $ echo CTX_CLUSTER1 = ${
- CTX_CLUSTER1
- }, CTX_CLUSTER2 = ${
- CTX_CLUSTER2
- }
- CTX_CLUSTER1 = cluster-1, CTX_CLUSTER2 = cluster-2
部署示例微服务
我们先在集群 1 的 foo 命名空间上部署 sleep 微服务.
- $ kubectl create --context=$CTX_CLUSTER1 namespace foo
- namespace/foo created
- $ kubectl label --context=$CTX_CLUSTER1 namespace foo istio-injection=enabled
- namespace/foo labeled
- $ kubectl apply --context=$CTX_CLUSTER1 -n foo -f samples/sleep/sleep.YAML
- serviceaccount/sleep created
- service/sleep created
- deployment.apps/sleep created
- $ export SLEEP_POD=$(kubectl get --context=$CTX_CLUSTER1 -n foo pod -l App=sleep -o jsonpath={
- .items..metadata.name
- })
现在我们在集群 2 的 bar 命名空间上部署 httpbin 微服务:
- $ kubectl create --context=$CTX_CLUSTER2 namespace bar
- namespace/bar created
- $ kubectl label --context=$CTX_CLUSTER2 namespace bar istio-injection=enabled
- namespace/bar labeled
- $ kubectl apply --context=$CTX_CLUSTER2 -n bar -f samples/httpbin/httpbin.YAML
- serviceaccount/httpbin created
- service/httpbin created
- deployment.apps/httpbin created
创建服务条目
现在我们需要在 Istio CoreDNS 上创建一个服务条目以便于我们可以从集群 1 中发现集群 2 上的服务. 由于所有的通信都会通过 Ingress 网关, 导出集群 2 Ingress 网关地址.
- 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}')
为了让集群 1 上的服务能够发现集群 2 上的 httpbin, 我们需要在集群 1 上为 httpbin.bar.global 创建一个 ServiceEntry. 这样可以保证集群 1 上的 Istio Core DNS 在集群 1 上的服务到达 httpbin.bar.global 这个端点时, 可以到达集群 2 的 Ingress 网关. 下面的 YAML:
在 hosts 部分定义服务域名
位置是 mesh_INTERNAL, 因为我们需要把其他服务当作同一个服务网格的一部分
将服务暴露在 8000 端口上
我们需要给该服务提供一个独特的 IP 地址. 该 IP 地址不需要可路由, 并且你可以使用 240.0.0.0/16 范围内的任意地址
我们在端点地址部分上定义集群 2 ingress 网关地址, 以便于请求可以路由给它. 端口 15443 是 Ingress 网关的 SNI 识别的 Envoy 代理端口, 用于在目标群集服务的 Pod 之间路由流量.
应用 YAML 文件:
- $ kubectl apply --context=$CTX_CLUSTER1 -n foo -f - <<EOF
- apiVersion: networking.istio.io/v1alpha3
- kind: ServiceEntry
- metadata:
- name: httpbin-bar
- spec:
- hosts:
- - 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}
- ports:
- http1: 15443 # Do not change this port value
- EOF
- serviceentry.networking.istio.io/httpbin-bar created
测试服务
现在让我们从 sleep 微服务中产生一些流量, 看看它是否能到达集群 2 上运行的 httpbin 微服务.
- $ kubectl exec --context=$CTX_CLUSTER1 $SLEEP_POD -n foo -c sleep -- curl -I httpbin.bar.global:8000/headers
- % Total % Received % Xferd Average Speed Time Time Time Current
- Dload Upload Total Spent Left Speed
- 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0HTTP/1.1 200 OK
- 0 519 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
- server: envoy
- date: Sat, 16 May 2020 23:03:22 GMT
- content-type: application/JSON
- content-length: 519
- access-control-allow-origin: *
- access-control-allow-credentials: true
- x-envoy-upstream-service-time: 37
我们得到一个成功的响应! 恭喜你, 我们已经成功地使用 Istio 在多个 Kubernetes 集群之间配置了服务发现.
结 论
感谢你的阅读, 希望你能喜欢这篇文章.
这是一个在多个集群上运行的高可用 Istio 服务网格配置的演示. 你也可以有一个共享的控制平面配置, 但这并不推荐用于生产 -- 如果你因为中断而失去一个集群, 你也会失去对正在运行的集群的控制.
来源: https://www.cnblogs.com/rancherlabs/p/13389639.html