Istio開啟mtls請求503問題分析

博雲技術社群發表於2019-07-01


背景


為測試Istio流量管理,將兩個服務sleep、flaskapp的兩個版本v1、v2(部署檔案見參考連結)部署到Istio環境中,透過sleep-v1向flaskapp發起呼叫,正常結果會交替列印出結果v1和v2,然而在呼叫過程中報錯503 reset reason: connection failure,故將問題的步驟、現象、分析、驗證整理於此。



步驟


部署sleep、flaskapp應用,同時Istio平臺開啟mTls,名稱空間kangxzh開啟自動注入,部署如下圖所示:



kubectl apply -f sleep.istio.yaml -n kangxzh

kubectl apply -f flask.isito.yaml -n kangxzh

#檢視pod建立情況
kubectl -n kangxzh get pod -w

flaskapp-v1 -775d bb9b79-z54fj    2 / 2      Running                       13s
flaskapp-v2-d454cdd47-mdb8s     2 / 2      Running                       14s
sleep-v1 -7f 45c6cf94-zgdsf       2 / 2      Running                       19 h
sleep-v2 -58d ff94b49-fz6sj       2 / 2      Running                       19


現象


在sleep應用中發起http請求,呼叫flaskapp,curl ,如下所示:




#


export SOURCE_POD=$(kubectl get pod -l app= sleep ,version=v1 -o jsonpath={.items..metadata.name})
# 進入sleep發起http請求
kubectl -n kangxzh  exec  -it -c  sleep  $SOURCE_POD bash
bash- 4.4 # curl 
# 響應
upstream  connect  error  or  disconnect/ reset  before headers.  reset  reason: connection failure 


背景


1.檢測flaskapp tls 配置,如下:



[root@kubernetes-master flaskapp]

# istioctl authn tls-check flaskapp-v1-775dbb9b79-z54fj flaskapp.kangxzh.svc.cluster.local


HOST:PORT                                 STATUS     SERVER     CLIENT     AUTHN POLICY     DESTINATION RULE
flaskapp.kangxzh.svc.cluster.local: 80      OK         mTLS       mTLS        default /          default /istio-system 


STATUS OK 證明flaskapp tls配置正確。


進入sleep istio-proxy向flaskapp發起http請求:




kubectl

 -n kangxzh exec -it -c istio-proxy 

$SOURCE_POD

 bash

# 發起請求
curl 
# 響應
v1 


2.發現透過istio-proxy可以得到相應,因為開啟了mtls,透過istio-proxy直接請求是需要新增istio相關證書的,此時沒有加入證書也可請求,所以想到檢查flaskapp iptables配置,如下所示:




# 獲取程式號


PID=$(docker inspect --format {{.State.Pid}} $(docker ps | grep flaskapp-v1 | awk  '{print $1}'  | head -n 1))
# 檢視iptables 規則
nsenter -t  ${PID}  -n iptables -t nat -L -n -v
# 輸出
Chain PREROUTING (policy ACCEPT 477 packets, 28620 bytes)
 pkts bytes target     prot opt  in      out      source                destination
  487 29220 ISTIO_INBOUND  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain INPUT (policy ACCEPT 487 packets, 29220 bytes)
 pkts bytes target     prot opt  in      out      source                destination

Chain OUTPUT (policy ACCEPT 220 packets, 20367 bytes)
 pkts bytes target     prot opt  in      out      source                destination
    0   480 ISTIO_OUTPUT  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain POSTROUTING (policy ACCEPT 220 packets, 20367 bytes)
 pkts bytes target     prot opt  in      out      source                destination

Chain ISTIO_INBOUND (1 references)
 pkts bytes target     prot opt  in      out      source                destination
   10   600 ISTIO_IN_REDIRECT  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80     #是沒有的,修改後增加

Chain ISTIO_IN_REDIRECT (1 references)
 pkts bytes target     prot opt  in      out      source                destination
   10   600 REDIRECT   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            redir ports 15001

Chain ISTIO_OUTPUT (1 references)
 pkts bytes target     prot opt  in      out      source                destination
    0     0 ISTIO_REDIRECT  all  --  *      lo      0.0.0.0/0           !127.0.0.1
    8   480 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            owner UID match 1337
    0     0 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            owner GID match 1337
    0     0 RETURN     all  --  *      *       0.0.0.0/0            127.0.0.1
    0     0 ISTIO_REDIRECT  all  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain ISTIO_REDIRECT (2 references)
 pkts bytes target     prot opt  in      out      source                destination
    0     0 REDIRECT   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            redir ports 15001 


證明envoy沒有劫持到flaskapp 80的流量,也就是說上述第2步是sleep-istio-proxy直接請求flaskapp,沒有經過flaskapp-istio-proxy 轉發。


3. 此時才檢查flaskapp deployment,如下所示:



...

---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flaskapp-v1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: flaskapp
        version: v1
    spec:
      containers:
      - name: flaskapp
        image: dustise/flaskapp
        imagePullPolicy: IfNotPresent
        ports:
          - name: http
            containerPort: 80   #缺少containerPort
        env:
        - name: version
          value: v1
... 


官網說明中:



Pod ports: Pods must include an 

explicit

 list 

of

 the ports 

each

 container listens 

on

. Use a containerPort configuration 

in

 the container specification 

for

 

each

 port. Any unlisted ports bypass the Istio proxy.

# 未列出來來的埠都會繞過istio proxy 


同時describe flaskapp pod 如下所示:



kubectl 

describe

 pod flaskapp-v1

-6

df8d69fb8-fb5mr -n kangxzh

#
istio-proxy:
    ... 省略若干
    Args:
      ...
       --concurrency
       2
       --controlPlaneAuthPolicy
      MUTUAL_TLS
       --statusPort
       15020
       --applicationPorts
       ""   #為空 


在deployment中增加containerPort: 80後,如下所示:



istio-proxy:

    ... 省略若干
    Args:
      ...
       --concurrency
      2
       --controlPlaneAuthPolicy
      MUTUAL_TLS
       --statusPort
      15020
       --applicationPorts
      80 

注意:在Istio1.2版本以後也可透過設定Pod annotation 中 traffic.sidecar.istio.io/includeInboundPorts來達到同樣的目的,預設值為Pod的containerPorts列表,逗號分隔的監聽埠列表,這些流量會被重定向到 Sidecar,* 會重定向所有埠,具體詳情參見官網1.2新特性(見參考連結)


驗證


sleep 發起請求:



[root@kubernetes-master flaskapp]

# kubectl -n kangxzh exec -it -c sleep $SOURCE_POD bash


bash -4.4 # curl 
#響應
v1 


sleep-istio-proxy 未攜帶證書,發起請求:




kubectl

 -n kangxzh exec -it -c istio-proxy 

$SOURCE_POD

 bash

istio-proxy @sleep -v1-7f45c6cf94-zgdsf:/$ curl 
#響應
curl: ( 56 ) Recv failure: Connection reset by peer 
sleep-istio-proxy 攜帶證書,發起請求
istio-proxy @sleep -v1-7f45c6cf94-zgdsf:/$ curl 
#響應
v1 



參考連結


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69923336/viewspace-2649191/,如需轉載,請註明出處,否則將追究法律責任。

相關文章