Istio - 集成ELK - HPE_INVALID_METHOD, lumberjack protocol error

之前在K8s平台,采用的ELK(Elasticsearch+Logstash+Kibana+Filebeat)的日志采集与展示方案,

K8s方案

方案1

在每个K8s Node主机上设置DemonSet->Filebeat,通过Filebeat收集所有当前Node上pod容器中的stdout日志输出,需要每个应用配置stdout日志输出(在springboot log4j2中需要配置console日志输出),同时Logstash、ES部署在K8s集群外;

log4j2配置: 

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="off" monitorInterval="1800">
    <properties>
        <property name="LOG_HOME">/data/logs/project_name/</property>
        <property name="FILE_NAME">project_name</property>
    </properties>
    
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n"/>
        </Console>

        ...
    </Appenders>
    
    <Loggers>
        <Logger name="com.mx" level="trace" additivity="false">
            <AppenderRef ref="..."/>
            <AppenderRef ref="Console"/>
        </Logger>
    </Loggers>
</Configuration>

方案2

利用K8s中pod内可以存在多个docker容器,即在每个app所对应的pod中再单独添加一个filebeat容器,并且app容器的日志输出目录和filebeat容器日志监控目录挂载到同一本地文件目录下,由此伴生的filebeat容器来负责app容器日志的采集;同时Logstash、ES部署在K8s集群外;

方案1采用DemonSet的方式占用资源少(不必每个app都单独启动一个Demonset),但是由于开发都比较习惯log输出目录下日志的配置与查看方式,并且基于目录的日志采集配置比较灵活(可指定不同日志输出目录) ,故最终使用了方案2的方式;

Isito方案

在Isito中延用了K8s中的方案2,但是在Istio中所有的外部请求(如filebeat->logstash)都要经过sidecar(istio-proxy),

即在Istio中,filebeat要经过istio-proxy后才能将日志上传到Logstash:filebeat->istio-proxy->logstash

Isito - ELK - 问题

起初使用该方案在华为云上没有问题,但是到了公司的测试环境后发现日志怎么也上传不上去,并且发现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中查看到日志;

发布了56 篇原创文章 · 获赞 6 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/luo15242208310/article/details/101346017