大家好,欢迎来到IT知识分享网。
什么是SideCar?
Sidecar模式定义:
Sidecar 模式是一种常用于微服务架构中的设计模式,该模式允许将应用程序的核心功能与辅助功能(如日志记录、监控、配置管理、网络通信等)分离开来。在这种设计模式中,每个微服务主容器旁边都有一个“边车”(Sidecar)容器运行辅助功能,就像摩托车旁的边车一样,Sidecar 容器和主容器共享同一个生命周期和网络空间。
你专心开车,其他交给我。
整体Sidecar就是这样:
总结:把非核心业务杂七杂八的东西分离出来,微服务的关注点尽可能只在业务上面,减少业务开发的复杂度。
Sidecar主要干啥?
Sidecar模式通常会处理以下范围的功能:
- 网络通信:
- 代理和管理微服务之间的通信,例如用来处理进出的网络流量、服务发现、负载均衡、断路、重试和超时。
- 安全性:
- 实现安全协议,如TLS加密、认证、授权和密钥管理。
- 监控与日志记录:
- 收集和导出日志、性能度量指标和追踪信息,以供监控系统使用。
- 配置管理:
- 动态加载和管理配置数据,而无需重启应用程序。
- 故障处理和调试:
- 提供调试支持,记录崩溃报告和性能瓶颈。
- 健康检查:
- 周期性地检查主服务的健康,并可实施自我修复措施。
- API 网关或接口转换:
- 处理服务的REST或gRPC API,提供API网关功能,或者对老旧系统进行接口转换。
- 服务依赖抽象:
- 管理服务间的数据库连接、队列等系统资源的访问。
- 请求/响应转换:
- 对进出的请求或响应数据进行转换或扩展。
Sidecar有哪些实现?
Sidecar在容器化和微服务领域有很多实现:
1. Envoy
Envoy是一个开源的、高性能的边缘和服务代理,专门设计用于云原生应用环境。由Lyft公司首次开发发布,后来成为了Cloud Native Computing Foundation(CNCF)的一部分。它的设计允许它同时在应用程序的边缘和内部使用,作为边缘网关、负载均衡器或服务网格的一部分,以提高微服务之间的通信质量和效率。
- Istio
Istio是一个开源的服务网格,用于连接、保护、控制和观察在Kubernetes集群中运行的服务。它为微服务提供一种统一的方式来管理网络通信,安全性,策略和观察性,无需改变应用本身的代码。Istio利用了Envoy代理,它作为Sidecar部署在每个服务的Pod中,拦截所有进出Pod的网络通信。
- Linkerd
Linkerd是一个开源的服务网格,专门为云原生应用设计,用以在微服务架构中提供可靠的服务间通信。它提供关键功能,如服务发现、负载均衡、故障处理、请求路由和安全性,在不改动服务代码的情况下,使得服务更容易监控、管理和控制。Linkerd是由Buoyant公司开源的,并且是Cloud Native Computing Foundation(CNCF)的一部分。 - …
自己搞一个简单的?
我们个人势单力薄,搞一个像他们这么有高级功能的组件还是挺费时间的,况且我们还在温饱线上挣扎。
但是又想在这块搞点小事情,那么整个简单的。
先来个简单的需求
一个业务系统部署在k8s集群中,每个服务采用一个Pod一个服务的方式部署,每个Pod都有一个Service。
那根据SideCar的拓扑,我们可以在Service和Pod中容器之间加一个Sidecar来管理流量,像这样:
在这个拓扑中,所有流量先进SVC(逻辑上哈),然后转发给车最后转发给Pod。
车的具体需求?
- 管理HTTP流量(TCP的暂时不支持):只开发一个IP白名单规则。如果请求这个服务的IP不在这个白名单中,则返回404,否则转发该请求。
- 白名单规则配置:支持单个IP地址,支持CIDR地址。
需求就是这么简单,我们让SVC把流量先转给车,车处理了一下以后再转发给业务服务。
准备开干
首先开发一个HTTP服务器
使用Go built-in API就可以很简单开发实现一个HTTP服务器,就是使用net包:
http.HandleFunc("/", handler) err = http.ListenAndServe(conf.Server.Addr, nil) if err != nil { log.Fatal("ListenAndServe: ", err) }
COPY
几行代码搞定,额,这还是有点快,让人猝不及防。那这样我们的HTTP服务器就搞定了
其次 读取配置文件
我们用yaml来定义白名单配置,白名单中有IP和CIDR地址。
whitelist: - 192.168.1.1 - 192.168.1.2 - 10.22.81.0/24 - ::1
COPY
然后我们使用yaml解析库来读取它。
先来下载一下依赖库:
go get gopkg.in/yaml.v2
COPY
然后使用库提供的api来读取yaml文件:
type Conf struct { Server Server `yaml:"server"` Downstream Downstream `yaml:"downstream"` Whitelist []string `yaml:"whitelist"` } err = yaml.Unmarshal(source, &conf) if err != nil { log.Panic(err) }
COPY
设置HTTP的请求处理函数
我们请求处理函数从X-FORWARDED-FOR
协议头来获取请求的Ip列表字符串,字符串以ip1,ip2,ip3,...
来组成的。
我们只取第一个,就是上面示例的ip1
,因为只有这个IP才表示请求方的IP,其他都是代理方的。
func handler(w http.ResponseWriter, r *http.Request) { ipStr := r.Header.Get("X-FORWARDED-FOR") if ipStr == "" { ipStr = strings.Split(r.RemoteAddr, ":")[0] } else { ipStr = strings.TrimSpace(strings.Split(ipStr, ",")[0]) } // 如果IP地址在白名单中,那么就转发请求 if ipInWhitelist(ipStr, conf.Whitelist) { serveReverseProxy(conf.Downstream.URL, w, r) return } // 否则返回404 http.NotFound(w, r) }
COPY
转发请求
Go内建包net实现了ReverseProxy,我们直接使用httputil.NewSingleHostReverseProxy
就可以直接转发HTTP请求,很快~。
func serveReverseProxy(target string, w http.ResponseWriter, r *http.Request) { url, _ := url.Parse(target) proxy := httputil.NewSingleHostReverseProxy(url) r.URL.Host = url.Host r.URL.Scheme = url.Scheme r.Header.Set("X-Forwarded-Host", r.Header.Get("Host")) r.Host = url.Host proxy.ServeHTTP(w, r) }
COPY
这样我们的核心功能就实现了。
一点小细节
net.ParseIP
net.ParseCIDR
就可以实现IP解析了。
transformToCIDR
这个函数就给IP地址增加/32转换成CIDR形式,大家可以不用太关注。
func ipInWhitelist(ipStr string, whitelist []string) bool { ip := net.ParseIP(ipStr) for _, cidr := range whitelist { _, ipNet, err := net.ParseCIDR(transformToCIDR(cidr)) if err != nil { return false } if ipNet.Contains(ip) { return true } } return false }
COPY
部署
开发这个简单的需求一百多行代码就可以搞定了,但是部署怎么办?
我们在k8s中不是有Service嘛,我们Service在配置流量转发规则的时候先转到我们的HTTP Server,然后我们HTTP再转发给业务服务。
Pod改造
原来我们的拓扑是这样的:
加上我们自己的sidecar就变成这样了:
随之而来的改造
- name: my-order-app image: my-registry-domain-name/ my-order-app:${my-order-app-version} imagePullPolicy: IfNotPresent ports: - containerPort: 8080
COPY
改造后:
containers: - name: sidecar image: my-registry-domain-name/my-custom-sidecar:latest imagePullPolicy: Always ports: - containerPort: 8081 - name: my-order-app image: my-registry-domain-name/ my-order-app:${my-order-app-version} imagePullPolicy: IfNotPresent ports: - containerPort: 8080
COPY
Pod的改造就完成了,接下来就是Service改造了。
Service改造
我们要把Service的目标端口改成我们自己的Sidecar应用才可以。
apiVersion: v1 kind: Service metadata: name: my-order-app-service namespace: my-app labels: app: my-order-app spec: ports: - name: my-order-http port: 8080 protocol: TCP targetPort: 8080 selector: app: my-order-app type: ClusterIP
COPY
现在我们要把Target改成8081
,也就是我们的Sidecar HTTP服务器端口。
apiVersion: v1 kind: Service metadata: name: my-order-app-service namespace: my-app labels: app: my-order-app spec: ports: - name: my-order-http port: 8080 protocol: TCP targetPort: 8081 selector: app: my-order-app type: ClusterIP
COPY
这样我们的Sidecar就搞定了。
总结
优点
关注点分离:通过将非核心功能从应用程序逻辑中分离出来,开发者可以更专注于业务逻辑。
可插拔性:Sidecar可以独立于应用程序部署和更新,使得维护工作更加灵活。
一致性:在多个服务中应用相同的配置和策略,不需要在每个服务上单独配置。
扩展性:新增功能时,可以在不影响现有服务的情况下,在Sidecar中添加新的组件。
增强的能力:例如,集中日志处理、安全性控制、以及动态路由等。
缺点(Sidecar的通病):
资源使用:每个Sidecar都会消耗额外的计算和内存资源,这可能导致资源的浪费。
复杂性:虽然单个服务的复杂性降低了,但整体架构可能会因为增加的组件而变得复杂。
调试困难:由于Sidecar模式涉及多个容器协同工作,调试和追踪问题可能比传统单体应用更加困难。
网络延迟:每个请求都要通过Sidecar代理,可能会增加网络延迟。
参考
微服务侧车模式深度解析:赋能云原生应用的终极指南(自己搞一个简单SideCar?) – 小厂程序员
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/134555.html