k8s 1.8下安装 istio 0.8 手动注入Envoy容器有问题

szihai 回复了问题 • 2 人关注 • 1 个回复 • 149 次浏览 • 2 天前 • 来自相关话题

service mesh istio 小实验

will835559313 发表了文章 • 0 个评论 • 558 次浏览 • 2018-06-18 17:57 • 来自相关话题

service mesh 入门实验

1.使用vagrant快速搭建linux实验环境
http://www.maogx.win/posts/20/

2.安装配置k8s(kubernetes)集群
http://www.maogx.win/posts/15/
http://www.maogx.win/posts/16/

3.istio安装测试
http://www.maogx.win/posts/24/

4.istio微服务实验
http://www.maogx.win/posts/25/

5.istio微服务实验之监控日志与可视化
http://www.maogx.win/posts/26/ 
 
6.istio-0.8长期支持版安装测试
http://www.maogx.win/posts/30/
 
7.istio-0.8长期支持版微服务实验
http://www.maogx.win/posts/31/
  查看全部
service mesh 入门实验

1.使用vagrant快速搭建linux实验环境
http://www.maogx.win/posts/20/

2.安装配置k8s(kubernetes)集群
http://www.maogx.win/posts/15/
http://www.maogx.win/posts/16/

3.istio安装测试
http://www.maogx.win/posts/24/

4.istio微服务实验
http://www.maogx.win/posts/25/

5.istio微服务实验之监控日志与可视化
http://www.maogx.win/posts/26/ 
 
6.istio-0.8长期支持版安装测试
http://www.maogx.win/posts/30/
 
7.istio-0.8长期支持版微服务实验
http://www.maogx.win/posts/31/
 

如何用Istio做一个前后端分离的博客?

sunshinexs 回复了问题 • 2 人关注 • 1 个回复 • 847 次浏览 • 2018-05-08 10:42 • 来自相关话题

istio 配置生效流程及源码简介

fudali 发表了文章 • 0 个评论 • 685 次浏览 • 2018-04-24 13:13 • 来自相关话题

istio 配置生效流程及源码简介

使用Istio微服务框架,业务逻辑写在哪里?有规定用什么语言写吗?

Online 回复了问题 • 2 人关注 • 1 个回复 • 1015 次浏览 • 2018-04-22 01:11 • 来自相关话题

微服务前方有雷,服务网格帮你趟过通信安全这个坑!

小数 发表了文章 • 0 个评论 • 686 次浏览 • 2018-04-19 18:14 • 来自相关话题

翻译:狄卫华 (博客地址 : https://blog.do1618.com)

作者:Christian Posta

原文:How a Service Mesh Can Help With Microservices Security

地址:http://blog.christianposta.com ... rity/




导读:

我看到很多客户转向微服务(他们是否应该是另外一个帖子的主题(注1)),他们试图通过这种方式解决一些组织化的规模问题。但是,转向微服务架构的细节往往会为旧问题带来一些新问题。


我与之交谈的大多数客户采用一种策略:架构上既有内部部署,也有公有云部署。将应用程序分解为更小的服务并拥有多个部署站点/平台会带来一些更大的挑战。在我看来,像 Istio 这样的服务网格实现旨在解决这些挑战中的一些问题。对于 Istio 和 Service Mesh ,我确实有很多话要说(注2),所以请随时关注@christianposta(注3) 参与并跟踪最新状态。



在微服务化的过程中你将面临的一个挑战是:安全


我知道,作为开发人员,你可能已经对安全非常憎恨——微服务使其更加糟糕。当我们将应用程序分解为更小的服务时,我们会增加被攻击的范围。虽然这有很多安全方面的问题(应用程序漏洞,平台漏洞,数据保护,传输/网络等),但在本文中我将主要集中在微服务如何相互通信以及其出现的一些问题上。


传统上,我们认为网络边界足以保护我们;我们的应用程序在传输安全方面的问题不必考虑太多,因为我们处于 ”受保护的内部网络“。停下来思考一下,你是否使用 SSL/TLS 保护你的内部应用程序?


我们以前通过单体程序本地调用的所有通信都将暴露在开放的网络中。首先我们要做的就是加密所有的内部流量。如果你在实施微服务上没有使用 TLS 进行传输加密,那么你正在将面临着令人讨厌的安全问题。


部分成熟的客户已经实现了所有微服务通信加密,这并没有带来显著成本提升。搭建公钥基础设施、签发密钥和证书、安装、轮换等都是非常大的考验。尝试配置正确的信任库/密钥库(Java)、合适的SSL算法、确保拥有正确的证书链等都是让人感到头痛的事情。我个人试图让其能够正常工作浪费了很多天 。然后当其都能正常工作以后,你就不会再想去折腾它。


我也看到了开发人员使用了 SSL/TLS,然后将其代码部署到 IST/UAT 等测试环境中,但是最终发现相关的安全配置在底层环境中不能够正常工作;由于着急将产品部署到生产环境中,他们会执行诸如禁用 TLS 验证的操作。


像 Istio 这样的服务网格相当简化了这一点。借助 Istio,应用程序的所有实例都有自己的 Sidecar 容器。该 Sidecar 充当所有流入和流出网络通信的服务代理。


在使用服务代理可以获得的诸多好处(注4),与此文讨论相关的好处是能够透明地进行 TLS 加密。这意味着位于与应用程序请求路径中的代理承担了加密流量的责任。你的应用程序可以完全不用关心证书,信任库,密钥库等问题。 Istio 自动将证书和密钥关联到服务,代理使用它们来加密流量(提供双向TLS),并且 Istio 定期轮换密钥/证书,以减少泄露的风险。


举例来说,当 Istio 运行在 Kubernetes 上时(注5),无论你何时部署应用程序,只需要指定一个应用程序运行的服务帐户,之后,Istio 负责处理其余部分。Istio 将为你的服务帐户创建证书/密钥对,使用根 CA密钥 对证书签名,并在将证书/密钥作为 Kubernets 中的密码。密码将被挂载到你的应用程序和 Istio 服务代理运行的 Pod 中,代理将使用证书/密钥来建立双向 TLS。


微服务的另一个安全问题是责任混淆问题(注6)。在这种情况下,终端用户已经授权服务代表它做某件事。在这种情况下,服务可能被授权执行此操作,但特定用户可能不会。我们应该以某种方式将用户身份绑定,并基于身份来评估授权。方法之一就是使用像 JWT (注7) 的令牌。


相关的有以下几点:


首先,如果你传递明文的 JWT 令牌(不使用TLS/mTLS),那么你会遇到比较大的麻烦。令牌默认不进行加密(仅签名),他们很容易地被收集并重放(replay)到服务中。再次,这是 Istio mTLS 可以提供帮助的地方。但即使启用了 mTLS,令牌也可能以被其他的方式泄露(我看到令牌被硬编码到源代码中!)。如果你的所有服务都将 JWT 传递给其他所有服务,那么您将再次面临重放攻击问题。


其次,如果你试图在所有微服务器上进行 JWT 验证,则会遇到与弹性库相同的问题(注8)。每个服务都有自己的库和自己的 JWT 验证实现。尽管像 JBoss Keycloak(注9) 这样的项目提供了出色的多语言支持,但它对库维护人员以及依赖这些库的应用程序开发人员来说都是一种负担。确保它们全部实施正确,一致并统一是一个充满了问题的壮举。


值得庆幸的是,Istio 可以在这两个方面提供帮助。

首先,无论应用程序框架/语言如何,Istio 都可以为你自动进行 JWT 验证。你可以定义一个`EndUserAuthenticationPolicySpec`,它配置了将用于验证的身份/凭证提供者(注10):


---  apiVersion: config.istio.io/v1alpha2  kind: EndUserAuthenticationPolicySpec  metadata:        name: cars-api-auth-policy       namespace: tutorial  spec:        jwts:            - issuer: http://keycloak:8080/auth/realms/istio               jwks_uri: http://keycloak.tutorial:8080/ ... certs               audiences:                - cars-web然后你可以将它绑定到特定的服务:---   apiVersion: config.istio.io/v1alpha2  kind: EndUserAuthenticationPolicySpecBinding  metadata:       name: cars-api-auth-policy-binding       namespace: tutorial spec:       policies:         - name: cars-api-auth-policy             namespace: tutorial    services:         - name: cars-api             namespace: tutorial
 
注意:这个例子来自我的同事 Kamesh Sampath(注11)。在这个配置中,我们已经建立了 `Keycloak` 成为 JWT 令牌的身份管理者和发行者(遵循OpenID Connect)。有关更多信息,请参阅此博客(注12)。当请求进入服务时,如果它没有 JWT 持票人令牌,它将被拒绝。这个配置将安装 EnvoyJWT 过滤器(注13),该过滤器负责验证 JWT 的签名:



最后,JWT 令牌是如何地传播?


Istio 默认只会将 JWT 令牌传播一次,使用 JWT 令牌的主体,并将其传递到应用程序通过单独的 header 字段。 JWT 主体将通过 header 头部中的 `sec-istio-auth-userinfo` 携带信息。基于终端用户的身份和服务的身份,应用程序有责任重新提交新的令牌。通过这种方式,我们可以将令牌的范围限定为单次使用,而不是将 JWT 到处传播。对此的实施仍在发展中,我强烈建议遵循这里 (注14) 和这里(注15)。


现在就是这样。随着 Istio 内部安全性的加强,我会进一步跟进。关注我@christianposta (注16) 获取微服务,服务网格,Istio 等最新信息。



注:

1:http://blog.christianposta.com ... ices/

2:http://blog.christianposta.com/

3:https://twitter.com/christianposta

4:https://istio.io/docs/concepts ... .html

5:https://istio.io/docs/setup/ku ... .html

6:https://en.wikipedia.org/wiki/ ... oblem

7:https://jwt.io/

8:http://blog.christianposta.com ... ices/

9:http://www.keycloak.org/

10:https://istio.io/docs/referenc ... ySpec

11:https://twitter.com/kamesh_sampath

12:http://blog.keycloak.org/2018/ ... .html

13:https://github.com/istio/proxy ... ME.md

14:https://docs.google.com/docume ... lmyhf

15:https://docs.google.com/docume ... lmyhf

16:https://twitter.com/christianposta


  查看全部
翻译:狄卫华 (博客地址 : https://blog.do1618.com

作者:Christian Posta

原文:How a Service Mesh Can Help With Microservices Security

地址:http://blog.christianposta.com ... rity/




导读:

我看到很多客户转向微服务(他们是否应该是另外一个帖子的主题(注1)),他们试图通过这种方式解决一些组织化的规模问题。但是,转向微服务架构的细节往往会为旧问题带来一些新问题。


我与之交谈的大多数客户采用一种策略:架构上既有内部部署,也有公有云部署。将应用程序分解为更小的服务并拥有多个部署站点/平台会带来一些更大的挑战。在我看来,像 Istio 这样的服务网格实现旨在解决这些挑战中的一些问题。对于 Istio 和 Service Mesh ,我确实有很多话要说(注2),所以请随时关注@christianposta(注3) 参与并跟踪最新状态。



在微服务化的过程中你将面临的一个挑战是:安全


我知道,作为开发人员,你可能已经对安全非常憎恨——微服务使其更加糟糕。当我们将应用程序分解为更小的服务时,我们会增加被攻击的范围。虽然这有很多安全方面的问题(应用程序漏洞,平台漏洞,数据保护,传输/网络等),但在本文中我将主要集中在微服务如何相互通信以及其出现的一些问题上。


传统上,我们认为网络边界足以保护我们;我们的应用程序在传输安全方面的问题不必考虑太多,因为我们处于 ”受保护的内部网络“。停下来思考一下,你是否使用 SSL/TLS 保护你的内部应用程序?


我们以前通过单体程序本地调用的所有通信都将暴露在开放的网络中。首先我们要做的就是加密所有的内部流量。如果你在实施微服务上没有使用 TLS 进行传输加密,那么你正在将面临着令人讨厌的安全问题。


部分成熟的客户已经实现了所有微服务通信加密,这并没有带来显著成本提升。搭建公钥基础设施、签发密钥和证书、安装、轮换等都是非常大的考验。尝试配置正确的信任库/密钥库(Java)、合适的SSL算法、确保拥有正确的证书链等都是让人感到头痛的事情。我个人试图让其能够正常工作浪费了很多天 。然后当其都能正常工作以后,你就不会再想去折腾它。


我也看到了开发人员使用了 SSL/TLS,然后将其代码部署到 IST/UAT 等测试环境中,但是最终发现相关的安全配置在底层环境中不能够正常工作;由于着急将产品部署到生产环境中,他们会执行诸如禁用 TLS 验证的操作。


像 Istio 这样的服务网格相当简化了这一点。借助 Istio,应用程序的所有实例都有自己的 Sidecar 容器。该 Sidecar 充当所有流入和流出网络通信的服务代理。


在使用服务代理可以获得的诸多好处(注4),与此文讨论相关的好处是能够透明地进行 TLS 加密。这意味着位于与应用程序请求路径中的代理承担了加密流量的责任。你的应用程序可以完全不用关心证书,信任库,密钥库等问题。 Istio 自动将证书和密钥关联到服务,代理使用它们来加密流量(提供双向TLS),并且 Istio 定期轮换密钥/证书,以减少泄露的风险。


举例来说,当 Istio 运行在 Kubernetes 上时(注5),无论你何时部署应用程序,只需要指定一个应用程序运行的服务帐户,之后,Istio 负责处理其余部分。Istio 将为你的服务帐户创建证书/密钥对,使用根 CA密钥 对证书签名,并在将证书/密钥作为 Kubernets 中的密码。密码将被挂载到你的应用程序和 Istio 服务代理运行的 Pod 中,代理将使用证书/密钥来建立双向 TLS。


微服务的另一个安全问题是责任混淆问题(注6)。在这种情况下,终端用户已经授权服务代表它做某件事。在这种情况下,服务可能被授权执行此操作,但特定用户可能不会。我们应该以某种方式将用户身份绑定,并基于身份来评估授权。方法之一就是使用像 JWT (注7) 的令牌。


相关的有以下几点:


首先,如果你传递明文的 JWT 令牌(不使用TLS/mTLS),那么你会遇到比较大的麻烦。令牌默认不进行加密(仅签名),他们很容易地被收集并重放(replay)到服务中。再次,这是 Istio mTLS 可以提供帮助的地方。但即使启用了 mTLS,令牌也可能以被其他的方式泄露(我看到令牌被硬编码到源代码中!)。如果你的所有服务都将 JWT 传递给其他所有服务,那么您将再次面临重放攻击问题。


其次,如果你试图在所有微服务器上进行 JWT 验证,则会遇到与弹性库相同的问题(注8)。每个服务都有自己的库和自己的 JWT 验证实现。尽管像 JBoss Keycloak(注9) 这样的项目提供了出色的多语言支持,但它对库维护人员以及依赖这些库的应用程序开发人员来说都是一种负担。确保它们全部实施正确,一致并统一是一个充满了问题的壮举。


值得庆幸的是,Istio 可以在这两个方面提供帮助。

首先,无论应用程序框架/语言如何,Istio 都可以为你自动进行 JWT 验证。你可以定义一个`EndUserAuthenticationPolicySpec`,它配置了将用于验证的身份/凭证提供者(注10):


---  apiVersion: config.istio.io/v1alpha2  kind: EndUserAuthenticationPolicySpec  metadata:        name: cars-api-auth-policy       namespace: tutorial  spec:        jwts:            - issuer: http://keycloak:8080/auth/realms/istio               jwks_uri: http://keycloak.tutorial:8080/ ... certs               audiences:                - cars-web然后你可以将它绑定到特定的服务:---   apiVersion: config.istio.io/v1alpha2  kind: EndUserAuthenticationPolicySpecBinding  metadata:       name: cars-api-auth-policy-binding       namespace: tutorial spec:       policies:         - name: cars-api-auth-policy             namespace: tutorial    services:         - name: cars-api             namespace: tutorial
 
注意:这个例子来自我的同事 Kamesh Sampath(注11)。在这个配置中,我们已经建立了 `Keycloak` 成为 JWT 令牌的身份管理者和发行者(遵循OpenID Connect)。有关更多信息,请参阅此博客(注12)。当请求进入服务时,如果它没有 JWT 持票人令牌,它将被拒绝。这个配置将安装 EnvoyJWT 过滤器(注13),该过滤器负责验证 JWT 的签名:



最后,JWT 令牌是如何地传播?


Istio 默认只会将 JWT 令牌传播一次,使用 JWT 令牌的主体,并将其传递到应用程序通过单独的 header 字段。 JWT 主体将通过 header 头部中的 `sec-istio-auth-userinfo` 携带信息。基于终端用户的身份和服务的身份,应用程序有责任重新提交新的令牌。通过这种方式,我们可以将令牌的范围限定为单次使用,而不是将 JWT 到处传播。对此的实施仍在发展中,我强烈建议遵循这里 (注14) 和这里(注15)。


现在就是这样。随着 Istio 内部安全性的加强,我会进一步跟进。关注我@christianposta (注16) 获取微服务,服务网格,Istio 等最新信息。



注:

1:http://blog.christianposta.com ... ices/

2:http://blog.christianposta.com/

3:https://twitter.com/christianposta

4:https://istio.io/docs/concepts ... .html

5:https://istio.io/docs/setup/ku ... .html

6:https://en.wikipedia.org/wiki/ ... oblem

7:https://jwt.io/

8:http://blog.christianposta.com ... ices/

9:http://www.keycloak.org/

10:https://istio.io/docs/referenc ... ySpec

11:https://twitter.com/kamesh_sampath

12:http://blog.keycloak.org/2018/ ... .html

13:https://github.com/istio/proxy ... ME.md

14:https://docs.google.com/docume ... lmyhf

15:https://docs.google.com/docume ... lmyhf

16:https://twitter.com/christianposta


 

示例说明 | 想要正确使用Istio?这份sidecar说明书必不可少

小数 发表了文章 • 0 个评论 • 880 次浏览 • 2018-04-03 10:49 • 来自相关话题

作者:宋净超(Jimmy Song),Kubernetes、Cloud Native布道者、开源爱好者,个人博客https://jimmysong.io



我们知道 Istio 通过向 Pod 中注入一个 sidecar 容器来将 Pod 纳入到 Istio service mesh 中的,那么这些 sidecar 容器的注入遵循什么样的规范,需要给每个 Pod 增加哪些配置信息才能纳入 Istio service mesh 中呢?这篇文章将给您答案。


本文同时归档到 kubernetes-handbook中(注1),更新请以handbook为准。



Pod Spec 中需满足的条件

为了成为 Service Mesh 中的一部分,kubernetes 集群中的每个 Pod 都必须满足如下条件,这些规范不是由 Istio 自动注入的,而需要 生成 kubernetes 应用部署的 YAML 文件时需要遵守的:
Service 关联:每个 pod 都必须只属于某一个 Kubernetes Service(注2) (当前不支持一个 pod 同时属于多个 service)。命名的端口:Service 的端口必须命名。端口的名字必须遵循如下格式 <protocol>[-<suffix>],可以是 http、http2、 grpc、 mongo、 或者 redis 作为 <protocol> ,这样才能使用 Istio 的路由功能。例如 name: http2-foo 和 name: http 都是有效的端口名称,而 name: http2foo 不是。如果端口的名称是不可识别的前缀或者未命名,那么该端口上的流量就会作为普通的 TCP 流量来处理(除非使用 Protocol: UDP 明确声明使用 UDP 端口)。带有 app label 的 Deployment:我们建议 kubernetes 的Deploymenet 资源的配置文件中为 Pod 明确指定 applabel。每个 Deployment 的配置中都需要有个与其他 Deployment 不同的含有意义的 app label。app label 用于在分布式追踪中添加上下文信息。Mesh 中的每个 pod 里都有一个 Sidecar:最后,Mesh 中的每个 pod 都必须运行与 Istio 兼容的 sidecar。以下部分介绍了将 sidecar 注入到 pod 中的两种方法:使用istioctl 命令行工具手动注入,或者使用 Istio Initializer 自动注入。注意 sidecar 不涉及到流量,因为它们与容器位于同一个 pod 中。



将普通应用添加到 Istio service mesh 中

Istio 官方的示例 Bookinfo(注3)中并没有讲解如何将服务集成 Istio,只给出了 YAML 配置文件,而其中需要注意哪些地方都没有说明,假如我们自己部署的服务如何使用 Istio 呢?现在我们有如下两个普通应用(代码在 GitHub 上),它们都不具备微服务的高级特性,比如限流和熔断等,通过将它们部署到 kubernetes 并使用 Istio 来管理:
k8s-app-monitor-test:用来暴露 json 格式的 metricsk8s-app-monitor-agent:访问上面那个应用暴露的 metrics 并生成监控图


这两个应用的 YAML 配置如下,其中包含了 Istio ingress 配置,并且符合 Istio 对 Pod 的 spec 配置所指定的规范。


k8s-app-monitor-istio-all-in-one.yaml文件


apiVersion: extensions/v1beta1kind: Deploymentmetadata:

  annotations:

    kompose.cmd: kompose convert -f docker-compose.yaml    kompose.version: 1.10.0 ()  creationTimestamp: null

  labels:

    app: k8s-app-monitor-agent  name: k8s-app-monitor-agentspec:

  replicas: 1

  template:

    metadata:

      creationTimestamp: null

      labels:

        app: k8s-app-monitor-agent    spec:

      containers:

      - env:

        - name: SERVICE_NAME          value: k8s-app-monitor-test        image: jimmysong/k8s-app-monitor-agent:749f547        name: monitor-agent        ports:

        - containerPort: 8888

      restartPolicy: Always---apiVersion: v1kind: Servicemetadata:

  annotations:

    kompose.cmd: kompose convert -f docker-compose.yaml    kompose.version: 1.10.0 ()  creationTimestamp: null

  labels:

    app: k8s-app-monitor-agent  name: k8s-app-monitor-agentspec:

  ports:

  - name: "http"

    port: 8888

    targetPort: 8888

  selector:

    app: k8s-app-monitor-agent---apiVersion: extensions/v1beta1kind: Deploymentmetadata:

  annotations:

    kompose.cmd: kompose convert -f docker-compose.yaml    kompose.version: 1.10.0 ()  creationTimestamp: null

  labels:

    app: k8s-app-monitor-test  name: k8s-app-monitor-testspec:

  replicas: 1

  template:

    metadata:

      creationTimestamp: null

      labels:

        app: k8s-app-monitor-test    spec:

      containers:

      - image: jimmysong/k8s-app-monitor-test:9c935dd        name: monitor-test        ports:

        - containerPort: 3000

      restartPolicy: Always---apiVersion: v1kind: Servicemetadata:

  annotations:

    kompose.cmd: kompose convert -f docker-compose.yaml    kompose.version: 1.10.0 ()  creationTimestamp: null

  labels:

    app: k8s-app-monitor-test  name: k8s-app-monitor-testspec:

  ports:

  - name: "http"

    port: 3000

    targetPort: 3000

  selector:

    app: k8s-app-monitor-test---## Istio ingressapiVersion: extensions/v1beta1kind: Ingressmetadata:

  name: k8s-app-monitor-agent-ingress  annotations:

    kubernetes.io/ingress.class: "istio"spec:

  rules:

  - http:

      paths:

      - path: /k8s-app-monitor-agent        backend:

          serviceName: k8s-app-monitor-agent          servicePort: 8888


其中有两点配置需要注意。


Deployment 和 Service 中的 label 名字必须包含 app,zipkin 中的 tracing 需要使用到这个标签才能追踪

Service 中的 ports 配置和必须包含一个名为 http 的 port,这样在 Istio ingress 中才能暴露该服务


注意:该 YAML 文件中 annotations 是因为我们一开始使用 docker-compose 部署在本地开发测试,后来再使用 kompose 将其转换为 kubernetes 可识别的 YAML 文件。

然后执行下面的命令就可以基于以上的 YAML 文件注入 sidecar 配置并部署到 kubernetes 集群中。


kubectl apply -n default -f <(istioctl kube-inject -f manifests/istio/k8s-app-monitor-istio-all-in-one.yaml)


如何在本地启动 kubernetes 集群进行测试可以参考 kubernetes-vagrant-centos-cluster 中的说明(注4)。



Sidecar 注入说明


手动注入需要修改控制器的配置文件,如 deployment。通过修改 deployment 文件中的 pod 模板规范可实现该deployment 下创建的所有 pod 都注入 sidecar。添加/更新/删除 sidecar 需要修改整个 deployment。


自动注入会在 pod 创建的时候注入 sidecar,无需更改控制器资源。Sidecar 可通过以下方式更新:


手动选择删除 pod

系统得进行 deployment 滚动更新


手动或者自动注入都使用同样的模板配置。自动注入会从 istio-system 命名空间下获取 istio-inject 的 ConfigMap。手动注入可以通过本地文件或者 Configmap 。



参考

Installing Istio Sidecar(注5)


注:

1、https://jimmysong.io/kubernetes-handbook/

2、https://kubernetes.io/docs/con ... vice/

3、https://istio.io/docs/guides/bookinfo.html

4、https://github.com/rootsongjc/ ... uster

5、https://istio.io/docs/setup/ku ... .html
  查看全部
作者:宋净超(Jimmy Song),Kubernetes、Cloud Native布道者、开源爱好者,个人博客https://jimmysong.io



我们知道 Istio 通过向 Pod 中注入一个 sidecar 容器来将 Pod 纳入到 Istio service mesh 中的,那么这些 sidecar 容器的注入遵循什么样的规范,需要给每个 Pod 增加哪些配置信息才能纳入 Istio service mesh 中呢?这篇文章将给您答案。


本文同时归档到 kubernetes-handbook中(注1),更新请以handbook为准。



Pod Spec 中需满足的条件

为了成为 Service Mesh 中的一部分,kubernetes 集群中的每个 Pod 都必须满足如下条件,这些规范不是由 Istio 自动注入的,而需要 生成 kubernetes 应用部署的 YAML 文件时需要遵守的:
  1. Service 关联:每个 pod 都必须只属于某一个 Kubernetes Service(注2) (当前不支持一个 pod 同时属于多个 service)。
  2. 命名的端口:Service 的端口必须命名。端口的名字必须遵循如下格式 <protocol>[-<suffix>],可以是 http、http2、 grpc、 mongo、 或者 redis 作为 <protocol> ,这样才能使用 Istio 的路由功能。例如 name: http2-foo 和 name: http 都是有效的端口名称,而 name: http2foo 不是。如果端口的名称是不可识别的前缀或者未命名,那么该端口上的流量就会作为普通的 TCP 流量来处理(除非使用 Protocol: UDP 明确声明使用 UDP 端口)。
  3. 带有 app label 的 Deployment:我们建议 kubernetes 的Deploymenet 资源的配置文件中为 Pod 明确指定 applabel。每个 Deployment 的配置中都需要有个与其他 Deployment 不同的含有意义的 app label。app label 用于在分布式追踪中添加上下文信息。
  4. Mesh 中的每个 pod 里都有一个 Sidecar:最后,Mesh 中的每个 pod 都必须运行与 Istio 兼容的 sidecar。以下部分介绍了将 sidecar 注入到 pod 中的两种方法:使用istioctl 命令行工具手动注入,或者使用 Istio Initializer 自动注入。注意 sidecar 不涉及到流量,因为它们与容器位于同一个 pod 中。




将普通应用添加到 Istio service mesh 中

Istio 官方的示例 Bookinfo(注3)中并没有讲解如何将服务集成 Istio,只给出了 YAML 配置文件,而其中需要注意哪些地方都没有说明,假如我们自己部署的服务如何使用 Istio 呢?现在我们有如下两个普通应用(代码在 GitHub 上),它们都不具备微服务的高级特性,比如限流和熔断等,通过将它们部署到 kubernetes 并使用 Istio 来管理:
  • k8s-app-monitor-test:用来暴露 json 格式的 metrics
  • k8s-app-monitor-agent:访问上面那个应用暴露的 metrics 并生成监控图



这两个应用的 YAML 配置如下,其中包含了 Istio ingress 配置,并且符合 Istio 对 Pod 的 spec 配置所指定的规范。


k8s-app-monitor-istio-all-in-one.yaml文件


apiVersion: extensions/v1beta1kind: Deploymentmetadata:

  annotations:

    kompose.cmd: kompose convert -f docker-compose.yaml    kompose.version: 1.10.0 ()  creationTimestamp: null

  labels:

    app: k8s-app-monitor-agent  name: k8s-app-monitor-agentspec:

  replicas: 1

  template:

    metadata:

      creationTimestamp: null

      labels:

        app: k8s-app-monitor-agent    spec:

      containers:

      - env:

        - name: SERVICE_NAME          value: k8s-app-monitor-test        image: jimmysong/k8s-app-monitor-agent:749f547        name: monitor-agent        ports:

        - containerPort: 8888

      restartPolicy: Always---apiVersion: v1kind: Servicemetadata:

  annotations:

    kompose.cmd: kompose convert -f docker-compose.yaml    kompose.version: 1.10.0 ()  creationTimestamp: null

  labels:

    app: k8s-app-monitor-agent  name: k8s-app-monitor-agentspec:

  ports:

  - name: "http"

    port: 8888

    targetPort: 8888

  selector:

    app: k8s-app-monitor-agent---apiVersion: extensions/v1beta1kind: Deploymentmetadata:

  annotations:

    kompose.cmd: kompose convert -f docker-compose.yaml    kompose.version: 1.10.0 ()  creationTimestamp: null

  labels:

    app: k8s-app-monitor-test  name: k8s-app-monitor-testspec:

  replicas: 1

  template:

    metadata:

      creationTimestamp: null

      labels:

        app: k8s-app-monitor-test    spec:

      containers:

      - image: jimmysong/k8s-app-monitor-test:9c935dd        name: monitor-test        ports:

        - containerPort: 3000

      restartPolicy: Always---apiVersion: v1kind: Servicemetadata:

  annotations:

    kompose.cmd: kompose convert -f docker-compose.yaml    kompose.version: 1.10.0 ()  creationTimestamp: null

  labels:

    app: k8s-app-monitor-test  name: k8s-app-monitor-testspec:

  ports:

  - name: "http"

    port: 3000

    targetPort: 3000

  selector:

    app: k8s-app-monitor-test---## Istio ingressapiVersion: extensions/v1beta1kind: Ingressmetadata:

  name: k8s-app-monitor-agent-ingress  annotations:

    kubernetes.io/ingress.class: "istio"spec:

  rules:

  - http:

      paths:

      - path: /k8s-app-monitor-agent        backend:

          serviceName: k8s-app-monitor-agent          servicePort: 8888


其中有两点配置需要注意。


Deployment 和 Service 中的 label 名字必须包含 app,zipkin 中的 tracing 需要使用到这个标签才能追踪

Service 中的 ports 配置和必须包含一个名为 http 的 port,这样在 Istio ingress 中才能暴露该服务


注意:该 YAML 文件中 annotations 是因为我们一开始使用 docker-compose 部署在本地开发测试,后来再使用 kompose 将其转换为 kubernetes 可识别的 YAML 文件。

然后执行下面的命令就可以基于以上的 YAML 文件注入 sidecar 配置并部署到 kubernetes 集群中。


kubectl apply -n default -f <(istioctl kube-inject -f manifests/istio/k8s-app-monitor-istio-all-in-one.yaml)


如何在本地启动 kubernetes 集群进行测试可以参考 kubernetes-vagrant-centos-cluster 中的说明(注4)。



Sidecar 注入说明


手动注入需要修改控制器的配置文件,如 deployment。通过修改 deployment 文件中的 pod 模板规范可实现该deployment 下创建的所有 pod 都注入 sidecar。添加/更新/删除 sidecar 需要修改整个 deployment。


自动注入会在 pod 创建的时候注入 sidecar,无需更改控制器资源。Sidecar 可通过以下方式更新:


手动选择删除 pod

系统得进行 deployment 滚动更新


手动或者自动注入都使用同样的模板配置。自动注入会从 istio-system 命名空间下获取 istio-inject 的 ConfigMap。手动注入可以通过本地文件或者 Configmap 。



参考

Installing Istio Sidecar(注5)


注:

1、https://jimmysong.io/kubernetes-handbook/

2、https://kubernetes.io/docs/con ... vice/

3、https://istio.io/docs/guides/bookinfo.html

4、https://github.com/rootsongjc/ ... uster

5、https://istio.io/docs/setup/ku ... .html
 

Istio服务网格高级流量镜像,7种模式解决流量镜像难题

小数 发表了文章 • 0 个评论 • 479 次浏览 • 2018-03-28 10:41 • 来自相关话题

作者:Christian Posta

翻译:吕德路 (https://github.com/lvdelu)

原文:Advanced Traffic-shadowing Patterns for Microservices With Istio Service Mesh



导言:


微服务可以加快系统开发速度和降低时间成本(注1)。然而,不能天真地认为只进行快速开发和变更就足够了(注2)。

如何在微服务中降低开发和变更的风险,Istio Service Mesh 提供了一种有助于降低将变更带入生产风险的方法,即将生产流量镜像到测试群集或软件的新版本中,并在我们引导实时流量之前针对问题进行测试。

这使我们能够将实际的用例和模糊的使用情况发送到我们的代码中,而我们在非生产模拟中的测试可能不会被捕获到。


在我以前的文章中,我写了关于 Istio Service Mesh 有一个非常棒的功能对流量进行镜像(注3)。对于 Istio 和 Service Mesh,我确实有很多话要说(注4),所以请随时关注@christianposta(注5)参与并保持查看最新的文章。

今天的主要课程是:



流量镜像的难题

当我们将生产流量镜像到测试集群、或生产中的灰度集群时,我们将会面临一些挑战。

首先,
如何在不影响生产服务关键路径的情况下获得生产集群的流量?
 
是否需要过滤掉这些请求中的个人信息?如何让测试集群不干扰实时协作者服务?如果服务对数据进行了更改,如何隔离这些更改而不影响生产服务?


这些都是真正的挑战,或许会被用作不尝试流量镜像的理由。但恕我直言,镜像代表了安全发布中更重要、更强大的技术之一,所以让我们看看有哪些模式来解决这些问题。如下所示:
 
在不影响生产关键路径的前提下将生产流量镜像到测试集群将流量定义为流量镜像镜像之后的实时服务流量与测试群集流量对比为某些测试配置文件提供协作服务合成事务虚拟化测试集群的数据库实现测试集群的数据库

让我们继续深入研究。



在不影响生产关键路径的前提下将生产流量镜像到测试集群

这可以说是最重要的部分。如果,在不影响生产流量的情况下,不能可靠地将流量镜像到测试群集,那么就应该停止。 不能为我们的“奇思妙想”牺牲生产的可靠性和可用性。 


通常我们会使用代理来镜像此流量。 Envoy Proxy(注6)是一个可用于此操作的代理。 Istio 是一种服务网格,它使用 Envoy 作为启用此功能的默认代理。有关更多信息,请参阅 Istio 镜像任务。


所以基本上,服务网格(Istio)已经位于我们生产流量的关键路径,以实现弹性,安全性,策略规划,路由控制等之间,并且还可以将流量镜像到我们的测试集群。 


事实上,这就是我在上一篇博客中深入探讨的内容(注7)。 重要的是来自生产中的流量通过带外数据被异步镜像。 任何响应都会被忽略。






对于熟悉所谓“企业集成模式”的读者(谢谢 Gregor Hohpe!),你会注意到这种“镜像”的东西实际上是一种 flavor 或 EIP(注8)。



将流量定义为流量镜像

另一个重要的考虑是识别我们已经镜像的流量。 我们需要能够辨别出用于测试目的的实时生产流量。 使用 Istio / Envoy 时,被镜像的的流量会自动用额外的上下文进行标记。


例如,当 Istio 镜像流量时,它会追加(注9)-shdow 到主机或者权限头中。 对于某些实现来说,目前这是一个问题,因-shadow将被添加到主机的末尾,所以 foobar:8080 的 Host 头将以这样的头部结尾:foobar:8080-shadow,这在技术上并非有效 HTTP 1.X。


在 Envoy 中使用此修复程序后(注10),-shadow 后缀将被添加到主机名,以便 foobar:8080 变成 foobar-shadow:8080。









镜像之后的实时服务流量与测试群集流量对比

一旦依赖流量镜像就可以做一些有趣的事情,也许我们希望通过进入测试集群的流量和我们从生产实时看到的期望行为进行对比。

例如,我们可能希望将预期的请求结果或API合同中任何偏离的请求结果与向前和向后兼容性进行比较。我们可以插入一个负责这种类型的流量协调的代理,以及一个可以进行有趣比较的代理。Twitter Diffy(注11)是这些代理中的一个,它已经在 Twitter 应用到了生产(注12),并且其它地方也将会这么做。它基本上需要镜像流量(感谢 Istio 和 Envoy,我们已经做到了这一点),并调用实时服务和新服务并比较结果。它能够检测结果中的 “noise” 并忽略它(时间戳,单调增加计数器等),通过首先调用两个实时服务实例来检测 “noise",然后忽略那些用于测试服务调用的部分。






Diffy 还有一个非常棒的网页/仪表板,用于查看调用结果,它们的差异以及基于特定特征的过滤。 最后,Diffy 有一个很好的管理控制台,用于查看关于调用比较的指标和统计数据。







我在这里有一个演示(注13),非常感谢 Prashant Khanduri,Puneet Khanduri 和 Alex Soto。 在我制作过程中,留意观看此演示视频。



为某些测试配置文件提供协作服务

当我们部署一个新版本的服务并将流量镜像到测试集群时,我们需要注意对其他环境的影响。我们的服务通常需要与其他服务协作(查询数据,更新数据等)。如果与其他服务的协作仅仅是读取或 GET 请求,并且这些协作者能够承担额外的负载,这可能不成问题。但是,如果我们的服务在我们的协作者中改变了数据,我们需要确保这些调用指向测试流量而不是真正的生产流量。你可以为你的部署创建不同的安装配置,从而注入这些配置。


例如,我们注入了 test.prod.com,而不是 live.prod.com 作为下游服务。如果在 Kubernetes上部署,则可以使用不同的 maps(注14)配置来控制此功能。


另一个有趣的方法是使用诸如 Hoverfly(注15)或 Microcks(注16)之类的东西部署虚拟化测试流量。使用这些服务虚拟化工具,你可以策划预期的请求/响应对,并将值发生变化的流量导向这些返回预期响应的代理。








合成事务


在很多情况下,我们服务的新版本需要改变其本地数据存储中的数据。它可能会向协作者服务发出调用来改变数据,但也许我们不能(或不应该)使用先前的技术(服务虚拟化)来存储这些调用。


另一种方法是更明确地通过调用(比如在我们之前添加的镜像模式中我们添加了-shadow)来表明这些请求应该再一个“合成事务”结果中,即,这些不是真正的事务,并且再它们在请求结束时应该采取任何补偿来撤消他们。我们可以为我们的请求添加一个头文件,或者甚至可以使其成为请求主体的一部分,以表明某个事务是“合成的”。当我们这样做时,我们正在指示参与服务正常处理请求,包括所有数据操作,然后在提交之前回滚事务。请注意,这适用于事务性数据存储,但可能不适用于其他数据存储。在这些情况下,如果你已经有工作单元的概念,则可以将合成语义附加到该语义上。否则,最好不要试图通过合成事务来隔离和放弃更改。  








这种方法对于执行全路径请求很有用,包括数据存储,获得更好的时序保真度和双测试方法可能捕捉不到的数据干扰/不匹配问题。


这种方法的一大缺点是它按惯例实施,难以执行。 它可能与你拥有和控制的服务一起工作,但可能无法扩展到许多参与协作的合作者。 你不愿意试图在所有服务中强制执行这个约定,并且有一个单独的服务不能正确地实现这个回滚功能,然后把所有的东西混淆起来。 在严格控制和协调部署中使用此模式。



虚拟化测试集群的数据库


在针对镜像流量进行测试时,我们已经开始涉及与处理数据相关的问题。通常,如果你的测试集群使用数据存储,并且测试服务以某种形式更新/插入/变更数据,则需要隔离这些更改。当用信头或嵌入式标志等信号发送时,我们只是简单地回滚任何更改,但这并不总是个办法。


在镜像流量时处理数据问题的另一种方法是为测试群集使用可替代的数据存储。你可以使用一个空的数据存储并使用测试数据填充它,并针对该数据运行镜像流量。但是,如果你使用的是像 Diffy(上面提到的)之类的东西,则可能会在响应比较中收到大量误报,因为测试群集中的数据正在使用测试数据,而实时服务正在使用生产数据。处理这个问题的一个好方法就是虚拟化数据层。我们让测试集群使用一个与生产数据存储相同数据的数据存储。






当我们这样做时,我们可以获得生产数据的当前一致视图,也可以在不影响生产数据存储的情况下写入数据存储。 我们可以使用像 JBoss Teiid(注17)这样的工具轻松完成此操作。 Teiid 为所有类型的数据存储系统提供连接器,包括 RDBMS,No-SQL 系统,平面文件,hadoop,salesforce 等,并且可以为我们的测试集群虚拟化它们。 当你这样做时,任何时候变更的数据可以一次性写入数据库而服务无感知。 我有一系列博客讨论了这篇关于微服务迁移的博客文章(注18)。


实现测试集群的数据库

最后,另一种扩展先前数据虚拟化技术的方法是完全实现数据存储。这样,我们测试集群的数据存储基本上与生产集群的数据存储相同,并且通过流处理不断更新。工作方式是使用(CDC - 更改数据捕获)(注19)从生产数据库捕获更改,然后将这些更改发送到新数据库。一些数据存储允许将其作为内置的复制机制(想想 MySQL 的从节点或者其他),但很多时候这些是只读的。你可以使用像Debezium(注20)这样的更改数据捕获工具来构建简单的 CDC 系统,以便你的测试数据存储具有完全复制的生产数据库副本并且不受约束的使用它。 


Debezium 为不同的数据存储提供连接器(注21),并从这些数据库中获取更改事件(即读取事务日志)并将这些更改传送到 Apache Kafka(注22)。从那里,你可以使用任何流处理工具将这些流实现到你的测试数据库中。 FWIW,上面提到的 Teiid(注23)很快就会有这个功能。






此外,如果你已经拥有数据流管道,使用事件驱动架构或使用某种事件源数据机制,那么这个“实现”测试数据库将成为更好的选择。




总结

在实践中,将生产流量镜像到我们的测试群集(无论该群集是存在于生产环境还是非生产环境中)是降低新部署风险的非常有效的方法。 


多年来,推特和亚马逊这样的大型 webops 公司一直在这样做。 这种方法带来了一些挑战,但是上述模式中讨论的方法存在有效的解决方案。 


如果你认为我错过了某些东西,或者觉得有一个我没有涉及到的令人讨厌的问题,请与我联系,我会很乐意与你讨论并将其添加到此博客的更新中。 谢谢!





1、https://www.slideshare.net/cep ... -2017

2、 https://www.cnet.com/news/zuck ... more/

3、http://blog.christianposta.com ... ease/

4、http://blog.christianposta.com/

5、https://twitter.com/christianposta

6、https://www.envoyproxy.io/docs ... olicy

7、http://blog.christianposta.com ... ease/

8、http://www.enterpriseintegrati ... .html

9、https://www.envoyproxy.io/docs ... olicy

10、https://github.com/envoyproxy/envoy/pull/2600

11、https://github.com/twitter/diffy

12、https://blog.twitter.com/engin ... .html

13、https://github.com/christian-p ... me.md

14、https://kubernetes.io/docs/tas ... gmap/

15、https://hoverfly.io/

16、 http://microcks.github.io/

17、http://teiid.jboss.org/

18、 http://blog.christianposta.com ... -iii/

19、https://en.wikipedia.org/wiki/Change_data_capture

20、http://debezium.io/

21、http://debezium.io/docs/

22、http://kafka.apache.org/

23、http://teiid.jboss.org/ 



社区活动:

3月31日(周六),数人云联合ServiceComb社区,并由ServiceMesh社区支持,开启meetup系列活动 Building Microservice 第2期 北京站 :微服务,从架构到发布,已经开始报名啦,扫码报名!
 





  查看全部
作者:Christian Posta

翻译:吕德路 (https://github.com/lvdelu)

原文:Advanced Traffic-shadowing Patterns for Microservices With Istio Service Mesh



导言:


微服务可以加快系统开发速度和降低时间成本(注1)。然而,不能天真地认为只进行快速开发和变更就足够了(注2)。

如何在微服务中降低开发和变更的风险,Istio Service Mesh 提供了一种有助于降低将变更带入生产风险的方法,即将生产流量镜像到测试群集或软件的新版本中,并在我们引导实时流量之前针对问题进行测试。

这使我们能够将实际的用例和模糊的使用情况发送到我们的代码中,而我们在非生产模拟中的测试可能不会被捕获到。


在我以前的文章中,我写了关于 Istio Service Mesh 有一个非常棒的功能对流量进行镜像(注3)。对于 Istio 和 Service Mesh,我确实有很多话要说(注4),所以请随时关注@christianposta(注5)参与并保持查看最新的文章。

今天的主要课程是:



流量镜像的难题

当我们将生产流量镜像到测试集群、或生产中的灰度集群时,我们将会面临一些挑战。

首先,
  • 如何在不影响生产服务关键路径的情况下获得生产集群的流量?

 
  • 是否需要过滤掉这些请求中的个人信息?
  • 如何让测试集群不干扰实时协作者服务?
  • 如果服务对数据进行了更改,如何隔离这些更改而不影响生产服务?



这些都是真正的挑战,或许会被用作不尝试流量镜像的理由。但恕我直言,镜像代表了安全发布中更重要、更强大的技术之一,所以让我们看看有哪些模式来解决这些问题。如下所示:
 
  • 在不影响生产关键路径的前提下将生产流量镜像到测试集群
  • 将流量定义为流量镜像
  • 镜像之后的实时服务流量与测试群集流量对比
  • 为某些测试配置文件提供协作服务
  • 合成事务
  • 虚拟化测试集群的数据库
  • 实现测试集群的数据库


让我们继续深入研究。



在不影响生产关键路径的前提下将生产流量镜像到测试集群

这可以说是最重要的部分。如果,在不影响生产流量的情况下,不能可靠地将流量镜像到测试群集,那么就应该停止。 不能为我们的“奇思妙想”牺牲生产的可靠性和可用性。 


通常我们会使用代理来镜像此流量。 Envoy Proxy(注6)是一个可用于此操作的代理。 Istio 是一种服务网格,它使用 Envoy 作为启用此功能的默认代理。有关更多信息,请参阅 Istio 镜像任务。


所以基本上,服务网格(Istio)已经位于我们生产流量的关键路径,以实现弹性,安全性,策略规划,路由控制等之间,并且还可以将流量镜像到我们的测试集群。 


事实上,这就是我在上一篇博客中深入探讨的内容(注7)。 重要的是来自生产中的流量通过带外数据被异步镜像。 任何响应都会被忽略。

1.png


对于熟悉所谓“企业集成模式”的读者(谢谢 Gregor Hohpe!),你会注意到这种“镜像”的东西实际上是一种 flavor 或 EIP(注8)。



将流量定义为流量镜像

另一个重要的考虑是识别我们已经镜像的流量。 我们需要能够辨别出用于测试目的的实时生产流量。 使用 Istio / Envoy 时,被镜像的的流量会自动用额外的上下文进行标记。


例如,当 Istio 镜像流量时,它会追加(注9)-shdow 到主机或者权限头中。 对于某些实现来说,目前这是一个问题,因-shadow将被添加到主机的末尾,所以 foobar:8080 的 Host 头将以这样的头部结尾:foobar:8080-shadow,这在技术上并非有效 HTTP 1.X。


在 Envoy 中使用此修复程序后(注10),-shadow 后缀将被添加到主机名,以便 foobar:8080 变成 foobar-shadow:8080。


2.png




镜像之后的实时服务流量与测试群集流量对比

一旦依赖流量镜像就可以做一些有趣的事情,也许我们希望通过进入测试集群的流量和我们从生产实时看到的期望行为进行对比。

例如,我们可能希望将预期的请求结果或API合同中任何偏离的请求结果与向前和向后兼容性进行比较。我们可以插入一个负责这种类型的流量协调的代理,以及一个可以进行有趣比较的代理。Twitter Diffy(注11)是这些代理中的一个,它已经在 Twitter 应用到了生产(注12),并且其它地方也将会这么做。它基本上需要镜像流量(感谢 Istio 和 Envoy,我们已经做到了这一点),并调用实时服务和新服务并比较结果。它能够检测结果中的 “noise” 并忽略它(时间戳,单调增加计数器等),通过首先调用两个实时服务实例来检测 “noise",然后忽略那些用于测试服务调用的部分。

3.png


Diffy 还有一个非常棒的网页/仪表板,用于查看调用结果,它们的差异以及基于特定特征的过滤。 最后,Diffy 有一个很好的管理控制台,用于查看关于调用比较的指标和统计数据。

4.png



我在这里有一个演示(注13),非常感谢 Prashant Khanduri,Puneet Khanduri 和 Alex Soto。 在我制作过程中,留意观看此演示视频。



为某些测试配置文件提供协作服务

当我们部署一个新版本的服务并将流量镜像到测试集群时,我们需要注意对其他环境的影响。我们的服务通常需要与其他服务协作(查询数据,更新数据等)。如果与其他服务的协作仅仅是读取或 GET 请求,并且这些协作者能够承担额外的负载,这可能不成问题。但是,如果我们的服务在我们的协作者中改变了数据,我们需要确保这些调用指向测试流量而不是真正的生产流量。你可以为你的部署创建不同的安装配置,从而注入这些配置。


例如,我们注入了 test.prod.com,而不是 live.prod.com 作为下游服务。如果在 Kubernetes上部署,则可以使用不同的 maps(注14)配置来控制此功能。


另一个有趣的方法是使用诸如 Hoverfly(注15)或 Microcks(注16)之类的东西部署虚拟化测试流量。使用这些服务虚拟化工具,你可以策划预期的请求/响应对,并将值发生变化的流量导向这些返回预期响应的代理。

5.png




合成事务


在很多情况下,我们服务的新版本需要改变其本地数据存储中的数据。它可能会向协作者服务发出调用来改变数据,但也许我们不能(或不应该)使用先前的技术(服务虚拟化)来存储这些调用。


另一种方法是更明确地通过调用(比如在我们之前添加的镜像模式中我们添加了-shadow)来表明这些请求应该再一个“合成事务”结果中,即,这些不是真正的事务,并且再它们在请求结束时应该采取任何补偿来撤消他们。我们可以为我们的请求添加一个头文件,或者甚至可以使其成为请求主体的一部分,以表明某个事务是“合成的”。当我们这样做时,我们正在指示参与服务正常处理请求,包括所有数据操作,然后在提交之前回滚事务。请注意,这适用于事务性数据存储,但可能不适用于其他数据存储。在这些情况下,如果你已经有工作单元的概念,则可以将合成语义附加到该语义上。否则,最好不要试图通过合成事务来隔离和放弃更改。  


6.png



这种方法对于执行全路径请求很有用,包括数据存储,获得更好的时序保真度和双测试方法可能捕捉不到的数据干扰/不匹配问题。


这种方法的一大缺点是它按惯例实施,难以执行。 它可能与你拥有和控制的服务一起工作,但可能无法扩展到许多参与协作的合作者。 你不愿意试图在所有服务中强制执行这个约定,并且有一个单独的服务不能正确地实现这个回滚功能,然后把所有的东西混淆起来。 在严格控制和协调部署中使用此模式。



虚拟化测试集群的数据库


在针对镜像流量进行测试时,我们已经开始涉及与处理数据相关的问题。通常,如果你的测试集群使用数据存储,并且测试服务以某种形式更新/插入/变更数据,则需要隔离这些更改。当用信头或嵌入式标志等信号发送时,我们只是简单地回滚任何更改,但这并不总是个办法。


在镜像流量时处理数据问题的另一种方法是为测试群集使用可替代的数据存储。你可以使用一个空的数据存储并使用测试数据填充它,并针对该数据运行镜像流量。但是,如果你使用的是像 Diffy(上面提到的)之类的东西,则可能会在响应比较中收到大量误报,因为测试群集中的数据正在使用测试数据,而实时服务正在使用生产数据。处理这个问题的一个好方法就是虚拟化数据层。我们让测试集群使用一个与生产数据存储相同数据的数据存储。

7.png


当我们这样做时,我们可以获得生产数据的当前一致视图,也可以在不影响生产数据存储的情况下写入数据存储。 我们可以使用像 JBoss Teiid(注17)这样的工具轻松完成此操作。 Teiid 为所有类型的数据存储系统提供连接器,包括 RDBMS,No-SQL 系统,平面文件,hadoop,salesforce 等,并且可以为我们的测试集群虚拟化它们。 当你这样做时,任何时候变更的数据可以一次性写入数据库而服务无感知。 我有一系列博客讨论了这篇关于微服务迁移的博客文章(注18)。


实现测试集群的数据库

最后,另一种扩展先前数据虚拟化技术的方法是完全实现数据存储。这样,我们测试集群的数据存储基本上与生产集群的数据存储相同,并且通过流处理不断更新。工作方式是使用(CDC - 更改数据捕获)(注19)从生产数据库捕获更改,然后将这些更改发送到新数据库。一些数据存储允许将其作为内置的复制机制(想想 MySQL 的从节点或者其他),但很多时候这些是只读的。你可以使用像Debezium(注20)这样的更改数据捕获工具来构建简单的 CDC 系统,以便你的测试数据存储具有完全复制的生产数据库副本并且不受约束的使用它。 


Debezium 为不同的数据存储提供连接器(注21),并从这些数据库中获取更改事件(即读取事务日志)并将这些更改传送到 Apache Kafka(注22)。从那里,你可以使用任何流处理工具将这些流实现到你的测试数据库中。 FWIW,上面提到的 Teiid(注23)很快就会有这个功能。

8.png


此外,如果你已经拥有数据流管道,使用事件驱动架构或使用某种事件源数据机制,那么这个“实现”测试数据库将成为更好的选择。




总结

在实践中,将生产流量镜像到我们的测试群集(无论该群集是存在于生产环境还是非生产环境中)是降低新部署风险的非常有效的方法。 


多年来,推特和亚马逊这样的大型 webops 公司一直在这样做。 这种方法带来了一些挑战,但是上述模式中讨论的方法存在有效的解决方案。 


如果你认为我错过了某些东西,或者觉得有一个我没有涉及到的令人讨厌的问题,请与我联系,我会很乐意与你讨论并将其添加到此博客的更新中。 谢谢!





1、https://www.slideshare.net/cep ... -2017

2、 https://www.cnet.com/news/zuck ... more/

3、http://blog.christianposta.com ... ease/

4、http://blog.christianposta.com/

5、https://twitter.com/christianposta

6、https://www.envoyproxy.io/docs ... olicy

7、http://blog.christianposta.com ... ease/

8、http://www.enterpriseintegrati ... .html

9、https://www.envoyproxy.io/docs ... olicy

10、https://github.com/envoyproxy/envoy/pull/2600

11、https://github.com/twitter/diffy

12、https://blog.twitter.com/engin ... .html

13、https://github.com/christian-p ... me.md

14、https://kubernetes.io/docs/tas ... gmap/

15、https://hoverfly.io/

16、 http://microcks.github.io/

17、http://teiid.jboss.org/

18、 http://blog.christianposta.com ... -iii/

19、https://en.wikipedia.org/wiki/Change_data_capture

20、http://debezium.io/

21、http://debezium.io/docs/

22、http://kafka.apache.org/

23、http://teiid.jboss.org/ 



社区活动:

3月31日(周六),数人云联合ServiceComb社区,并由ServiceMesh社区支持,开启meetup系列活动 Building Microservice 第2期 北京站 :微服务,从架构到发布,已经开始报名啦,扫码报名!
 

promote.png

 

使用Istio简化微服务系列三:如何才能做“金丝雀部署”,并通过Istio增加流量?

小数 发表了文章 • 0 个评论 • 528 次浏览 • 2018-03-27 10:10 • 来自相关话题

作者:Nithin Mallya

原文:Simplifying Microservices with Istio in Google Kubernetes Engine — Part III


我写的关于 Istio 的文章是 Istio 网站上文档的一部分。请阅读官方文档以了解更多信息。


在本系列的第一部分中(使用Istio简化微服务系列一:如何用Isito解决Spring Cloud Netflix部署微服务的挑战?),我们看到了如何使用 Istio 来简化我们的微服务之间的沟通。


在本系列的第二部分中(使用Istio简化微服务系列二:如何通过HTTPS与外部服务进行通信?),我们学会了使用 Istio egress rules 来控制服务网格之外的服务的访问。

在这一部分中,我们将看到如何才能做“金丝雀部署”(Canary Deployments),并通过 Istio 增加流量。


背景:

在过去的文章中,我详细解释了我们如何使用 Kubernetes 进行蓝/绿部署。这是一种部署技术,在此技术中,我们部署了与应用程序当前版本和新版本相同的生产环境。这项技术使我们能够执行零停机时间部署(Zero Downtime Deployments, 简称:ZDD),以确保我们的用户在切换到新版本时不受影响。有了这两个版本(当前版本和新版本)也使我们能够在新版本出现任何问题时进行回滚。


我们还需要的是能够将流量增加(或下降)到我们的应用程序的新版本,并监控它以确保没有负面影响。实现这一点的一种方法是使用“金丝雀部署”或“金丝雀”发行版。


一个不太有趣的事实:当矿工们带着金丝雀进入矿场时,任何有毒气体都会首先杀死金丝雀,并以此警告矿工们离开矿井。


同样地,在应用程序部署世界中,使用“金丝雀部署”,我们可以将应用程序的新版本部署到生产中,并只向这个新部署发送一小部分流量。这个新版本将与当前版本并行运行,并在我们将所有流量切换到新版本之前提醒我们注意任何问题。


例如:我们应用程序的 v1 可以占到90%的流量,而 v2 可以得到另外的10%。如果一切看起来都很好,我们可以将 v2 流量增加到25%,50%,最终达到100%。Istio Canary 部署的另一个优势是,我们可以根据请求中的自定义标头来增加流量。例如,在我们的应用程序的v2中设置了一个特定 cookie 头值的流量的10%。


注意:虽然“金丝雀部署”“可以”与 A/B 测试一起使用,以查看用户如何从业务度量的角度对新版本做出反应,但其背后的真正动机是确保应用程序从功能角度上满意地执行。此外,企业所有者可能希望在更长的时间内(例如:许多天甚至几周)进行 A/B 测试,而不是金丝雀码头可能采取的措施。因此,把它们分开是明智的。


Let's see it in action

从第一部分我们知道,我们的 PetService 与 PetDetailsService(v1) 和 PetMedicalHistoryService(v1) 进行了会谈。对 PetService的调用的输出如下:

$ curl http://108.59.82.93/pet/123

{
  "petDetails": {
    "petName": "Maximus",
    "petAge": 5,
    "petOwner": "Nithin Mallya",
    "petBreed": "Dog"
  },
  "petMedicalHistory": {
    "vaccinationList": [
      "Bordetella, Leptospirosis, Rabies, Lyme Disease"
    ]
  }
}

在上面的回复中,你会注意到 petBreed 说“狗”。然而,Maximus 是德国牧羊犬,这时候我们需要修改 PetDetailsService,以便正确返回品种。


因此,我们创建了 PetDetailsService 的 v2,它将返回“德国牧羊犬”。但是,我们希望确保在将所有流量驱动到 v2 之前,我们可以使用一小部分用户来测试这个服务的 v2。


在下面的图1中,我们看到流量被配置成这样,50%的请求将被定向到 v1 和50%到 v2,我们的 “金丝雀部署”。(它可以是任意数字,取决于变化的大小,并尽量减少负面影响)。







      图1:我们可以将 PetDetailsServic e的 v2 部署为金丝雀部署和匝道流量。


步骤

1、创建 PetDetails Service 的 v2 版本并像以前一样部署它。 (请参阅 petdetailservice / kube 文件夹下的 petinfo.yaml)

$ kubectl get pods

NAME                                         READY     STATUS    RESTARTS      AGE

petdetailsservice-v1-2831216563-qnl10        2/2        Running      0          19h

petdetailsservice-v2-2943472296-nhdxt       2/2       Running       0           2h

petmedicalhistoryservice-v1-28468096-hd7ld   2/2       Running      0          19h

petservice-v1-1652684438-3l112               2/2       Running      0      19h




2、创建一个RouteRule,将流量分成 petdetailsservice 的50%(v1)和50%(v2),如下所示:

cat <<EOF | istioctl create -f -
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
  name: petdetailsservice-default
spec:
  destination:
    name: petdetailsservice
  route:
  - labels:
      version: v1
    weight: 50
  - labels:
      version: v2
    weight: 50
EOF

$ istioctl get routerule

NAME    KIND     NAMESPACE

petdetailsservice-default RouteRule.v1alpha2.config.istio.io default




3、现在,如果你访问 PetService,你应该看到替代请求分别返回“Dog”和“German Shepherd Dog”,如下所示:

$ curl http://108.59.82.93/pet/123

{
  "petDetails": {
    "petName": "Maximus",
    "petAge": 5,
    "petOwner": "Nithin Mallya",
    "petBreed": "Dog"
  },
  "petMedicalHistory": {
    "vaccinationList": [
      "Bordetella, Leptospirosis, Rabies, Lyme Disease"
    ]
  }
}

$ curl http://108.59.82.93/pet/123

{
  "petDetails": {
    "petName": "Maximus",
    "petAge": 5,
    "petOwner": "Nithin Mallya",
    "petBreed": "German Shepherd Dog"
  },
  "petMedicalHistory": {
    "vaccinationList": [
      "Bordetella, Leptospirosis, Rabies, Lyme Disease"
    ]
  }
}



It works!

这引出了一个问题:我们不能用 Kubernetes Canary Deployments 来做到这一点吗?简短的答案是肯定的。


然而,这样做的步骤更复杂,也有局限性:

你仍然需要创建 PetDetailsService  (v1和v2)的两个部署,但是你需要手动限制在部署过程中 v2 副本的数量,以维护 v1:v2 比。例如:你可以使用10个副本部署 v1,并将v2 部署到2个副本,以获得10:2的负载平衡,等等。


由于所有的 pod 无论版本是否相同,Kubernetes 集群中的流量负载平衡仍然受到随机性的影响。


基于业务量的自动伸缩 pods 也是有问题的,因为我们需要单独的 autoscale 的2个部署,它可以根据每个服务的流量负载分配来做出不同的行为。


如果我们想根据某些标准(如 request headers)仅允许某些用户使用/限制流量,则Kubernetes Canary Deployments可能无法实现此目标。


结论:你刚刚看到了创建一个“金丝雀部署”和增加 Istio 的流量是多么容易。马克西姆斯也很高兴!(小数:下图就是马克西姆斯...嗯...很帅气!)








资源:

1、Part I of this article series: https://medium.com/google-clou ... 922b8

2、Part II of this article series: https://medium.com/google-clou ... 33089

3、The Istio home page https://istio.io/

4、DevOxx Istio presentation by Ray Tsang: https://www.youtube.com/watch% ... D231s

5、Github link to this example: https://github.com/nmallya/istiodemo

6、All things Kubernetes: https://kubernetes.io/


ServiceMesh微信交流群:

添加微信xiaoshu062,备注:服务网格,即可加入Service Mesh微信交流群。


社区活动:

3月31日(周六),数人云联合ServiceComb社区,并由ServiceMesh社区支持,开启meetup系列活动 Building Microservice 第2期 北京站 :微服务,从架构到发布,已经开始报名啦,扫码报名!
 





 
  查看全部
作者:Nithin Mallya

原文:Simplifying Microservices with Istio in Google Kubernetes Engine — Part III


我写的关于 Istio 的文章是 Istio 网站上文档的一部分。请阅读官方文档以了解更多信息。


在本系列的第一部分中(使用Istio简化微服务系列一:如何用Isito解决Spring Cloud Netflix部署微服务的挑战?),我们看到了如何使用 Istio 来简化我们的微服务之间的沟通。


在本系列的第二部分中(使用Istio简化微服务系列二:如何通过HTTPS与外部服务进行通信?),我们学会了使用 Istio egress rules 来控制服务网格之外的服务的访问。

在这一部分中,我们将看到如何才能做“金丝雀部署”(Canary Deployments),并通过 Istio 增加流量。


背景:

在过去的文章中,我详细解释了我们如何使用 Kubernetes 进行蓝/绿部署。这是一种部署技术,在此技术中,我们部署了与应用程序当前版本和新版本相同的生产环境。这项技术使我们能够执行零停机时间部署(Zero Downtime Deployments, 简称:ZDD),以确保我们的用户在切换到新版本时不受影响。有了这两个版本(当前版本和新版本)也使我们能够在新版本出现任何问题时进行回滚。


我们还需要的是能够将流量增加(或下降)到我们的应用程序的新版本,并监控它以确保没有负面影响。实现这一点的一种方法是使用“金丝雀部署”或“金丝雀”发行版。


一个不太有趣的事实:当矿工们带着金丝雀进入矿场时,任何有毒气体都会首先杀死金丝雀,并以此警告矿工们离开矿井。


同样地,在应用程序部署世界中,使用“金丝雀部署”,我们可以将应用程序的新版本部署到生产中,并只向这个新部署发送一小部分流量。这个新版本将与当前版本并行运行,并在我们将所有流量切换到新版本之前提醒我们注意任何问题。


例如:我们应用程序的 v1 可以占到90%的流量,而 v2 可以得到另外的10%。如果一切看起来都很好,我们可以将 v2 流量增加到25%,50%,最终达到100%。Istio Canary 部署的另一个优势是,我们可以根据请求中的自定义标头来增加流量。例如,在我们的应用程序的v2中设置了一个特定 cookie 头值的流量的10%。


注意:虽然“金丝雀部署”“可以”与 A/B 测试一起使用,以查看用户如何从业务度量的角度对新版本做出反应,但其背后的真正动机是确保应用程序从功能角度上满意地执行。此外,企业所有者可能希望在更长的时间内(例如:许多天甚至几周)进行 A/B 测试,而不是金丝雀码头可能采取的措施。因此,把它们分开是明智的。


Let's see it in action

从第一部分我们知道,我们的 PetService 与 PetDetailsService(v1) 和 PetMedicalHistoryService(v1) 进行了会谈。对 PetService的调用的输出如下:

$ curl http://108.59.82.93/pet/123

{
  "petDetails": {
    "petName": "Maximus",
    "petAge": 5,
    "petOwner": "Nithin Mallya",
    "petBreed": "Dog"
  },
  "petMedicalHistory": {
    "vaccinationList": [
      "Bordetella, Leptospirosis, Rabies, Lyme Disease"
    ]
  }
}

在上面的回复中,你会注意到 petBreed 说“狗”。然而,Maximus 是德国牧羊犬,这时候我们需要修改 PetDetailsService,以便正确返回品种。


因此,我们创建了 PetDetailsService 的 v2,它将返回“德国牧羊犬”。但是,我们希望确保在将所有流量驱动到 v2 之前,我们可以使用一小部分用户来测试这个服务的 v2。


在下面的图1中,我们看到流量被配置成这样,50%的请求将被定向到 v1 和50%到 v2,我们的 “金丝雀部署”。(它可以是任意数字,取决于变化的大小,并尽量减少负面影响)。


微信图片_20180327100820.jpg


      图1:我们可以将 PetDetailsServic e的 v2 部署为金丝雀部署和匝道流量。


步骤

1、创建 PetDetails Service 的 v2 版本并像以前一样部署它。 (请参阅 petdetailservice / kube 文件夹下的 petinfo.yaml)

$ kubectl get pods

NAME                                         READY     STATUS    RESTARTS      AGE

petdetailsservice-v1-2831216563-qnl10        2/2        Running      0          19h

petdetailsservice-v2-2943472296-nhdxt       2/2       Running       0           2h

petmedicalhistoryservice-v1-28468096-hd7ld   2/2       Running      0          19h

petservice-v1-1652684438-3l112               2/2       Running      0      19h




2、创建一个RouteRule,将流量分成 petdetailsservice 的50%(v1)和50%(v2),如下所示:

cat <<EOF | istioctl create -f -
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
  name: petdetailsservice-default
spec:
  destination:
    name: petdetailsservice
  route:
  - labels:
      version: v1
    weight: 50
  - labels:
      version: v2
    weight: 50
EOF

$ istioctl get routerule

NAME    KIND     NAMESPACE

petdetailsservice-default RouteRule.v1alpha2.config.istio.io default




3、现在,如果你访问 PetService,你应该看到替代请求分别返回“Dog”和“German Shepherd Dog”,如下所示:

$ curl http://108.59.82.93/pet/123

{
  "petDetails": {
    "petName": "Maximus",
    "petAge": 5,
    "petOwner": "Nithin Mallya",
    "petBreed": "Dog"
  },
  "petMedicalHistory": {
    "vaccinationList": [
      "Bordetella, Leptospirosis, Rabies, Lyme Disease"
    ]
  }
}

$ curl http://108.59.82.93/pet/123

{
  "petDetails": {
    "petName": "Maximus",
    "petAge": 5,
    "petOwner": "Nithin Mallya",
    "petBreed": "German Shepherd Dog"
  },
  "petMedicalHistory": {
    "vaccinationList": [
      "Bordetella, Leptospirosis, Rabies, Lyme Disease"
    ]
  }
}



It works!

这引出了一个问题:我们不能用 Kubernetes Canary Deployments 来做到这一点吗?简短的答案是肯定的。


然而,这样做的步骤更复杂,也有局限性:

你仍然需要创建 PetDetailsService  (v1和v2)的两个部署,但是你需要手动限制在部署过程中 v2 副本的数量,以维护 v1:v2 比。例如:你可以使用10个副本部署 v1,并将v2 部署到2个副本,以获得10:2的负载平衡,等等。


由于所有的 pod 无论版本是否相同,Kubernetes 集群中的流量负载平衡仍然受到随机性的影响。


基于业务量的自动伸缩 pods 也是有问题的,因为我们需要单独的 autoscale 的2个部署,它可以根据每个服务的流量负载分配来做出不同的行为。


如果我们想根据某些标准(如 request headers)仅允许某些用户使用/限制流量,则Kubernetes Canary Deployments可能无法实现此目标。


结论:你刚刚看到了创建一个“金丝雀部署”和增加 Istio 的流量是多么容易。马克西姆斯也很高兴!(小数:下图就是马克西姆斯...嗯...很帅气!)


1_6uuUOOk5AVyeQ8QTkMFrrg.jpeg



资源:

1、Part I of this article series: https://medium.com/google-clou ... 922b8

2、Part II of this article series: https://medium.com/google-clou ... 33089

3、The Istio home page https://istio.io/

4、DevOxx Istio presentation by Ray Tsang: https://www.youtube.com/watch% ... D231s

5、Github link to this example: https://github.com/nmallya/istiodemo

6、All things Kubernetes: https://kubernetes.io/


ServiceMesh微信交流群:

添加微信xiaoshu062,备注:服务网格,即可加入Service Mesh微信交流群。



社区活动:

3月31日(周六),数人云联合ServiceComb社区,并由ServiceMesh社区支持,开启meetup系列活动 Building Microservice 第2期 北京站 :微服务,从架构到发布,已经开始报名啦,扫码报名!
 

promote.png

 
 

下发规则到集群istio是通过是什么方式保障事务的一致性的?

chym 回复了问题 • 2 人关注 • 2 个回复 • 295 次浏览 • 2018-03-25 17:26 • 来自相关话题