Istio Sidecar の起動シーケンスによるアプリケーション コンテナ ネットワークの障害

1. 問題点

オンライン アプリケーションは Spring Cloud K8S Config モジュールを統合しています。アプリケーションが起動すると、K8S ConfigMap を構成として読み取ります。最近、オンライン アプリケーションが起動時に次の例外ログを報告することが観察されています (常にではなく、時折発生します)これは、アプリケーションが K8S ConfigMap 構成を取得できず、K8s ConfigMap の構成が実際には有効になっていないことを示します。

2023-02-28 11:18:16.950+0800 [main] WARN  o.s.c.k.f.c.Fabric8ConfigMapPropertySource - 
`Can't read configMap with name: [my-app] in namespace: [my-app-ns]. Ignoring.`
io.fabric8.kubernetes.client.KubernetesClientException: 
`Operation: [get]  for kind: [ConfigMap]  with name: [my-app]  in namespace: [my-app-ns]  failed`.
...
Caused by: java.net.ConnectException: `Failed to connect to /10.96.0.1:443`
	at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.kt:297)
...
Caused by: java.net.ConnectException: `Connection refused (Connection refused)`
	at java.base/java.net.PlainSocketImpl.socketConnect(Native Method)
	at java.base/java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)	
...

K8S RBAC 権限構成の問題と K8S クラスター ネットワークの問題のトラブルシューティングを行った後、最終的にバックエンド アプリケーションが Istio と統合されてデプロイされている、つまり Istio Sidecar が自動的に挿入されていることがわかりました。
ポッド内のコンテナはspec.containersの宣言順に従って順次起動され、すべてのコンテナが起動する前にinitContainersが実行されるため、コンテナの起動シーケンスは以下のようになります。

istio-init
app
istio-proxy

つまり、 istio-init はポッド内の iptables を変更して、 istio-proxy がポッド内のすべてのトラフィックを引き継ぐようにします (そのため、アプリ内のすべてのネットワーク リクエストは istio-proxy を経由する必要があります)。アプリの起動プロセス、istio-proxy には起動がまだ完了していない可能性があり、その結果ネットワーク例外が発生します。
つまり、アプリケーションが K8S ConfigMap を読み取るとき、istio-proxy はまだ開始されていないため、ネットワーク接続は拒否されます。
上記の問題の解決策は、ネットワーク異常を回避するために、istio-proxy が正常に起動された後にアプリケーション コンテナーを起動できるようにすることです。

2. Istio 1.7 以降のバージョンのソリューション

istio 1.7 の変更ノートでは、最初に開始するサイドカーの設定をサポートするために、values.global.proxy.holdApplicationUntilProxyStarts 構成オプションがサポートされることが発表されています。values.global.proxy.holdApplicationUntilProxyStarts はデフォルトで無効になっており、次の方法で有効にできます
。次の設定:

--set values.global.proxy.holdApplicationUntilProxyStarts=true

2.1 方法 1: Istio インストール時のグローバル設定

# 默认使用default profile(可通过--set profile=default|demo|...调整)
istioctl install
# 设置sidecar优先启动(且sidecar启动成功后再启动其他应用容器) - 1.7新特性
--set values.global.proxy.holdApplicationUntilProxyStarts=true

2.2 方法 2: アノテーションによるアプリケーションへのデプロイメント

注:
このメソッドはまだ実際にテストされておらず、Istio 1.7 以降の環境はありません。Istio 公式ドキュメントに従ってコンパイルされています。
特定の Istio 公式ドキュメントの説明については、https:
//istio.io/latest/docs/を参照してください。 Reference/config/istio.mesh.v1alpha1/#ProxyConfig

核となる注釈は次のとおりです。

annotations:
  # 重点:配置proxy - 设置proxy启动成功后再启动其他应用
  proxy.istio.io/config: |
    holdApplicationUntilProxyStarts: true

具体的な設定は以下のとおりです。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
    version: v1
spec:
  selector:
    matchLabels:
      app: my-app
      version: v1
  replicas: 1
  template:
    metadata:
      labels:
        app: my-app
        version: v1
      annotations:
        # 开启Istio Sidecar自动注入
        sidecar.istio.io/inject: true
        # 重点:配置proxy - 设置proxy启动成功后再启动其他应用
        proxy.istio.io/config: |
          holdApplicationUntilProxyStarts: true
    spec:
      containers:
        - name: app
          image: registry/app:latest
          ports:
            - name: http-port
              containerPort: 8080
              protocol: TCP       

2.3holdApplicationUntilProxyStarts の有効化効果

holdApplicationUntilProxyStarts を true に設定すると、実際の効果は次のようになります。
(1) サイドカー istio-proxy コンテナを最初にポッド コンテナに配置します (つまり、最初に起動します)。
ここに画像の説明を挿入

(2) istio-proxy ライフサイクルを設定して、サイドカー コンテナーが正常に開始されるまで確実にブロックされるようにします (ポッド内の他のコンテナーの開始をブロックします)。
ここに画像の説明を挿入

3. Istio 1.7 より前のソリューション

Istio 1.7 より前のバージョンでは、holdApplicationUntilProxyStarts 構成が提供されておらず、K8S ライフサイクルと組み合わせて同じ目的、つまりアプリケーション
コンテナをブロックし、アプリケーション コンテナに istio-proxy 起動ポートを監視させることができます。 )。
具体的な手順については、https: //github.com/istio/istio/issues/11130#issuecomment-506659562
ここに画像の説明を挿入
を参照してください。 コア構成は次のとおりです。

# 注:此处配置需结合Istio Sidecar注入一起使用,若未开启Istio Sidecar,则移除此配置
lifecycle:
  postStart:
    httpGet:
      path: /healthz/ready
      port: 15020
      scheme: HTTP

具体的な設定は以下のとおりです。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
    version: v1
spec:
  selector:
    matchLabels:
      app: my-app
      version: v1
  replicas: 1
  template:
    metadata:
      labels:
        app: my-app
        version: v1
      annotations:
        # 开启Istio Sidecar自动注入
        sidecar.istio.io/inject: true
    spec:
      containers:
        - name: app
          image: registry/app:latest
          ports:
            - name: http-port
              containerPort: 8080
              protocol: TCP
          # 阻塞app容器,使app容器监听sidecar启动端口,若监听sidecar启动端口不通,则重启app容器(直到sidecar启动就绪)
          lifecycle:
            postStart:
              httpGet:
                path: /healthz/ready
                port: 15020
          

実際のデプロイ中に、以前に K8S ConfigMap を読み取れなかったログが表示されることが確認できますが、このログが表示された場合は、Istio Sidecar が正常に起動していない (ネットワークが接続されていない) ことを意味し、K8S がアプリケーション コンテナが再起動されます。ログを再度観察し、K8S ConfigMap Success (エラー ログなし) を読み取ります。このように、アプリケーション コンテナに Istio Sidecar Readiness Probe を監視させることで、アプリケーション コンテナは、Istio Sidecar が正常に開始されない前にアプリケーション コンテナ自体を繰り返し再起動することを強制され、Istio Sidecar が正常に開始された後に確実に開始されます。最終的なアプリケーションコンテナが開始されます。


参考:
ポッド内のコンテナーの実行順序を制御するためのいくつかの姿勢
Istio 1.7 がサイドカーの起動順序を保証する方法
Github - 問題 - サイドカーが完全に実行される前にアプリ コンテナーがネットワークに接続できない #11130

おすすめ

転載: blog.csdn.net/luo15242208310/article/details/129257489