如何将服务迁移到网格中

如何管理应用服务

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)使用以下端口和协议。

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

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

服务器优先协议

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

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

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

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

因为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