sidecar它的原理是什么,怎么使用呢?
创始人
2024-09-25 18:48:28
0

什么是sidecar?

kubernetes-sidecar-what-is.png

sidecar,直译为边车。 如上图所示,边车就是加装在摩托车旁来达到拓展功能的目的,比如行驶更加稳定,可以拉更多的人和货物,坐在边车上的人可以给驾驶员指路等。边车模式通过给应用服务加装一个“边车”来达到控制逻辑的分离的目的。

对于微服务来讲,我们可以用边车模式来做诸如 日志收集、服务注册、服务发现、限流、鉴权等不需要业务服务实现的控制面板能力。通常和边车模式比较的就是像spring-cloud那样的sdk模式,像上面提到的这些能力都通过sdk实现。

kubernetes-sidecar-what-can-do.png

这两种实现模式各有优劣,sidecar模式会引入额外的性能损耗以及延时,但传统的sdk模式会让代码变得臃肿并且升级复杂,控制面能力和业务面能力不能分开升级。

sidecar 实现原理

介绍了sidecar的诸多功能,但是,sidecar是如何做到这些能力的呢?

原来,在kubernetes中,一个pod是部署的最小单元,但一个pod里面,允许运行多个container(容器),多个container(容器)之间共享存储卷和网络栈。这样子,我们就可以多container来做sidecar,或者init-container(初始化容器)来调整挂载卷的权限

kubernetes-sidecar-inside.png

日志收集sidecar

日志收集sidecar的原理是利用多个container间可以共用挂载卷的原理实现的,通过将应用程序的日志路径挂出,用另一个程序访问路径下的日志来实现日志收集,这里用cat来替代了日志收集,部署yaml模板如下

apiVersion: v1 kind: Pod metadata:   name: webserver spec:   volumes:     - name: shared-logs       emptyDir: {}    containers:     - name: nginx       image: ttbb/nginx:mate       volumeMounts:         - name: shared-logs           mountPath: /opt/sh/openresty/nginx/logs      - name: sidecar-container       image: ttbb/base       command: ["sh","-c","while true; do cat /opt/sh/openresty/nginx/logs/nginx.pid; sleep 30; done"]       volumeMounts:         - name: shared-logs           mountPath: /opt/sh/openresty/nginx/logs  

使用kubectl create -f 创建pod,通过kubectl logs命令就可以看到sidecar-container打印的日志输出

kubectl logs webserver sidecar-container 

转发请求sidecar

这一节我们来实现,一个给应用程序转发请求的sidecar,应用程序代码如下

use std::io::prelude::*; use std::net::{TcpListener, TcpStream};  fn main() {     let listener = TcpListener::bind("127.0.0.1:7878").unwrap();      for stream in listener.incoming() {         let stream = stream.unwrap();          handle_connection(stream);     }     println!("Hello, world!"); }  fn handle_connection(mut stream: TcpStream) {     let mut buffer = [0; 1024];      stream.read(&mut buffer).unwrap();      let contents = "Hello";      let response = format!(         "HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n{}",         contents.len(),         contents     );      println!("receive a request!");     stream.write(response.as_bytes()).unwrap();     stream.flush().unwrap(); } 

我们再来写一个sidecar,它会每15秒向应用程序发出请求

use std::thread; use std::time::Duration;  fn main() {     loop {         thread::sleep(Duration::from_secs(15));         let response = reqwest::blocking::get("http://localhost:7878").unwrap();         println!("{}", response.text().unwrap())     } } 

通过仓库下的intput/build.sh脚本构造镜像,运行yaml如下

apiVersion: v1 kind: Pod metadata:   name: webserver spec:   containers:     - name: input-server       image: sidecar-examples:input-http-server      - name: input-sidecar       image: sidecar-examples:sidecar-input 

通过查看kubectl logs input input-http-server可以看到input-http-server收到了请求

receive a request! receive a request! 

拦截请求sidecar

应用程序代码,它会每15s向localhost发出请求

package com.shoothzj.sidecar  import akka.actor.typed.ActorSystem import akka.actor.typed.scaladsl.Behaviors import akka.http.scaladsl.Http import akka.http.scaladsl.model._  import scala.concurrent.{ExecutionContextExecutor, Future} import scala.util.{Failure, Success}  object HttpClient {     def main(args: Array[String]): Unit = {         while (true) {             Thread.sleep(15_000L)             implicit val system: ActorSystem[Nothing] = ActorSystem(Behaviors.empty, "SingleRequest")             // needed for the future flatMap/onComplete in the end             implicit val executionContext: ExecutionContextExecutor = system.executionContext              val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(uri = "http://localhost:7979/hello"))              responseFuture                     .onComplete {                         case Success(res) => println(res)                         case Failure(_) => sys.error("something wrong")                     }         }     } } 

我们再来写一个sidecar,它会拦截http请求并打印日志

package com.shoothzj.sidecar  import akka.actor.typed.ActorSystem import akka.actor.typed.scaladsl.Behaviors import akka.http.scaladsl.Http import akka.http.scaladsl.model._ import akka.http.scaladsl.server.Directives._  import scala.concurrent.ExecutionContextExecutor import scala.io.StdIn  object HttpServer {      def main(args: Array[String]): Unit = {          implicit val system: ActorSystem[Nothing] = ActorSystem(Behaviors.empty, "my-system")         // needed for the future flatMap/onComplete in the end         implicit val executionContext: ExecutionContextExecutor = system.executionContext          val route =             path("hello") {                 get {                     println("receive a request")                     complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "

Say hello to akka-http

")) } } val bindingFuture = Http().newServerAt("localhost", 7979).bind(route) while (true) { Thread.sleep(15_000L) } } }

通过仓库下的output/build.sh脚本构造镜像,运行yaml如下

apiVersion: v1 kind: Pod metadata:   name: output spec:   volumes:     - name: shared-logs       emptyDir: {}    containers:     - name: output-workload       image: sidecar-examples:output-workload       imagePullPolicy: Never      - name: sidecar-output       image: sidecar-examples:sidecar-output       imagePullPolicy: Never 

通过查看kubectl logs output output-workload可以看到output-sidecar收到了请求

HttpResponse(200 OK,List(Server: akka-http/10.2.9, Date: Tue, 29 Mar 2022 00:15:47 GMT),HttpEntity.Strict(text/html; charset=UTF-8,31 bytes total),HttpProtocol(HTTP/1.1)) HttpResponse(200 OK,List(Server: akka-http/10.2.9, Date: Tue, 29 Mar 2022 00:16:02 GMT),HttpEntity.Strict(text/html; charset=UTF-8,31 bytes total),HttpProtocol(HTTP/1.1)) HttpResponse(200 OK,List(Server: akka-http/10.2.9, Date: Tue, 29 Mar 2022 00:16:17 GMT),HttpEntity.Strict(text/html; charset=UTF-8,31 bytes total),HttpProtocol(HTTP/1.1)) HttpResponse(200 OK,List(Server: akka-http/10.2.9, Date: Tue, 29 Mar 2022 00:16:32 GMT),HttpEntity.Strict(text/html; charset=UTF-8,31 bytes total),HttpProtocol(HTTP/1.1)) HttpResponse(200 OK,List(Server: akka-http/10.2.9, Date: Tue, 29 Mar 2022 00:16:47 GMT),HttpEntity.Strict(text/html; charset=UTF-8,31 bytes total),HttpProtocol(HTTP/1.1)) HttpResponse(200 OK,List(Server: akka-http/10.2.9, Date: Tue, 29 Mar 2022 00:17:02 GMT),HttpEntity.Strict(text/html; charset=UTF-8,31 bytes total),HttpProtocol(HTTP/1.1)) HttpResponse(200 OK,List(Server: akka-http/10.2.9, Date: Tue, 29 Mar 2022 00:17:17 GMT),HttpEntity.Strict(text/html; charset=UTF-8,31 bytes total),HttpProtocol(HTTP/1.1)) HttpResponse(200 OK,List(Server: akka-http/10.2.9, Date: Tue, 29 Mar 2022 00:17:32 GMT),HttpEntity.Strict(text/html; charset=UTF-8,31 bytes total),HttpProtocol(HTTP/1.1)) 

相关内容

热门资讯

法子透视挂!广东雀神辅助器透视... 法子透视挂!广东雀神辅助器透视(辅助)都是是有辅助插件(哔哩哔哩)1)广东雀神辅助器透视有没有挂:进...
最新消息!杭州都莱到底有没有挂... 最新消息!杭州都莱到底有没有挂!一直真的是有开挂辅助app(有挂技巧)-哔哩哔哩该软件可以轻松地帮助...
方针透视挂!皇豪辅助(辅助)切... 方针透视挂!皇豪辅助(辅助)切实存在有辅助app(哔哩哔哩)1、完成皇豪辅助辅助器v3.3的残局,帮...
有消息称!小闲辅助软件下载!一... 有消息称!小闲辅助软件下载!一贯是有开挂辅助挂(有挂详细)-哔哩哔哩1、这是跨平台的小闲辅助软件下载...
项目透视挂!拱趴大菠萝如何会赢... 项目透视挂!拱趴大菠萝如何会赢(辅助)总是真的有辅助脚本(哔哩哔哩)破解侠是真的助透视。每个模型中均...
第三方辅助!创思维激k辅助器视... 第三方辅助!创思维激k辅助器视频!竟然是有开挂辅助攻略(有挂分享)-哔哩哔哩1、下载好创思维激k辅助...
讲义透视挂!掌心辅助插件(辅助... 讲义透视挂!掌心辅助插件(辅助)果然是真的有辅助工具(哔哩哔哩)1、首先打开辅助器下载最新版本,在辅...
据文件显示!哈糖大菠萝可以开挂... 据文件显示!哈糖大菠萝可以开挂吗!果然存在有开挂辅助器(有挂技巧)-哔哩哔哩1. 选牌创建新账号,点...
要领透视挂!新星游房间链接辅助... 要领透视挂!新星游房间链接辅助(辅助)一直一直总是有辅助神器(哔哩哔哩)1、起透看视 辅助软件价格2...
黑科技辅助挂!新上游拼十辅助!... 黑科技辅助挂!新上游拼十辅助!真是是真的有开挂辅助工具(详细教程)-哔哩哔哩1、让任何用户在无需安装...