Kubernetesの接続トラブルシューティング:execとport-forwardの効果的な活用
主要なコンテナオーケストレーションプラットフォームであるKubernetesは、コンテナ化されたアプリケーションのデプロイ、スケーリング、管理を自動化する力を提供します。その宣言的な性質は多くの運用タスクを簡素化しますが、接続性や内部アプリケーションの問題のトラブルシューティングは依然として課題となることがあります。アプリケーションやその内部状態への直接アクセスが必要な場合、kubectl execとkubectl port-forwardはデバッグの武器庫に不可欠なツールです。
この記事では、コンテナ内でコマンドを実行するためのkubectl execと、サービスへの安全なローカルアクセスを確立するためのkubectl port-forwardの実践的な使い方を説明します。これらのコマンドを習得することで、アプリケーションの動作についてより深い洞察を得て、ネットワークの問題を診断し、接続の問題をより効率的に解決し、最終的にKubernetesデプロイメントの信頼性とパフォーマンスを向上させることができます。
kubectl execを理解する
kubectl execコマンドを使用すると、Pod内の実行中のコンテナ内でコマンドを実行できます。これは、ログの調査、構成の確認、およびアプリケーションが存在する場所で直接診断ツールを実行するのに非常に役立ちます。
基本構文
kubectl execの基本的な構文は次のとおりです。
kubectl exec <pod-name> -- <command> [args...]
<pod-name>: コマンドを実行したいPodの名前です。--: このセパレータは重要です。これはkubectlのフラグと、コンテナ内で実行したいコマンドを区別します。<command>: コンテナ内で実行するコマンド(例:ls、cat、ping)です。[args...]: コマンドの引数です。
対話型シェルアクセス
kubectl execの最も一般的な用途の1つは、コンテナ内にインタラクティブシェル(bashやshなど)を取得することです。これにより、コンテナのファイルシステムを探索し、複数のコマンドを実行できます。
インタラクティブシェルを取得するには:
kubectl exec -it <pod-name> -- /bin/bash
-i(または--stdin):アタッチされていなくても標準入力を開いたままにします。-t(または--tty):擬似TTYを割り当てます。これはインタラクティブシェルセッションに必要です。
例: my-app-podという名前のPodでbashシェルにアクセスする:
kubectl exec -it my-app-pod -- /bin/bash
中に入ったら、標準的なLinuxコマンドを使用できます。シェルを終了するには、exitと入力するか、Ctrl+Dを押します。
単一コマンドの実行
対話型シェルなしで単一のコマンドを実行することもできます。これは、簡単な確認やスクリプト作成に役立ちます。
例: my-app-podの/appディレクトリ内のファイルを確認する:
kubectl exec my-app-pod -- ls /app
例: 設定ファイルconfig.yamlの内容を表示する:
kubectl exec my-app-pod -- cat /etc/my-app/config.yaml
Pod内のコンテナを指定する
Podに複数のコンテナがある場合は、-cフラグを使用して、コマンドを実行するコンテナを指定する必要があります。
kubectl exec <pod-name> -c <container-name> -- <command>
例: multi-container-podのsidecar-containerでenvを実行する:
kubectl exec multi-container-pod -c sidecar-container -- env
kubectl port-forwardを理解する
kubectl port-forwardコマンドを使用すると、ローカルマシンからKubernetesクラスター内の特定のPodまたはサービスへのセキュアなトンネルを確立できます。これは、外部に公開されていないアプリケーションのデバッグ、データベースへのアクセス、または内部APIのテストに非常に貴重です。
基本構文
一般的な構文は次のとおりです。
kubectl port-forward <pod-name> <local-port>:<remote-port>
<pod-name>: 接続したいPodの名前です。<local-port>: ローカルマシン上で接続をリッスンするポートです。<remote-port>: 転送されたトラフィックを受信するPod上のポートです。
例: ローカルポート8080をmy-app-podのポート80に転送する:
kubectl port-forward my-app-pod 8080:80
このコマンドが実行されると、Webブラウザでhttp://localhost:8080にアクセスするか、ローカルマシンでcurlのようなツールを使用してアプリケーションにアクセスできます。
サービスへの転送
特定のPodではなく、Kubernetesサービスにトラフィックを転送することもできます。kubectlは、そのサービスをバックアップするPodを自動的に選択します。
kubectl port-forward service/<service-name> <local-port>:<service-port>
例: ローカルポート3000をmy-serviceサービスのポート80に転送する:
kubectl port-forward service/my-service 3000:80
DeploymentまたはStatefulSetへの転送
同様に、DeploymentまたはStatefulSetに転送することもできます。kubectlは、指定されたリソースによって管理されているPodの1つを選択します。
kubectl port-forward deployment/<deployment-name> <local-port>:<container-port>
kubectl port-forward statefulset/<statefulset-name> <local-port>:<container-port>
特定のアドレスへのバインド
デフォルトでは、port-forwardはlocalhostにバインドされます。--addressフラグを使用して、別のローカルアドレスを指定できます。
kubectl port-forward --address 127.0.0.1 <pod-name> <local-port>:<remote-port>
複数ポートの転送
kubectl port-forwardは複数のポートを同時に転送できます。
kubectl port-forward my-app-pod 8080:80 9090:90
このコマンドは、ローカルポート8080をPodのポート80に、ローカルポート9090をPodのポート90に転送します。
一般的なトラブルシューティングシナリオと解決策
シナリオ1:アプリケーションが応答しないが、Podは正常に見える場合。
- 問題: Podは実行されているが、サービスへのリクエストが失敗するかタイムアウトする。アプリケーションに内部構成の問題があるか、停止している可能性がある。
kubectl execによる解決策:- Podにインタラクティブシェルで入る:
kubectl exec -it <pod-name> -- /bin/bash - シェル内で、アプリケーションログを確認する(例:
tail -f /var/log/myapp.log)。 - アプリケーションの内部構成ファイルを確認する。
- Pod内から
pingやcurl(インストールされている場合)を使用して、他のサービスへのネットワーク接続を確認する。
- Podにインタラクティブシェルで入る:
kubectl port-forwardによる解決策:- アプリケーションのリッスンポートにポートを転送する:
kubectl port-forward <pod-name> 8080:<app-port> http://localhost:8080経由でローカルからアプリケーションにアクセスを試みる。これにより、問題がKubernetesのサービスディスカバリやIngressにあるのか、それともアプリケーション自体が応答していないのかを判断するのに役立つ。
- アプリケーションのリッスンポートにポートを転送する:
シナリオ2:Podで実行中のデータベースをデバッグする必要がある場合。
- 問題: ローカルのデータベースクライアントを、Kubernetes Pod内で実行中のデータベースに接続して、データを調査したりクエリを実行したりする必要がある。
kubectl port-forwardによる解決策:- データベースを実行しているPodとそのポートを特定する(例:
mysql-pod、ポート3306)。 - ローカルポートをデータベースポートに転送する:
kubectl port-forward mysql-pod 3306:3306 - 適切なデータベース認証情報を使用して、ローカルデータベースクライアントを
localhost:3306に接続するように構成する。
- データベースを実行しているPodとそのポートを特定する(例:
シナリオ3:Pod内のDNS解決の問題を診断する。
- 問題: Pod内のアプリケーションがサービス名で他のサービスに到達できない。これはDNSの問題を示唆している。
kubectl execによる解決策:- Podにインタラクティブシェルで入る:
kubectl exec -it <pod-name> -- /bin/bash - シェル内で、既知のサービス名を解決しようと試みる:
nslookup <service-name>.<namespace>.svc.cluster.localまたはdig <service-name>.<namespace>.svc.cluster.local。 /etc/resolv.confの内容を確認し、Pod内のクラスターのDNS設定が正しいことを確認する。
- Podにインタラクティブシェルで入る:
ベストプラクティスとヒント
port-forwardを実行し続ける:kubectl port-forwardはフォアグラウンドで実行されます。ターミナルウィンドウを開いたままにする必要があります。バックグラウンドで実行するには、nohupやscreen/tmuxのようなツールを使用できます。- デバッグ時は特定のPodを使用する: サービスへの転送は便利ですが、特定インスタンスの問題を特定するには、その名前を使用して特定のPodに転送する方が多くの場合効果的です。
- セキュリティ: 公開するポートに注意してください。絶対に必要でない限り、機密性の高いポートの転送は避け、ローカルマシンが保護されていることを確認してください。
- リソース使用量:
kubectl execはリソースを消費する可能性があります。特に本番クラスターでは、慎重に使用してください。 - 権限:
kubectlコンテキストが、Pod内でコマンドを実行したりポートを転送したりするために必要な権限を持っていることを確認してください。
結論
kubectl execとkubectl port-forwardは、Kubernetesアプリケーションとそのネットワーク環境を可視化するための強力なツールです。execは実行中のコンテナと直接対話し、詳細な検査とコマンド実行を可能にし、port-forwardはローカルマシンとクラスター内のサービス間のギャップを埋め、シームレスなデバッグとテストを容易にします。これらのコマンドを通常のトラブルシューティングワークフローに統合することで、複雑な接続性やアプリケーションの問題を解決するのに必要な時間と労力を大幅に削減し、より堅牢で信頼性の高いKubernetesデプロイメントを実現できます。