如何在生产中使用 Kubernetes 运行 Istio。 第1部分

什么是 Istio? 这就是所谓的服务网格,一种在网络上添加抽象层的技术。 我们拦截集群中的全部或部分流量,并用它执行一组特定的操作。 哪一个? 例如,我们做智能路由,或者我们实现断路器的方式,我们可以组织“金丝雀部署”,将部分流量切换到新版本的服务,或者我们可以限制外部交互并控制从集群到集群的所有行程。外部网络。 可以设置策略规则来控制不同微服务之间的行程。 最后,我们可以获得整个网络交互图,并使统一的指标收集对应用程序完全透明。

您可以阅读有关工作机制的信息 官方文档。 Istio 是一个非常强大的工具,可以让您解决许多任务和问题。 在本文中,我想回答开始使用 Istio 时通常出现的主要问题。 这将帮助您更快地处理它。

如何在生产中使用 Kubernetes 运行 Istio。 第1部分

的操作原理

Istio 由两个主要区域组成 - 控制平面和数据平面。 控制平面包含确保其余部分正确运行的主要组件。 在当前版本(1.0)中,控制平面具有三个主要组件:Pilot、Mixer、Citadel。 我们不会考虑 Citadel,它需要生成证书来确保服务之间的双向 TLS。 让我们仔细看看Pilot和Mixer的装置和用途。

如何在生产中使用 Kubernetes 运行 Istio。 第1部分

Pilot 是主要的控制组件,它分发有关集群中的所有信息 - 服务、端点和路由规则(例如,金丝雀部署规则或断路器规则)。

Mixer 是一个可选的控制平面组件,能够收集指标、日志以及有关网络交互的任何信息。 他还监控政策规则的遵守情况和速率限制的遵守情况。

数据平面是使用 sidecar 代理容器实现的。 默认使用强大。 特使代理。 可以用其他实现代替,例如nginx(nginmesh)。

为了使 Istio 的工作对应用程序完全透明,有一个自动注入系统。 最新实现适用于 Kubernetes 1.9+ 版本(mutational reporting webhook)。 对于 Kubernetes 版本 1.7、1.8,可以使用初始化程序。

Sidecar 容器使用 GRPC 协议连接到 Pilot,这允许您针对集群中发生的更改优化推送模型。 GRPC 从 1.6 版本开始就在 Envoy 中使用,在 Istio 中从 0.8 版本开始使用,它是一个 Pilot-agent - Envoy 上的一个 golang 包装器,用于配置启动选项。

Pilot 和 Mixer 是完全无状态的组件,所有状态都保存在内存中。 它们的配置以 Kubernetes 自定义资源的形式设置,存储在 etcd 中。
Istio-agent 获取 Pilot 的地址并向其打开 GRPC 流。

正如我所说,Istio 实现的所有功能对应用程序完全透明。 让我们看看如何。 算法是这样的:

  1. 部署新版本的服务。
  2. 根据 sidecar 容器注入方法,istio-init 容器和 istio-agent 容器(envoy)是在应用配置阶段添加的,或者它们已经可以手动插入到 Kubernetes Pod 实体的描述中。
  3. istio-init 容器是一个将 iptables 规则应用于 pod 的脚本。 有两个选项可用于将流量配置为包装在 istio-agent 容器中:使用 iptables 重定向规则,或 代理. 在撰写本文时,默认方法是使用重定向规则。 在 istio-init 中,可以配置应拦截哪些流量并将其发送到 istio-agent。 例如,为了拦截所有传入和所有传出的流量,您需要设置参数 -i и -b 转化为意义 *. 您可以指定要拦截的特定端口。 为了不拦截特定子网,您可以使用标志指定它 -x.
  4. 执行 init 容器后,将启动主要容器,包括 Pilot-agent(特使)。 它通过 GRPC 连接到已部署的 Pilot,并接收有关集群中所有现有服务和路由策略的信息。 根据收到的数据,他配置集群并将它们直接分配到 Kubernetes 集群中我们应用程序的端点。 还需要注意一个重要的点:envoy 动态配置它开始监听的监听器(IP、端口对)。 因此,当请求进入 pod 并使用 sidecar 中的重定向 iptables 规则进行重定向时,envoy 已经可以成功处理这些连接并了解在哪里进一步代理流量。 同样在这个阶段,信息被发送到 Mixer(我们稍后会看到),并且发送跟踪跨度。

结果,我们得到了整个 Envoy 代理服务器网络,我们可以从一个点(Pilot)进行配置。 所有入站和出站请求都通过 Envoy。 此外,仅拦截 TCP 流量。 这意味着 Kubernetes 服务 IP 使用 kube-dns over UDP 进行解析,无需更改。 然后,在解析之后,传出的请求将被 Envoy 拦截并处理,Envoy 已经决定了请求应该发送到哪个端点(或者在访问策略或算法的断路器的情况下不发送)。

我们弄清楚了 Pilot,现在我们需要了解 Mixer 是如何工作的以及为什么需要它。 你可以阅读它的官方文档 这里.

当前形式的 Mixer 由两个组件组成:istio-telemetry、istio-policy(在 0.8 版本之前,它是一个 istio-mixer 组件)。 两者都是混合器,各自负责自己的任务。 Istio 遥测通过 GRPC 从 sidecar Report 容器接收有关谁去哪里以及使用哪些参数的信息。 Istio-policy 接受检查请求以验证是否满足策略规则。 当然,策略检查并不是对每个请求都执行,而是在客户端(在 sidecar 中)缓存一段时间。 报告检查作为批量请求发送。 我们稍后看看如何配置以及应该发送哪些参数。

Mixer 应该是一个高度可用的组件,可确保遥测数据的组装和处理工作不间断。 该系统作为多级缓冲器的结果而获得。 最初,数据在容器的 sidecar 端缓冲,然后在混合器端缓冲,然后发送到所谓的混合器后端。 因此,如果任何系统组件发生故障,缓冲区就会增大并在系统恢复后被刷新。 Mixer 后端是发送遥测数据的端点:statsd、newrelic 等。 您可以编写自己的后端,这非常简单,我们将看看如何做到这一点。

如何在生产中使用 Kubernetes 运行 Istio。 第1部分

总而言之,使用 istio-telemetry 的方案如下。

  1. 服务 1 向服务 2 发送请求。
  2. 当离开服务 1 时,请求被包装在它自己的 sidecar 中。
  3. Sidecar Envoy 监视请求如何发送到服务 2 并准备必要的信息。
  4. 然后使用报告请求将其发送到 istio-telemetry。
  5. Istio-telemetry 确定是否应将此报告发送到后端、应发送到哪些后端以及发送哪些数据。
  6. 如果需要,Istio-telemetry 将报告数据发送到后端。

现在让我们看看如何在系统中部署 Istio,仅由主要组件(Pilot 和 sidecar envoy)组成。

首先我们看一下Pilot读取到的主要配置(mesh):

apiVersion: v1
kind: ConfigMap
metadata:
  name: istio
  namespace: istio-system
  labels:
    app: istio
    service: istio
data:
  mesh: |-

    # пока что не включаем отправку tracing информации (pilot настроит envoy’и таким образом, что отправка не будет происходить)
    enableTracing: false

    # пока что не указываем mixer endpoint’ы, чтобы sidecar контейнеры не отправляли информацию туда
    #mixerCheckServer: istio-policy.istio-system:15004
    #mixerReportServer: istio-telemetry.istio-system:15004

    # ставим временной промежуток, с которым будет envoy переспрашивать Pilot (это для старой версии envoy proxy)
    rdsRefreshDelay: 5s

    # default конфигурация для envoy sidecar
    defaultConfig:
      # аналогично как rdsRefreshDelay
      discoveryRefreshDelay: 5s

      # оставляем по умолчанию (путь к конфигурации и бинарю envoy)
      configPath: "/etc/istio/proxy"
      binaryPath: "/usr/local/bin/envoy"

      # дефолтное имя запущенного sidecar контейнера (используется, например, в именах сервиса при отправке tracing span’ов)
      serviceCluster: istio-proxy

      # время, которое будет ждать envoy до того, как он принудительно завершит все установленные соединения
      drainDuration: 45s
      parentShutdownDuration: 1m0s

      # по умолчанию используются REDIRECT правила iptables. Можно изменить на TPROXY.
      #interceptionMode: REDIRECT

      # Порт, на котором будет запущена admin панель каждого sidecar контейнера (envoy)
      proxyAdminPort: 15000

      # адрес, по которому будут отправляться trace’ы по zipkin протоколу (в начале мы отключили саму отправку, поэтому это поле сейчас не будет использоваться)
      zipkinAddress: tracing-collector.tracing:9411

      # statsd адрес для отправки метрик envoy контейнеров (отключаем)
      # statsdUdpAddress: aggregator:8126

      # выключаем поддержку опции Mutual TLS
      controlPlaneAuthPolicy: NONE

      # адрес, на котором будет слушать istio-pilot для того, чтобы сообщать информацию о service discovery всем sidecar контейнерам
      discoveryAddress: istio-pilot.istio-system:15007

所有主要控制组件(控制平面)都将位于 Kubernetes 中的命名空间 istio-system 中。

至少,我们只需要部署Pilot。 为此,我们将使用 这样的配置。

我们将手动配置容器的注入 sidecar。

初始化容器:

initContainers:
 - name: istio-init
   args:
   - -p
   - "15001"
   - -u
   - "1337"
   - -m
   - REDIRECT
   - -i
   - '*'
   - -b
   - '*'
   - -d
   - ""
   image: istio/proxy_init:1.0.0
   imagePullPolicy: IfNotPresent
   resources:
     limits:
       memory: 128Mi
   securityContext:
     capabilities:
       add:
       - NET_ADMIN

还有边车:

       name: istio-proxy
       args:
         - "bash"
         - "-c"
         - |
           exec /usr/local/bin/pilot-agent proxy sidecar 
           --configPath 
           /etc/istio/proxy 
           --binaryPath 
           /usr/local/bin/envoy 
           --serviceCluster 
           service-name 
           --drainDuration 
           45s 
           --parentShutdownDuration 
           1m0s 
           --discoveryAddress 
           istio-pilot.istio-system:15007 
           --discoveryRefreshDelay 
           1s 
           --connectTimeout 
           10s 
           --proxyAdminPort 
           "15000" 
           --controlPlaneAuthPolicy 
           NONE
         env:
         - name: POD_NAME
           valueFrom:
             fieldRef:
               fieldPath: metadata.name
         - name: POD_NAMESPACE
           valueFrom:
             fieldRef:
               fieldPath: metadata.namespace
         - name: INSTANCE_IP
           valueFrom:
             fieldRef:
               fieldPath: status.podIP
         - name: ISTIO_META_POD_NAME
           valueFrom:
             fieldRef:
               fieldPath: metadata.name
         - name: ISTIO_META_INTERCEPTION_MODE
           value: REDIRECT
         image: istio/proxyv2:1.0.0
         imagePullPolicy: IfNotPresent
         resources:
           requests:
             cpu: 100m
             memory: 128Mi
           limits:
             memory: 2048Mi
         securityContext:
           privileged: false
           readOnlyRootFilesystem: true
           runAsUser: 1337
         volumeMounts:
         - mountPath: /etc/istio/proxy
           name: istio-envoy

为了一切能够成功启动,需要为Pilot创建ServiceAccount、ClusterRole、ClusterRoleBinding、CRD,其说明可以参见 这里.

因此,我们用 Envoy 注入 sidecar 的服务应该成功启动,接收来自 Pilot 的所有发现并处理请求。

重要的是要了解所有控制平面组件都是无状态应用程序,并且可以毫无问题地水平扩展。 所有数据都以 Kubernetes 资源的自定义描述的形式存储在 etcd 中。

此外,Istio(仍处于实验阶段)能够在集群外运行,并且能够监视和摸索多个 Kubernetes 集群之间的服务发现。 您可以阅读更多相关内容 这里.

对于多集群安装,请注意以下限制:

  1. Pod CIDR 和 Service CIDR 在所有集群中必须是唯一的,并且不得重叠。
  2. 所有 CIDR Pod 必须可从集群之间的任何 CIDR Pod 访问。
  3. 所有 Kubernetes API 服务器必须可以相互访问。

这是帮助您开始使用 Istio 的初始信息。 然而,仍然存在很多陷阱。 例如,路由外部流量(集群外部)的功能、调试 sidecar 的方法、分析、设置混合器和编写自定义混合器后端、设置跟踪机制及其使用 envoy 的操作。
所有这些我们将在以下出版物中考虑。 提出你的问题,我会尽力解答。

来源: habr.com

添加评论