学习gRPC - 3.深入学习一个成熟的gRPC应用

只要你肯坚持,才会体会到放弃的快乐

Posted by 叉叉敌 on November 15, 2020

前面2篇介绍了 gRPC 的关键概念以及演示程序。了解工作的基础知识后, 将了解 k8s 在其容器运行时接口技术。

gRPC的应用范围

自从2015年作为开源项目发布以来,gRPC 在大大小小的企业中都取得了成长。然而,尽管 gRPC 作为一种服务器端技术很受欢迎,但它在面向公众的 api 中几乎没有出现。这主要有两个原因。首先,gRPC 依赖 HTTP/2作为其传输协议。虽然主要的客户端浏览器自2015年以来一直支持 HTTP/2,但截至2020年7月,互联网上只有不到一半的网站支持服务器端的协议。在客户端和 web 服务器之间使用 gRPC 的认同还没有到来。面向公众采用 gRPC 的进展缓慢的第二个原因是,使用特定的基于 gRPC 的 API 的客户机需要访问服务器使用的相同模式定义

与像 REST 这样使用 HTTP/1.1的 API 格式相比,必须共享一个共同的 protobuf 文件是一个重要的约束,并且需要客户端对 API 提供的数据结构没有预先知识。使用 REST,只需调用 URL,然后以自描述数据格式(如 JSON、 XML 或 YAML)返回一些数据。

简而言之,gRPC 的复杂性使其难以适用于标准、商业网站和公共 api。然而,这项技术在服务器端正在蓬勃发展。

许多客户在 gRPC 上建立数据图。在一个典型的公司里,你现在已经有了上百个服务,而且 gRPC 是针对这些微服务的 api 的最佳技术,因为它是如此集中,如此高效。它是为“数据中心内部”的用例设计的,但它不是连接到应用程序的正确技术.

现在你明白了吧。确实使用了很多,但是大部分是隐藏在公众视野之外的。它用于促进服务器端后端服务之间闪电般的快速、高效的通信,通常用于数据中心资源根据实时波动的负载自动伸缩的情况。

而且,在现实世界中如何使用 gRPC 的一个主要例子是在 Kubernetes 容器运行时接口(K8S CRI)中,这项技术实际上就是这种自动缩放的同义词。K8s 的一个关键特性是容器编排。K8S CRI 是在 Kubernetes 下管理集装箱的关键组件。而且,gRPC 已经融入了编曲技术的结构中。让我们来看看。

在容器运行时接口中使用 gRPC

为了理解如何使用 gRPC 作为容器运行时接口的通信机制,需要对 Kubernetes 的工作方式有一个高层次的理解,特别是对容器在其体系结构中所扮演的角色。

Kubernetes 是一种服务管理和容器编排技术,旨在支持以 web 规模运行的分布式应用程序。K8s系结构背后的基本逻辑是,应用程序或 API 的功能在 Kubernetes 通过一种称为service的资源来表示。service是网络上应用程序的抽象。给定服务表示的实际逻辑驻留在另一个称为 pod 的抽象资源中。

理解k8s的 service和pod

比如一个应用程序中存在的三个服务的示例。一个服务提供访问功能。另一个提供目录信息,第三个提供购买功能。这些服务都可以通过 IP 地址或 DNS 名称在网络上进行标识。因此,使用应用程序的使用者将相应地调用网络上的服务。然而,该服务没有自己的功能。相反,service的功能是由驻留在服务绑定到的一个或多个pod中的逻辑提供的。

1

如上所述,pod 是一种抽象资源。Pod 是一个托管 Linux 容器的组织单元。容器是封装和隔离执行编程逻辑的进程的机制。(见下图2)

2

在容器中运行的进程的示例有 web 服务器、消息代理、数据库和其他类型的可执行二进制文件。一个吊舱可以容纳一个或多个容器,其中每个容器的功能都是独一无二的。换句话说,同时拥有 web 服务器容器和数据库容器的 pod 是非常有可能的。然而,需要注意的是,配置一个 pod 并不仅仅是包含随机数量的容器来承载。定义具有多个容器的 pod 的结构是一项复杂的工作。

需要知道的重要事情是: 在 Kubernetes,服务代表网络的功能。这种功能存在于POD中。给定 pod 中功能的实现是在 pod 中承载的容器中执行的。

这就把我们带到了集装箱。集装箱在 Kubernetes 不是凭空出现的。它们需要被制造出来,而且需要以一种短暂的方式制造出来。K8s是一种动态技术。它可以上下调整资源规模以满足当前的需求。这包括根据需要创建和销毁容器。

在 Kubernetes 有一种抽象的资源叫做部署(deployment)。部署的任务是保证在给定的 Kubernetes 部署中应该运行的所有容器确实正在运行。这一点很重要,因为 Kubernetes 保证为集群定义的状态将始终得到维护

集装箱实现的机制

在进入容器运行时以及 gRPC 在容器实现过程中所扮演的角色之前,了解容器实现背后的机制是有用的。 在 Kubernetes,虚拟机被称为节点。Kubernetes 集群由控制器节点组成,控制一组组成的工作者节点中的活动。简而言之,控制器节点是老板,工作节点是工作者。

BvIFKi

集群中的每个工作者节点都有一个名为 kubelet 的代理。可以将 kubelet 视为节点的主管。它接受来自控制器平面的命令,在其节点上执行一些工作,然后确保完成工作。Kubelet 的一个任务是在其工作节点上创建和销毁容器。

为什么一个节点直接与容器一起工作? 我认为一个 pod 是容器的父节点

  • Pod 是绑定到服务的逻辑组织单元。服务表示网络上的应用程序逻辑。Pod 为服务提供逻辑
  • 虽然 pod 确实是组织单位,是容器的父级,但是创建和销毁容器的实际工作是由容器所在的工作节点完成的。
  • 把一个节点想象成一个家具工厂。有许多劳动者(集装箱)在许多工作台(工作舱)上劳动。一个工作台可能正在做椅子,另一个桌子。在工厂的前门是一个执行订单的雇员。这个“订单填充器”知道每个工作台的位置以及它生成的产品。可以将订单填充器看作是一个 Kubernetes 服务。当客户来到工厂并请求一把椅子时,订单填充器调用生产椅子的工作台,并为客户拿到一把椅子。
  • 虽然一个劳动者被分配到一个特定的工作台(一个吊舱) ,工作台并没有雇佣任何劳动者。相反,工厂的工头负责雇佣和分配工人到工作台上。你可以把工头想象成 K8S 的 kubelet。

然而,kubelet 不做这项工作。(记住,kubelet 是一个包工头)相反,它告诉容器运行时接口(CRI)来完成这项工作。

在每个 Kubernetes 工作节点中运行的 kubelet 实例告诉 CRI 创建容器,以响应来自运行在 Kubernetes Controller 节点上的 API 服务器的通知

4

gRPC 和CRI

Kubelet 告诉 CRI 要做什么的方式是通过与嵌入在 CRI 中的 grc 服务器进行交互。

kubelet 使用 gRPC 在工作节点上创建和销毁容器,与 Container Runtime Interface 进行交互

tAk82U

当需要在一个节点上创建或者销毁一个容器时,kubelet 向运行在该节点 CRI 实例上的 gRPC 服务器发送一条消息来执行该操作,然后 CRI 与安装在工作节点上的容器运行时引擎进行交互,以执行必要的操作。

例如,当 kubelet 想要创建一个容器时,它使用它的 gRPC 客户机将 CreateContainerRequest 消息发送到 CRI 组件上托管的 RPC (远程过程调用)函数 CreateContainer ()。CreateContainer 函数和 CreateContainerRequest.

//用于使用 Kubernetes Container Runtime Interface 创建容器的 gRPC 函数和消息类型
// CreateContainer creates a new container in specified PodSandbox
rpc CreateContainer(CreateContainerRequest) returns (CreateContainerResponse) {}

message CreateContainerRequest {
    // ID of the PodSandbox in which the container should be created.
    string pod_sandbox_id = 1;
    // Config of the container.
    ContainerConfig config = 2;
    // Config of the PodSandbox. This is the same config that was passed
    // to RunPodSandboxRequest to create the PodSandbox. It is passed again
    // here just for easy reference. The PodSandboxConfig is immutable and
    // remains the same throughout the lifetime of the pod.
    PodSandboxConfig sandbox_config = 3;
}

CRI 将创建请求发送到安装在节点上的实际容器运行时。容器运行时创建容器。 允许从一个节点上的各种容器运行时中安装一个。可以安装可靠的 Docker 运行时,但也可以安装其他运行时,例如 containerd、 rkt 或 cri-o、 declared、 cree-oh。(在自定义集群时,选择最适合给定 Kubernetes 安装的容器运行时提供了额外的灵活性。)

一旦容器创建完成,CRI 将返回 protobuf 文件中定义的 CreateContainerResponse 消息,该消息由 gRPC 客户机和服务器共享。CreateContainerResponse 的定义

//CRI grc 服务器返回一个 CreateContainerResponse 消息,其中包含所创建容器的唯一标识符。
message CreateContainerResponse {
    // ID of the created container.
    string container_id = 1;
}

创建和销毁容器只是从 Container Runtime Interface 执行的两个活动。还有其他一些方法,比如停止容器、重新启动容器、将容器列入 pod 中、更新容器的配置信息等等。

gRPC 驱动了 kubelet 和 CRI 之间的所有消息交换。请记住,kubelet 和 CRI 之间的信息交换需要以闪电般的速度进行,有时甚至需要十亿分之一秒的时间。一个典型的以 web 规模运行的 Kubernetes 集群可能有成千上万个容器在数十个、甚至数百个节点中有效地运行。因此,在通信流水线中,速度和效率至关重要, gRPC 就符合条件

readmore

https://kubernetes.io/docs/home/

K8s

https://en.wikipedia.org/wiki/Kubernetes

github博客 微信公众号:chasays, 欢迎关注一起吹牛逼,也可以加微信号「xxd_0225」互吹。