27.4. ovnkube-trace を使用した Openflow のトレース

OVN と OVS のトラフィックフローは、ovnkube-trace という単一のユーティリティーでシミュレートできます。ovnkube-trace ユーティリティーは、ovn-traceovs-appctl ofproto/trace、および ovn-detrace を実行し、その情報を 1 つの出力に関連付けます。

専用コンテナーから ovnkube-trace バイナリーを実行できます。OpenShift Container Platform 4.7 以降のリリースでは、バイナリーをローカルホストにコピーして、そのホストから実行することもできます。

注記

現在、Quay イメージのバイナリーは、デュアル IP スタックまたは IPv6 のみの環境では機能しません。これらの環境では、ソースからビルドする必要があります。

27.4.1. ローカルホストへの ovnkube-trace のインストール

ovnkube-trace ツールは、OVN-Kubernetes で動作する OpenShift Container Platform クラスター内のポイント間における任意の UDP または TCP トラフィックのパケットシミュレーションをトレースします。ovnkube-trace バイナリーをローカルホストにコピーして、クラスターに対して実行できるようにします。

前提条件

  • OpenShift CLI (oc) がインストールされている。
  • cluster-admin 権限を持つユーザーとしてクラスターにログインしている。

手順

  1. 次のコマンドを使用して Pod 変数を作成します。

    $  POD=$(oc get pods -n openshift-ovn-kubernetes -l app=ovnkube-master -o name | head -1 | awk -F '/' '{print $NF}')
  2. ローカルホストで次のコマンドを実行して、ovnkube-master Pod からバイナリーをコピーします。

    $  oc cp -n openshift-ovn-kubernetes $POD:/usr/bin/ovnkube-trace ovnkube-trace
  3. 次のコマンドを実行して、ovnkube-trace を実行可能にします。

    $  chmod +x ovnkube-trace
  4. 次のコマンドを実行して、ovnkube-trace で使用可能なオプションを表示します。

    $  ./ovnkube-trace -help

    予想される出力

    I0111 15:05:27.973305  204872 ovs.go:90] Maximum command line arguments set to: 191102
    Usage of ./ovnkube-trace:
      -dst string
        	dest: destination pod name
      -dst-ip string
        	destination IP address (meant for tests to external targets)
      -dst-namespace string
        	k8s namespace of dest pod (default "default")
      -dst-port string
        	dst-port: destination port (default "80")
      -kubeconfig string
        	absolute path to the kubeconfig file
      -loglevel string
        	loglevel: klog level (default "0")
      -ovn-config-namespace string
        	namespace used by ovn-config itself
      -service string
        	service: destination service name
      -skip-detrace
        	skip ovn-detrace command
      -src string
        	src: source pod name
      -src-namespace string
        	k8s namespace of source pod (default "default")
      -tcp
        	use tcp transport protocol
      -udp
        	use udp transport protocol

    サポートされているコマンドライン引数は、namespace、Pod、サービスなど、よく知られた Kubernetes コンストラクトであるため、MAC アドレス、宛先ノードの IP アドレス、または ICMP タイプを見つける必要はありません。

    ログレベルは次のとおりです。

    • 0 (最小出力)
    • 2 (トレースコマンドの結果を示すより詳細な出力)
    • 5 (デバッグ出力)

27.4.2. ovnkube-trace の実行

ovn-trace を実行して、OVN 論理ネットワーク内のパケット転送をシミュレートします。

前提条件

  • OpenShift CLI (oc) がインストールされている。
  • cluster-admin 権限を持つユーザーとしてクラスターにログインしている。
  • ローカルホストに ovnkube-trace がインストールされている。

例: デプロイされた Pod からの DNS 解決が機能することをテストする

この例は、デプロイされた Pod からクラスターで実行されるコア DNS Pod への DNS 解決をテストする方法を示しています。

手順

  1. 次のコマンドを入力して、default namespace で Web サービスを開始します。

    $ oc run web --namespace=default --image=nginx --labels="app=web" --expose --port=80
  2. openshift-dns namespace で実行されている Pod を一覧表示します。

    oc get pods -n openshift-dns

    出力例

    NAME                  READY   STATUS    RESTARTS   AGE
    dns-default-467qw     2/2     Running   0          49m
    dns-default-6prvx     2/2     Running   0          53m
    dns-default-fkqr8     2/2     Running   0          53m
    dns-default-qv2rg     2/2     Running   0          49m
    dns-default-s29vr     2/2     Running   0          49m
    dns-default-vdsbn     2/2     Running   0          53m
    node-resolver-6thtt   1/1     Running   0          53m
    node-resolver-7ksdn   1/1     Running   0          49m
    node-resolver-8sthh   1/1     Running   0          53m
    node-resolver-c5ksw   1/1     Running   0          50m
    node-resolver-gbvdp   1/1     Running   0          53m
    node-resolver-sxhkd   1/1     Running   0          50m

  3. 次の ovn-kube-trace コマンドを実行して、DNS 解決が機能していることを確認します。

    $ ./ovnkube-trace \
      -src-namespace default \ 1
      -src web \ 2
      -dst-namespace openshift-dns \ 3
      -dst dns-default-467qw \ 4
      -udp -dst-port 53 \ 5
      -loglevel 0 6
    1
    ソース Pod の namespace
    2
    ソース Pod 名
    3
    宛先 Pod の namespace
    4
    宛先 Pod 名
    5
    udp トランスポートプロトコルを使用します。ポート 53 は、DNS サービスが使用するポートです。
    6
    ログレベルを 1 に設定します (0 は最小限で、5 はデバッグです)。

    予想される出力

    I0116 10:19:35.601303   17900 ovs.go:90] Maximum command line arguments set to: 191102
    ovn-trace source pod to destination pod indicates success from web to dns-default-467qw
    ovn-trace destination pod to source pod indicates success from dns-default-467qw to web
    ovs-appctl ofproto/trace source pod to destination pod indicates success from web to dns-default-467qw
    ovs-appctl ofproto/trace destination pod to source pod indicates success from dns-default-467qw to web
    ovn-detrace source pod to destination pod indicates success from web to dns-default-467qw
    ovn-detrace destination pod to source pod indicates success from dns-default-467qw to web

    この出力は、デプロイされた Pod から DNS ポートへの解決が成功し、その反対方向への解決も成功したことを示しています。つまり、Web Pod がコア DNS からの DNS 解決を行う場合に、UDP ポート 53 で双方向のトラフィックがサポートされていることがわかります。

たとえば、これが機能せず、ovn-traceovs-appctl ofproto/traceovn-detrace、およびその他のデバッグタイプ情報を取得する場合は、ログレベルを 2 に上げて、次のようにコマンドを再度実行します。

$ ./ovnkube-trace \
  -src-namespace default \
  -src web \
  -dst-namespace openshift-dns \
  -dst dns-default-467qw \
  -udp -dst-port 53 \
  -loglevel 2

このログレベルの出力は多すぎるため、ここにはリストできません。障害状況では、このコマンドの出力は、どのフローがそのトラフィックを破棄しているかを示します。たとえば、egress または ingress ネットワークポリシーが、そのトラフィックを許可しないクラスターで設定されている場合などがあります。

例: デバッグ出力を使用して設定済みのデフォルトの拒否を確認する

この例は、デバッグ出力を使用して、デフォルトのingress 拒否ポリシーがトラフィックをブロックしていることを特定する方法を示しています。

手順

  1. すべての namespace におけるすべての Pod からの ingress を拒否する deny-by-default ポリシーを定義する次の YAML を作成します。YAML を deny-by-default.yaml ファイルに保存します。

    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: deny-by-default
      namespace: default
    spec:
      podSelector: {}
      ingress: []
  2. 次のコマンドを入力して、ポリシーを適用します。

    $ oc apply -f deny-by-default.yaml

    出力例

    networkpolicy.networking.k8s.io/deny-by-default created

  3. 次のコマンドを入力して、default namespace で Web サービスを開始します。

    $ oc run web --namespace=default --image=nginx --labels="app=web" --expose --port=80
  4. 次のコマンドを実行して、prod namespace を作成します。

    $ oc create namespace prod
  5. 次のコマンドを実行して、prod namespace にラベルを付けます。

    $ oc label namespace/prod purpose=production
  6. 次のコマンドを実行して、alpine イメージを prod namespace にデプロイし、シェルを開始します。

    $ oc run test-6459 --namespace=prod --rm -i -t --image=alpine -- sh
  7. 別のターミナルセッションを開きます。
  8. この新しいターミナルセッションで ovn-trace を実行して、namespace prod で実行されているソース Pod test-6459default namespace で実行されている宛先 Pod 間の通信の失敗を確認します。

    $ ./ovnkube-trace \
     -src-namespace prod \
     -src test-6459 \
     -dst-namespace default \
     -dst web \
     -tcp -dst-port 80 \
     -loglevel 0

    予想される出力

    I0116 14:20:47.380775   50822 ovs.go:90] Maximum command line arguments set to: 191102
    ovn-trace source pod to destination pod indicates failure from test-6459 to web

  9. 次のコマンドを実行して、ログレベルを 2 に上げて、失敗の理由を明らかにします。

    $ ./ovnkube-trace \
     -src-namespace prod \
     -src test-6459 \
     -dst-namespace default \
     -dst web \
     -tcp -dst-port 80 \
     -loglevel 2

    予想される出力

    ct_lb_mark /* default (use --ct to customize) */
    ------------------------------------------------
     3. ls_out_acl_hint (northd.c:6092): !ct.new && ct.est && !ct.rpl && ct_mark.blocked == 0, priority 4, uuid 32d45ad4
        reg0[8] = 1;
        reg0[10] = 1;
        next;
     4. ls_out_acl (northd.c:6435): reg0[10] == 1 && (outport == @a16982411286042166782_ingressDefaultDeny), priority 2000, uuid f730a887 1
        ct_commit { ct_mark.blocked = 1; };

    1
    デフォルトの拒否ポリシーが設定されているため、ingress トラフィックがブロックされています。
  10. ラベルが purpose=production の特定の namespace 内にあるすべての Pod からのトラフィックを許可するポリシーを作成します。YAML を web-allow-prod.yaml ファイルに保存します。

    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: web-allow-prod
      namespace: default
    spec:
      podSelector:
        matchLabels:
          app: web
      policyTypes:
      - Ingress
      ingress:
      - from:
        - namespaceSelector:
            matchLabels:
              purpose: production
  11. 次のコマンドを入力して、ポリシーを適用します。

    $ oc apply -f web-allow-prod.yaml
  12. 次のコマンドを入力して、ovnkube-trace を実行し、トラフィックが許可されていることを確認します。

    $ ./ovnkube-trace \
     -src-namespace prod \
     -src test-6459 \
     -dst-namespace default \
     -dst web \
     -tcp -dst-port 80 \
     -loglevel 0

    予想される出力

    I0116 14:25:44.055207   51695 ovs.go:90] Maximum command line arguments set to: 191102
    ovn-trace source pod to destination pod indicates success from test-6459 to web
    ovn-trace destination pod to source pod indicates success from web to test-6459
    ovs-appctl ofproto/trace source pod to destination pod indicates success from test-6459 to web
    ovs-appctl ofproto/trace destination pod to source pod indicates success from web to test-6459
    ovn-detrace source pod to destination pod indicates success from test-6459 to web
    ovn-detrace destination pod to source pod indicates success from web to test-6459

  13. 開いているシェルで次のコマンドを実行します。

     wget -qO- --timeout=2 http://web.default

    予想される出力

    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
    html { color-scheme: light dark; }
    body { width: 35em; margin: 0 auto;
    font-family: Tahoma, Verdana, Arial, sans-serif; }
    </style>
    </head>
    <body>
    <h1>Welcome to nginx!</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>
    
    <p>For online documentation and support please refer to
    <a href="http://nginx.org/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>
    
    <p><em>Thank you for using nginx.</em></p>
    </body>
    </html>

27.4.3. 関連情報