Istio是一款优秀的Service Mesh,很好的补齐了 k8s 在微服务治理上的这部分能力。同时,两者结合后,在生产环境可能因为错误的配置等原因遇到一些问题,本篇主要记录下踩到的一些坑。
Istio协议选择
Istio 默认支持代理所有 TCP 流量。包括 HTTP、HTTPS、gRPC 以及原始 TCP 协议。但为了提供额外的能力,比如路由和丰富的指标,必须确定协议。协议可以被自动检测或者手动声明。
协议可以在Service定义中手动指定。
可以通过以下两种方式配置:
- 通过端口名称配置:name: [-]。
- 在版本 1.18+ 的Kubernetes,通过 appProtocol 字段配置:appProtocol: 。
例如,Service 通过 appProtocol 、名称分别定义一个 mysql 端口和一个 http 端口:
kind: Service
metadata:
name: myservice
spec:
ports:
- port: 3306
name: database
appProtocol: mysql
- port: 80
name: http-web
但是在实际生产过程中,由于错误配置,name字段未按照规范命名,同时没有appProtocal字段,导致协议被自动检查,使用Http协议,导致解析失败。案例如下:
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
ports:
- name: kafka-gRPC-8090
protocol: gRPC
port: 8090
targetPort: 8090
- name: http-addition
protocol: TCP
port: 8001
targetPort: 8001
我们可以看到在 ports 中的name字段起点不是协议名,导致被自动检查,使用了错误的协议。
官方具体的配置指导链接:istio.io/latest/zh/d…
Istio优雅终止
当项目上线新特性时,经常出现grpc断链告警,经过排查,是envoy被强杀,业务容器还未处理完,就结束了。
当使用Istio,流量会先经过sicecar。
当 Pod 开始停止时,它将从服务的 endpoints 中摘除掉,不再转发流量给它,同时 Sidecar 也会收到 SIGTERM 信号,立刻不再接受 inbound 新连接,但会保持存量 inbound 连接继续处理,outbound 方向流量仍然可以正常发起。
若 Pod 没有很快退出,istio 默认是会在停止开始的 5s 后强制杀死 envoy,当 envoy 进程不在了也就无法转发任何流量(不管是 inbound 还是 outbound 方向)。
所以如果业务容器处理时间较长,导致未处理完,就断开了,这时就会有问题。
这时,我们可以对参数 terminationDrainDuration 设置合理值。zheg
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
annotations:
proxy.istio.io/config: |
terminationDrainDuration: 30s # 这里自定义 Envoy 优雅终止时长
labels:
app: nginx
同时,增加 preStopHook,能够执行一定时间的 sleep,这个主要是影响 “新建请求” 到业务 Pod,也就是业务新特性刚发布进行灰度时。 例如:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: abc
name: abc
spec:
replicas: 1
selector:
matchLabels:
app: abc
template:
metadata:
labels:
app: abc
spec:
containers:
image: xxxx.com/abc:v1
imagePullPolicy: IfNotPresent
name: app
ports:
- containerPort: 8086
name: http
protocol: TCP
lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 10"] # 延迟关闭 10秒 -- T2
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 60 # 容忍关闭时间 60秒 -- T1, T3时间就是 60 - 10 = 50秒
主要参考的文章链接:
www.jianshu.com/p/87b5b0688… zhuanlan.zhihu.com/p/378077951
livenessProbe就绪探针崩溃,Pod重启
之前遇到了一次生产故障,流量激增,CPU骤增,就绪探针崩溃,导致Pod一直重启,使得原先的问题扩大化,临时采取的措施是,删除就绪探针配置,避免Pod重启。
实际情况与这篇文章类似:blog.csdn.net/oqqYuan1234…
同时,生产环境的istio为1.8版本,不支持TCP livenessprobe 探测,增加配置,临时使用netstat检查端口是否正常。设置类似如下:
apiVersion: v1
kind: Pod
metadata:
name: liveness-pod
namespace: default
spec:
containers:
- name: myapp
image: xxxxx
imagePullPolicy: IfNotPresent
livenessProbe:
exec:
command: ['sh','-c','netstat -nlp|grep -w 5160'] #检测端口是否存在
initialDelaySeconds: 10 #Pod开启后,延迟10s再进行检测
官方问题描述链接:github.com/istio/istio…
后续的版本弥补了这一缺陷,github.com/istio/istio…
参考文档:blog.fatedier.com/2021/08/24/…