この記事はKMCアドベントカレンダー2023の24日目です。
この記事ではインフラ初心者がkubernetesクラスタを立ててみたときに詰まった点をまとめてみました。
はじめに
最近、VPS上で公開していたポートフォリオや歌枠データベースをDocker上で立てられるようにし、自宅サーバーへと完全移行しました。
(自宅サーバーへサーバーを移行した話はこの辺りの記事にまとめました。)
しかし、自宅サーバーは諸々の理由で頻繁に電源が落ちるため、kubernetesを使って冗長構成にしたいと思うようになりました。また、毎回sshでログインしてデプロイをするのが手間だったので自動デプロイの基盤をkubernetesで作りたいと思うようになり、意を決してkubernetesのお勉強を始めました!
というわけで、これから先「お家Kubernetes環境を作ろう」シリーズとしてk8sのお勉強記録をつけていこうと思います。
今回はその第一段階として、VPS上にkubernetesのマルチノードクラスタを構成してみました。
環境
- lemon: Kagoya Cloud VPS 2コア 2GB
- lime: Kagoya Cloud VPS 2コア 2GB
(lemonやlimeはマシン名です)
- デプロイツール: kubeadm
- CRI: cri-dockerd
- CNI: Calico(で上手くいかなかったためWeave netにした(後述))
ネタバレ
細かいことは置いといてとりあえず結論を知りたい!と言う方へ
マルチノードクラスタ上でpodを作成し、port-forwardしてpodにアクセスしようとしたのですが、表題の通りpodにアクセスできないという問題が生じました。
$ kubectl port-forward hello-node-7c97b7fcf5-rj259 8080:8080
error: error upgrading connection: unable to upgrade connection: pod does not exist
結論から言うと、Calicoに必要なポートが使えないことが原因でした。VPSをローカルネットで繋いだりしたものの179番が通らなかったため、Calicoは諦めてWeaveworksを使うことにしました。
問題発生までの流れ
ざっくり言うと:
- kubeadm init
- Calicoのインストール
- kubeadm join
- hello-nodeのデプロイ・サービス作成
です。詳細に興味がない方は次章まで飛ばして大丈夫です。
Docker・コンテナランタイムのインストール
ドキュメントを眺めて、雑に馴染みのあるDocker Engineを選んでインストールしました。
(強いお友達はCRI-Oとかを勧めていた気がするが初心者の私には違いが分からないため一旦このまま進めます。)
kubeadm-config.yamlを記述
CRIにcri-dockerdを選んだため、kubeadm initするときに読み込むconfigファイルに次のように記述しました。後でCalicoを使うためにClusterConfiguration
のnetworking.podSubnet
もついでに設定しておきます。
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
nodeRegistration:
criSocket: unix:///run/cri-dockerd.sock
===
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: stable
networking:
podSubnet: "192.168.0.0/16"
criSocketはunix://
をつけないとエラーで怒られたので注意が必要です。
kubeadm init
マスターノードにしたいVPS上で
$ sudo kubeadm init --config=kubeadm-config.yaml
としました。表示されるコマンド(mkdir ...とか)をコピーして実行します。また、kubeadm joinコマンドは後で使うためコピーしてどこかにメモっておきます。
Calicoをインストール
Install Calicoのコマンドを順に実行しました。
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.4/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.4/manifests/custom-resources.yaml
kubeadm join
ワーカーノードにしたいVPS上にもdockerやcri-dockerdなどをインストールし、さっきメモったコマンドを実行します。
$ sudo kubeadm join ...(略) --cri-socket=unix:///var/run/cri-dockerd.sock
ワーカーノードでもCRIにcri-dockerdを使用しているため、kubeadm join ...
にオプションで--cri-socket=unix:///var/run/cri-dockerd.sock
を指定する必要があります。これを忘れるとCRIが複数あって云々と怒られました。
マスターノードに戻ってnodeを確認してみると、正常に追加できていそうです。
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
lemon Ready control-plane 27m v1.28.2
lime Ready <none> 19m v1.28.2
hello-nodeをデプロイ
チュートリアルに従って、hello-nodeのデプロイメント・サービスを作成します。
$ kubectl create deployment hello-node --image=registry.k8s.io/echoserver:1.4
$ kubectl expose deployment hello-node --port=8080
チュートリアルから単純にコピペするとserviceのtypeはLoadBalancerになっていますが、これを正しく使うにはMetalLbなどを入れる必要があるため、--type=LoadBalancerは消して実行します。
問題の内容
前章でマルチノードクラスタ上にhello-nodeのpod・serviceを作成することができました。
get pods
やらをすると、確かにpodやserviceが作成できていそうです。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-node-7c97b7fcf5-rj259 1/1 Running 0 21m
$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
hello-node 1/1 1 1 21m
$ kubectl get svc/hello-node
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-node ClusterIP 10.111.221.203 <pending> 8080:31781/TCP 18m
そこで、実際にpodに対してport-forwardしようとすると、
$ kubectl port-forward hello-node-7c97b7fcf5-rj259 8080:8080
error: error upgrading connection: unable to upgrade connection: pod does not exist
pod does not exist
と言われてしまいました。
試したこと
- namespaceが
default
になっているか確認→なっている。
$ kubectl get pod -A -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
calico-apiserver calico-apiserver-68644496f8-4w6wp 1/1 Running 0 46m 192.168.232.6 lemon <none> <none>
calico-apiserver calico-apiserver-68644496f8-h5v4r 1/1 Running 0 46m 192.168.232.5 lemon <none> <none>
calico-system calico-kube-controllers-69bbc55b7-d5slw 1/1 Running 0 46m 192.168.232.4 lemon <none> <none>
calico-system calico-node-4vwxs 0/1 Running 0 46m 10.150.11.1 lemon <none> <none>
calico-system calico-node-hrhhl 0/1 Running 1 (8m43s ago) 40m 10.150.11.1 lime <none> <none>
calico-system calico-typha-6c4fc595ff-kdqwn 1/1 Running 0 46m 10.150.11.1 lemon <none> <none>
calico-system csi-node-driver-d2fzq 2/2 Running 0 46m 192.168.232.2 lemon <none> <none>
calico-system csi-node-driver-z9xm7 2/2 Running 0 40m 192.168.124.129 lime <none> <none>
default hello-node-7c97b7fcf5-rj259 1/1 Running 0 39m 192.168.124.130 lime <none> <none>
kube-system coredns-5dd5756b68-6twqb 1/1 Running 0 48m 192.168.232.3 lemon <none> <none>
kube-system coredns-5dd5756b68-rkwdv 1/1 Running 0 48m 192.168.232.1 lemon <none> <none>
kube-system etcd-lemon 1/1 Running 0 48m 10.150.11.1 lemon <none> <none>
kube-system kube-apiserver-lemon 1/1 Running 0 48m 10.150.11.1 lemon <none> <none>
kube-system kube-controller-manager-lemon 1/1 Running 0 48m 10.150.11.1 lemon <none> <none>
kube-system kube-proxy-8n2r9 1/1 Running 0 48m 10.150.11.1 lemon <none> <none>
kube-system kube-proxy-m8qlt 1/1 Running 0 40m 10.150.11.1 lime <none> <none>
kube-system kube-scheduler-lemon 1/1 Running 0 48m 10.150.11.1 lemon <none> <none>
tigera-operator tigera-operator-7f8cd97876-pm4hz 1/1 Running 0 46m 10.150.11.1 lemon <none> <none>
- serviceで指定すると?→できない。
$ kubectl port-forward svc/hello-node 8080:8080
error: error upgrading connection: unable to upgrade connection: pod does not exist
- podSubnetが被っている説?を検証
kubeadm-config.yaml
のpodSubnetを次のように修正。
networking:
podSubnet: 10.244.0.0/16
この変更を加えてkubeadm reset
、kubeadm init
をしたところ、色々と苦戦したのですが結局上手くいきませんでした。
この部分で詰まった点は記事1つ分くらいになりそうなのでここでは省略することにします。
- Calicoの必須ポートを確認
CalicoのNetwork requirementsに記載のポートが公開されていないことに気づきました。
179番を公開するのはあまり良くないと考え、Kagoya Cloud VPSのローカルネットワークを使ってVPSを同一ネットワーク上に配置しました。
Kagoyaのマニュアルに従ってIPを10.0.0.1/16, 10.0.0.2/16にしました。
しかし、同一ネットワークに配置しても179番が使えず、Calicoの使用を断念しました。
- Weave netをいれてみる
すぐには上手くいきませんでした。
ログを見てみたところ、設定したIPで通信されていませんでした。
- localAPIEndpointを設定する
kubeadm-config.yaml
のInitConfiguration
を次のように修正しました。
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
nodeRegistration:
criSocket: unix:///run/cri-dockerd.sock
localAPIEndpoint:
advertiseAddress: 10.0.0.1
bindPort: 6443
...
これでkubeadm reset + kubeadm initを再度行ったのですが、なお上手くいきませんでした。
- Calicoの設定を抹消
/etc/cni/net.d
、/opt/cni/bin
にcalicoの設定が残っていたためすべて削除して再起動したところ、上手くいきました!!
教訓
- インストールするパッケージ等のrequirementsはちゃんと確認する!
必須ポートが開いていることを確認できていなかったのが最大の原因 - エラーが起きたらちゃんとログを読もう!
最後に
今回エラーを解消するに当たり、WalnutsとSouthball、他KMCの先輩方にたくさん助けていただきました。ありがとうございます!!
この次は手元のminikube上でnextサーバー構築に挑戦していきたいと思います。