草庐IT

k8s 与istio

程序员札记 2023-09-22 原文

如果你听说过服务网格,并尝试过 Istio ,你可能有以下问题。

  1. 为什么 Istio 要在 Kubernetes 上运行?
  2. Kubernetes 和服务网格在云原生应用架构中分别扮演什么角色?
  3. Istio 扩展了 Kubernetes 的哪些方面?它解决了哪些问题?
  4. Kubernetes、Envoy 和 Istio 之间是什么关系?

本文将带大家了解 Kubernetes 和 Istio 的内部工作原理。此外,我会介绍 Kubernetes 中的负载均衡方法,并解释为什么有了 Kubernetes 后还需要 Istio。

Kubernetes 本质上是通过声明式配置来实现应用生命周期管理,而服务网格本质上是提供应用间的流量、安全管理和可观察性。如果你已经使用 Kubernetes 搭建了一个稳定的应用平台,那么如何设置服务间调用的负载均衡和流量控制?是否有这样一个通用的工具或者说平台(非 SDK),可以实现?这就需要用到服务网格了。

Envoy 引入了 xDS 协议,这个协议得到了各种开源软件的支持,比如 Istio、MOSN 等。Envoy 将 xDS 贡献给服务网格或云原生基础设施。Envoy 本质上是一个现代版的代理,可以通过 API 进行配置,在此基础上衍生出许多不同的使用场景–比如 API Gateway、服务网格中的 sidecar 代理和边缘代理。

本文包含以下内容。

  • kube-proxy 的作用描述。
  • Kubernetes 在微服务管理方面的局限性。
  • Istio 服务网格的功能介绍。
  • Kubernetes、Envoy 和 Istio 服务网格中一些概念的比较。

Kubernetes vs Service Mesh

下图显示了 Kubernetes 中的服务访问关系和服务网格(每个 pod 模型一个 sidecar)。

Kubernetes vs Service Mesh

流量转发

Kubernetes 集群中的每个节点都部署了一个 kube-proxy 组件,该组件与 Kubernetes API Server 进行通信,获取集群中的服务信息,然后设置 iptables 规则,将服务请求直接发送到对应的 Endpoint(属于同一组服务的 pod)。

服务发现

Service Discovery

Istio 可以跟踪 Kubernetes 中的服务注册,也可以在控制平面中通过平台适配器与其他服务发现系统对接;然后生成数据平面的配置(使用 CRD,这些配置存储在 etcd 中),数据平面的透明代理。数据平面的透明代理以 sidecar 容器的形式部署在每个应用服务的 pod 中,这些代理都需要请求控制平面同步代理配置。代理之所以 “透明”,是因为应用容器完全不知道代理的存在。过程中的 kube-proxy 组件也需要拦截流量,只不过 kube-proxy 拦截的是进出 Kubernetes 节点的流量–而 sidecar 代理拦截的是进出 pod 的流量。

服务网格的劣势

由于 Kubernetes 的每个节点上都运行着很多 pod,所以在每个 pod 中放入原有的 kube-proxy 路由转发功能,会增加响应延迟–由于 sidecar 拦截流量时跳数更多,消耗更多的资源。为了对流量进行精细化管理,将增加一系列新的抽象功能。这将进一步增加用户的学习成本,但随着技术的普及,这种情况会慢慢得到缓解。

服务网格的优势

kube-proxy 的设置是全局的,无法对每个服务进行细粒度的控制,而 service mesh 通过 sidecar proxy 的方式将 Kubernetes 中的流量控制从服务层中抽离出来–可以实现更大的弹性。

Kube-proxy 的不足之处

首先,如果转发的 pod 不能正常服务,它不会自动尝试其他 pod。每个 pod 都有一个健康检查机制,当一个 pod 出现健康问题时,kubelet 会重启 pod,kube-proxy 会删除相应的转发规则。另外,节点 Port 类型的服务不能添加 TLS 或更复杂的消息路由机制。

Kube-proxy 实现了一个 Kubernetes 服务的多个 pod 实例之间的流量负载均衡,但如何对这些服务之间的流量进行精细化控制–比如将流量按百分比划分给不同的应用版本(这些应用版本都是同一个服务的一部分,但在不同的部署上),或者做金丝雀发布(灰度发布)和蓝绿发布?

Kubernetes 社区给出了一个使用 Deployment 做金丝雀发布 的方法,本质上是通过修改 pod 的标签来给部署的服务分配不同的 pod。

Kubernetes Ingress vs Istio Gateway

如上所述,kube-proxy 只能在 Kubernetes 集群内路由流量。Kubernetes 集群的 pod 位于 CNI 创建的网络中。Ingress 是在 Kubernetes 中创建的资源对象,用于集群外部的通信。它由位于 Kubernetes 边缘节点上的入口控制器驱动,负责管理南北向流量。Ingress 必须与各种 Ingress 控制器对接,比如 nginx ingress 控制器traefik 。Ingress 只适用于 HTTP 流量,使用简单。它只能通过匹配有限的字段来路由流量——如服务、端口、HTTP 路径等。这使得它无法对 TCP 流量进行路由,如 MySQL、Redis 和各种 RPC。这就是为什么你会看到人们在 ingress 资源注释中写 Nginx 配置语言的原因(注:使用 Nginx Ingress Controller 可以通过 配置 ConfigMap 和 Service 的方式 来变通支持 TCP 和 UDP 流量转发)。直接路由南北流量的唯一通行方法是使用服务的 LoadBalancer 或 NodePort,前者需要云厂商支持,后者需要额外的端口管理。

Istio Gateway 的功能与 Kubernetes Ingress 类似,它负责进出集群的南北流量。Istio Gateway 描述了一个负载均衡器,用于承载进出服务网格边缘的连接。该规范描述了一组开放端口和这些端口所使用的协议,以及用于负载均衡的 SNI 配置等。Gateway 是一个 CRD 扩展,它也重用了 sidecar 代理的功能;详细配置请参见 Istio 网站

Envoy

Envoy 是 Istio 中默认的 sidecar 代理。Istio 基于 Enovy 的 xDS 协议扩展了其控制平面。在讨论 Envoy 的 xDS 协议之前,我们需要先熟悉 Envoy 的基本术语。下面是 Envoy 的架构图。

Envoy 架构图

基础概念

以下是 Enovy 中你应该知道的基本术语。

  • 下游。下游主机连接到 Envoy,发送请求,并接收响应,即发送请求的主机。
  • 上游:上游主机。上游主机接收来自 Envoy 的连接和请求,并返回响应;即接收请求的主机。
  • Listener:监听器。监听器是一个命名的网络地址(如端口、UNIX 域套接字等);下游客户端可以连接到这些监听器。Envoy 将一个或多个监听器暴露给下游主机进行连接。
  • 集群。集群是一组逻辑上相同的上游主机,Envoy 连接到它们。Envoy 通过服务发现来发现集群的成员。可以选择通过主动的健康检查来确定集群成员的健康状态。Envoy 通过负载均衡策略来决定集群中哪个成员的请求路由。

在 Envoy 中可以设置多个监听器,每个监听器可以设置一个过滤链(过滤链表),而且过滤链是可扩展的,这样我们可以更方便地操纵流量的行为–比如设置加密、私有 RPC 等。

xDS 协议是由 Envoy 提出的,是 Istio 中默认的 sidecar 代理,但只要实现了 xDS 协议,理论上也可以作为 Istio 中的 sidecar 代理 —— 比如蚂蚁集团开源的 MOSN

[
image

Istio 是一个功能非常丰富的服务网格,包括以下功能。

  • 流量管理。这是 Istio 最基本的功能。
  • 策略控制。实现访问控制系统、遥测采集、配额管理、计费等功能。
  • 可观察性。在 sidecar 代理中实现。
  • 安全认证。由 Citadel 组件进行密钥和证书管理。

Istio 中的流量管理

Istio 中定义了以下 CRD 来帮助用户进行流量管理。

  • 网关。网关描述了一个运行在网络边缘的负载均衡器,用于接收传入或传出的 HTTP/TCP 连接。
  • 虚拟服务(VirtualService)。VirtualService 实际上是将 Kubernetes 服务连接到 Istio 网关。它还可以执行额外的操作,例如定义一组流量路由规则,以便在主机寻址时应用。
  • DestinationRule。DestinationRule 定义的策略决定了流量被路由后的访问策略。简单来说,它定义了流量的路由方式。其中,这些策略可以定义为负载均衡配置、连接池大小和外部检测(用于识别和驱逐负载均衡池中不健康的主机)配置。
  • EnvoyFilter。EnvoyFilter 对象描述了代理服务的过滤器,可以自定义 Istio Pilot 生成的代理配置。这种配置一般很少被主用户使用。
  • ServiceEntry。默认情况下,Istio 服务 Mesh 中的服务无法发现 Mesh 之外的服务。ServiceEntry 可以在 Istio 内部的服务注册表中添加额外的条目,从而允许 Mesh 中自动发现的服务访问并路由到这些手动添加的服务。

Kubernetes vs xDS vs Istio

在回顾了 Kubernetes 的 kube-proxy 组件、xDS 和 Istio 对流量管理的抽象后,现在我们仅从流量管理的角度来看看这三个组件 / 协议的比较(注意,三者并不完全等同)。

Kubernetes xDS Istio service mesh
Endpoint Endpoint WorkloadEntry
Service Route VirtualService
kube-proxy Route DestinationRule
kube-proxy Listener EnvoyFilter
Ingress Listener Gateway
Service Cluster ServiceEntry

核心观点

  • Kubernetes 的本质是应用生命周期管理,具体来说就是部署和管理(伸缩、自动恢复、发布)。
  • Kubernetes 为微服务提供了一个可扩展、高弹性的部署和管理平台。
  • 服务网格是基于透明代理,通过 sidecar 代理拦截服务之间的流量,然后通过控制平面配置管理它们的行为。
  • 服务网格将流量管理与 Kubernetes 解耦,不需要 kube-proxy 组件来支持服务网格内的流量;通过提供更接近微服务应用层的抽象来管理服务间的流量、安全性和可观察性。
  • xDS 是服务网格的协议标准之一。
  • 服务网格是 Kubernetes 中服务的一个更高层次的抽象。

总结

如果说 Kubernetes 管理的对象是一个 pod,那么服务网格管理的对象就是一个服务,所以用 Kubernetes 管理微服务,然后应用服务网格就可以了。如果你连服务都不想管理,那就用 Knative 这样的无服务器平台,不过这是后话

有关k8s 与istio的更多相关文章

  1. k8s-污点 (Taint)和容忍 (Tolerations) - 2

    文章目录一、污点(Taint)1、污点简介2、污点的组成3、污点的设置和去除二、容忍(Tolerations)1、容忍简介2、容忍的基本用法3、示例4、多污点与多容忍配置三、警戒(cordon)和转移(drain)四、Pod启动阶段(相位phase)五、故障排除步骤一、污点(Taint)节点亲和性,是Pod的一种属性(偏好或硬性要求),它使Pod被吸引到一类特定的节点Taint则相反,它使节点能够排斥一类特定的PodTaint和Toleration相互配合,可以用来避免Pod被分配到不合适的节点上。每个节点上都可以应用一个或多个taint,这表示对于那些不能容忍这些taint的Pod,是不会被

  2. 云原生(十八) | Kubernetes篇之Kubernetes(k8s)工作负载 - 2

    文章目录Kubernetes(k8s)工作负载一、Workloads二、Pod三、Deployment四、RC、RS、DaemonSet、StatefulSet五、Job、CronJob1、Job2、CronJob六、GCKubernetes(k8s)工作负载一、Workloads什么是工作负载(Workloads)工作负载是运行在Kubernetes上的一个应用程序。一个应用很复杂,可能由单个组件或者多个组件共同完成。无论怎样我们可以用一组Pod来表示一个应用,也就是一个工作负载Pod又是一组容器(Containers)所以关系又像是这样工作负载(Workloads)控制一组PodPod控制

  3. K8s部署PHP项目 - 2

    前言    前端时间PHP项目部署升级需要,需要把Laravel开发的项目部署K8s上,下面以laravel项目为例,讲解采用yaml文件方式部署项目。一、部署步骤1.创建Dockerfile文件Dockerfile是一个用来构建镜像的文本文件,在容器运行时,需要把项目文件和项目运行所必须的组件安装其中。#基础镜像FROMphp:7.4-fpm#时区ARGTZ=Asia/Shanghai#更换容器时区RUNcp"/usr/share/zoneinfo/$TZ"/etc/localtime&&echo"$TZ">/etc/timezone#替换成阿里apt-get源RUNsed-i"s@http

  4. 【k8s】二、containerd的安装 - 2

    目录前言安装containerd解压安装配置成systemd任务安装runc​编辑安装cni配置containerd镜像源containerd基本使用拓展阅读nerdctl工具安装及使用整体脚本总结写在后面前言上一篇文章,我们介绍了虚拟机的基础环境以及基础的网络配置,还有一些k8s节点要用到基础环境配置。本文将带领大家把containerd给安装了containerd的项目官方地址https://github.com/containerd/containerdcontainerd的发布版本地址如下https://github.com/containerd/containerd/releases

  5. idea连接远程k8s集群使用kubernetes-client - 2

    文章目录一.k8s集群修改config1.1备份当前k8s集群配置文件1.2删除当前k8s集群的apiserver的cert和key1.3生成新的apiserver的cert和key1.4刷新admin.conf1.5重启apiserver1.6刷新.kube/config二.安装kubectl2.1下载kubectl2.2配置kubectl三.使用kubernetes-client操作k8s集群3.1依赖3.2注意(可忽略)3.3创建StatefulSet3.4运行shell命令3.5删除StatefulSet3.6线上运行注意一.k8s集群修改config因为默认的是内网IP,复制出来后,

  6. [k8s] error: Readiness probe failed: HTTP probe failed with statuscode: 503 - 2

    k8sissue: error:Readinessprobefailed:HTTPprobefailedwithstatuscode:503explanation:Kubernetes为准备和活动探测返回HTTP503错误的事实意味着到后端的连接可能有问题。有趣的是,这不是重点。这些探针不是用来执行HTTP流的端到端测试的。探测只用于验证它们所监视的服务是否响应。简单地说,好的是自己设置的readiness探针(probe)起作用了,不好的是,自己的配置文件可能有一些其他方面的问题。具体是什么方面的问题呢?就是创建出来的container里的报错信息Read-onlyfilesystem/xx

  7. k8s日志收集 - 2

    日志收集介绍日志收集的目的:分布式日志数据统一收集,实现集中式查询和管理故障排查安全信息和事件管理报表统计及展示功能日志收集的价值:日志查询、问题排查、故障恢复和故障自愈应用日志分析,错误报警性能分析,用户行为分析k8s常用的日志收集方式:在节点上进行收集,基于daemonset部署日志收集容器,实现json-file类型(标准输出/dev/stdout,错误输出/dev/stderr)日志收集使用sidecar容器收集当前Pod内一个或多个业务容器的日志,通常基于emptyDir实现业务容器与sidecar容器之间的日志共享在容器内内置日志收集进程ES集群部署使用主机如下:IP主机名角色19

  8. k8s API Server 中的认证、鉴权、准入、限流总结分享 - 2

    文章目录概述认证认证插件基于静态token的认证服务实践基于X509证书认证实践基于webhook认证实践鉴权k8s中RBAC的使用授权实践准入场景配额管理实践插件插件开发限流APIPriorityandFairnessAPF中的排队FlowSchema与PriorityLevelConfiguration(队列权重配置)调试命令概述kube-apiserver是k8s最重要的控制组件之一,主要提供以下功能:提供集群管理的RESTAPI接口,包括认证授权、数据校验以及集群状态变更等k8s中所有模块与etcd的数据交互都需要走APIServer,禁止直接和etcd通信APIServer请求流程概

  9. k8s教程(service篇)-DNS服务搭建和配置 - 2

    文章目录01引言02DNS服务在k8s的发展2.1SkyDNS2.2KubeDNS2.3CoreDNS03搭建CoreDNS服务3.1修改每个Node上kubelet的DNS启动参数3.2部署CoreDNS服务3.2.1ConfigMap3.2.2Deployment3.2.3Service04服务名的DNS解析05CoreDNS配置5.1示例一:设置插件5.2示例二:自定义域名5.3示例三:转发域名查询到上游DNS服务器上06引言01引言声明:本文为《Kubernetes权威指南:从Docker到Kubernetes实践全接触(第5版)》的读书笔记作为服务发现机制的基本功能,在集群内需要能够

  10. 【云原生 | Kubernetes 系列】K8s 实战 Kubernetes 声明式对象的 增 删 改 查 - 2

    Kubernetes声明式对象的增删改查前言一、创建对象二、更新对象三、删除对象四、查看对象总结前言我们可以通过在一个目录中存储多个对象配置文件、并使用kubectlapply来递归地创建和更新对象来创建、更新和删除Kubernetes对象。这种方法会保留对现有对象已作出的修改,而不会将这些更改写回到对象配置文件中。kubectldiff也会给你呈现apply将作出的变更的预览。一、创建对象使用kubectlapply来创建指定目录中配置文件所定义的所有对象,除非对应对象已经存在:$kubectlapply-f/此操作会在每个对象上设置kubectl.kubernetes.io/last-ap

随机推荐