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

Istio小数 发表了文章 • 0 个评论 • 2 次浏览 • 58 分钟前 • 来自相关话题

翻译:狄卫华 (博客地址 : 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


 

Service Mesh vs API Gateway,用途特征大相径庭?

ServiceMesh小数 发表了文章 • 0 个评论 • 212 次浏览 • 3 天前 • 来自相关话题

作者:Kasun Indrasiri

翻译:赵化冰(博客链接:http://zhaohuabing.com/)

原文:Service Mesh vs API Gateway

地址:https://medium.com/microservic ... 9bf56




在我前一篇关于 Service Mesh 的文章中(注1)有几个关于 Service Mesh 和 API Gateway 之间关系的问题。因此在我打算在本篇文章中讨论 Service Mesh 和 API Gateway 的用途。


为了区分 API Gateway 和 Service Mesh,让我们先分别看看两者的主要特征。


API Gateway:将你的服务作为被管理的API暴露给外部系统

使用 API Gateway 的主要目的是将你的微服务作为被管理的 API 暴露给外部系统。因此,我们在 API Gateway 层开发的 API 或者边界服务对外提供了业务功能。

API/Edge 服务调用下游微服务,通过组合/混装多个下游微服务形成业务逻辑。

API/Edge 服务需要以一种可靠的方式调用下游服务,因此需要应用断路器,超时,负载均衡/故障转移等可靠性模式。因此大部分的 API Gateway解决方案都内置了这些特性。

API Gateway 也需要内置对以下特性的支持,包括:服务发现,分析(可见性:性能指标,监控,分布式日志,分布式调用追踪) 和安全。

API Gateway 和 API 管理生态系统的其他这些组件的关系紧密,比如: API 市场/商店, API 发布门户。




Service Mesh

现在我们来看看Service Mesh有哪些不同。

Service Mesh是一个网络通信基础设施, 可以用于将网络功能从你的服务代码中剥离出来。

采用 Service Mesh, 你不用在服务代码中实现用于可靠通信的模式如断路,超时等,类似地,Service Mesh 也提供了服务发现,服务可见性等其他功能。




API Gateway and Service Mesh实践

API Gateway 和 Service Mesh 之间的主要不同点在于 API Gateway 是暴露 API/Edge 服务的关键组件,而 Service Mesh 则仅仅是一个服务间通信的基础设施,并不了解你应用中的业务逻辑。

下图说明了 API Gateway 和 Service Mesh 的关系。如同我们上所说,他们之间也有一些重叠的部分(例如断路器等),但重要的是需要理解这两者是用于完全不同的用途。

图1: API Gateway和Service Mesh实践








如图所示,Service Mesh 作为 Sidecar 和服务一起部署,它是独立于服务的业务逻辑的。


另一方面,API Gateway host 了所有的 API 服务(这些API服务有明确定义的业务功能),它是你应用的业务逻辑的一部分。API Gateway 可以具有内建的服务间通信能力,但它也可以使用 Service Mesh 来调用下游服务。(API Gateway->Service Mesh->Microservices)。


在API管理层次,你可以使用API Gateway内建的服务间通信能力;也可以通过Service Mesh来调用下游服务,以将应用网络通信功能从应用程序转移到Service Mesh中。




译者按:

API Gateway 和 Service Mesh 的关系是我最近一直在思考的问题,也和同事及社区的朋友之间进行了一些讨论。这篇短文很清晰地总结了两者之间的相似之处以及这两者在微服务架构中的不同用途。


文章中提到 “可以使用API Gateway内建的服务间通信能力;也可以通过Service Mesh来调用下游服务”。在和同事讨论时,大家提到一个比较重要的考虑因素是在 API Gateway 处引入一个 Sidecar 可能带来的额外延迟。


API Gateway 作为微服务引用的流量入口,其对效率要求较高,如果随 API Gateway 部署一个 Sidecar,可能对效率有一定影响。


我对此未进行测试,但从理论上来说,服务发现,重试,断路等逻辑无论放到 API Gateway 还是 Service Mesh 中耗时应该是差不多的,部署 Sidecar 只是增加了创建一个本地链接的消耗,如下图所示:







将 API Gateway 和 Service Mesh 的功能进行清晰划分,API Gateway 负责应用逻辑,Service Mes h负责服务通讯,Metrics 收集等微服务基础设施,这样划分后在架构上更为清晰。对于效率问题,我们可以考虑对 API Gateway 进行水平扩展来解决。




注:

1、https://medium.com/microservic ... a3c9a 查看全部
作者:Kasun Indrasiri

翻译:赵化冰(博客链接:http://zhaohuabing.com/

原文:Service Mesh vs API Gateway

地址:https://medium.com/microservic ... 9bf56




在我前一篇关于 Service Mesh 的文章中(注1)有几个关于 Service Mesh 和 API Gateway 之间关系的问题。因此在我打算在本篇文章中讨论 Service Mesh 和 API Gateway 的用途。


为了区分 API Gateway 和 Service Mesh,让我们先分别看看两者的主要特征。


API Gateway:将你的服务作为被管理的API暴露给外部系统

使用 API Gateway 的主要目的是将你的微服务作为被管理的 API 暴露给外部系统。因此,我们在 API Gateway 层开发的 API 或者边界服务对外提供了业务功能。

API/Edge 服务调用下游微服务,通过组合/混装多个下游微服务形成业务逻辑。

API/Edge 服务需要以一种可靠的方式调用下游服务,因此需要应用断路器,超时,负载均衡/故障转移等可靠性模式。因此大部分的 API Gateway解决方案都内置了这些特性。

API Gateway 也需要内置对以下特性的支持,包括:服务发现,分析(可见性:性能指标,监控,分布式日志,分布式调用追踪) 和安全。

API Gateway 和 API 管理生态系统的其他这些组件的关系紧密,比如: API 市场/商店, API 发布门户。




Service Mesh

现在我们来看看Service Mesh有哪些不同。

Service Mesh是一个网络通信基础设施, 可以用于将网络功能从你的服务代码中剥离出来。

采用 Service Mesh, 你不用在服务代码中实现用于可靠通信的模式如断路,超时等,类似地,Service Mesh 也提供了服务发现,服务可见性等其他功能。




API Gateway and Service Mesh实践

API Gateway 和 Service Mesh 之间的主要不同点在于 API Gateway 是暴露 API/Edge 服务的关键组件,而 Service Mesh 则仅仅是一个服务间通信的基础设施,并不了解你应用中的业务逻辑。

下图说明了 API Gateway 和 Service Mesh 的关系。如同我们上所说,他们之间也有一些重叠的部分(例如断路器等),但重要的是需要理解这两者是用于完全不同的用途。

图1: API Gateway和Service Mesh实践


微信图片_20180416102911.jpg



如图所示,Service Mesh 作为 Sidecar 和服务一起部署,它是独立于服务的业务逻辑的。


另一方面,API Gateway host 了所有的 API 服务(这些API服务有明确定义的业务功能),它是你应用的业务逻辑的一部分。API Gateway 可以具有内建的服务间通信能力,但它也可以使用 Service Mesh 来调用下游服务。(API Gateway->Service Mesh->Microservices)。


在API管理层次,你可以使用API Gateway内建的服务间通信能力;也可以通过Service Mesh来调用下游服务,以将应用网络通信功能从应用程序转移到Service Mesh中。




译者按:

API Gateway 和 Service Mesh 的关系是我最近一直在思考的问题,也和同事及社区的朋友之间进行了一些讨论。这篇短文很清晰地总结了两者之间的相似之处以及这两者在微服务架构中的不同用途。


文章中提到 “可以使用API Gateway内建的服务间通信能力;也可以通过Service Mesh来调用下游服务”。在和同事讨论时,大家提到一个比较重要的考虑因素是在 API Gateway 处引入一个 Sidecar 可能带来的额外延迟。


API Gateway 作为微服务引用的流量入口,其对效率要求较高,如果随 API Gateway 部署一个 Sidecar,可能对效率有一定影响。


我对此未进行测试,但从理论上来说,服务发现,重试,断路等逻辑无论放到 API Gateway 还是 Service Mesh 中耗时应该是差不多的,部署 Sidecar 只是增加了创建一个本地链接的消耗,如下图所示:

微信图片_20180416102956.jpg



将 API Gateway 和 Service Mesh 的功能进行清晰划分,API Gateway 负责应用逻辑,Service Mes h负责服务通讯,Metrics 收集等微服务基础设施,这样划分后在架构上更为清晰。对于效率问题,我们可以考虑对 API Gateway 进行水平扩展来解决。




注:

1、https://medium.com/microservic ... a3c9a

Service Mesh第三梯队,不可忽略的Nginmesh

ServiceMesh小数 发表了文章 • 0 个评论 • 214 次浏览 • 2018-04-11 15:13 • 来自相关话题

作者简介:

      赵化冰是一名程序员及开源软件爱好者,目前在NFV&SDN编排开源社区ONAP担任MSB项目负责人,致力于高性能,高可用微服务架构在编排领域的应用。

      博客链接:http://zhaohuabing.com/


目录
前言安装Kubernetes Cluster安装Istio控制面和Bookinfo查看自动注入的sidecar关联阅读参考




1. 前言

Nginmesh 是 NGINX 的 Service Mesh 开源项目,用于 Istio 服务网格平台中的数据面代理。它旨在提供七层负载均衡和服务路由功能,与 Istio 集成作为 sidecar 部署,并将以“标准,可靠和安全的方式”使得服务间通信更容易。Nginmesh 在今年底已经连续发布了0.2和0.3版本,提供了服务发现,请求转发,路由规则,性能指标收集等功能。

备注:本文安装指南基于Ubuntu 16.04,在Centos上某些安装步骤的命令可能需要稍作改动。









2. 安装Kubernetes Cluster

Kubernetes Cluster 包含 etcd, api server, scheduler,controller manager 等多个组件,组件之间的配置较为复杂,如果要手动去逐个安装及配置各个组件,需要了解 kubernetes,操作系统及网络等多方面的知识,对安装人员的能力要求较高。kubeadm提供了一个简便,快速安装 Kubernetes Cluster 的方式,并且可以通过安装配置文件提供较高的灵活性,因此我们采用 kubeadm 安装 kubernetes cluster。

首先参照 kubeadm的说明文档(注1) 在计划部署 kubernetes cluster 的每个节点上安装 docker,kubeadm, kubelet 和 kubectl。

安装 docker

apt-get update
apt-get install -y docker.io

使用 google 的源安装 kubelet kubeadm 和 kubectl

apt-get update && apt-get install -y apt-transport-https
curl -s https://packages.cloud.google. ... y.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet kubeadm kubectl

使用 kubeadmin 安装 kubernetes cluster

Nginmesh 使用 Kubernetes的 Initializer 机制 (注2)来实现 sidecar 的自动注入。Initializer 目前是 kubernetes 的一个 Alpha feature,缺省是未启用的,需要通过api server的参数(注3)打开。因此我们先创建一个 kubeadm-conf 配置文件,用于配置 api server的启动参数。

apiVersion: kubeadm.k8s.io/v1alpha1
kind: MasterConfiguration
apiServerExtraArgs:
 admission-control: Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ValidatingAdmissionWebhook,ResourceQuota,DefaultTolerationSeconds,MutatingAdmissionWebhook
 runtime-config: admissionregistration.k8s.io/v1alpha1

使用 kubeadmin init 命令创建 kubernetes master 节点。 可以先试用 –dry-run 参数验证一下配置文件。

kubeadm init --config kubeadm-conf --dry-run

如果一切正常,kubeadm 将提示:Finished dry-running successfully. Above are the resources that would be created.

下面再实际执行创建命令

kubeadm init --config kubeadm-conf

kubeadm 会花一点时间拉取 docker image,命令完成后,会提示如何将一个 work node 加入 cluster。如下所示:

kubeadm join --token fffbf6.13bcb3563428cf23 10.12.5.15:6443 --discovery-token-ca-cert-hash sha256:27ad08b4cd9f02e522334979deaf09e3fae80507afde63acf88892c8b72f143f

备注:目前 kubeadm 只能支持在一个节点上安装 master,支持高可用的安装将在后续版本实现。kubernetes 官方给出的 workaround 建议是定期备份 etcd 数据kubeadm limitations。

Kubeadm 并不会安装 Pod 需要的网络,因此需要手动安装一个 Pod 网络,这里采用的是 Calico

kubectl apply -f https://docs.projectcalico.org ... .yaml

使用 kubectl 命令检查 master 节点安装结果

ubuntu@kube-1:~$ kubectl get all
NAME             TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
svc/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   12m

在每台工作节点上执行上述 kubeadm join 命令,即可把工作节点加入集群中。使用kubectl 命令检查 cluster 中的节点情况。

ubuntu@kube-1:~$ kubectl get nodes
NAME      STATUS    ROLES     AGE       VERSION
kube-1    Ready     master    21m       v1.9.0
kube-2    Ready     <none>    47s       v1.9.0




3. 安装Istio控制面和Bookinfo

参考 Nginmesh文档 (注4)安装 Istio 控制面和 Bookinfo 该文档的步骤清晰明确,这里不再赘述。

需要注意的是,在 Niginmesh 文档中,建议通过 Ingress 的 External IP 访问 bookinfo应用程序。但 Loadbalancer 只在支持的云环境中才会生效(注5),并且还需要进行一定的配置。如我在 Openstack 环境中创建的 cluster,则需要参照该文档(注6)对Openstack 进行配置后,Openstack 才能够支持 kubernetes 的 Loadbalancer service。如未进行配置,通过命令查看 Ingress External IP 一直显示为 pending 状态。

NAME            TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                                                            AGE
istio-ingress   LoadBalancer   10.111.158.10   <pending>     80:32765/TCP,443:31969/TCP                                         11m
istio-mixer     ClusterIP      10.107.135.31   <none>        9091/TCP,15004/TCP,9093/TCP,9094/TCP,9102/TCP,9125/UDP,42422/TCP   11m
istio-pilot     ClusterIP      10.111.110.65   <none>        15003/TCP,443/TCP                                                  11m

如不能配置云环境提供 Loadbalancer 特性, 我们可以直接使用集群中的一个节点IP:Nodeport 访问 Bookinfo 应用程序。

http://10.12.5.31:32765/productpage

想要了解更多关于如何从集群外部进行访问的内容,可以参考如何从外部访问Kubernetes集群中的应用?(注7)




4. 查看自动注入的sidecar

使用 kubectl get pod reviews-v3-5fff595d9b-zsb2q -o yaml 命令查看 Bookinfo 应用的 reviews 服务的 Pod。

apiVersion: v1
kind: Pod
metadata:
 annotations:
   sidecar.istio.io/status: injected-version-0.2.12
 creationTimestamp: 2018-01-02T02:33:36Z
 generateName: reviews-v3-5fff595d9b-
 labels:
   app: reviews
   pod-template-hash: "1999151856"
   version: v3
 name: reviews-v3-5fff595d9b-zsb2q
 namespace: default
 ownerReferences:
 - apiVersion: extensions/v1beta1
   blockOwnerDeletion: true
   controller: true
   kind: ReplicaSet
   name: reviews-v3-5fff595d9b
   uid: 5599688c-ef65-11e7-8be6-fa163e160c7d
 resourceVersion: "3757"
 selfLink: /api/v1/namespaces/default/pods/reviews-v3-5fff595d9b-zsb2q
 uid: 559d8c6f-ef65-11e7-8be6-fa163e160c7d
spec:
 containers:
 - image: istio/examples-bookinfo-reviews-v3:0.2.3
   imagePullPolicy: IfNotPresent
   name: reviews
   ports:
   - containerPort: 9080
     protocol: TCP
   resources: {}
   terminationMessagePath: /dev/termination-log
   terminationMessagePolicy: File
   volumeMounts:
   - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
     name: default-token-48vxx
     readOnly: true
 - args:
   - proxy
   - sidecar
   - -v
   - "2"
   - --configPath
   - /etc/istio/proxy
   - --binaryPath
   - /usr/local/bin/envoy
   - --serviceCluster
   - reviews
   - --drainDuration
   - 45s
   - --parentShutdownDuration
   - 1m0s
   - --discoveryAddress
   - istio-pilot.istio-system:15003
   - --discoveryRefreshDelay
   - 1s
   - --zipkinAddress
   - zipkin.istio-system:9411
   - --connectTimeout
   - 10s
   - --statsdUdpAddress
   - istio-mixer.istio-system:9125
   - --proxyAdminPort
   - "15000"
   - --controlPlaneAuthPolicy
   - NONE
   env:
   - name: POD_NAME
     valueFrom:
       fieldRef:
         apiVersion: v1
         fieldPath: metadata.name
   - name: POD_NAMESPACE
     valueFrom:
       fieldRef:
         apiVersion: v1
         fieldPath: metadata.namespace
   - name: INSTANCE_IP
     valueFrom:
       fieldRef:
         apiVersion: v1
         fieldPath: status.podIP
   image: nginmesh/proxy_debug:0.2.12
   imagePullPolicy: Always
   name: istio-proxy
   resources: {}
   securityContext:
     privileged: true
     readOnlyRootFilesystem: false
     runAsUser: 1337
   terminationMessagePath: /dev/termination-log
   terminationMessagePolicy: File
   volumeMounts:
   - mountPath: /etc/istio/proxy
     name: istio-envoy
   - mountPath: /etc/certs/
     name: istio-certs
     readOnly: true
   - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
     name: default-token-48vxx
     readOnly: true
 dnsPolicy: ClusterFirst
 initContainers:
 - args:
   - -p
   - "15001"
   - -u
   - "1337"
   image: nginmesh/proxy_init:0.2.12
   imagePullPolicy: Always
   name: istio-init
   resources: {}
   securityContext:
     capabilities:
       add:
       - NET_ADMIN
     privileged: true
   terminationMessagePath: /dev/termination-log
   terminationMessagePolicy: File
   volumeMounts:
   - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
     name: default-token-48vxx
     readOnly: true
 nodeName: kube-2
 restartPolicy: Always
 schedulerName: default-scheduler
 securityContext: {}
 serviceAccount: default
 serviceAccountName: default
 terminationGracePeriodSeconds: 30
 tolerations:
 - effect: NoExecute
   key: node.kubernetes.io/not-ready
   operator: Exists
   tolerationSeconds: 300
 - effect: NoExecute
   key: node.kubernetes.io/unreachable
   operator: Exists
   tolerationSeconds: 300
 volumes:
 - emptyDir:
     medium: Memory
   name: istio-envoy
 - name: istio-certs
   secret:
     defaultMode: 420
     optional: true
     secretName: istio.default
 - name: default-token-48vxx
   secret:
     defaultMode: 420
     secretName: default-token-48vxx
status:
 conditions:
 - lastProbeTime: null
   lastTransitionTime: 2018-01-02T02:33:54Z
   status: "True"
   type: Initialized
 - lastProbeTime: null
   lastTransitionTime: 2018-01-02T02:36:06Z
   status: "True"
   type: Ready
 - lastProbeTime: null
   lastTransitionTime: 2018-01-02T02:33:36Z
   status: "True"
   type: PodScheduled
 containerStatuses:
 - containerID: docker://5d0c189b9dde8e14af4c8065ee5cf007508c0bb2b3c9535598d99dc49f531370
   image: nginmesh/proxy_debug:0.2.12
   imageID: docker-pullable://nginmesh/proxy_debug@sha256:6275934ea3a1ce5592e728717c4973ac704237b06b78966a1d50de3bc9319c71
   lastState: {}
   name: istio-proxy
   ready: true
   restartCount: 0
   state:
     running:
       startedAt: 2018-01-02T02:36:05Z
 - containerID: docker://aba3e114ac1aa87c75e969dcc1b0725696de78d3407c5341691d9db579429f28
   image: istio/examples-bookinfo-reviews-v3:0.2.3
   imageID: docker-pullable://istio/examples-bookinfo-reviews-v3@sha256:6e100e4805a8c10c47040ea7b66f10ad619c7e0068696032546ad3e35ad46570
   lastState: {}
   name: reviews
   ready: true
   restartCount: 0
   state:
     running:
       startedAt: 2018-01-02T02:35:47Z
 hostIP: 10.12.5.31
 initContainerStatuses:
 - containerID: docker://b55108625832a3205a265e8b45e5487df10276d5ae35af572ea4f30583933c1f
   image: nginmesh/proxy_init:0.2.12
   imageID: docker-pullable://nginmesh/proxy_init@sha256:f73b68839f6ac1596d6286ca498e4478b8fcfa834e4884418d23f9f625cbe5f5
   lastState: {}
   name: istio-init
   ready: true
   restartCount: 0
   state:
     terminated:
       containerID: docker://b55108625832a3205a265e8b45e5487df10276d5ae35af572ea4f30583933c1f
       exitCode: 0
       finishedAt: 2018-01-02T02:33:53Z
       reason: Completed
       startedAt: 2018-01-02T02:33:53Z
 phase: Running
 podIP: 192.168.79.138
 qosClass: BestEffort
 startTime: 2018-01-02T02:33:39Z

该命令行输出的内容相当长,我们可以看到 Pod 中注入了一个 nginmesh/proxy_debug container , 还增加了一个 initContainer nginmesh/proxy_init。这两个容器是通过kubernetes initializer 自动注入到 pod 中的。这两个 container 分别有什么作用呢?让我们看一下 Nginmesh 源代码中的说明(注8):

proxy_debug, which comes with the agent and NGINX.

proxy_init, which is used for configuring iptables rules for transparently injecting an NGINX proxy from the proxy_debug image into an application pod.

proxy_debug 就是 sidecar 代理,proxy_init 则用于配置 iptable 规则,以将应用的流量导入到 sidecar 代理中。

查看 proxy_init 的 Dockerfile 文件,可以看到 proxy_init 其实是调用了prepare_proxy.sh(注9)这个脚本来创建 iptable 规则。

proxy_debug Dockerfile

FROM debian:stretch-slim
RUN apt-get update && apt-get install -y iptables
ADD prepare_proxy.sh /
ENTRYPOINT ["/prepare_proxy.sh"]

prepare_proxy.sh节选

...omitted for brevity 

# Create a new chain for redirecting inbound and outbound traffic to
# the common Envoy port.
iptables -t nat -N ISTIO_REDIRECT                                             -m comment --comment "istio/redirect-common-chain"
iptables -t nat -A ISTIO_REDIRECT -p tcp -j REDIRECT --to-port ${ENVOY_PORT}  -m comment --comment "istio/redirect-to-envoy-port"

# Redirect all inbound traffic to Envoy.
iptables -t nat -A PREROUTING -j ISTIO_REDIRECT                               -m comment --comment "istio/install-istio-prerouting"

# Create a new chain for selectively redirecting outbound packets to
# Envoy.
iptables -t nat -N ISTIO_OUTPUT                                               -m comment --comment "istio/common-output-chain"

...omitted for brevity





4. 关联阅读

Istio  及Bookinfo 示例程序安装试用笔记(注10)




5. 参考

Service Mesh with Istio and NGINX(注11)

Using kubeadm to Create a Cluster(注12)

Kubernetes Reference Documentation-Dynamic Admission Control(注13)



注:

1、https://kubernetes.io/docs/set ... beadm

2、https://kubernetes.io/docs/adm ... izers

3、https://kubernetes.io/docs/adm ... lpha-

4、https://github.com/nginmesh/nginmesh

5、https://kubernetes.io/docs/con ... ancer

6、https://docs.openstack.org/mag ... .html

7、http://zhaohuabing.com/2017/11 ... side/

8、https://github.com/nginmesh/ng ... agent

9、https://github.com/nginmesh/ng ... xy.sh

10、https://github.com/nginmesh/ng ... xy.sh

11、https://github.com/nginmesh/nginmesh/

12、https://kubernetes.io/docs/set ... hosts

13、https://kubernetes.io/docs/set ... hosts


  查看全部
作者简介:

      赵化冰是一名程序员及开源软件爱好者,目前在NFV&SDN编排开源社区ONAP担任MSB项目负责人,致力于高性能,高可用微服务架构在编排领域的应用。

      博客链接:http://zhaohuabing.com/


目录
  1. 前言
  2. 安装Kubernetes Cluster
  3. 安装Istio控制面和Bookinfo
  4. 查看自动注入的sidecar
  5. 关联阅读
  6. 参考





1. 前言

Nginmesh 是 NGINX 的 Service Mesh 开源项目,用于 Istio 服务网格平台中的数据面代理。它旨在提供七层负载均衡和服务路由功能,与 Istio 集成作为 sidecar 部署,并将以“标准,可靠和安全的方式”使得服务间通信更容易。Nginmesh 在今年底已经连续发布了0.2和0.3版本,提供了服务发现,请求转发,路由规则,性能指标收集等功能。

备注:本文安装指南基于Ubuntu 16.04,在Centos上某些安装步骤的命令可能需要稍作改动。


11.png




2. 安装Kubernetes Cluster

Kubernetes Cluster 包含 etcd, api server, scheduler,controller manager 等多个组件,组件之间的配置较为复杂,如果要手动去逐个安装及配置各个组件,需要了解 kubernetes,操作系统及网络等多方面的知识,对安装人员的能力要求较高。kubeadm提供了一个简便,快速安装 Kubernetes Cluster 的方式,并且可以通过安装配置文件提供较高的灵活性,因此我们采用 kubeadm 安装 kubernetes cluster。

首先参照 kubeadm的说明文档(注1) 在计划部署 kubernetes cluster 的每个节点上安装 docker,kubeadm, kubelet 和 kubectl。

安装 docker

apt-get update
apt-get install -y docker.io

使用 google 的源安装 kubelet kubeadm 和 kubectl

apt-get update && apt-get install -y apt-transport-https
curl -s https://packages.cloud.google. ... y.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet kubeadm kubectl

使用 kubeadmin 安装 kubernetes cluster

Nginmesh 使用 Kubernetes的 Initializer 机制 (注2)来实现 sidecar 的自动注入。Initializer 目前是 kubernetes 的一个 Alpha feature,缺省是未启用的,需要通过api server的参数(注3)打开。因此我们先创建一个 kubeadm-conf 配置文件,用于配置 api server的启动参数。

apiVersion: kubeadm.k8s.io/v1alpha1
kind: MasterConfiguration
apiServerExtraArgs:
 admission-control: Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ValidatingAdmissionWebhook,ResourceQuota,DefaultTolerationSeconds,MutatingAdmissionWebhook
 runtime-config: admissionregistration.k8s.io/v1alpha1

使用 kubeadmin init 命令创建 kubernetes master 节点。 可以先试用 –dry-run 参数验证一下配置文件。

kubeadm init --config kubeadm-conf --dry-run

如果一切正常,kubeadm 将提示:Finished dry-running successfully. Above are the resources that would be created.

下面再实际执行创建命令

kubeadm init --config kubeadm-conf

kubeadm 会花一点时间拉取 docker image,命令完成后,会提示如何将一个 work node 加入 cluster。如下所示:

kubeadm join --token fffbf6.13bcb3563428cf23 10.12.5.15:6443 --discovery-token-ca-cert-hash sha256:27ad08b4cd9f02e522334979deaf09e3fae80507afde63acf88892c8b72f143f

备注:目前 kubeadm 只能支持在一个节点上安装 master,支持高可用的安装将在后续版本实现。kubernetes 官方给出的 workaround 建议是定期备份 etcd 数据kubeadm limitations。

Kubeadm 并不会安装 Pod 需要的网络,因此需要手动安装一个 Pod 网络,这里采用的是 Calico

kubectl apply -f https://docs.projectcalico.org ... .yaml

使用 kubectl 命令检查 master 节点安装结果

ubuntu@kube-1:~$ kubectl get all
NAME             TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
svc/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   12m

在每台工作节点上执行上述 kubeadm join 命令,即可把工作节点加入集群中。使用kubectl 命令检查 cluster 中的节点情况。

ubuntu@kube-1:~$ kubectl get nodes
NAME      STATUS    ROLES     AGE       VERSION
kube-1    Ready     master    21m       v1.9.0
kube-2    Ready     <none>    47s       v1.9.0




3. 安装Istio控制面和Bookinfo

参考 Nginmesh文档 (注4)安装 Istio 控制面和 Bookinfo 该文档的步骤清晰明确,这里不再赘述。

需要注意的是,在 Niginmesh 文档中,建议通过 Ingress 的 External IP 访问 bookinfo应用程序。但 Loadbalancer 只在支持的云环境中才会生效(注5),并且还需要进行一定的配置。如我在 Openstack 环境中创建的 cluster,则需要参照该文档(注6)对Openstack 进行配置后,Openstack 才能够支持 kubernetes 的 Loadbalancer service。如未进行配置,通过命令查看 Ingress External IP 一直显示为 pending 状态。

NAME            TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                                                            AGE
istio-ingress   LoadBalancer   10.111.158.10   <pending>     80:32765/TCP,443:31969/TCP                                         11m
istio-mixer     ClusterIP      10.107.135.31   <none>        9091/TCP,15004/TCP,9093/TCP,9094/TCP,9102/TCP,9125/UDP,42422/TCP   11m
istio-pilot     ClusterIP      10.111.110.65   <none>        15003/TCP,443/TCP                                                  11m

如不能配置云环境提供 Loadbalancer 特性, 我们可以直接使用集群中的一个节点IP:Nodeport 访问 Bookinfo 应用程序。

http://10.12.5.31:32765/productpage

想要了解更多关于如何从集群外部进行访问的内容,可以参考如何从外部访问Kubernetes集群中的应用?(注7)




4. 查看自动注入的sidecar

使用 kubectl get pod reviews-v3-5fff595d9b-zsb2q -o yaml 命令查看 Bookinfo 应用的 reviews 服务的 Pod。

apiVersion: v1
kind: Pod
metadata:
 annotations:
   sidecar.istio.io/status: injected-version-0.2.12
 creationTimestamp: 2018-01-02T02:33:36Z
 generateName: reviews-v3-5fff595d9b-
 labels:
   app: reviews
   pod-template-hash: "1999151856"
   version: v3
 name: reviews-v3-5fff595d9b-zsb2q
 namespace: default
 ownerReferences:
 - apiVersion: extensions/v1beta1
   blockOwnerDeletion: true
   controller: true
   kind: ReplicaSet
   name: reviews-v3-5fff595d9b
   uid: 5599688c-ef65-11e7-8be6-fa163e160c7d
 resourceVersion: "3757"
 selfLink: /api/v1/namespaces/default/pods/reviews-v3-5fff595d9b-zsb2q
 uid: 559d8c6f-ef65-11e7-8be6-fa163e160c7d
spec:
 containers:
 - image: istio/examples-bookinfo-reviews-v3:0.2.3
   imagePullPolicy: IfNotPresent
   name: reviews
   ports:
   - containerPort: 9080
     protocol: TCP
   resources: {}
   terminationMessagePath: /dev/termination-log
   terminationMessagePolicy: File
   volumeMounts:
   - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
     name: default-token-48vxx
     readOnly: true
 - args:
   - proxy
   - sidecar
   - -v
   - "2"
   - --configPath
   - /etc/istio/proxy
   - --binaryPath
   - /usr/local/bin/envoy
   - --serviceCluster
   - reviews
   - --drainDuration
   - 45s
   - --parentShutdownDuration
   - 1m0s
   - --discoveryAddress
   - istio-pilot.istio-system:15003
   - --discoveryRefreshDelay
   - 1s
   - --zipkinAddress
   - zipkin.istio-system:9411
   - --connectTimeout
   - 10s
   - --statsdUdpAddress
   - istio-mixer.istio-system:9125
   - --proxyAdminPort
   - "15000"
   - --controlPlaneAuthPolicy
   - NONE
   env:
   - name: POD_NAME
     valueFrom:
       fieldRef:
         apiVersion: v1
         fieldPath: metadata.name
   - name: POD_NAMESPACE
     valueFrom:
       fieldRef:
         apiVersion: v1
         fieldPath: metadata.namespace
   - name: INSTANCE_IP
     valueFrom:
       fieldRef:
         apiVersion: v1
         fieldPath: status.podIP
   image: nginmesh/proxy_debug:0.2.12
   imagePullPolicy: Always
   name: istio-proxy
   resources: {}
   securityContext:
     privileged: true
     readOnlyRootFilesystem: false
     runAsUser: 1337
   terminationMessagePath: /dev/termination-log
   terminationMessagePolicy: File
   volumeMounts:
   - mountPath: /etc/istio/proxy
     name: istio-envoy
   - mountPath: /etc/certs/
     name: istio-certs
     readOnly: true
   - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
     name: default-token-48vxx
     readOnly: true
 dnsPolicy: ClusterFirst
 initContainers:
 - args:
   - -p
   - "15001"
   - -u
   - "1337"
   image: nginmesh/proxy_init:0.2.12
   imagePullPolicy: Always
   name: istio-init
   resources: {}
   securityContext:
     capabilities:
       add:
       - NET_ADMIN
     privileged: true
   terminationMessagePath: /dev/termination-log
   terminationMessagePolicy: File
   volumeMounts:
   - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
     name: default-token-48vxx
     readOnly: true
 nodeName: kube-2
 restartPolicy: Always
 schedulerName: default-scheduler
 securityContext: {}
 serviceAccount: default
 serviceAccountName: default
 terminationGracePeriodSeconds: 30
 tolerations:
 - effect: NoExecute
   key: node.kubernetes.io/not-ready
   operator: Exists
   tolerationSeconds: 300
 - effect: NoExecute
   key: node.kubernetes.io/unreachable
   operator: Exists
   tolerationSeconds: 300
 volumes:
 - emptyDir:
     medium: Memory
   name: istio-envoy
 - name: istio-certs
   secret:
     defaultMode: 420
     optional: true
     secretName: istio.default
 - name: default-token-48vxx
   secret:
     defaultMode: 420
     secretName: default-token-48vxx
status:
 conditions:
 - lastProbeTime: null
   lastTransitionTime: 2018-01-02T02:33:54Z
   status: "True"
   type: Initialized
 - lastProbeTime: null
   lastTransitionTime: 2018-01-02T02:36:06Z
   status: "True"
   type: Ready
 - lastProbeTime: null
   lastTransitionTime: 2018-01-02T02:33:36Z
   status: "True"
   type: PodScheduled
 containerStatuses:
 - containerID: docker://5d0c189b9dde8e14af4c8065ee5cf007508c0bb2b3c9535598d99dc49f531370
   image: nginmesh/proxy_debug:0.2.12
   imageID: docker-pullable://nginmesh/proxy_debug@sha256:6275934ea3a1ce5592e728717c4973ac704237b06b78966a1d50de3bc9319c71
   lastState: {}
   name: istio-proxy
   ready: true
   restartCount: 0
   state:
     running:
       startedAt: 2018-01-02T02:36:05Z
 - containerID: docker://aba3e114ac1aa87c75e969dcc1b0725696de78d3407c5341691d9db579429f28
   image: istio/examples-bookinfo-reviews-v3:0.2.3
   imageID: docker-pullable://istio/examples-bookinfo-reviews-v3@sha256:6e100e4805a8c10c47040ea7b66f10ad619c7e0068696032546ad3e35ad46570
   lastState: {}
   name: reviews
   ready: true
   restartCount: 0
   state:
     running:
       startedAt: 2018-01-02T02:35:47Z
 hostIP: 10.12.5.31
 initContainerStatuses:
 - containerID: docker://b55108625832a3205a265e8b45e5487df10276d5ae35af572ea4f30583933c1f
   image: nginmesh/proxy_init:0.2.12
   imageID: docker-pullable://nginmesh/proxy_init@sha256:f73b68839f6ac1596d6286ca498e4478b8fcfa834e4884418d23f9f625cbe5f5
   lastState: {}
   name: istio-init
   ready: true
   restartCount: 0
   state:
     terminated:
       containerID: docker://b55108625832a3205a265e8b45e5487df10276d5ae35af572ea4f30583933c1f
       exitCode: 0
       finishedAt: 2018-01-02T02:33:53Z
       reason: Completed
       startedAt: 2018-01-02T02:33:53Z
 phase: Running
 podIP: 192.168.79.138
 qosClass: BestEffort
 startTime: 2018-01-02T02:33:39Z

该命令行输出的内容相当长,我们可以看到 Pod 中注入了一个 nginmesh/proxy_debug container , 还增加了一个 initContainer nginmesh/proxy_init。这两个容器是通过kubernetes initializer 自动注入到 pod 中的。这两个 container 分别有什么作用呢?让我们看一下 Nginmesh 源代码中的说明(注8):

proxy_debug, which comes with the agent and NGINX.

proxy_init, which is used for configuring iptables rules for transparently injecting an NGINX proxy from the proxy_debug image into an application pod.

proxy_debug 就是 sidecar 代理,proxy_init 则用于配置 iptable 规则,以将应用的流量导入到 sidecar 代理中。

查看 proxy_init 的 Dockerfile 文件,可以看到 proxy_init 其实是调用了prepare_proxy.sh(注9)这个脚本来创建 iptable 规则。

proxy_debug Dockerfile

FROM debian:stretch-slim
RUN apt-get update && apt-get install -y iptables
ADD prepare_proxy.sh /
ENTRYPOINT ["/prepare_proxy.sh"]

prepare_proxy.sh节选

...omitted for brevity 

# Create a new chain for redirecting inbound and outbound traffic to
# the common Envoy port.
iptables -t nat -N ISTIO_REDIRECT                                             -m comment --comment "istio/redirect-common-chain"
iptables -t nat -A ISTIO_REDIRECT -p tcp -j REDIRECT --to-port ${ENVOY_PORT}  -m comment --comment "istio/redirect-to-envoy-port"

# Redirect all inbound traffic to Envoy.
iptables -t nat -A PREROUTING -j ISTIO_REDIRECT                               -m comment --comment "istio/install-istio-prerouting"

# Create a new chain for selectively redirecting outbound packets to
# Envoy.
iptables -t nat -N ISTIO_OUTPUT                                               -m comment --comment "istio/common-output-chain"

...omitted for brevity





4. 关联阅读

Istio  及Bookinfo 示例程序安装试用笔记(注10)




5. 参考

Service Mesh with Istio and NGINX(注11)

Using kubeadm to Create a Cluster(注12)

Kubernetes Reference Documentation-Dynamic Admission Control(注13)



注:

1、https://kubernetes.io/docs/set ... beadm

2、https://kubernetes.io/docs/adm ... izers

3、https://kubernetes.io/docs/adm ... lpha-

4、https://github.com/nginmesh/nginmesh

5、https://kubernetes.io/docs/con ... ancer

6、https://docs.openstack.org/mag ... .html

7、http://zhaohuabing.com/2017/11 ... side/

8、https://github.com/nginmesh/ng ... agent

9、https://github.com/nginmesh/ng ... xy.sh

10、https://github.com/nginmesh/ng ... xy.sh

11、https://github.com/nginmesh/nginmesh/

12、https://kubernetes.io/docs/set ... hosts

13、https://kubernetes.io/docs/set ... hosts


 

Service Mesh深度思考 | DreamMesh抛砖引玉(3)-艰难的过渡

ServiceMesh小数 发表了文章 • 0 个评论 • 138 次浏览 • 2018-04-11 15:10 • 来自相关话题

作者:

       敖小剑,资深码农,十六年软件开发经验,微服务专家,Service Mesh布道师。专注于基础架构,Cloud Native 拥护者,敏捷实践者,坚守开发一线打磨匠艺的架构师。机缘巧合下对基础架构和微服务有过深入研究和实践。

        博客链接:https://skyao.io



在上一篇中,我们讨论的话题是:如果没有做好Cloud Native的准备,该怎么上Service Mesh。本章继续讨论,假定Cloud Native已经准备好,看看Service Mesh的道路是否就一帆风顺。



问题所在


如何从非Service Mesh体系过渡到Service Mesh?


我们需要考虑的是:

即使一切准备就绪,对于一个有存量应用的系统而言,绝无可能将所有应用都一起改为Service Mesh,然后一夜之间上线。


必然会有一个中间过渡状态,一部分应用开始搬迁到 Service Mesh,一部分还停留在原有体系。


那么,在过渡阶段,Service Mesh 内的服务和 Service Mesh 外的服务在通讯时会遇到哪些问题?



场景分析


我们来看一个具体的例子,有三个服务,调用关系分别是 A->B->C,然后在最前面架设 API Gateway。非常典型的微服务体系:






这里可以是 spring cloud/dubbo/motan 等各种侵入式微服务架构,左边的注册中心/registry 的实现也可以有多种,服务间通讯的方式也不尽相同。但是,都不影响我们的讨论。


上图可以看到,在标准的微服务框架中,处理这样一个请求,调用方式是清晰明了的。


如果开始转向 Service Mesh 体系,无论是 Istio/Conduit,都会引入一个新的 K8S 体系。为了充分演示,我们选择将服务B转移到 Service Mesh。调用关系就一下变成复杂:






这里我们引入两个术语(TBD:应该是业界通用术语吧?待确认):


东西向通讯:指微服务间相互调用。

南北向通讯:指外界访问微服务体系,通常是通过API Gateway。


当B被迁移后,B原有的上游调用(A调用B)和下游调用(B调用C),虽然业务语意上依然还是东西向通讯,但是由于跨了体系导致原有的调用方式被打破。只能另想办法,目前看通常的做法都是改走南北向通讯。



影响


而这个改变会带来巨大的工作量:


   1. B的所有上游服务都要修改

原有的标准服务间通讯(通过sdk进行服务发现/负载均衡等)都废弃,需要改为对k8s体系入口如Ingress的调用。然后在Ingress这边也要做好对服务B的配置。

  2. B对所有下游服务的调用方式都要修改


同样,原有的标准服务间通讯都废弃,需要改为对API Gateway的调用。然后在API Gateway这边也要做好对下游服务的配置。


而通讯机制改变带来的工作量不是唯一的问题,还有一个内部服务对外暴露的问题:

在原有体系中,服务B和服务C都是内部服务,完全可以不对外暴露,API Gateway访问的只是服务A;

迁移之后,为了让服务B的上游服务能够访问到服务B,就不得不将服务B暴露出来;

同样,为了让服务B能够访问它的下游服务,就不得不将服务C暴露出来。

原体系中只有服务A对外暴露,现在服务B和服务C也不得不暴露。而对外暴露服务,就意味着必然还会有一堆相关的工作需要完成:

认证

授权

加密

……


而这些都意味着:工作量/复杂度/更多的开发测试上线。






后续影响

随着应用往 Service Mesh 体系的逐渐迁移,我们开始迁移服务C和服务A。


先看服务C迁移到来的变化:







此时服务B到服务C的调用从原来的走 API Gateway 改变为 Service Mesh 体系内的服务间调用。然后 API Gateway 不再需要调用服务C,可以去除和服务C相关的内容。


再看服务A的迁移:








此时服务B不再需要暴露,而服务A的暴露方式发生变化,另外服务A调用服务B的方式也有改变。


我们抛开细节,只看整体:在服务 A/B/C 迁移到 Service Mesh 体系的过程中,服务间调用方式和对外暴露方式的变化,带来了一系列的工作量。而耗费这些工作量的中间环节,在整体迁移完成之后都会消失。换言之,都是迫不得已的临时投入,对最后的系统不产生增益。


直白一点:在过渡阶段的这诸多折腾,只是完成了服务迁移,而不能带来任何收益。这一点,无疑是令人沮丧的。


问题本质

反思一下:为何服务只是体系间迁移一下,就需要增加这么多不带来实际收益的工作量和复杂度?到底我们上面这些折腾是在做什么?

很明显,在这个过程中,我们没有任何业务改动,三个服务的实现也没有发生任何变化。

那么,改变的东西是什么?


是服务间通讯:


迁移过程中,服务A/B/C之间的通讯在业务语意上虽然依然属于东西向的服务间通讯机制,但是在实现上,却不得不临时转为南北向的网关到服务的通讯机制。


这个转变是无奈的,两个体系之间存在以下问题导致无法继续走东西向服务间通讯机制:


1. 没有共同的registry,因此无法相互感知;

2. 没有可以直接连通的网络通道,原有的服务间通讯被迫走公开的API Gateway和Ingress通道;

3. 两个体系的服务间通讯机制也可能不同,导致迁移之后不得不重新实现服务间通讯机制;

4. API Gateway和Ingress对于服务暴露的方式也不尽相同,各种特性如认证/加密/服务路由等方式也很可能完全不同。

这就如同江河中的淡水鱼,如果要随波汇入大海,就必须要能适应海水。


然后我们的问题在于,在过渡阶段,不得不花费大量投入来的完成被两个体系分割的服务间通讯,增加了大量额外的工作。



后记

有没有办法解决这个问题,或者部分减轻工作量,为将来的 Service Mesh 转型做好准备?

后续章节会深入探讨这个话题,给出部分解决方案,也欢迎大家给出意见或者参与讨论。

有兴趣的朋友,请添加小数微信:xiaoshu062,加入service mesh内部讨论群。



讨论和反馈

冉启春:任何两个架构体系的迁移都是痛苦的

于文涛:运维团队负责容器化和k8s,基础架构部负责数据库拆分和分库分表以及底层中间件,业务平台部门参与微服务业务改造,其实路径没有统一的,得看不同团队的执行结果和如何协调了。谁强势先突破可能会有主导权。不过一般的路径是先底层后业务层。


  查看全部
作者:

       敖小剑,资深码农,十六年软件开发经验,微服务专家,Service Mesh布道师。专注于基础架构,Cloud Native 拥护者,敏捷实践者,坚守开发一线打磨匠艺的架构师。机缘巧合下对基础架构和微服务有过深入研究和实践。

        博客链接:https://skyao.io



在上一篇中,我们讨论的话题是:如果没有做好Cloud Native的准备,该怎么上Service Mesh。本章继续讨论,假定Cloud Native已经准备好,看看Service Mesh的道路是否就一帆风顺。



问题所在


如何从非Service Mesh体系过渡到Service Mesh?


我们需要考虑的是:

即使一切准备就绪,对于一个有存量应用的系统而言,绝无可能将所有应用都一起改为Service Mesh,然后一夜之间上线。


必然会有一个中间过渡状态,一部分应用开始搬迁到 Service Mesh,一部分还停留在原有体系。


那么,在过渡阶段,Service Mesh 内的服务和 Service Mesh 外的服务在通讯时会遇到哪些问题?



场景分析


我们来看一个具体的例子,有三个服务,调用关系分别是 A->B->C,然后在最前面架设 API Gateway。非常典型的微服务体系:

1.png


这里可以是 spring cloud/dubbo/motan 等各种侵入式微服务架构,左边的注册中心/registry 的实现也可以有多种,服务间通讯的方式也不尽相同。但是,都不影响我们的讨论。


上图可以看到,在标准的微服务框架中,处理这样一个请求,调用方式是清晰明了的。


如果开始转向 Service Mesh 体系,无论是 Istio/Conduit,都会引入一个新的 K8S 体系。为了充分演示,我们选择将服务B转移到 Service Mesh。调用关系就一下变成复杂:

2.png


这里我们引入两个术语(TBD:应该是业界通用术语吧?待确认):


东西向通讯:指微服务间相互调用。

南北向通讯:指外界访问微服务体系,通常是通过API Gateway。


当B被迁移后,B原有的上游调用(A调用B)和下游调用(B调用C),虽然业务语意上依然还是东西向通讯,但是由于跨了体系导致原有的调用方式被打破。只能另想办法,目前看通常的做法都是改走南北向通讯。



影响


而这个改变会带来巨大的工作量:


   1. B的所有上游服务都要修改

原有的标准服务间通讯(通过sdk进行服务发现/负载均衡等)都废弃,需要改为对k8s体系入口如Ingress的调用。然后在Ingress这边也要做好对服务B的配置。

  2. B对所有下游服务的调用方式都要修改


同样,原有的标准服务间通讯都废弃,需要改为对API Gateway的调用。然后在API Gateway这边也要做好对下游服务的配置。


而通讯机制改变带来的工作量不是唯一的问题,还有一个内部服务对外暴露的问题:

在原有体系中,服务B和服务C都是内部服务,完全可以不对外暴露,API Gateway访问的只是服务A;

迁移之后,为了让服务B的上游服务能够访问到服务B,就不得不将服务B暴露出来;

同样,为了让服务B能够访问它的下游服务,就不得不将服务C暴露出来。

原体系中只有服务A对外暴露,现在服务B和服务C也不得不暴露。而对外暴露服务,就意味着必然还会有一堆相关的工作需要完成:

认证

授权

加密

……


而这些都意味着:工作量/复杂度/更多的开发测试上线。






后续影响

随着应用往 Service Mesh 体系的逐渐迁移,我们开始迁移服务C和服务A。


先看服务C迁移到来的变化:

3.png



此时服务B到服务C的调用从原来的走 API Gateway 改变为 Service Mesh 体系内的服务间调用。然后 API Gateway 不再需要调用服务C,可以去除和服务C相关的内容。


再看服务A的迁移:


4.png



此时服务B不再需要暴露,而服务A的暴露方式发生变化,另外服务A调用服务B的方式也有改变。


我们抛开细节,只看整体:在服务 A/B/C 迁移到 Service Mesh 体系的过程中,服务间调用方式和对外暴露方式的变化,带来了一系列的工作量。而耗费这些工作量的中间环节,在整体迁移完成之后都会消失。换言之,都是迫不得已的临时投入,对最后的系统不产生增益。


直白一点:在过渡阶段的这诸多折腾,只是完成了服务迁移,而不能带来任何收益。这一点,无疑是令人沮丧的。


问题本质

反思一下:为何服务只是体系间迁移一下,就需要增加这么多不带来实际收益的工作量和复杂度?到底我们上面这些折腾是在做什么?

很明显,在这个过程中,我们没有任何业务改动,三个服务的实现也没有发生任何变化。

那么,改变的东西是什么?


是服务间通讯:


迁移过程中,服务A/B/C之间的通讯在业务语意上虽然依然属于东西向的服务间通讯机制,但是在实现上,却不得不临时转为南北向的网关到服务的通讯机制。


这个转变是无奈的,两个体系之间存在以下问题导致无法继续走东西向服务间通讯机制:


1. 没有共同的registry,因此无法相互感知;

2. 没有可以直接连通的网络通道,原有的服务间通讯被迫走公开的API Gateway和Ingress通道;

3. 两个体系的服务间通讯机制也可能不同,导致迁移之后不得不重新实现服务间通讯机制;

4. API Gateway和Ingress对于服务暴露的方式也不尽相同,各种特性如认证/加密/服务路由等方式也很可能完全不同。

这就如同江河中的淡水鱼,如果要随波汇入大海,就必须要能适应海水。


然后我们的问题在于,在过渡阶段,不得不花费大量投入来的完成被两个体系分割的服务间通讯,增加了大量额外的工作。



后记

有没有办法解决这个问题,或者部分减轻工作量,为将来的 Service Mesh 转型做好准备?

后续章节会深入探讨这个话题,给出部分解决方案,也欢迎大家给出意见或者参与讨论。

有兴趣的朋友,请添加小数微信:xiaoshu062,加入service mesh内部讨论群。



讨论和反馈

冉启春:任何两个架构体系的迁移都是痛苦的

于文涛:运维团队负责容器化和k8s,基础架构部负责数据库拆分和分库分表以及底层中间件,业务平台部门参与微服务业务改造,其实路径没有统一的,得看不同团队的执行结果和如何协调了。谁强势先突破可能会有主导权。不过一般的路径是先底层后业务层。


 

envoy的注入是怎么实现的?

回复

Envoy難易之相成也 回复了问题 • 1 人关注 • 1 个回复 • 187 次浏览 • 2018-04-04 17:21 • 来自相关话题

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

Istio小数 发表了文章 • 0 个评论 • 357 次浏览 • 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
 

Service Mesh深度思考 | DreamMesh抛砖引玉(2)-CloudNative

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

作者:
       敖小剑,资深码农,十六年软件开发经验,微服务专家,Service Mesh布道师。专注于基础架构,Cloud Native 拥护者,敏捷实践者,坚守开发一线打磨匠艺的架构师。机缘巧合下对基础架构和微服务有过深入研究和实践。
        博客链接:https://skyao.io
 
 
 
我对 Service Mesh 的第一个担忧,来自 Cloud Native。
 
 
Are You Ready?
 
作为 Cloud Native 的忠实拥护者,我从不怀疑 Cloud Native 的价值和前景。可以说,微服务/容器这些技术天然就适合走 Cloud Native 的道路。
 
但是,我担心的是:准备上 Service Mesh 的各位,是否都已经做到了 Ready for Cloud Native?
 

 
这真是一个尴尬的问题。
 
现实摆在眼前,根据我最近几个月跑过的企业客户(大大小小接近二十家)的实际情况看,可以说:情况非常不乐观。
 
备注: 这里只讨论普通企业用户,对于技术和管理都比较先进的互联网大公司来说,Cloud Native的普及情况要好很多。
 
这就引出了下面这个问题:
 
如果没有Cloud Native基础,那还能不能用Service Mesh?
 
 
 
发展路径
 
这里有三条发展路径可选:
 
1、先Cloud Native,再Service Mesh
 
理论上说,这是最合理的:先把底层基础设施铺好,再在其上构建上层业务应用。
 
具体说,就是先上云/容器/k8s,应用暂时维持原状。不管是单体应用,还是基于Dubbo/Spring Cloud等侵入式开发框架的微服务应用,先上云再说。更直白一点,上k8s。
 
等待Istio/Conduit成熟之后,再迁移到Service Mesh方案。
 
 
 2、先Service Mesh,再Cloud Native
 
这个方案理论上也是可行的:先用Service Mesh方案完成微服务体系建设,之后再迁移到k8s平台。
 
之所以说理论上没有问题,是指Service Mesh从设计理念上,对底层是不是容器并没有特别要求。无论是容器/虚拟机/物理机,Service Mesh都是可行的。
 
 
3、同时上 Service Mesh 加 Cloud Native
 
通常来说我们不赞成同时进行这两个技术变革,因为涉及到的内容实在太多,集中在一起,指望一口气吃成大胖子,容易被噎住。
 
但是不管怎么样这条路终究还是存在的,而且如果决心够大+愿意投入+高人护航,也不失是一个一次性彻底解决问题的方案,先列在这里。
 
 
 
何去何从
 
路径1和路径2,在讨论该如何选择之前,还有一个问题:就是路径2是不是真的可行?

 
青黄不接的尴尬

我们前面说道路径2理论上是可行的,但是目前的实际情况是真要选择就会发现:难。这要从目前市面上的 Service Mesh 产品谈起,按照我的划分方式,我将目前主流的四个 Service Mesh 产品划分为两代:
第一代 Service Mesh,包括 Linkerd 和 Envoy。
 
这两个产品目前都是 production ready,而且都和平台无关,对物理机/虚拟机/容器都可以支持。
第二代 Service Mesh,包括 Istio 和 Conduit
 
这两个产品目前都还在发展中,暂时都未能达到 production ready。
 
如果要在当前时刻进行 Service Mesh 的技术选型,我们就会发现这样一个尴尬的局面:
Istio 和 Conduit 还没有 production ready,上线不适合,只能继续等待。
 
Linkerd 和 Envoy 倒是可用,但是,在了解 Istio 和 Conduit 之后,又有多少人愿意在现在选择上 Linkerd 和 Envoy?
 
所谓青黄不接,便是如此。
 
在接下来的讨论中,我们假定大家都是在等待 Istio 和 Conduit。
 
我们回到前面的话题,限定 Istio 和 Conduit,如果选择路径2(先 Service Mesh,再 Cloud Native),会如何?
 
 
 
对平台的要求
  
Conduit

首先 Conduit 非常坚定执着的”Say No”了,官网非常清晰的表述:
 
Conduit is a next-generation ultralight service mesh for Kubernetes.
 
私底下和 William (小编注:Buoyant CEO)就此简单聊过,他给出来的回答很委婉也很实在:Conduit 总要从某个地方起步,K8S是目前最好选择。以后可以支持,但是肯定先 K8S 再说。考虑到 Conduit 和 Buoyant 公司的处境,尤其全公司才二十,我们不能要求太多。
 
可以明确的说,短期之内,起码2018年,Conduit 官方不会有对  K8S之外的支持。

 
Istio   

Isito 最早版本是只支持 K8S 的,后来陆续提供了对其他非 K8S 环境的支持,比如 Docker+Consul/Eureka 的方案,还有计划中但是还没有完成的 Cloud Fountry 和 Mesos 集成。
 
对于 VM,Istio 有提供一个 VM 解决方案,具体看见官方文档:
Integrating Virtual Machines集成虚拟机: 中文翻译版本
 
从文档上看是可以支持部分服务在 K8S 之外:
 
TBD: 需要继续调研看 Istio 是否可以在纯粹的  VM环境下运行,即完全脱离 K8S 和容器。
 
 
 
平台要求总结
 
Conduit 和 Istio(还有待最后确认)对容器/K8s/Cloud Native 都有要求,导致目前路径2(先 Service Mesh,再 Cloud Native)几乎没有无法实现,至少在不改动 Conduit 和 Istio 的情况下。
 
这就意味着,只能走路径1(先 Cloud Native,再 Service Mesh),也就回到了最早的问题: 做好了 Cloud Native 的准备吗?
 
 
 
后记
 
需要做一个市场调查,要有足够多的样本:
 
企业客户对微服务和容器,是打算先上容器/K8S再上微服务,还是希望可以直接在虚拟机/物理机上做微服务,后面再迁移到K8S?
 
有兴趣的朋友,添加小数微信:xiaoshu062,加入service mesh微信交流群,一起讨论~
 
 
 
讨论和反馈
 
在这篇博客文章编写前一天晚上,和来自 Google Istio 开发团队的Hu同学有过一次长时间的讨论。
 
在征得同意之后我将讨论内容整理如下。特别鸣谢Hu同学的指点:
 
Hu: 你好,这么晚还在工作?
 
敖小剑:正在整理思路。
 
Hu: 文章写的很好。
 
敖小剑:您客气了,还是你们产品做的好,istio我是报以厚望。
 
Hu:希望不要让大家失望,能够解决一些实际问题。
 
敖小剑:一起努力吧,就算有小的不足,也还是有机会改进的,istio的大方向我是非常认可的。
 
Hu:恩,现在是一个新时代的开始,cloud native是大势所趋,后面我们会看到更多有趣的技术出来。有什么想法和建议,也欢迎在istio的工作组里提。
 
敖小剑:我现在是一边等istio的production ready版本,一边着手准备,为落地可能遇到的问题或者需求预先研究一下。
 
国内可能情况和美国不太一样,目前国内企业,尤其传统形的企业,他们的技术基础非常糟糕,离cloud native差距很远。
 
但是他们又有强烈的意愿上微服务。
 
Hu:对,但这也是机遇。国内的企业软件市场还有很大空间。美国公司喜欢新技术,跟的比较紧。
 
敖小剑:我选择istio这种service mesh方案来推微服务落地,本意是降低微服务普及的门槛。
 
这样普通企业用户才有机会玩转微服务,毕竟这些公司连spring cloud都玩的很吃力。
 
现在的问题是,istio比较强调cloud native,而这些企业用户基本都没有准备好cloud native。
 
Hu:呵呵,我觉得你的想法很好,不过可能有点超前。据我所知,即使在很多互联网大企业, service mesh也没有完全落地。第一步可能还是docker化和普及kubernetes。
 
敖小剑:我刚才还在看如何在非k8s,非docker环境下跑istio。嗯,你的思路是先准备好路,再让istio这辆车上路?我的思路有点倾向于让service mesh这个车在没路的情况下也能跑起来。
 
Hu:我的意思是要看条件,可以把非K8S方案作为一个过渡。最终还是要迁移到kube和云上。
 
敖小剑:嗯,对的,我想增加一个过渡阶段。
 
Hu:都可以的,就看企业的自身条件了。Google这边是提供不同解决方案的,但最终目标还是希望客户迁移到云上。
 
敖小剑:cloud native条件不成熟的情况下,先过渡一下,把应用迁移到非docker条件下的istio,先完成微服务化。
 
两条路,一条先cloud native再service mesh,一条先service mesh再cloud native。
 
Hu:恩,我觉得都是可行的。如果是重IT的公司,建议直接cloudnative。
 
敖小剑:不同企业可能演进的速度和步骤不一样。微服务化更多是业务团队推动,cloud native通常是运维和基础架构团队。
 
Hu:我对国内情况不了解,只是个人看法,呵呵。其实可能最重要的还是普及devops的模式,人的问题解决了,别的都好办。
 
敖小剑:嗯,我个人的感觉是技术导向的互联网公司容易做到cloud native,他们走你说的路线比较合理。但是普通企业用户可能会选择先微服务化。
 
当然这个我还要继续调研和确认,比较我现在接触的样本也不够多。所以,多讨论多沟通,确认好实际需要再说。
 
我这段时间会陆陆续续把想法写出来,然后提交大家讨论。希望你多给意见。
 
Hu:好的。
 
在这篇博客文章发表收集到的讨论和评论反馈:
 
张琦:我们的经验,必定要走你说的路径2,servicemesh甚至要充当从传统应用到Cloudnative之间的桥梁。例如在逐渐微服务化的过程中 用mesh来接入原来的单体应用 然后再一点一点去拆;或者用mesh接入其他协议的遗留应用来做一下协议转换,我记得微博也有这种用法
 
崔秀龙:posta那篇微服务改造的文章还是很可以参考的
 
肖晟:没错,企业随着IT架构的演进,上面提到的遗留应用并不在少数。需要解决协议适配等问题,又不想受限于服务总线类流量中心的瓶颈,mesh是一种理想的解决之道;而想要上mesh,又可能推动其上cloudnative。所以从企业总体来说,这个演变很可能是混合的,不过从单应用来说会是分步的。
 
肖晟:另外在思考的一个问题是,在一个企业IT架构下,由于不同技术标准或安全需求等因素的影响,有没有可能同时存在两套或多套servicemesh。
 
备注: 这个话题后面会有专门的章节
崔秀龙:我觉得是两个必须:必须容器云,必须打SC。
 
宋净超:理想很丰满,现实很骨感啊。
 
崔秀龙:我个人的感觉是有了SM之后,微服务的定义就很清晰了。
 
宋净超:同意。
 
孟樊亮:迁移到k8s,感觉是服务注册/发现/互通只是第一步,后续的治理和运维才是无尽大坑。
 
于文涛:我们公司应该是偏第一种方案,先走容器化,k8s后微服务化。不过微服务和也其实在同时推进。
 
 
 
 
推荐阅读:

Service Mesh深度思考 | DreamMesh抛砖引玉(1)-序
Istio服务网格高级流量镜像,7种模式解决流量镜像难题
使用Istio简化微服务系列三:如何才能做“金丝雀部署”,并通过Istio增加流量?
在Kubernetes平台上,应对不同场景外部流量引入集群,这3种工具改如何选择?
 
 
  查看全部
作者:
       敖小剑,资深码农,十六年软件开发经验,微服务专家,Service Mesh布道师。专注于基础架构,Cloud Native 拥护者,敏捷实践者,坚守开发一线打磨匠艺的架构师。机缘巧合下对基础架构和微服务有过深入研究和实践。
        博客链接:https://skyao.io
 
 
 
我对 Service Mesh 的第一个担忧,来自 Cloud Native
 
 
Are You Ready?
 

作为 Cloud Native 的忠实拥护者,我从不怀疑 Cloud Native 的价值和前景。可以说,微服务/容器这些技术天然就适合走 Cloud Native 的道路。
 
但是,我担心的是:准备上 Service Mesh 的各位,是否都已经做到了 Ready for Cloud Native?
 

 
这真是一个尴尬的问题。
 
现实摆在眼前,根据我最近几个月跑过的企业客户(大大小小接近二十家)的实际情况看,可以说:情况非常不乐观。
 
备注: 这里只讨论普通企业用户,对于技术和管理都比较先进的互联网大公司来说,Cloud Native的普及情况要好很多。
 
这就引出了下面这个问题:
 
如果没有Cloud Native基础,那还能不能用Service Mesh?
 
 
 
发展路径

 
这里有三条发展路径可选:
 
1、先Cloud Native,再Service Mesh
 
理论上说,这是最合理的:先把底层基础设施铺好,再在其上构建上层业务应用。
 
具体说,就是先上云/容器/k8s,应用暂时维持原状。不管是单体应用,还是基于Dubbo/Spring Cloud等侵入式开发框架的微服务应用,先上云再说。更直白一点,上k8s。
 
等待Istio/Conduit成熟之后,再迁移到Service Mesh方案。
 
 
 2、先Service Mesh,再Cloud Native
 
这个方案理论上也是可行的:先用Service Mesh方案完成微服务体系建设,之后再迁移到k8s平台。
 
之所以说理论上没有问题,是指Service Mesh从设计理念上,对底层是不是容器并没有特别要求。无论是容器/虚拟机/物理机,Service Mesh都是可行的。
 
 
3、同时上 Service Mesh 加 Cloud Native
 
通常来说我们不赞成同时进行这两个技术变革,因为涉及到的内容实在太多,集中在一起,指望一口气吃成大胖子,容易被噎住。
 
但是不管怎么样这条路终究还是存在的,而且如果决心够大+愿意投入+高人护航,也不失是一个一次性彻底解决问题的方案,先列在这里。
 
 
 
何去何从

 
路径1和路径2,在讨论该如何选择之前,还有一个问题:就是路径2是不是真的可行?

 
青黄不接的尴尬


我们前面说道路径2理论上是可行的,但是目前的实际情况是真要选择就会发现:难。这要从目前市面上的 Service Mesh 产品谈起,按照我的划分方式,我将目前主流的四个 Service Mesh 产品划分为两代:
  • 第一代 Service Mesh,包括 Linkerd 和 Envoy。

 
这两个产品目前都是 production ready,而且都和平台无关,对物理机/虚拟机/容器都可以支持。
  • 第二代 Service Mesh,包括 Istio 和 Conduit

 
这两个产品目前都还在发展中,暂时都未能达到 production ready。
 
如果要在当前时刻进行 Service Mesh 的技术选型,我们就会发现这样一个尴尬的局面:
  • Istio 和 Conduit 还没有 production ready,上线不适合,只能继续等待。

 
  • Linkerd 和 Envoy 倒是可用,但是,在了解 Istio 和 Conduit 之后,又有多少人愿意在现在选择上 Linkerd 和 Envoy?

 
所谓青黄不接,便是如此。
 
在接下来的讨论中,我们假定大家都是在等待 Istio 和 Conduit。
 
我们回到前面的话题,限定 Istio 和 Conduit,如果选择路径2(先 Service Mesh,再 Cloud Native),会如何?
 
 
 
对平台的要求
  
Conduit

首先 Conduit 非常坚定执着的”Say No”了,官网非常清晰的表述:
 
Conduit is a next-generation ultralight service mesh for Kubernetes.
 
私底下和 William (小编注:Buoyant CEO)就此简单聊过,他给出来的回答很委婉也很实在:Conduit 总要从某个地方起步,K8S是目前最好选择。以后可以支持,但是肯定先 K8S 再说。考虑到 Conduit 和 Buoyant 公司的处境,尤其全公司才二十,我们不能要求太多。
 
可以明确的说,短期之内,起码2018年,Conduit 官方不会有对  K8S之外的支持。

 
Istio   

Isito 最早版本是只支持 K8S 的,后来陆续提供了对其他非 K8S 环境的支持,比如 Docker+Consul/Eureka 的方案,还有计划中但是还没有完成的 Cloud Fountry 和 Mesos 集成。
 
对于 VM,Istio 有提供一个 VM 解决方案,具体看见官方文档:
  • Integrating Virtual Machines
  • 集成虚拟机: 中文翻译版本

 
从文档上看是可以支持部分服务在 K8S 之外:
 
TBD: 需要继续调研看 Istio 是否可以在纯粹的  VM环境下运行,即完全脱离 K8S 和容器。
 
 
 
平台要求总结

 
Conduit 和 Istio(还有待最后确认)对容器/K8s/Cloud Native 都有要求,导致目前路径2(先 Service Mesh,再 Cloud Native)几乎没有无法实现,至少在不改动 Conduit 和 Istio 的情况下。
 
这就意味着,只能走路径1(先 Cloud Native,再 Service Mesh),也就回到了最早的问题: 做好了 Cloud Native 的准备吗?
 
 
 
后记
 
需要做一个市场调查,要有足够多的样本:
 
企业客户对微服务和容器,是打算先上容器/K8S再上微服务,还是希望可以直接在虚拟机/物理机上做微服务,后面再迁移到K8S?
 
有兴趣的朋友,添加小数微信:xiaoshu062,加入service mesh微信交流群,一起讨论~
 
 
 
讨论和反馈
 

在这篇博客文章编写前一天晚上,和来自 Google Istio 开发团队的Hu同学有过一次长时间的讨论。
 
在征得同意之后我将讨论内容整理如下。特别鸣谢Hu同学的指点:
 
Hu: 你好,这么晚还在工作?
 
敖小剑:正在整理思路。
 
Hu: 文章写的很好。
 
敖小剑:您客气了,还是你们产品做的好,istio我是报以厚望。
 
Hu:希望不要让大家失望,能够解决一些实际问题。
 
敖小剑:一起努力吧,就算有小的不足,也还是有机会改进的,istio的大方向我是非常认可的。
 
Hu:恩,现在是一个新时代的开始,cloud native是大势所趋,后面我们会看到更多有趣的技术出来。有什么想法和建议,也欢迎在istio的工作组里提。
 
敖小剑:我现在是一边等istio的production ready版本,一边着手准备,为落地可能遇到的问题或者需求预先研究一下。
 
国内可能情况和美国不太一样,目前国内企业,尤其传统形的企业,他们的技术基础非常糟糕,离cloud native差距很远。
 
但是他们又有强烈的意愿上微服务。
 
Hu:对,但这也是机遇。国内的企业软件市场还有很大空间。美国公司喜欢新技术,跟的比较紧。
 
敖小剑:我选择istio这种service mesh方案来推微服务落地,本意是降低微服务普及的门槛。
 
这样普通企业用户才有机会玩转微服务,毕竟这些公司连spring cloud都玩的很吃力。
 
现在的问题是,istio比较强调cloud native,而这些企业用户基本都没有准备好cloud native。
 
Hu:呵呵,我觉得你的想法很好,不过可能有点超前。据我所知,即使在很多互联网大企业, service mesh也没有完全落地。第一步可能还是docker化和普及kubernetes。
 
敖小剑:我刚才还在看如何在非k8s,非docker环境下跑istio。嗯,你的思路是先准备好路,再让istio这辆车上路?我的思路有点倾向于让service mesh这个车在没路的情况下也能跑起来。
 
Hu:我的意思是要看条件,可以把非K8S方案作为一个过渡。最终还是要迁移到kube和云上。
 
敖小剑:嗯,对的,我想增加一个过渡阶段。
 
Hu:都可以的,就看企业的自身条件了。Google这边是提供不同解决方案的,但最终目标还是希望客户迁移到云上。
 
敖小剑:cloud native条件不成熟的情况下,先过渡一下,把应用迁移到非docker条件下的istio,先完成微服务化。
 
两条路,一条先cloud native再service mesh,一条先service mesh再cloud native。
 
Hu:恩,我觉得都是可行的。如果是重IT的公司,建议直接cloudnative。
 
敖小剑:不同企业可能演进的速度和步骤不一样。微服务化更多是业务团队推动,cloud native通常是运维和基础架构团队。
 
Hu:我对国内情况不了解,只是个人看法,呵呵。其实可能最重要的还是普及devops的模式,人的问题解决了,别的都好办。
 
敖小剑:嗯,我个人的感觉是技术导向的互联网公司容易做到cloud native,他们走你说的路线比较合理。但是普通企业用户可能会选择先微服务化。
 
当然这个我还要继续调研和确认,比较我现在接触的样本也不够多。所以,多讨论多沟通,确认好实际需要再说。
 
我这段时间会陆陆续续把想法写出来,然后提交大家讨论。希望你多给意见。
 
Hu:好的。
 
在这篇博客文章发表收集到的讨论和评论反馈:
 
张琦:我们的经验,必定要走你说的路径2,servicemesh甚至要充当从传统应用到Cloudnative之间的桥梁。例如在逐渐微服务化的过程中 用mesh来接入原来的单体应用 然后再一点一点去拆;或者用mesh接入其他协议的遗留应用来做一下协议转换,我记得微博也有这种用法
 
崔秀龙:posta那篇微服务改造的文章还是很可以参考的
 
肖晟:没错,企业随着IT架构的演进,上面提到的遗留应用并不在少数。需要解决协议适配等问题,又不想受限于服务总线类流量中心的瓶颈,mesh是一种理想的解决之道;而想要上mesh,又可能推动其上cloudnative。所以从企业总体来说,这个演变很可能是混合的,不过从单应用来说会是分步的。
 
肖晟:另外在思考的一个问题是,在一个企业IT架构下,由于不同技术标准或安全需求等因素的影响,有没有可能同时存在两套或多套servicemesh。
 
备注: 这个话题后面会有专门的章节
崔秀龙:我觉得是两个必须:必须容器云,必须打SC。
 
宋净超:理想很丰满,现实很骨感啊。
 
崔秀龙:我个人的感觉是有了SM之后,微服务的定义就很清晰了。
 
宋净超:同意。
 
孟樊亮:迁移到k8s,感觉是服务注册/发现/互通只是第一步,后续的治理和运维才是无尽大坑。
 
于文涛:我们公司应该是偏第一种方案,先走容器化,k8s后微服务化。不过微服务和也其实在同时推进。
 
 
 
 
推荐阅读:

Service Mesh深度思考 | DreamMesh抛砖引玉(1)-序
Istio服务网格高级流量镜像,7种模式解决流量镜像难题
使用Istio简化微服务系列三:如何才能做“金丝雀部署”,并通过Istio增加流量?
在Kubernetes平台上,应对不同场景外部流量引入集群,这3种工具改如何选择?
 
 
 

Kubernetes NodePorts vs LoadBalancers vs Ingress,到底应该什么时候使用?

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

作者:Sandeep Dinesh

翻译:狄卫华

原文:Kubernetes NodePort vs LoadBalancer vs Ingress? When should I use what?

原文链接:https://medium.com/google-clou ... 849e0



最近有人向我了解 NodePorts ,LoadBalancers 和 Ingress 之间的区别是怎么样的。 它们都是将外部流量引入群集的方式,适用的场景却各不相同。 本文接下来我们将介绍它们的工作原理以及适用的相关场景。


注意:文中所述内容适用于 GKE (Google Kubernetes Engine 注1)。 如果你在其他云平台上运行使用步骤略有不同,比如 minikube 或其他相关软件。 我也不打算过多深入技术细节, 如果你有兴趣了解更多,Kubernetes 官方文档(注2)会提供更多的有用资源!



ClusterIP

ClusterIP 服务是 Kubernetes 默认的服务类型。 如果你在集群内部创建一个服务,则在集群内部的其他应用程序可以进行访问,但是不具备集群外部访问的能力。

ClusterIP 服务的 YAML 文件看起来像这样:


apiVersion: v1


kind: Service

metadata:  

  name: my-internal-service

selector:    

  app: my-app

spec:

  type: ClusterIP

  ports:  

  - name: http

    port: 80

    targetPort: 80

    protocol: TCP


如果不能从互联网访问 ClusterIP 服务,我为什么要谈论它呢?事实上,你可以通过 Kubernetes 代理进行访问。








感谢 Ahmet Alp Balkan(注3)提供的图表


启动 Kubernetes 代理:

$ kubectl proxy --port=8080

现在,可以通过 Kubernetes API 通过以下的模式来访问这个服务:


http://localhost:8080/api/v1/p ... t%3B/,


通过这种方式可以使用以下的地址来访问我们上述定义的服务:

http://localhost:8080/api/v1/p ... http/


何时使用这种访问方式?


有以下几种场景,你可以使用 Kubernetes 代理的方式来访问服务:

1. 调试服务或者某些情况下通过笔记本电脑直接连接服务

2. 允许内部的通信,显示内部的仪表盘(dashboards)等

因为此种方式需要作为一个授权用户运行 kubectl,因此不应该用来暴露服务至互联网访问或者用于生产环境。


NodePort

NodePort 服务通过外部访问服务的最基本的方式。顾名思义,NodePort 就是在所有的节点或者虚拟机上开放特定的端口,该端口的流量将被转发到对应的服务。
 





从技术上层面,这不能算是最准确的图表,但我认为它能够直观展示了 NodePort 的工作方式。

NodePort 服务的 YAML 文件看起来像这样:

apiVersion: v1

kind: Service

metadata:  

  name: my-nodeport-service

selector:    

  app: my-app

spec:

  type: NodePort

  ports:  

  - name: http

    port: 80

    targetPort: 80

    nodePort: 30036

    protocol: TCP

从根本上讲,NodePort 方式的服务与 ClusterIP 方式的服务有两个区别。第一,类型是 NodePort,这需要指定一个称作 nodePort 的附加端口,并在所有节点上打开对应的端口。如果我们不具体指定端口,集群会选择一个随机的端口。大多数的情况下,我们都可以让 Kubernetes 帮我们选择合适的端口。正如 thockin(注4) 所描述的那样,有许多相关的注意事项(caveats)关于那些端口可供我们使用。


何时使用这种访问方式?

NodePort 方式有许多缺点:

1. 每个服务占用一个端口
2. 可以使用的  30000-32767 范围端口 (译者注:可以通过api-server启动参数service-node-port-range,指定限制范围,默认为30000-32767)
3. 如果节点/虚拟机IP地址发生更改,需要进行相关处理


由于上述原因,我不建议在生产环境中使用直接暴露服务。 如果运行的服务不要求高可用或者非常关注成本,这种方法则比较适合。 很好的例子就是用于演示或临时使用的程序。



LoadBalancer

LoadBalancer 服务是暴露服务至互联网最标准的方式。在 GKE 上,这将启动一个网络负载均衡器(注5),它会提供一个 IP 地址,以将所有流量转发到服务。






感谢 Ahmet Alp Balkan提供图表

何时使用这种访问方式?这是公开服务的默认的方法。指定的端口上流量都将被转发到对应的服务,不经过过滤和其他路由等操作。这种方式意味着转发几乎任何类型的流量,如HTTP,TCP,UDP,Websockets,gRPC或其他。


这种方式最大的缺点是,负载均衡器公开的每个服务都将获取独立 IP 地址,而我们则必须为每个暴露的服务对应的负载均衡器支付相关费用,这可能会变得非常昂贵!




Ingress

和上述讨论的服务方式不同,Ingress 实际上并不是服务类型中的一种。相反,它位于多个服务的前端充当一个智能路由或者集群的入口点。

你可以使用 Ingress 做很多不同的事情,并且不同类型的 Ingress 控制也具备不同的能力。

GKE 默认的 Ingress 控制器将启动一个 HTTP(S) 的负载均衡器。则将使我们可以基于访问路径和子域名将流量路由到后端服务。例如,你可以将 `foo.yourdomain.com` 下的流量转发到 foo 服务,将`yourdomain.com/bar/` 路径下的流量转发到 bar 服务。







感谢 Ahmet Alp Balkan提供图表


在 GKE 上定义 L7层 HTTP 负载均衡器的 Ingress 对象定义的 YAML 看起来像这样:

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

  name: my-ingress

spec:

  backend:

    serviceName: other

    servicePort: 8080

  rules:

  - host: foo.mydomain.com

    http:

      paths:

      - backend:

          serviceName: foo

          servicePort: 8080

  - host: mydomain.com

    http:

      paths:

      - path: /bar/*

        backend:

          serviceName: bar

          servicePort: 8080


何时使用这种方式?Ingress 方式可能是暴露服务的最强大的方式,但也最复杂。现在有不同类型的 Ingress 控制器,包括 Google 云 负载均衡器(注6), Nginx(注7), Contour(注8), Istio(注9)等。此外,还有 Ingress 控制器的许多插件,比如 cert-manager(注10)可以用来自动为服务提供 SSL 证书。


如果希望在同一个IP地址下暴露多个服务,并且它们都使用相同的 L7 协议(通常是HTTP),则 Ingress 方式最有用。 如果使用本地 GCP 集成,则只需支付一台负载平衡器费用,并且是“智能”性 Ingress ,可以获得许多开箱即用的功能(如SSL,Auth,路由等)。


资源:

Kubernetes:https://medium.com/tag/kubernetes?source=post

Microservices:https://medium.com/tag/microservices?source=post

Services:https://medium.com/tag/services?source=post

Load Balancing:https://medium.com/tag/load-balancing?source=post

Ingress:https://medium.com/tag/ingress?source=post





1、https://cloud.google.com/gke

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

3、https://medium.com/@ahmetb

4、(https://medium.com/@thockin)

5、https://cloud.google.com/compu ... work/

6、https://cloud.google.com/kuber ... ancer

7、https://github.com/kubernetes/ingress-nginx

8、https://github.com/heptio/contour

9、https://istio.io/docs/tasks/tr ... .html

10、https://github.com/jetstack/cert-manager
  查看全部
作者:Sandeep Dinesh

翻译:狄卫华

原文:Kubernetes NodePort vs LoadBalancer vs Ingress? When should I use what?

原文链接:https://medium.com/google-clou ... 849e0



最近有人向我了解 NodePorts ,LoadBalancers 和 Ingress 之间的区别是怎么样的。 它们都是将外部流量引入群集的方式,适用的场景却各不相同。 本文接下来我们将介绍它们的工作原理以及适用的相关场景。


注意:文中所述内容适用于 GKE (Google Kubernetes Engine 注1)。 如果你在其他云平台上运行使用步骤略有不同,比如 minikube 或其他相关软件。 我也不打算过多深入技术细节, 如果你有兴趣了解更多,Kubernetes 官方文档(注2)会提供更多的有用资源!



ClusterIP

ClusterIP 服务是 Kubernetes 默认的服务类型。 如果你在集群内部创建一个服务,则在集群内部的其他应用程序可以进行访问,但是不具备集群外部访问的能力。

ClusterIP 服务的 YAML 文件看起来像这样:


apiVersion: v1


kind: Service

metadata:  

  name: my-internal-service

selector:    

  app: my-app

spec:

  type: ClusterIP

  ports:  

  - name: http

    port: 80

    targetPort: 80

    protocol: TCP


如果不能从互联网访问 ClusterIP 服务,我为什么要谈论它呢?事实上,你可以通过 Kubernetes 代理进行访问。


1.png



感谢 Ahmet Alp Balkan(注3)提供的图表


启动 Kubernetes 代理:

$ kubectl proxy --port=8080

现在,可以通过 Kubernetes API 通过以下的模式来访问这个服务:


http://localhost:8080/api/v1/p ... t%3B/


通过这种方式可以使用以下的地址来访问我们上述定义的服务:

http://localhost:8080/api/v1/p ... http/


何时使用这种访问方式?


有以下几种场景,你可以使用 Kubernetes 代理的方式来访问服务:

1. 调试服务或者某些情况下通过笔记本电脑直接连接服务

2. 允许内部的通信,显示内部的仪表盘(dashboards)等

因为此种方式需要作为一个授权用户运行 kubectl,因此不应该用来暴露服务至互联网访问或者用于生产环境。


NodePort

NodePort 服务通过外部访问服务的最基本的方式。顾名思义,NodePort 就是在所有的节点或者虚拟机上开放特定的端口,该端口的流量将被转发到对应的服务。
 
2.png


从技术上层面,这不能算是最准确的图表,但我认为它能够直观展示了 NodePort 的工作方式。

NodePort 服务的 YAML 文件看起来像这样:

apiVersion: v1

kind: Service

metadata:  

  name: my-nodeport-service

selector:    

  app: my-app

spec:

  type: NodePort

  ports:  

  - name: http

    port: 80

    targetPort: 80

    nodePort: 30036

    protocol: TCP

从根本上讲,NodePort 方式的服务与 ClusterIP 方式的服务有两个区别。第一,类型是 NodePort,这需要指定一个称作 nodePort 的附加端口,并在所有节点上打开对应的端口。如果我们不具体指定端口,集群会选择一个随机的端口。大多数的情况下,我们都可以让 Kubernetes 帮我们选择合适的端口。正如 thockin(注4) 所描述的那样,有许多相关的注意事项(caveats)关于那些端口可供我们使用。


何时使用这种访问方式?

NodePort 方式有许多缺点:

1. 每个服务占用一个端口
2. 可以使用的  30000-32767 范围端口 (译者注:可以通过api-server启动参数service-node-port-range,指定限制范围,默认为30000-32767)
3. 如果节点/虚拟机IP地址发生更改,需要进行相关处理


由于上述原因,我不建议在生产环境中使用直接暴露服务。 如果运行的服务不要求高可用或者非常关注成本,这种方法则比较适合。 很好的例子就是用于演示或临时使用的程序。



LoadBalancer

LoadBalancer 服务是暴露服务至互联网最标准的方式。在 GKE 上,这将启动一个网络负载均衡器(注5),它会提供一个 IP 地址,以将所有流量转发到服务。

3.png


感谢 Ahmet Alp Balkan提供图表

何时使用这种访问方式?这是公开服务的默认的方法。指定的端口上流量都将被转发到对应的服务,不经过过滤和其他路由等操作。这种方式意味着转发几乎任何类型的流量,如HTTP,TCP,UDP,Websockets,gRPC或其他。


这种方式最大的缺点是,负载均衡器公开的每个服务都将获取独立 IP 地址,而我们则必须为每个暴露的服务对应的负载均衡器支付相关费用,这可能会变得非常昂贵!




Ingress

和上述讨论的服务方式不同,Ingress 实际上并不是服务类型中的一种。相反,它位于多个服务的前端充当一个智能路由或者集群的入口点。

你可以使用 Ingress 做很多不同的事情,并且不同类型的 Ingress 控制也具备不同的能力。

GKE 默认的 Ingress 控制器将启动一个 HTTP(S) 的负载均衡器。则将使我们可以基于访问路径和子域名将流量路由到后端服务。例如,你可以将 `foo.yourdomain.com` 下的流量转发到 foo 服务,将`yourdomain.com/bar/` 路径下的流量转发到 bar 服务。


4.png


感谢 Ahmet Alp Balkan提供图表


在 GKE 上定义 L7层 HTTP 负载均衡器的 Ingress 对象定义的 YAML 看起来像这样:

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

  name: my-ingress

spec:

  backend:

    serviceName: other

    servicePort: 8080

  rules:

  - host: foo.mydomain.com

    http:

      paths:

      - backend:

          serviceName: foo

          servicePort: 8080

  - host: mydomain.com

    http:

      paths:

      - path: /bar/*

        backend:

          serviceName: bar

          servicePort: 8080


何时使用这种方式?Ingress 方式可能是暴露服务的最强大的方式,但也最复杂。现在有不同类型的 Ingress 控制器,包括 Google 云 负载均衡器(注6), Nginx(注7), Contour(注8), Istio(注9)等。此外,还有 Ingress 控制器的许多插件,比如 cert-manager(注10)可以用来自动为服务提供 SSL 证书。


如果希望在同一个IP地址下暴露多个服务,并且它们都使用相同的 L7 协议(通常是HTTP),则 Ingress 方式最有用。 如果使用本地 GCP 集成,则只需支付一台负载平衡器费用,并且是“智能”性 Ingress ,可以获得许多开箱即用的功能(如SSL,Auth,路由等)。


资源:

Kubernetes:https://medium.com/tag/kubernetes?source=post

Microservices:https://medium.com/tag/microservices?source=post

Services:https://medium.com/tag/services?source=post

Load Balancing:https://medium.com/tag/load-balancing?source=post

Ingress:https://medium.com/tag/ingress?source=post





1、https://cloud.google.com/gke

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

3、https://medium.com/@ahmetb

4、(https://medium.com/@thockin)

5、https://cloud.google.com/compu ... work/

6、https://cloud.google.com/kuber ... ancer

7、https://github.com/kubernetes/ingress-nginx

8、https://github.com/heptio/contour

9、https://istio.io/docs/tasks/tr ... .html

10、https://github.com/jetstack/cert-manager
 

有没有一个可用的现成例子项目?

交流问答SNOW 回复了问题 • 6 人关注 • 4 个回复 • 896 次浏览 • 2018-03-28 17:09 • 来自相关话题

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

Istio小数 发表了文章 • 0 个评论 • 202 次浏览 • 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