Kubernetesクラスターをホームラボに立てる
- 2021.11.21
- パソコン
Kubernetesとは
Kubernetesとは、コンテナのオーケストレーションツールで、昨今のエンジニア業界では切っても切れないです。コンテナを使うプラットフォームとして有名なのはDockerですね。このDockerを使って、開発作業をするととても便利で、環境依存しないし、そのまま運用環境にも持っていけるという素晴らしいものです。
Dockerについてはいずれ語っても良いのですが、ググればいくらでも出てきます。以下のページはとても分かりやすくまとめてあります。
Qiita – なぜ Docker を使うのか? 小規模シス管向けの Docker のススメ
単純なシステムであれば、コンテナ一つでサービスを提供すればいいのですが、実際の運用はそうはいきません。1日のアクセスが1000くらいのシステムなのに、何かのSNSでバズっていきなりある日から1日のアクセスが1万とか10万とかになるという事もあります。その時サイトが落ちてしまうと炎上します。または、絶対に落ちてはいけないシステムを言うものもあります。これを落ちないように管理構成するのがとても大変です。
オーケストレーションツールを使うと、アクセスや負荷によって1台だったWEBサーバを5台にするとか、バックエンドのアプリサーバが重くなってきたので2台にするとか、サーバが落ちたので自動で復旧させるとか、その手の仕事を自動でしてくれるのです。
なぜMinikubeではダメなのか?
Kubernetesは、クラスター構成のため複数サーバが必要です。システムを管理するマスターノードがあり、コンテナを走らせるワーカーノードが何台もあるというものです。運用環境は色々でオンプレの数台のサーバ構成もあれば、AWSなどのクラウドでマネージドのサービスを利用することもあります。
しかし、Minikubeはローカル環境(ローカルPC)で立てて、Kubernetesがどんなものか確認するためのテスト環境です。「Kubernetesってどんなものか?」、「どんなコマンドが実行できるのか?」、「その結果はどのように表示されるのか?」などの答えを得るものであって、お試しやテスト目的以外にはあまり使えません。
それでも、まずはお金をかけずに最低限動けばいいので使ってみたいという人にはお勧めです。以下の、公式サイトのドキュメントの通りにすれば30分から1時間でKubernetesを体験することができます。
kubernetes.io – Minikubeを使用してローカル環境でKubernetesを動かす
ただ、勉強するためでなく、これからシステムを運用するために急いで勉強が必要だったり、商用環境で使うためのトレーニングが必要な場合は、本物の複数台構成のクラスターを立てた方が実環境に近く、仕組みもよく理解することができます。
ホームラボのESXiに仮想環境を準備する
商用環境ほどのリソースはいらない
Kubernetesクラスターを立てると言っても、サーバPCが何台も必要とか、サーバラックを置かないといけないという事はありません。商用環境はCPU16コア、メモリ32GBのサーバが最低3台とか、個人でするにはコストがかかりすぎます。しかし、あくまでテスト環境なので、最低限のリソースで十分です。
ホームラボに関しては別途記事を作ろうと思いますが、vmware社のESXiやオープンソースのProxmoxなどを使えば、自宅の使っていないパソコンを仮想サーバのプラットフォームにすることができます。古いパソコンの中に仮想サーバを何台か立てて使用するわけです。
もし使っていないPCにCPU4コア、メモリ8GBのスペックがあれば、それで十分です。CPUは常にリソースを使い続けるわけでもないので、CPU2コアでメモリ2GBの仮想サーバを3台立てても十分使えます。Linuxのサーバはそもそもそんなにリソースを食いませんし、海外にはラズパイを並べてKubernetesクラスターを組んでいるエンジニアもたくさんいます。
今回のサーバ構成と参考情報
ESXiにCPU2コア、メモリ2G、HDD15GBの仮想サーバを3台立てます。スペックは以下の通り。
OSはUbuntu-20.04.2のサーバ版です。固定IPアドレスを設定し、追加のサービスは何も入れずにいちから設定します。
OSインストールして、最新の状態にアップグレードするまでは割愛します。
ネットワーク設定
例として、一番多そうなローカルIPの構成にしてみる。
- ルーター:192.168.1.1/24
これを元に、各サーバには固定IPアドレスを設定する。
- マスター:192.168.1.100/24
- ワーカー1:192.168.1.101/24
- ワーカー2:192.168.1.102/24
参考情報
以下のYoutube動画を参考に進めています。
github.com – “Install Kubernetes Cluster using kubeadm” by justmeandopensource
いちからすべて構築すると大変なので、公式のインストールツールであるkubeadmと公式ドキュメントを参考にします。
kubernetes.io – kubeadmのインストール
追加の情報として、以下のサイトも参照しました。
Kubernetes環境を構築して、実際にコンテナを動かしてみよう
KubeadmでKubernetesをインストールする方法ー簡易版
Kubernetesクラスターを構築する
1. マスター1台とワーカー2台の全てで同じ作業をする
Kubernetesインストール前の準備作業
rootユーザーになる
$ sudo su -
ファイヤーウォールを無効にする
# ufw disable
Firewall stopped and disabled on system startup
ファイヤーウォールが無効になっているのを確認する
# ufw status
Status: inactive
Swapを無効にして、起動時にも読み込まないようにする
# swapoff -a; sed -i '/swap/d' /etc/fstab
Kubernetes用のネットワーク設定をsysctlに行い、有効にする
# cat >>/etc/sysctl.d/kubernetes.conf<<EOF
> net.bridge.bridge-nf-call-ip6tables = 1
> net.bridge.bridge-nf-call-iptables = 1
> EOF
# sysctl --system
* Applying /etc/sysctl.d/10-console-messages.conf ...
kernel.printk = 4 4 1 7
・・・
* Applying /etc/sysctl.conf ...
Dockerインストール。とりあえず、ちゃんと動くのが確定しているバージョンを指定。
# apt install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common
# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
# add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
# apt update
# apt install -y docker-ce=5:19.03.10~3-0~ubuntu-focal containerd.io
Dockerサービスが稼働しているかを確認する。Ubuntuはサービスがインストールされると自動で有効になるが、CentOSなどでは自動起動に設定してからサービスを起動してあげる必要がある。
~# systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2021-11-21 04:39:38 UTC; 7min ago
TriggeredBy: ● docker.socket
Docs: https://docs.docker.com
Main PID: 24658 (dockerd)
Tasks: 10
Memory: 35.6M
CGroup: /system.slice/docker.service
└─24658 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
Nov 21 04:39:37 kube-master dockerd[24658]: time="2021-11-21T04:39:37.886498993Z" level=warning msg="Your kernel does not support cgroup rt runtime"
Nov 21 04:39:37 kube-master dockerd[24658]: time="2021-11-21T04:39:37.886511442Z" level=warning msg="Your kernel does not support cgroup blkio weight"
Nov 21 04:39:37 kube-master dockerd[24658]: time="2021-11-21T04:39:37.886517300Z" level=warning msg="Your kernel does not support cgroup blkio weight_d>
Nov 21 04:39:37 kube-master dockerd[24658]: time="2021-11-21T04:39:37.886687443Z" level=info msg="Loading containers: start."
Nov 21 04:39:37 kube-master dockerd[24658]: time="2021-11-21T04:39:37.970322326Z" level=info msg="Default bridge (docker0) is assigned with an IP addre>
Nov 21 04:39:38 kube-master dockerd[24658]: time="2021-11-21T04:39:38.015974929Z" level=info msg="Loading containers: done."
Nov 21 04:39:38 kube-master dockerd[24658]: time="2021-11-21T04:39:38.032958412Z" level=info msg="Docker daemon" commit=9424aeaee9 graphdriver(s)=overl>
Nov 21 04:39:38 kube-master dockerd[24658]: time="2021-11-21T04:39:38.033198058Z" level=info msg="Daemon has completed initialization"
Nov 21 04:39:38 kube-master systemd[1]: Started Docker Application Container Engine.
Nov 21 04:39:38 kube-master dockerd[24658]: time="2021-11-21T04:39:38.054864717Z" level=info msg="API listen on /run/docker.sock"
Kubernetesのインストール
キーとリポジトリを追加
# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
# echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" > /etc/apt/sources.list.d/kubernetes.list
Kubernetes本体のインストール
# apt update && apt install -y kubeadm=1.18.5-00 kubelet=1.18.5-00 kubectl=1.18.5-00
2. マスター1台で作業をする
Kubernetesクラスターを初期化する。※自分の環境のマスターノードのIPアドレスを間違えないように!
apiserver-advertise-address には、マスターノードのIPアドレスを指定する。
pod-network-cidr には、Pod間通信で使用するホストネットワークとかぶらないIPアドレス体系を指定する。これは、Calicoを使用するための指定項目。
# kubeadm init --apiserver-advertise-address=192.168.1.100 --pod-network-cidr=172.16.1.0/16 --ignore-preflight-errors=all
Calicoをデプロイ
# kubectl --kubeconfig=/etc/kubernetes/admin.conf create -f https://docs.projectcalico.org/v3.14/manifests/calico.yaml
マスターをクラスターに参加させる
# kubeadm token create --print-join-command
↑のコマンドの再度に、他のノードをクラスター参加させるために必要なトークン情報が出るので忘れずにメモすること。
3. ワーカーノード2台それぞれで作業をする
「 kubeadm token create –print-join-command 」コマンドの結果にあるものを、そのまま実行する。
# kubeadm join 192.168.1.100:6443 --token ea81ol.q6ffuvtc46v8w6g8 --discovery-token-ca-cert-hash sha256:ac6da276b9f6a29279f61fb8d649a86e857a5d2ff6a87a4e8a507cdd44a3f85b
それぞれのワーカーノードがクラスターに参加できればクラスターの構築終了です。
4. マスターノードの一般ユーザーでkubectlを使えるようにする
マスターノードの一般ユーザーとしてログインする。
※この処理を行えば他の端末からもkubectlコマンドを使ってkubernetesを操作できる。
マスターノードの「/etc/kubernetes/admin.conf」ファイルを、ユーザーホームの「.kube/config」として配置し、権限を与える。
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
ちゃんと動いているかチェックしてみる。なんだか、Serverバージョンが異なって見えるが、「get nodes」では正しく出ている。
$ kubectl version --short
Client Version: v1.18.5
Server Version: v1.18.20
$ kubectl cluster-info
Kubernetes master is running at https://192.168.1.100:6443
KubeDNS is running at https://192.168.1.100:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kube-master Ready master 17m v1.18.5
kube-worker1 Ready <none> 12m v1.18.5
kube-worker2 Ready <none> 12m v1.18.5
$ kubectl get pods
No resources found in default namespace.
$ kubectl get cs
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-0 Healthy {"health":"true"}
$ kubectl get all
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 21m
$ kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system calico-kube-controllers-65f8bc95db-bz77j 1/1 Running 1 23m
kube-system calico-node-5b45z 1/1 Running 1 23m
kube-system calico-node-9jdbp 1/1 Running 1 19m
kube-system calico-node-wjwsm 1/1 Running 1 19m
kube-system coredns-66bff467f8-krjgc 1/1 Running 1 24m
kube-system coredns-66bff467f8-z5x2l 1/1 Running 1 24m
kube-system etcd-kube-master 1/1 Running 1 24m
kube-system kube-apiserver-kube-master 1/1 Running 1 24m
kube-system kube-controller-manager-kube-master 1/1 Running 1 24m
kube-system kube-proxy-24px8 1/1 Running 1 24m
kube-system kube-proxy-f5xlh 1/1 Running 1 19m
kube-system kube-proxy-hk42p 1/1 Running 1 19m
kube-system kube-scheduler-kube-master 1/1 Running 1 24m
5.デプロイができるかをチェックする
nginxをデプロイして、表示できるかテストする。
$ kubectl create deploy nginx --image nginx
deployment.apps/nginx created
ポッドが作成されたかを確認する。名前から「 pod/nginx-f89759699-q8v5p 」だと分かる。このステータスが「ContainerCreating」から「Running」になればOK。
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/nginx-f89759699-q8v5p 0/1 ContainerCreating 0 15s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 43m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx 0/1 1 0 15s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-f89759699 1 1 0 15s
デプロイを直接確認することもできる。
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 1/1 1 1 62m
次に、NodePortタイプとして、ポート80番でデプロイを公開する。ポッドはKubernetesクラスター内部のIPアドレスからのみアクセスすることができるため、サービスとしての公開が必要になる。
$ kubectl expose deploy nginx --port 80 --type NodePort
service/nginx exposed
公開されたかどうか、サービスをチェックする。公開されたポート番号が32479であることが確認できる。
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 44m
nginx NodePort 10.98.166.162 <none> 80:32479/TCP 14s
再度、「get all」で情報を確認する。ステータスは「Running」になっている。
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/nginx-f89759699-q8v5p 1/1 Running 0 34m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 78m
service/nginx NodePort 10.98.166.162 <none> 80:32479/TCP 33m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx 1/1 1 1 34m
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-f89759699 1 1 1 34m
さらにポッドの詳細情報を確認する。「kube-worker2」でサービスが実行されていることが分かる。
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-f89759699-q8v5p 1/1 Running 0 45m 172.16.161.193 kube-worker2 <none> <none>
ただ、「NodePort」で公開しているので、クラスターのどのIPでもいいので、32479版のポートにhttpsでアクセスすれば、Nginxのウェルカム画面が表示される。例:https://192.168.1.100:32479/
確認が終わったので、サービスの公開を停止して、デプロイを削除する。
$ kubectl delete service nginx
service "nginx" deleted
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 110m
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 1/1 1 1 66m
$ kubectl delete deployment nginx
deployment.apps "nginx" deleted
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 111m
$ kubectl get deployments
No resources found in default namespace.
6. ローカルPC(WSL)からアクセスできるようにしておく
ローカルPCからアクセスするって、サーバに入ってkubectlコマンドをたたけば良いわけですが、実運用でそんな危険なことは行いません。また、サーバに色々便利ツールを入れてみたりも日本ではあまりしないと思います。
サーバに入って作業することはあっても、基本はローカルPCにて作業しますし、コードはGitで管理するし、運用にはRancherやクラウドプロバイダの管理用WebUIを使います。
ローカル環境には、WSL(実際にはWSL2)のUbuntu20.04LTSを使用します。
WSLはLinuxなので、Linux用の入れ方を公式サイトで確認する。
kubernetes.io – Install and Set Up kubectl on Linux
kubectlはクラスターと同じバージョンを入れるのがセオリーなので、まずがマスターノードで確認しておきます。相変わらずサーババージョンは変な出方をしているが、1.18.5を入れることにする。
$ kubectl version --short
Client Version: v1.18.5
Server Version: v1.18.20
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kube-master Ready master 3h21m v1.18.5
kube-worker1 Ready <none> 3h16m v1.18.5
kube-worker2 Ready <none> 3h16m v1.18.5
まずは、ホームフォルダに以下のファイルを作成します。ファイルの中身はサーバからコピーしてきます。ただ、Ubuntuサーバは初期状態ではrootでログインできませんので、scpコマンドでコピーしてくるという事はできません。rootパスワードを設定してもいいのですが、実サーバでそれをすると結構なセキュリティホールになりかねないのでお勧めできません。
$ mkdir -p $HOME/.kube
$ vi ~/.kube/config
$ chmod 600 ~/.kube/config
次に、kubectlコマンドをインストールします。
$ sudo apt-get install -y apt-transport-https ca-certificates curl
$ sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
$ echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
$ sudo apt-get update
$ sudo apt-get install -y kubectl=1.18.5-00
ちゃんと、コマンドが使えることを確かめてみる。これらの結果が表示されればサーバに接続されている。
$ kubectl cluster-info
$ kubectl get pods
$ kubectl get nodes
K9sを入れてKubernetesが使える人のふりをしてみる(おまけ)
K9sは、KubernetesをCLI(コマンドラインインターフェース)でグラフィカルに使う事の出来るツールです。
Kubernetesが、最初のKと最後のsの間に8文字のアルファベットがあるので「K8s」と表記されますが、それよりちょっと出たことができるという意味で「K9s」というしゃれたネーミングになっています。
公式ドキュメントを見る限り、どうもサクッとインストールさせてくれないらしい。Snapでも入れられるが、WSLはsystemdが動いてないので、そこをごにょごにょする必要がある。ということで、LinuxBrewで入れることにする。
LinuxBrewのインストール
$ sudo apt-get install build-essential curl git m4 ruby texinfo libbz2-dev libcurl4-openssl-dev libexpat-dev libncurses-dev zlib1g-dev
$ sudo apt-get install gettext
$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
ダウンロードや処理に時間がかかるので、しばらく放置してよい。その後は、画面の指示に従ってコマンドを実行するとhomebrewがインストールされる。
ちゃんとインストールされているかの確認は以下のコマンドで行える。
$ brew doctor
K9sのインストール
先ほどインストールしたbrewを使ってK9sをインストールする。
$ brew install k9s
インストールが終了したら、コマンドを実行してKubernetesクラスターの情報を参照できるかを確認する。
$ k9s
リモート接続のためか、リソースは表示されないようだ。使い方は以下のサイトを参照するとよい。
終了は「Ctrlキー+C」でOKの模様。
最後に一言
お疲れさまでした。
そのうち、RancherやPrometheus、Grafanaなども紹介できればいいかと思っています。
ホームラボについても電力と場所を取らずに、騒音も発しないやり方を紹介できればと思っています。
仕事の都合で、会社のナレッジベースには書き込んでも、ブログにするのは時間がかかるので面倒でやらないことが多いです。ただ、この手のドキュメントは英語の文献か英語の動画がほとんどで、困っている人も多いと思います。
何か記事にして欲しいことがあればコメントかお問い合わせフォームからご連絡いただければ助かります。
有料の情報の方が短時間で学べることに気が付いてきたので、ブラックフライデーを使ってUdemyで安く講座を受けようかと思っています。専門書もAmazonで安くなっているといいのですが。
-
前の記事
IP電話「Grandstream GXP1450」を設定する方法 2021.01.15
-
次の記事
Proxmoxでプライベートクラウドを立てる 2021.12.05