如何将服务迁移到网格中

如何管理应用服务

Istio为应用程序提供了大量功能,而对应用程序代码本身影响很小或没有影响。许多Kubernetes应用程序可以部署在启用Istio的集群中,而无需进行任何更改。但是,在部署支持Istio的应用程序时,可能需要特别考虑Istio的sidecar模型的某些含义。本文档介绍了这些应用程序注意事项以及Istio支持的特定要求。

pod 要求

要成为网格的一部分,Kubernetes pod必须满足以下要求:

  • 服务关联:即使Pod不公开任何端口,pod也必须至少属于一个Kubernetes服务。如果Pod属于多个Kubernetes服务,则这些服务不能将相同的端口号用于不同的协议,例如HTTP和TCP。

  • 应用程序的UID:确保您的pod没有使用用户ID(UID)值1337运行应用程序。

  • NET_ADMIN和NET_RAW功能:如果在您的集群中实施了PSP,并且除非使用Istio CNI插件,否则您的Pod必须具有NET_ADMIN和NET_RAW能力。Envoy代理的初始化容器需要这些功能。

要检查您的Pod是否允许NET_ADMIN和NET_RAW功能,您需要检查其服务帐户是否可以使用允许NET_ADMIN和NET_RAW功能的Pod安全策略。如果尚未在Pod的deployment中指定服务帐户,则Pod将使用其deployment所在的命名空间中的default服务帐户运行。

要列出服务帐户的功能,替换和 为对应的值,执行以下命令:

for psp in $(kubectl get psp -o jsonpath="{range .items[*]}{@.metadata.name}{'\n'}{end}"); do if [ $(kubectl auth can-i use psp/$psp --as=system:serviceaccount:<your namespace>:<your service account>) = yes ]; then kubectl get psp/$psp --no-headers -o=custom-columns=NAME:.metadata.name,CAPS:.spec.allowedCapabilities; fi; done

例如,要检查名称空间中的default服务帐户default,请运行以下命令:

for psp in $(kubectl get psp -o jsonpath="{range .items[*]}{@.metadata.name}{'\n'}{end}"); do if [ $(kubectl auth can-i use psp/$psp --as=system:serviceaccount:default:default) = yes ]; then kubectl get psp/$psp --no-headers -o=custom-columns=NAME:.metadata.name,CAPS:.spec.allowedCapabilities; fi; done

如果您在服务帐户的允许策略之一的功能列表中看到NET_ADMIN和NET_RAW或*,您的Pod有权运行Istio初始化容器。否则,需要提供对应的权限。

  • 具有应用程序和版本标签的Pod: 我们建议在使用Kubernetes Deployment的Pod规范中添加一个明确的app标签和version标签。应用程序和版本标签将上下文信息添加到Istio收集的指标和遥测中。。

    • app标签:每个部署应该有一个明显的 app一个有意义的价值标签。该app标签是用来添加在分布式跟踪上下文信息。

    • version标签:此标签指示对应于特定的部署应用程序的版本。

  • 命名服务端口:可以选择命名服务端口以显式指定协议。有关更多详细信息,请参见协议选择。

Istio使用的端口

Istio sidecar代理(Envoy)使用以下端口和协议。

端口

协议

描述

仅限Pod内部

15000

TCP协议

envoy管理端口(命令/诊断)

15001

TCP协议

envoy出站

15006

TCP协议

envoy入站

15008

TCP协议

envoy隧道端口(入站)

15020

HTTP

Istio代理,Envoy和应用程序合并的Prometheus遥测

15021

HTTP

健康检查

15090

HTTP

envoy prometheus 遥测

Istio控制平面(istiod)使用以下端口和协议。

port

协议

描述

仅本地主机

15010

GRPC

XDS和CA服务(纯文本)

15012

GRPC

XDS和CA服务(TLS,建议用于生产)

8080

HTTP

调试接口(已弃用)

443

HTTPS

网络挂钩

15014

HTTP

控制平面监控

为避免端口与边车冲突,应用程序不应使用Envoy使用的任何端口。

服务器优先协议

一些协议是"服务器优先"协议,这意味着服务器将发送第一个字节。这可能会影响 PERMISSIVEmTLS和自动协议选择。

这两个功能都通过检查连接的初始字节来确定协议来起作用,该协议与服务器优先协议不兼容。

为了支持这些情况,请按照Explicit协议选择步骤将应用程序的协议声明为TCP。

已知以下端口通常带有服务器优先协议,并且自动假定为TCP:

协议

端口

SMTP

25

DNS

53

MySQL

3306

MongoDB

27017

因为TLS通信不是服务器优先,所以TLS加密服务器优先通信将与自动协议检测一起使用,只要您确保对所有进行TLS嗅探的通信都进行了加密:

  • 配置服务器的mTLS模式STRICT。这将对所有请求强制执行TLS加密。

  • 配置服务器的mTLS模式DISABLE。这将禁用TLS嗅探,从而允许使用服务器优先协议。

  • 将所有客户端配置为TLS通常通过DestinationRule或依靠自动mTLS来发送流量。

  • 配置您的应用程序以直接发送TLS通信。

应用程序绑定地址

当Istio捕获入站流量时,它将重定向到该localhost地址。因此,应用程序应绑定到 localhost(127.0.0.1对于IPv4或::1IPv6)或通配符(0.0.0.0对于IPv4或::IPv6)。监听其Pod IP的应用程序将需要进行修改。

出站流量

为了支持Istio的流量路由功能,离开Pod的流量的路由可能与未部署Sidecar时的路由不同。

对于基于HTTP的流量,流量将基于Host标头进行路由。如果目标IP和Host标头未对齐,则可能导致意外行为。例如,像这样的请求curl 1.2.3.4 -H "Host: httpbin.default"将被路由到httpbin服务,而不是1.2.3.4。

对于基于非HTTP的流量(包括HTTPS),Istio无法访问Host标头,因此路由决策基于服务IP地址。

其中的一个含义是直接curl 匹配到Pod(例如)而不是Services的直接调用将不匹配。尽管流量可以通过,但不会获得完整的Istio功能,包括mTLS加密,流量路由和遥测。

协议选择

Istio支持代理任何TCP通信。这包括HTTP,HTTPS,gRPC以及原始TCP协议。为了提供其他功能,例如路由和富度量,必须确定协议。这可以自动完成,也可以明确指定。

不使用基于非TCP的协议(例如UDP)。这些协议将继续正常运行,不受Istio代理的任何拦截,但不能在仅代理的组件(例如入口或出口网关)中使用。

自动协议选择

Istio可以自动检测HTTP和HTTP/2通信。如果无法自动确定协议,则将流量视为纯TCP流量。

明确的协议选择

可以在服务定义中手动指定协议。

可以通过两种方式进行配置:

通过端口名称:name: [-]。 在Kubernetes 1.18+中,按appProtocol字段:appProtocol: 。 支持以下协议:

  • http

  • http2

  • https

  • tcp

  • tls

  • grpc

  • grpc-web

  • mongo

  • mysql*

  • redis*

  • udp (不会代理UDP,但可以将端口明确声明为UDP)

*这些协议默认情况下处于禁用状态,以避免意外启用实验功能。要启用它们,请配置相应的Pilot环境变量。

下面是一个服务的示例,该服务定义了一个mysqlby byappProtocol和一个httpport by name:

kind: Service
metadata:
  name: myservice
spec:
  ports:
  - number: 3306
    name: database
    appProtocol: mysql
  - number: 80
    name: http-web

Last updated