Nginxが展開できない
解いた人:とり
参照した問題・解説のサイト:Nginxが展開できない
使用環境・ツール
- Kubernetes
- Nginx
- Rook (解説に書いてあった)
Rookとは
kubernetes用のストレージオペレータ。ストレージをストレージソフトウェアを自己管理、自己スケーリング、および自己修復のストレージサービスに変えます。(公式ドキュメントから) なんとなくだけど、ストレージにPodの要素を加えることで、k8sの便利機能(スケーリングや修復)を扱えるようにしたサービスなのではないかと思った。(これはあくまで私の意見)
前提条件
/home/user/manifest
にあるファイルの内容を変更してはいけない
問題文でされた操作
- KubernetesのNginx用のマニフェストファイルをApplyした
VM名 | ホスト名 |
---|---|
kzz-k8s-master | 192.168.12.1 |
kzz-k8s-node1 | 192.168.12.2 |
kzz-k8s-node1 | 192.168.12.3 |
kzz-k8s-node1 | 192.168.12.4 |
バグの内容
- NginxのDeploymentがPendingになっている
理想の終了状態
- pendingとなっていたDeploymentが正常に稼働している。
- 正常化したDeploymentによって稼働するNginxで、解答するチームの名前が書かれたWebサイトが確認できるようになっている。
- 開始時と同じマニフェストのみが適用されている。
考えられる検証、修正手順
バグの原因を特定する案
- ログがあるならログ的なのを確認する → k8s側では特になかった
- 公式ドキュメントにデバッグ方法があった URL
- deploymentやserviceのファイルを読んでみる
- TCP80ポートが接続できる設定になっていない可能性もあると考えたが、その場合はrunning状態で外部IPに接続した時に画面が表示されないという現象が見られるはずなので今回のケースでは除外した。
- Googleで「nginx Pending k8s」と検索してみた
- k8sの公式ドキュメントのPodがPending状態に止まっている原因
- リソースが不十分
- hostPortの使用
- k8sの公式ドキュメントのPodがPending状態に止まっている原因
→ k8sの問題だしこの辺りがあり得そう。今回はこの場合だと考えて答えを作っていく。
修正手順案詳細
デバッグを頑張る
※ ここではhostnamesがnamespaceの名前
- サービスの存在確認
$ kubectl get svc hostnames
- サービスはDNS名によって機能しているか
$ nslookup hostnames
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: hostnames
Address 1: 10.0.1.175 hostnames.default.svc.cluster.local
> これが失敗した場合、おそらくPodとServiceが異なるNamespaceにあるため、ネームスペースで修飾された名前を試す
DNSについて色々試す。
$ nslookup hostnames.default
> クロスネームスペース名を使用するようにアプリケーションを調整するか、同じNamespaceでアプリとServiceを実行する必要がある
$ nslookup hostnames.default.svc.cluster.local
$ nslookup hostnames.default.svc.cluster.local 10.0.0.10
> 完全修飾名では検索できるのに、相対名ではできない場合、Podの/etc/resolv.confファイルが正しいことを確認する必要があります。Pod内から実行します
いっぱいあって全部キャッチアップするのは無理な気がした。
リソースが不十分な場合
- クラスターにノードを追加する
- マニフェストをいじらなくてはいけないのかと思ったけど、
kubeadm
というコマンドを使うと実行中のk8sに対して追加できるらしい
- マニフェストをいじらなくてはいけないのかと思ったけど、
ノードの追加
kubeadm join --token <token> <control-plane-host>:<control-plane-port> --discovery-token-ca-cert-hash sha256:<hash>
トークン一覧を見てみる
kubeadm token list
トークンは一時的なので、トークンの発行もできる。24hできれる
kubeadm token create
- 不要なPodを削除する
- これは問題的にできるのかな🤔 可能性としては低そう
- Podがノードよりも大きくないことを確認する
cpu: 1
の場合、cpu: 1.1
を要求するPodは決してスケジュールされない- キャパシティを調べるコマンド
kubectl get nodes -o yaml | egrep '\sname:|cpu:|memory:' kubectl get nodes -o json | jq '.items[] | {name: .metadata.name, cap: .status.capacity}'
hostPortの使用
- PodをhostPortにバインドすると、Podをスケジュールできる場所の数が制限される
- この辺りも微妙。おそらくこんな感じで設定するのだと考えられるが、これってマニフェストファイルをいじらないとダメな気がする🤔
ports: - name: liveness-port containerPort: 8080 hostPort: 8080
解説
めちゃ調べたんだけど全然違った!😭 むずい。
原因
Rookを削除する際にコンフィグ情報やログデータなどが保存されているdataDirHostPathを削除しなかったこと。
原因究明方法
/home/user/manifest
には、Flannel 、MetalLB、Rook、NginxのDeploymentが書かれたtest-nginx.yamlなどのマニフェストが保存されています。test-nginx.yamlはPVC 、そのPVCを/usr/share/nginx/htmlにマウントするNginx のDeployment 及び、Nginx を公開するためのLoadBalancer Serviceを定義します。
ここで、なんのサービスを使っているのかを確認する。PVCはPersistentVolumeClaimの略でユーザーによって要求されるストレージのことらしい。(詳細)。ちなみにFlannelはネットワーキングをいい感じにするやつ。MetalLBはベアメタル用のロードバランサー。ベアメタルってなんだよと思って調べたら「OSやソフトウェアなどがインストールされていないまっさらなハードディスク(物理サーバー)」のことらしいです。ベアメタル覚えた!
問題環境では、問題名にあるNginx だけでなくPVC もPendingとなっています。 PendingになっているPVCを
kubectl describe pvc cephfs-pvc
で確認すると、failed to provision volume with StorageClassとエラーが出ています。
問題文だけでは知らんがな問題。kubectl describe pvc cephfs-pvc
でpvcの状態をみれるのは覚えておいた方がいいかも。基本的にはkubectl describe <サービス> <namespace>
でいけるのではないかと。覚えとけば、ぐぐりで乗り越えられそう・
このKubernetesクラスタではRookを利用し、CephをPersistent Volumeとして使っています。このことから、Rookの設定の異常等を予想し、Rookのエラーを確認する必要があります。そのため、
/home/user/manifest
にあるRookのマニフェスト(cluster.yaml)では、無効化されているcrash-collectorを有効化し適用します。立ち上がったcrash-collectorをkubectl describe
で確認すると、Unable to attach or mount volumesとなっています。
ここでcrash-collectorを有効化し適用とあるが、crash-collector知らないとできない気がするな〜〜。無効化することができるのかは微妙。無効以外できたら60%くらいの点は入りそう。
Rookがマウントしてそうな場所を探すと、 cluster.yamlの33行目にdataDirHostPath: /var/lib/rookなる行があります。 そして、この直前の31行目のコメントに、 Important: if you reinstall the cluster, make sure you delete this directory from each host or else the mons will fail to start on the new cluster. と書かれています。
日本語に訳すと「クラスタを再インストールする場合は、各ホストからこのディレクトリを削除してください。そうしないと、新しいクラスタでのmonsの起動に失敗します。」みたいです。
解決手順
解決方法としては、RookのDocumentに書かれた通りにクラスターの清掃を行うだけ。
- 適用されているRookを削除(ここでは6つのyamlに対して
kubectl delete -f hoge.yaml
をしている) - 該当するディレクトリ(
/var/lib/rook
)を削除 crash-collector
を無効化- crashモジュールが提供する機能をRookから使う用のコントローラーらしい
- 無効にするのに設定がいるのかどうなのかよくわからなかった。
- https://zenn.dev/satoru_takeuchi/articles/33560b2e753972
kubectl apply -f hoge.yaml
をするkubectl exec -it ”Pod名” -- bash
でpodの中に入る- その中のShellで、
echo -e "<a>”チーム名”</a>" > /usr/share/nginx/html/index.html
をする