エラーの概要
Kubernetesで401エラーが発生するのは、APIサーバーへのリクエストに対して認証に失敗した状態を示します。認証トークンの有効期限切れ、認証情報の不足、または権限がないServiceAccountの使用が典型的な原因です。このエラーが出ると、kubectlコマンドの実行やPodからAPIサーバーへのアクセスが拒否されます。
実際のエラーメッセージ例
error: You must be logged in to the server (Unauthorized)
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "Unauthorized",
"reason": "Unauthorized",
"code": 401
}
kubectl logs pod-name -n default
Error from server (Unauthorized): pods "pod-name" is forbidden: User "system:serviceaccount:default:default" cannot get resource "pods" in API group "" in the namespace "default"
よくある原因と解決手順
原因1:kubeconfig設定の無効化または存在しない認証情報
kubeconfig内の証明書やトークンが無効になっている、または参照しているファイルが削除されている場合に401エラーが発生します。クラスタをセットアップした時点での認証情報が失われたり、パスが誤っていたりすることが多いです。
# ~/.kube/config
apiVersion: v1
clusters:
- cluster:
certificate-authority: /etc/kubernetes/pki/ca.crt # ファイルが削除済み
server: https://10.0.0.1:6443
name: my-cluster
contexts:
- context:
cluster: my-cluster
user: admin-user
name: my-context
current-context: my-context
users:
- name: admin-user
user:
client-certificate: /home/user/.certs/client.crt # パスが誤っている
client-key: /home/user/.certs/client.key
After(修正後):
# ~/.kube/config
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTi...(Base64エンコードされた証明書)
server: https://10.0.0.1:6443
name: my-cluster
contexts:
- context:
cluster: my-cluster
user: admin-user
name: my-context
current-context: my-context
users:
- name: admin-user
user:
client-certificate-data: LS0tLS1CRUdJTi...(Base64エンコードされた証明書)
client-key-data: LS0tLS1CRUdJTi...(Base64エンコードされた秘密鍵)
原因2:ServiceAccountのRBAC権限不足
PodがAPI呼び出しを試みる際、割り当てられたServiceAccountに必要なRole/ClusterRoleバインディングがないか、RoleBinding自体が誤った権限設定になっている場合です。PodはServiceAccountの認証情報は持っていますが、その用途に対する権限がないため401に見える実質403エラーが発生します。
# ServiceAccountは存在するが、Role/RoleBindingがない
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-sa
namespace: production
---
# Podの定義
apiVersion: v1
kind: Pod
metadata:
name: app-pod
namespace: production
spec:
serviceAccountName: app-sa
containers:
- name: app
image: myapp:latest
# Podがこの先APIサーバーにアクセスするが権限がない
After(修正後):
# ServiceAccountの定義
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-sa
namespace: production
---
# Roleの定義
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: app-role
namespace: production
rules:
- apiGroups: [""]
resources: ["pods", "services"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list"]
---
# RoleBindingでServiceAccountにRoleを割り当て
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: app-rolebinding
namespace: production
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: app-role
subjects:
- kind: ServiceAccount
name: app-sa
namespace: production
---
# Podの定義
apiVersion: v1
kind: Pod
metadata:
name: app-pod
namespace: production
spec:
serviceAccountName: app-sa
containers:
- name: app
image: myapp:latest
原因3:トークンの有効期限切れまたは無効なトークン
OIDCやその他の外部認証を使用している場合、IDトークンやアクセストークンの有効期限が切れていることがあります。または、手動で作成したトークンが無効になっている可能性もあります。
# 有効期限切れのトークンでログイン試行
kubectl config set-credentials user-with-expired-token \
--token=eyJhbGciOiJSUzI1NiIsImtpZCI6IjEwIn0.eyJleHAiOjE2MDAwMDAwMDB9.invalid
# または環境変数で無効なトークンを指定
export KUBECONFIG=/path/to/config
# configファイルに無効なtoken文字列が記載されている
After(修正後):
# 新しい有効なトークンを取得して設定(クラスタの管理者に確認)
kubectl config set-credentials user-with-valid-token \
--token=$(kubectl create token <serviceaccount-name> -n <namespace>)
# または対話的にログイン情報を更新
aws eks update-kubeconfig --name <cluster-name> --region <region>
# またはGKEの場合
gcloud container clusters get-credentials <cluster-name> --zone <zone>
ツール固有の注意点
Kubernetes RBAC設定の検証
エラーが本当に401(認証失敗)なのか、403(認可失敗)なのかを区別することが重要です。以下のコマンドで現在のユーザー・ServiceAccountの権限を確認できます。
# 現在のコンテキストとユーザーを確認
kubectl config current-context
kubectl config get-contexts
# ServiceAccountのトークンを確認(Podから実行)
cat /run/secrets/kubernetes.io/serviceaccount/token
# 特定のServiceAccountに割り当てられたロールを確認
kubectl get rolebinding -n <namespace> -o wide
kubectl get clusterrolebinding -o wide | grep <serviceaccount-name>
# APIサーバーのアクセス権限を一覧表示
kubectl auth can-i --list --as=system:serviceaccount:<namespace>:<sa-name>
マルチクラスタ環境での認証
複数のKubernetesクラスタを管理する場合、kubeconfig内に複数のクラスタ定義が存在しており、誤ったコンテキストで操作している可能性があります。
# 設定されているすべてのクラスタを表示
kubectl config get-clusters
# 特定のクラスタに切り替え
kubectl config use-context <cluster-name>
# 切り替え後に接続確認
kubectl cluster-info
外部認証プロバイダー(OIDC)の場合
OIDCを使用している場合、トークンの更新が自動的に行われていない可能性があります。kubeloginなどのOIDCヘルパーが正しく設定されているか確認してください。
# OIDCの認証情報が正しく設定されているか確認
kubectl config view | grep oidc
それでも解決しない場合
デバッグコマンドと確認事項
# APIサーバーへの詳細なリクエストログを出力
kubectl -v=8 get pods
# 現在のユーザー情報を確認
kubectl whoami
# kube-apiserverのログを確認(クラスタ管理者権限が必要)
kubectl logs -n kube-system -l component=kube-apiserver --tail=100
# ノード上のkubelet認証ログを確認(マスターノードにSSH接続)
sudo journalctl -u kubelet -n 50
確認すべきログの場所
- kube-apiserver ログ:
/var/log/pods/kube-system_kube-apiserver-*/またはコンテナログ - kubelet ログ:
journalctl -u kubeletまたは/var/log/kubelet.log - kubectl のデバッグ出力:
-v=6から-v=10のフラグを使用
公式ドキュメント参照
コミュニティリソース
- Kubernetes GitHub Issues:認証関連の既知問題を検索
- Kubernetes Slack コミュニティ:
#generalチャネルで質問
免責事項:本記事の内容は、執筆時点の公開情報をもとに作成したものです。ソフトウェアの仕様は予告なく変更されることがあります。最新の情報は各ツールの公式サポートページをご確認ください。本記事の情報を利用した結果生じたいかなる損害についても、著者および運営者は責任を負いかねます。
この記事でエラーは解決しましたか?