はじめに
これは完全に失敗談です。
前提環境
- kubernetes 1.23 (masterはシングルノード)
やらかした内容
kube-apiserverと同じIPとPortのサービスをデプロイしてしまいました。
※シングルノード構成で「10.0.0.1」がマスターノード(kubernetes APIサーバ)のIPアドレスです。
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
ports:
- protocol: TCP
port: 6443
targetPort: 443
externalIPs:
- 10.0.0.1
回復策検討と実施
これでkube-apiserverのPodが再起動のループを始めてしまい、kubectlが使えなくなります。
当初かなり焦りましたが、アプリケーションのPodは継続して稼働できているので、うかつな操作をせずに回復策を検討しました。
再起動のループをしているのでAPIへの疎通ができません。また、crictlでコンテナに入ろうとしてもコンテナIDが変わってしまい、長時間は入れません。しばらく考えてkube-apiserverへのアクセスは諦めました。
kubernetesへの知識がある程度あったので、kube-apiserverのデータは全てetcdに保存される事を知っていました。
なので、今度はetcdに直接接続して問題となったServiceリソースの削除を試みました。
etcdへの接続はetcdctlというコマンドを使います。
kubernetesのetcdでは証明書やキーが必要となるので、事前にStatic Podのマニフェストを確認しておきます。
# grep pki /etc/kubernetes/manifests/etcd.yaml
- --cert-file=/etc/kubernetes/pki/etcd/server.crt
- --key-file=/etc/kubernetes/pki/etcd/server.key
- --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt
- --peer-key-file=/etc/kubernetes/pki/etcd/peer.key
- --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
- --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
- mountPath: /etc/kubernetes/pki/etcd
path: /etc/kubernetes/pki/etcd
このうち「--cert-file」「--key-file」「-trusted-ca-file」が必要になるようです。
接続先のポート番号についてもマニフェストから確認できます。
# grep advertise-client-urls /etc/kubernetes/manifests/etcd.yaml
kubeadm.kubernetes.io/etcd.advertise-client-urls: https://10.0.0.1:2379
- --advertise-client-urls=https://10.0.0.1:2379
接続先とポート番号を指定して接続してみます。
# ETCDCTL_API=3 etcdctl endpoint status \
--endpoints=https://[127.0.0.1]:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
https://[127.0.0.1]:2379, 63044e73c12f33cd, 3.5.1, 20 MB, true, 86, 270366839
無事に接続できるようです。良かった。
問題となったサービスリソースのキーを検索します。昔は「list」というコマンドがあったようなのですが、今は「get /」とするようです。
# ETCDCTL_API=3 etcdctl get / --prefix --keys-only \
--endpoints=https://[127.0.0.1]:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
| grep my-service
思い切ってキーを削除します。
# ETCDCTL_API=3 etcdctl del '/registry/services/specs/default/my-service' \
--endpoints=https://[127.0.0.1]:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
削除後はmasterノードを再起動します。
# reboot
シングル masterは単純に再起動で良いかと思います。今回はなんとかこれで回復はできました。
おわりに
見事にServiceリソースだけでkubernetesを操作不能に陥らせる事ができました!!自宅だからと言って、admin権限は怖いですね。
kubectlが使えないという、管理者にはかなりインパクトがあるものなので、kubernetes初学者へのトラブルシュート問題に良い内容かなと思いました。
Amazon EKSだと以下のような設定で制限できるようです。
OpenShiftは以下の設定です。