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中查看到日誌;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章