之前在K8s平台,采用的ELK(Elasticsearch+Logstash+Kibana+Filebeat)的日志采集与展示方案,
方案1
在每个K8s Node主机上设置DemonSet->Filebeat,通过Filebeat收集所有当前Node上pod容器中的stdout日志输出,需要每个应用配置stdout日志输出(在springboot log4j2中需要配置console日志输出),同时Logstash、ES部署在K8s集群外;
log4j2配置:
/data/logs/project_name/
project_name
...
方案2
利用K8s中pod内可以存在多个docker容器,即在每个app所对应的pod中再单独添加一个filebeat容器,并且app容器的日志输出目录和filebeat容器日志监控目录挂载到同一本地文件目录下,由此伴生的filebeat容器来负责app容器日志的采集;同时Logstash、ES部署在K8s集群外;
方案1采用DemonSet的方式占用资源少(不必每个app都单独启动一个Demonset),但是由于开发都比较习惯log输出目录下日志的配置与查看方式,并且基于目录的日志采集配置比较灵活(可指定不同日志输出目录) ,故最终使用了方案2的方式;
在Isito中延用了K8s中的方案2,但是在Istio中所有的外部请求(如filebeat->logstash)都要经过sidecar(istio-proxy),
即在Istio中,filebeat要经过istio-proxy后才能将日志上传到Logstash:filebeat->istio-proxy->logstash
起初使用该方案在华为云上没有问题,但是到了公司的测试环境后发现日志怎么也上传不上去,并且发现K8s环境下日志是可以上传成功的,但是切换到Istio后日志便无法上传;
查看了Filebeat后,发现如下异常日志:
并且查看了app应用的istio-proxy日志,发现如下error:
lumberjack protocol error,HPE_INVALID_METHOD均揭示了istio-proxy和Logstash协议版本不匹配的问题,
起初看到lumberjack protocol error时,调查到了Istio 1.1.x 仅支持IPV4(1.2版本支持K8s IPV6),而Logstash默认监听IPV6,
可能是IP协议版本不匹配的问题,所以通过修改了Logstash的/usr/local/logstash-6.5.4/config/jvm.options中的JVM启动参数,添加如下jvm options:
-Djava.net.preferIPv4Stack=true
-Djava.net.preferIPv6Addresses=false
重启Logstash之后通过netstat进行查看,Logstash已经切换到IPV4:
但是Filebeat还是无法成功上传日志;
之后看到istio-proxy提示HPE_INVALID_METHOD时,调查到envoy目前不支持自定义的Http method,估计是Logstash支持的协议中使用了自定义的method,导致istio-proxy无法成功上传日志;
最后想到既然k8s集群支持ELK,而Istio集群(filebeat需要经过istio-proxy)不支持ELK,那么如果可以设置istio-proxy不去拦截filebeat->logstash的请求,而是由filebeat直接去访问logstash是否就可以成功了呢?
查看Istio官网direct-access-to-external-services,直接修改istio-system.configmap.istio-sidecar-injector中traffic.sidecar.istio.io/includeOutboundIPRanges为K8s集群内的IPRange(SERVICE_CIDR,CLUSTER_CIDR),如此Istio sidecar仅会去拦截K8s集群内的服务(即K8s集群内的Isito Traffic都会生效),而集群外的IPRange(例如单独部署在集群外的Logstash)都不会去拦截,修改后重启pod后便会看到istio-init初始化容器启动参数发生变化(如下图):
istio-init启动参数说明:
-p: 指定重定向所有 TCP 流量的 Envoy 端口(默认为 $ENVOY_PORT = 15001)
-u: 指定未应用重定向的用户的 UID。通常,这是代理容器的 UID(默认为 $ENVOY_USER 的 uid,istio_proxy 的 uid 或 1337)
-g: 指定未应用重定向的用户的 GID。(与 -u param 相同的默认值)
-m: 指定入站连接重定向到 Envoy 的模式,“REDIRECT” 或 “TPROXY”(默认为 $ISTIO_INBOUND_INTERCEPTION_MODE)
-b: 逗号分隔的入站端口列表,其流量将重定向到 Envoy(可选)。使用通配符 “*” 表示重定向所有端口。为空时表示禁用所有入站重定向(默认为 $ISTIO_INBOUND_PORTS)
-d: 指定要从重定向到 Envoy 中排除(可选)的入站端口列表,以逗号格式分隔。使用通配符“*” 表示重定向所有入站流量(默认为 $ISTIO_LOCAL_EXCLUDE_PORTS)
-i: 指定重定向到 Envoy(可选)的 IP 地址范围,以逗号分隔的 CIDR 格式列表。使用通配符 “*” 表示重定向所有出站流量。空列表将禁用所有出站重定向(默认为 $ISTIO_SERVICE_CIDR)
-x: 指定将从重定向中排除的 IP 地址范围,以逗号分隔的 CIDR 格式列表。使用通配符 “*” 表示重定向所有出站流量(默认为 $ISTIO_SERVICE_EXCLUDE_CIDR)。
参考连接:理解 Istio Service Mesh 中 Envoy 代理 Sidecar 注入及流量劫持
如上操作后,istio-proxy放过了对Logstash请求的拦截,直接通过filebeat去请求Logstash后发现日志成功上传到了Logstash->ES,之后便可在Kibana中查看到日志;