Likbez将启动Istio


Isstio服务网格


也就是说,我们已经使用Istio一年了。 然后他就走了。 我们在Kubernetes集群中的性能大幅下降,我们希望进行分布式跟踪,并让Istio运行Jaeger并加以解决。 服务网格非常适合我们的基础架构,因此我们决定投资此工具。


我不得不受苦,但我们对此进行了广泛的研究。 这是系列文章中的第一篇,我将介绍Istio如何与Kubernetes集成以及我们从中了解到的工作。 有时,我们会涉足技术领域,但并不遥远。 进一步会有更多的职位。


什么是Istio?


Istio是服务网格配置工具。 它读取Kubernetes集群的状态并升级到L7代理(HTTP和gRPC),这些代理在Kubernetes容器中作为辅助工具实现。 这些附属工具是Envoy容器,可从Istio Pilot API(和gRPC服务)读取配置并通过它路由流量。 借助强大的L7代理,我们可以使用指标,跟踪,重试逻辑,断路器,负载平衡和Canary部署。


让我们从头开始:Kubernetes


在Kubernetes中,我们使用deploy或StatefulSet在下面创建。 或者,它可以是没有高级控制器的“香草”。 然后,Kubernetes会尽力维持所需的状态-它在节点上的集群中创建pod,并确保它们启动和重启。 创建基础时,Kubernetes会经历API生命周期,确保每个步骤都成功,然后才在集群上最终创建基础。


API生命周期阶段:



感谢Banzai Cloud的精彩图片。


步骤之一是修改准入网络钩子。 这是Kubernetes生命周期中的一个单独部分,在Kubernetes中,在提交到etcd存储库(Kubernetes配置的真相)之前,对资源进行了自定义。 Istio在这里发挥他的魔力。


修改准入网络挂钩


当创建一个子项(通过kubectlDeployment )时,它会经历这个生命周期,并且通过修改访问权限的webhooks会对其进行更改,然后再将其发布到大世界。


在安装Istio的过程中,istio-sidecar-injector被添加为配置资源,用于修改webhooks:


 $ kubectl get mutatingwebhookconfiguration NAME AGE istio-sidecar-injector 87d 

并配置:


 apiVersion: admissionregistration.k8s.io/v1beta1 kind: MutatingWebhookConfiguration metadata: labels: app: istio-sidecar-injector chart: sidecarInjectorWebhook-1.0.4 heritage: Tiller name: istio-sidecar-injector webhooks: - clientConfig: caBundle: redacted service: name: istio-sidecar-injector namespace: istio-system path: /inject failurePolicy: Fail name: sidecar-injector.istio.io namespaceSelector: matchLabels: istio-injection: enabled rules: - apiGroups: - "" apiVersions: - v1 operations: - CREATE resources: - pods 

它说Kubernetes应该将所有炉床创建事件发送到istio-system命名空间中的istio-sidecar-injector ,如果该命名空间具有istio-injection=enabled 。 注入程序在PodSpec中还包括两个容器:一个用于设置代理规则的临时容器,另一个用于自身代理的容器。 边车注入器根据来自istio-sidecar-injector配置图的模板插入这些容器。 此过程也称为“照顾”。


边车舱


Sidecar是我们魔术师Istio的the俩。 Istio巧妙地弯曲了所有东西,如果您不了解细节,那么从外面看就象魔术一样。 如果您突然需要调试网络请求,了解他们会很有用。


初始化和代理容器


Kubernetes有一个临时的一次性初始化容器,可以在主要容器之前运行。 他们汇集资源,迁移数据库,或者像Istio一样配置网络规则。


Istio使用Envoy将所有请求代理到所需路径的提交中。 为此,Istio创建iptables规则,它们将传入和传出的流量直接发送到Envoy,并巧妙地将流量代理到其目的地。 流量会绕开一小步,但您已经获得了分布式跟踪,查询指标和策略实施。 在此文件中,从Istio存储库中,您可以看到 Istio如何创建iptables规则。


@jimmysongio在iptables规则和Envoy代理之间绘制了一个极好的连接图:



特使-特使交通


Envoy接收所有传入和传出的流量,因此所有流量通常都在Envoy内部移动,如图所示。 Istio代理是另一个容器,已添加到由Istio边车注入器修改的所有吊舱中。 在此容器中,Envoy进程开始,该进程接收来自炉床的所有流量(某些例外,例如来自Kubernetes集群的流量)。


Envoy进程通过实现Istio的Envoy v2 API发现所有路由。


特使和飞行员


Envoy本身没有逻辑来检测集群中的Pod和服务。 它是数据平面,需要控制平面进行引导。 Envoy配置参数请求主机或服务端口通过gRPC API接收此配置。 Istio通过其Pilot服务满足了gRPC API的要求。 Envoy根据通过修改的Webhook实现的sidecar配置连接到此API。 该API具有Envoy需要为集群发现和路由的所有流量规则。 这是服务网格。



数据交换“在<->飞行员下”


Pilot连接到Kubernetes集群,读取集群状态并等待更新。 它监视Kubernetes集群中的Pod,服务和端点,然后为连接到该Pilot的所有Envoy边车提供正确的配置。 这是Kubernetes和Envoy之间的桥梁。



从飞行员到Kubernetes


在Kubernetes中创建或更新Pod,服务或端点时,Pilot会了解到这一点,并将必要的配置发送到所有连接的Envoy实例。


正在发送什么配置?


Envoy从Istio Pilot获得什么配置?


默认情况下,Kubernetes通过管理endpointsevice (服务)解决您的网络问题。 可以使用以下命令打开端点列表:


 kubectl get endpoints 

这是群集中所有IP和端口及其地址的列表(通常这些是从部署创建的Pod)。 为了配置路由数据并将其发送到Envoy,了解Istio非常重要。


服务,侦听器和路线


当您在Kubernetes集群中创建服务时,您将包括一些快捷方式,通过这些快捷方式可以选择所有合适的Pod。 当您将流量发送到服务的IP时,Kubernetes会为此流量选择流量。 例如,命令


 curl my-service.default.svc.cluster.local:3000 

首先,它将在default名称空间中找到分配给my-service的虚拟IP,并将该IP转发流量到与服务标签匹配的子服务器。


Istio和Envoy稍微改变了这种逻辑。 Istio根据Kubernetes集群中的服务和端点配置Envoy,并使用Envoy的智能路由和负载平衡功能绕过Kubernetes服务。 Envoy无需一次代理一个IP,而是直接连接到IP壁炉。 为此,Istio将Kubernetes配置映射到Envoy配置


Kubernetes,Istio和Envoy这两个词略有不同,目前尚不清楚他们吃什么。


服务项目


Kubernetes中的服务映射到Envoy中的集群 。 Envoy群集包含一个端点列表,即用于处理请求的实例的IP(或主机名)。 要查看在Istio sidecar-pod中配置的群集列表,请运行istioctl proxy-config cluster < > 。 该命令以炉膛为单位显示当前的状态。 以下是我们其中一种环境的示例:


 $ istioctl proxy-config cluster taxparams-6777cf899c-wwhr7 -n applications SERVICE FQDN PORT SUBSET DIRECTION TYPE BlackHoleCluster - - - STATIC accounts-grpc-gw.applications.svc.cluster.local 80 - outbound EDS accounts-grpc-public.applications.svc.cluster.local 50051 - outbound EDS addressvalidator.applications.svc.cluster.local 50051 - outbound EDS 

所有相同的服务都在此命名空间中:


 $ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) accounts-grpc-gw ClusterIP 10.3.0.91 <none> 80/TCP accounts-grpc-public ClusterIP 10.3.0.202 <none> 50051/TCP addressvalidator ClusterIP 10.3.0.56 <none> 50051/TCP 

Istio如何知道哪个协议使用该服务? 通过端口条目中的name字段为服务清单配置协议。


 $ kubectl get service accounts-grpc-public -o yaml apiVersion: v1 kind: Service metadata: name: accounts-grpc-public spec: ports: - name: grpc port: 50051 protocol: TCP targetPort: 50051 

如果存在grpcgrpc-前缀,则Istio将为该服务配置HTTP2协议。 我们通过痛苦的经验中学到了当代理配置因为未指定http或grpc前缀而损坏时Istio如何使用端口名...


如果在Envoy中使用kubectl和“管理端口转发”页面,则可以看到Account-grpc-public端点是Pilot在Envoy中通过HTTP2协议实现的群集。 这证实了我们的假设:


 $ kubectl -n applications port-forward otherpod-dc56885ff-dqc6t 15000:15000 & $ curl http://localhost:15000/config_dump | yq r - ... - cluster: circuit_breakers: thresholds: - {} connect_timeout: 1s eds_cluster_config: eds_config: ads: {} service_name: outbound|50051||accounts-grpc-public.applications.svc.cluster.local http2_protocol_options: max_concurrent_streams: 1073741824 name: outbound|50051||accounts-grpc-public.applications.svc.cluster.local type: EDS ... 

端口15000是Envoy的管理页面 ,可在每个小车上使用。


听众


侦听器识别Kubernetes端点以将流量传递到炉膛。 地址验证服务在此处具有一个端点:


 $ kubectl get ep addressvalidator -o yaml apiVersion: v1 kind: Endpoints metadata: name: addressvalidator subsets: - addresses: - ip: 10.2.26.243 nodeName: ip-10-205-35-230.ec2.internal targetRef: kind: Pod name: addressvalidator-64885ccb76-87l4d namespace: applications ports: - name: grpc port: 50051 protocol: TCP 

因此,地址验证炉床在端口50051上具有一个侦听器:


 $ kubectl -n applications port-forward addressvalidator-64885ccb76-87l4d 15000:15000 & $ curl http://localhost:15000/config_dump | yq r - ... dynamic_active_listeners: - version_info: 2019-01-13T18:39:43Z/651 listener: name: 10.2.26.243_50051 address: socket_address: address: 10.2.26.243 port_value: 50051 filter_chains: - filter_chain_match: transport_protocol: raw_buffer ... 

路线


在Istio中,代替了标准的Kubernetes Ingress对象,而是采用了更加抽象和高效的自定义资源-VirtualService。 VirtualService通过将路由绑定到网关将路由映射到上游群集。 这是如何将Kubernetes Ingress与Ingress控制器一起使用。


即,我们将Istio入口网关用于所有内部GRPC流量:


 apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: grpc-gateway spec: selector: istio: ingressgateway servers: - hosts: - '*' port: name: http2 number: 80 protocol: HTTP2 --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: grpc-gateway spec: gateways: - grpc-gateway hosts: - '*' http: - match: - uri: prefix: /namely.address_validator.AddressValidator retries: attempts: 3 perTryTimeout: 2s route: - destination: host: addressvalidator port: number: 50051 

乍看之下,您在示例中将一无所知。 在这里看不到它,但是Istio-IngressGateway部署基于istio: ingressgateway记录需要哪些终结点。 在此示例中,IngressGateway通过HTTP2通过端口80为所有域路由流量。 VirtualService为此网关实现路由,匹配/namely.address_validator.AddressValidator前缀,并在两秒钟内通过重试规则将addressvalidator通过端口50051传递到上游服务。


如果我们重定向Istio-IngressGateway的pod端口并查看Envoy的配置,我们将看到VirtualService的作用:


 $ kubectl -n istio-system port-forward istio-ingressgateway-7477597868-rldb5 15000 ... - match: prefix: /namely.address_validator.AddressValidator route: cluster: outbound|50051||addressvalidator.applications.svc.cluster.local timeout: 0s retry_policy: retry_on: 5xx,connect-failure,refused-stream num_retries: 3 per_try_timeout: 2s max_grpc_timeout: 0s decorator: operation: addressvalidator.applications.svc.cluster.local:50051/namely.address_validator.AddressValidator* ... 

在Istio挖掘时我们用Google搜索了什么


发生错误503或404


原因不同,但通常是:


  • Sidecar应用程序无法联系Pilot(检查Pilot是否正在运行)。
  • Kubernetes服务清单的协议无效。
  • VirtualService / Envoy配置将路由写入错误的上游群集。 从边缘服务开始,在该处您期望传入流量,并检查Envoy日志。 或使用Jaeger之类的工具查找错误。

Istio代理日志中的NR / UH / UF是什么意思?


  • NR-无路线。
  • UH-上游不健康(上游无法操作)。
  • UF-上游故障(上游故障)。

在Envoy网站上阅读更多内容


关于Istio的高可用性


  • 将NodeAffinity添加到Istio组件,以在不同的访问区域中均匀分布炉床,并增加最少的副本数。
  • 使用Horizo​​ntal Pod Autoscaling功能启动新版本的Kubernetes。 最重要的炉床将根据负载进行缩放。

cronjob为什么不结束?


完成主要工作量后,便车集装箱继续工作。 要解决此问题,请在PodSpec中添加注释sidecar.istio.io/inject: “false”以禁用cronjobs中的sidecar。


如何安装Istio?


我们使用Spinnaker进行部署,但通常会获取最新的Helm图表,将其联想起来,使用helm template -f values.yml并在Github上提交文件以查看更改,然后通过kubectl apply -f -应用它们。 这是为了避免在不同版本中意外更改CRD或API。


感谢Bobby TablesMichael Hamrah协助撰写了这篇文章。

Source: https://habr.com/ru/post/zh-CN441616/


All Articles