冒頭まとめ
kubectl get podsなどを実行したとき、次のエラーが出ることがあります。
Unable to connect to the server: dial tcp: lookup api.example.com: no such host
The connection to the server 127.0.0.1:6443 was refused - did you specify the right host or port?
どちらもkubectlからKubernetes APIサーバーへ接続できていません。ただし、直す場所は後半の文言によって異なります。
| 後半の文言 | 最初に疑う場所 |
|---|---|
connection refused | APIサーバーの停止、ホスト、ポート |
no such host | DNS、VPN、kubeconfig内のホスト名 |
i/o timeout、TLS handshake timeout | 経路、VPN、ファイアウォール、負荷 |
x509:、tls: | CA証明書、接続先名、証明書の期限 |
no configuration has been provided | kubeconfigの有無と読み込み元 |
最初に、kubectlが選んでいるcontextとAPIサーバーのURLを確認してください。
kubectl config current-context
kubectl config view --minify
kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}{"\n"}'
想定外のクラスターが表示された場合は、ネットワークを調べる前にkubeconfigの読み込み元を直します。
Unable to connect to the serverとは
kubectlは、kubeconfigからAPIサーバーの場所、接続に使う認証情報、現在のcontextを読み取ります。その情報を使って接続を試み、名前解決、TCP接続、TLS接続などの段階で失敗すると、Unable to connect to the serverが表示されます。
kubectlの実装では、接続時のエラーがconnection refusedを含む場合だけ、次の専用メッセージへ変換します。
The connection to the server <host>:<port> was refused - did you specify the right host or port?
それ以外の接続エラーは、元の原因を後ろに付けた次の形式になります。
Unable to connect to the server: <接続に失敗した理由>
したがって、Unable to connect to the serverだけを見ても原因は決まりません。コロン以降にあるno such host、timeout、tlsなどを省略せずに確認することが重要です。
なお、これはPodやDeploymentのエラーではありません。kubectlがAPIサーバーへ到達する前後で止まっているため、kubectl logsやPodの再起動では解決できません。
kubeconfigとcontextを確認する
kubectlが接続に使う情報はkubeconfigにあります。まず、利用できるcontextと現在選ばれているcontextを確認します。
kubectl config get-contexts
kubectl config current-context
kubectl config view --minify
--minifyを付けると、現在のcontextに関係するclusterとuserへ表示を絞れます。server:に書かれたURLが、接続したいクラスターのAPIサーバーか確認してください。
kubeconfigの読み込み規則は次の順序です。
--kubeconfigを指定した場合は、その1ファイルだけを使うKUBECONFIG環境変数がある場合は、列挙されたファイルをマージする- どちらもない場合は、通常
$HOME/.kube/configを使う
この規則はKubeconfigファイルを使用したクラスターアクセスの構成に記載されています。
LinuxまたはmacOSでは、環境変数を次のように確認できます。
printf '%s\n' "$KUBECONFIG"
ls -l "$HOME/.kube/config"
Windows PowerShellでは次を使います。
$Env:KUBECONFIG
Test-Path "$HOME\.kube\config"
KUBECONFIGには複数のファイルを指定できます。区切りはLinuxとmacOSではコロン、Windowsではセミコロンです。複数ファイルに同名のclusterやuserがあると、マージ結果が想定と異なることがあります。
確認のために特定のファイルだけを使う場合は、--kubeconfigを明示します。
kubectl --kubeconfig=/path/to/config config view --minify
kubectl --kubeconfig=/path/to/config get nodes
この指定で接続できるなら、クラスターではなく、通常実行時に読み込まれているkubeconfigやcontextが原因です。
error: no configuration has been providedやcluster has no server definedが出る場合は、TCP接続より前に設定の読み込みで止まっています。クラスター管理者または利用しているクラウド・ローカルクラスターの公式手順から、kubeconfigを取得し直してください。入手元が不明なkubeconfigは、認証プラグインなどを通じてコードを実行する可能性があるため使用しないでください。
connection refusedの対処
次の文言は、指定されたホストとポートへのTCP接続が拒否された場合に表示されます。
The connection to the server <host>:<port> was refused - did you specify the right host or port?
名前解決や経路が完全に失敗した場合とは異なり、接続先から拒否が返っています。主な原因は、APIサーバーが停止している、kubeconfigのポートが古い、クラスターを作り直したのに以前の接続先を参照している、といったものです。
まず、現在の接続先を取り出します。
kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}{"\n"}'
localhost:8080や、削除済みクラスターのIPアドレスが出る場合は、正しいkubeconfigを取得し直します。minikubeなどのローカルクラスターを使っている場合は、クラスター自体が起動しているかも確認してください。
管理対象のクラスターなら、control planeやAPIサーバー前段のロードバランサーが正常かを管理画面や監視から確認します。利用者側から接続できないという理由だけで、control planeを再起動しないでください。VPN、接続元制限、誤ったcontextでも同じように利用不能になるためです。
no such host・timeoutの対処
次の文言は、kubeconfigに書かれたホスト名をDNSで解決できない場合に出ます。
Unable to connect to the server: dial tcp: lookup api.example.com: no such host
APIサーバーのURLを確認し、そのホスト名が現在の環境から解決できるか調べます。
kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}{"\n"}'
nslookup api.example.com
社内DNSやプライベートDNSでのみ解決できるホストなら、VPNへ接続してから再確認します。クラスターを再作成したあとに古いホスト名が残っている場合は、DNS設定を手作業で書き換えるのではなく、正しいkubeconfigを取得し直してください。
i/o timeoutやTLS handshake timeoutの場合は、接続先へ応答が返る前に制限時間を超えています。VPN、ファイアウォール、プロキシ、APIサーバー前段のロードバランサーを確認します。
到達性だけを確認したい場合は、kubeconfigに表示されたURLを使い、短い接続時間で試します。
curl --connect-timeout 5 https://api.example.com:6443/readyz
認証情報を付けていないため、401 Unauthorizedや403 Forbiddenが返る場合があります。ただし、その応答が返るならDNS、TCP、TLSの接続は少なくとも成立しています。
自己署名証明書などでcurlの検証だけが失敗する場合、経路の確認に限って-kを使う方法もあります。
curl -k --connect-timeout 5 https://api.example.com:6443/readyz
-kはサーバー証明書の検証を無効にします。中間者攻撃を検出できなくなるため、恒久的な設定や通常のAPI操作には使用しないでください。kubectl側のTLS検証を無効にする解決策でもありません。
TLSエラーの対処
Unable to connect to the server:の後ろにx509:やtls:がある場合は、APIサーバーには接続を試みていますが、証明書の検証またはTLSハンドシェイクに失敗しています。
よくある原因は次のとおりです。
- クラスターを再作成したため、kubeconfig内のCAが古い
- 証明書の有効期限が切れている
- kubeconfigの接続先名と証明書の対象名が一致しない
- 途中のプロキシが別の証明書を返している
kubeconfig内の接続先と証明書設定を確認します。
kubectl config view --minify
certificate-authorityまたはcertificate-authority-dataと、serverの組み合わせが同じクラスターから取得されたものか確認してください。クラスターを作り直した場合は、古いCAだけを残して接続先を手作業で変えるのではなく、kubeconfig一式を再取得します。
insecure-skip-tls-verify: trueを恒久的に設定すると、kubectlが接続先の正当性を確認できなくなります。原因調査を省略するための対処としては使わないでください。
証明書が正しく、その後にUnauthorizedやForbiddenへ変わった場合は、接続自体は成立しています。次にトークン、クライアント証明書、exec認証プラグイン、RBACを調べます。
似たエラーとの違い
error: You must be logged in to the server (Unauthorized)は、APIサーバーへ到達したあとに認証で拒否されたエラーです。kubeconfigの接続先ではなく、認証情報の期限やログイン状態を確認します。
Error from server (Forbidden)は認証された利用者に操作権限がない状態です。接続障害ではなく、RBACなどの認可設定を確認します。
Error from server (NotFound)やthe server could not find the requested resourceは、APIサーバーから応答を受け取っています。リソース名、namespace、APIの種類やバージョンが調査対象です。
error: no configuration has been providedは、接続を試す前にkubeconfigを読み込めなかったエラーです。Unable to connect to the serverとは発生段階が異なります。
PodのPending、CrashLoopBackOff、ImagePullBackOffは、APIサーバーへ接続したあとに確認できるワークロード側の状態です。kubectl自体が接続できない今回のエラーとは分けて考えます。
解決手順のまとめ
最初にkubectl config current-contextとkubectl config view --minifyを実行し、kubectlが選んでいるクラスター、利用者、APIサーバーのURLを確認します。
設定が違う場合は、--kubeconfig、KUBECONFIG、$HOME/.kube/configの読み込み規則を確認してください。新しい端末、コンテナ、CIでは、kubeconfigや認証プラグインを渡していないことがあります。
接続先が正しければ、後半の文言に従って切り分けます。connection refusedはAPIサーバーとポート、no such hostはDNSとVPN、timeoutは経路とファイアウォール、x509やtlsは証明書と接続先名を確認します。
curl -kやinsecure-skip-tls-verifyで警告を消すことを解決策にしないでください。TLS検証を外して到達性を確認した場合も、最終的には正しいCAとkubeconfigでkubectlが接続できる状態へ戻す必要があります。
免責事項:本記事の内容は一般的なKubernetes環境を前提としています。kubeconfigには認証情報や外部コマンドの設定が含まれる場合があります。共有、公開、編集を行う前に内容を確認し、TLS検証やアクセス制御を無効化しないでください。
この記事でエラーは解決しましたか?