FSM 作为一个服务网格产品,通过"统一服务目录"的概念来管理和兼容多种微服务架构。它能够自动识别并整合部署的服务到一个集中的服务目录中,这样做的好处是可以实现微服务间的实时和自动化交互,无论这些服务是部署在 Kubernetes(K8s)上还是其他环境中。
对于非 K8s 环境,FSM 提供了对多种流行的服务注册中心的支持,这意味着它能够与这些不同的服务发现系统集成,包括:
- Consul:由 HashiCorp 提供的服务网格解决方案,用于服务发现和配置。
- Eureka:Netflix 开发的服务发现工具,是 Spring Cloud Netflix 微服务套件的一部分。
- Nacos:阿里巴巴开源的服务发现和配置管理系统,旨在提供云原生应用的动态服务发现和服务配置管理。
通过适配这些注册中心,FSM 强化了它在混合架构种的应用能力,使得用户可以不受限于特定的微服务框架即可享受服务网格带来的便利。我们相信,这种兼容性会使得 FSM 成为多样化微服务环境中的强有力的服务网格选择。
统一服务目录
统一服务目录提供了一个平滑的集成体验。通过将来自不同微服务注册中心的服务信息抽象并封装为 Kubernetes 服务(K8s Service),FSM 实现了服务信息的统一化。这样做有几个关键优势:
- 简化的服务发现:不同来源的服务无需为不同的发现机制编写和维护多套代码,一切都通过 K8s Service 进行统一的处理。
- 降低了复杂度:由于不同的服务注册中心可能有各自的 API 和交互方式,将它们封装为 K8s Service 后,用户只需与 K8s 的 API 和交互模式打交道,这简化了操作。
- 无缝的云原生集成:对于已经在 Kubernetes 上运行的服务,这种统一的服务模型可以无缝集成,进一步加强了服务之间的互操作性。
连接器
FSM 通过使用特定于框架的连接器(Connector)来实现与不同微服务注册中心的对接。每个连接器都负责与特定注册中心(如 Consul、Eureka 或 Nacos)通信,执行服务注册信息、监控服务变更、封装为 K8s Service、写入集群等关键任务。
连接器是独立运行的组件,使用 Go 开发(理论上也可以支持其他语言),可以使用对应注册中心提供的包进行快速地对接。
接下来演示如何将 Sping Cloud Consul 微服务接入到服务网格,并测试最常用的场景灰度发布。
演示
为了演示 Spring Cloud 微服务接入服务网格,我们重写了经典的 BookStore 应用 github.com/addozhang/s...
目前这个应用支持 Netflix Eureka 和 Hashicorp Consul 两种注册中心(编译时通过设置切换),具体的使用方式可以参考 文档。
初始化
首先克隆仓库。
shell
git clone https://github.com/addozhang/springboot-bookstore-demo.git
接下来就是部署 Consul,为了演示的简单,这里使用 Deployment 运行了单节点的实例。
shell
kubectl apply -n default -f manifests/consul.yaml
部署 FSM
安装 FSM CLI。
shell
system=$(uname -s | tr [:upper:] [:lower:])
arch=$(dpkg --print-architecture)
release=v1.1.4
curl -L https://github.com/flomesh-io/fsm/releases/download/${release}/fsm-${release}-${system}-${arch}.tar.gz | tar -vxzf -
./${system}-${arch}/fsm version
sudo cp ./${system}-${arch}/fsm /usr/local/bin/
部署控制平面和连接器,在部署时需要用到如下几个参数:
fsm.serviceAccessMode
:服务的访问模式,mixed
表示支持使用 Service 名和 pod IP 的访问。fsm.deployConsulConnector
:部署 Consul 连接器fsm.cloudConnector.consul.deriveNamespace
:将 Consul 服务封装位 K8s Service 后,该 Service 所位于的命名空间。fsm.cloudConnector.consul.httpAddr
:Consul 的访问地址fsm.cloudConnector.consul.passingOnly
:仅同步健康的服务节点fsm.cloudConnector.consul.suffixTag
:默认情况下 Consul 连接器会在指定的命名空间下创建服务同名的 Service,而在进行灰度发布时我们需要为不同版本创建同步的 Service,比如bookstore-v1
、bookstore-v2
代表bookstore
的两个不同版本。后缀v1
和v2
通常与 Service 的标签选择器一致。这里suffixTag
就表示将服务节点的tag
version
的值作为服务名的后缀。在示例应用中,通过为服务节点添加环境变量SPRING_CLOUD_CONSUL_DISCOVERY_TAGS="version=v1"
,来指定版本的标签。
shell
export fsm_namespace=fsm-system
export fsm_mesh_name=fsm
export consul_svc_addr="$(kubectl get svc -l name=consul -o jsonpath='{.items[0].spec.clusterIP}')"
fsm install \
--mesh-name "$fsm_mesh_name" \
--fsm-namespace "$fsm_namespace" \
--set=fsm.serviceAccessMode=mixed \
--set=fsm.deployConsulConnector=true \
--set=fsm.cloudConnector.consul.deriveNamespace=consul-derive \
--set=fsm.cloudConnector.consul.httpAddr=$consul_svc_addr:8500 \
--set=fsm.cloudConnector.consul.passingOnly=false \
--set=fsm.cloudConnector.consul.suffixTag=version \
--timeout=900s
接下来要创建上面指定的命名空间,并将其纳入服务网格的管理。
shell
kubectl create namespace consul-derive
fsm namespace add consul-derive
kubectl patch namespace consul-derive -p '{"metadata":{"annotations":{"flomesh.io/mesh-service-sync":"consul"}}}' --type=merge
配置访问控制策略
默认情况下,网格内的服务可以访问网格外的服务;但反过来是不允许的。因此需要设置访问控制策略,允许 Consul 访问网格中的微服务,进行健康检查。
shell
kubectl apply -n consul-derive -f - <<EOF
kind: AccessControl
apiVersion: policy.flomesh.io/v1alpha1
metadata:
name: consul
spec:
sources:
- kind: Service
namespace: default
name: consul
EOF
部署应用
创建命名空间并将命名空间加入网格中。
shell
kubectl create namespace bookstore
kubectl create namespace bookbuyer
kubectl create namespace bookwarehouse
fsm namespace add bookstore bookbuyer bookwarehouse
部署应用。
shell
kubectl apply -n bookwarehouse -f manifests/consul/bookwarehouse-consul.yaml
kubectl apply -n bookstore -f manifests/consul/bookstore-consul.yaml
kubectl apply -n bookbuyer -f manifests/consul/bookbuyer-consul.yaml
在命名空间 consul-derive
下,可以看到同步的 Service。
shell
kubectl get service -n consul-derive
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
bookstore ClusterIP None <none> 14001/TCP 8m42s
bookstore-v1 ClusterIP None <none> 14001/TCP 8m42s
bookwarehouse ClusterIP None <none> 14001/TCP 8m38s
bookwarehouse-v1 ClusterIP None <none> 14001/TCP 8m38s
bookbuyer ClusterIP None <none> 14001/TCP 8m38s
bookbuyer-v1 ClusterIP None <none> 14001/TCP 8m38s
通过端口转发,或者创建 Ingress 规则,可以查看服务的运行情况:页面自动刷新并计数器不断增长。
灰度功能测试
接下来常见的灰度发布的场景了,参考 FSM 文档中的示例 我们使用基于权重的灰度发布。
发布新版本之前,要先创建 TrafficSplit bookstore-v1
,保证所有的流量都会路由到 bookstore-v1
:
shell
kubectl apply -n consul-derive -f - <<EOF
apiVersion: split.smi-spec.io/v1alpha4
kind: TrafficSplit
metadata:
name: bookstore-split
spec:
service: bookstore
backends:
- service: bookstore-v1
weight: 100
- service: bookstore-v2
weight: 0
EOF
接下来部署新版本 bookstore-v2
:
shell
kubectl apply -n bookstore -f ./manifests/consul/bookstore-v2-consul.yaml
此时通过端口转发查看 bookstore-v2
的页面,会发现计数器没有任何变化,这说明没有流量进入这个新版本的服务节点。
接下来修改流量拆分策略,将 50% 的流量路由到新版本中,将会看到 bookstore-v2
的计数器开始增加。
shell
kubectl apply -n consul-derive -f - <<EOF
apiVersion: split.smi-spec.io/v1alpha4
kind: TrafficSplit
metadata:
name: bookstore-split
spec:
service: bookstore
backends:
- service: bookstore-v1
weight: 50
- service: bookstore-v2
weight: 50
EOF
继续调整策略,将 100% 流量都路由到新版本中。在旧版本 bookstore-v1
的计数器将停止增加。
shell
kubectl apply -n consul-derive -f - <<EOF
apiVersion: split.smi-spec.io/v1alpha4
kind: TrafficSplit
metadata:
name: bookstore-split
spec:
service: bookstore
backends:
- service: bookstore-v1
weight: 0
- service: bookstore-v2
weight: 100
EOF
总结
FSM 通过复用 K8s Service 的方式,不仅提升了服务网格内服务的管理效率,而且为微服务架构中服务的统一管理和自动化交互提供了一个坚实的基础,同时也降低了从传统微服务注册中心向 K8s 生态迁移的难度。这种方式非常适合多种服务注册中心共存的复杂环境,可以帮助用户更平滑地过渡到云原生应用架构。
通过提供不同服务框架的连接器,可以快捷地将现有的微服务架构接入到服务网格中,利用服务网格提供的诸如流量管理、安全性保障和可观测性等高级功能。
对于用户来说,FSM 提供的平滑过渡方案特别重要,它们可以在不破坏现有服务的前提下,逐步地将自己的应用架构迁移到云原生平台。这种灵活性对于用户在现代化其技术栈和最大化其云基础设施投资方面至关重要。通过这种整合,用户可以更好地准备自己以适应不断变化的市场需求和技术趋势。