余ったPC1台を使ってオンプレKubernetesクラスタを構築してみる
はじめに
仕事ではGoogle Kubernetes Engine (GKE)を使ってのKubernetesクラスタ構築をしています。
仕事以外の時間でもKubernetesクラスタをゴリゴリ触ってみたいと思いました。
そこで、家の使っていない古いPCを使ってKubernetesクラスタをいちから作成してみることにしました。
(2020-01-26 追記)
当エントリでまとめたセットアップ手順をシンプルなシェルスクリプトにまとめ、公開しました。
クラスタを構成する「マスタサーバ」と「ノード」の2つの役割はどうするの?
Kubernetesクラスタには、マスターサーバとノードと言われるサーバが必要になります。
ざっくりいうと、 マスターサーバは管理者からの要求に答えてノード(後述)にコンテナを立ち上げたり、ノードに存在するコンテナの状況を監視します。
ノードはコンテナそのものを動かすサーバです。
「Hadoop HDFS」におけるマスタノードとスレーブノードに似ていますね。
したがって、できる限りマスターサーバは余裕のある状況が望ましいです。
ただし今回は検証環境である、またお金をかけたくないなどの理由から、
「マスタサーバ」x1台と「ノード」x1台を物理サーバx1台に共存させたいと思います。
セットアップ
Kubernetesクラスタを構築していきます。
OSのディストリビューション・バージョンを確認
さて、今回余っていた古いPCには Ubuntu18.04
がインストールされていたため、その環境をそのまま利用します。
$ uname -v
40~18.04.1-Ubuntu SMP Thu Nov 14 12:06:39 UTC 2019
Docker のインストール
セットアップ後は以下のコマンドを実行し、OSリブート時にもサービスが自動起動するようにしておきます。
$ sudo apt-get update -y
$ sudo apt-get install -y docker.io
$ sudo systemctl enable docker.service
# 現在ログインしているユーザが `docker` コマンドを実行できるようにしておく
$ sudo gpasswd -a "${USER}" docker
# 上記で設定したdockerグループへの所属は、一度ログインしないと反映されない
$ exit
正常にセットアップされたか配下のコマンドを実行すれば確認できます。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
**※まずここで詰まると先に進めないので、確実に docker ps
が正しく動作しているかを確認しましょう。
kubeadm のインストール
※CentOSの場合についても試すことができたので掲載しておきます。
Ubuntuの場合
apt
のリポジトリにKubernetesの設定を追加します。
$ sudo apt-get install -y gnupg gnupg2
$ curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg|sudo apt-key add -
$ echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kube.list
準備ができたのでインストールしてみます。
$ sudo apt-get update -y
$ sudo apt-get install -y kubeadm kubelet kubectl
正常にインストールできたか確認してみます。
# バージョン情報が表示されればOK
$ kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.2", GitCommit:"59603c6e503c87169aea6106f57b9f242f64df89", GitTreeState:"clean", BuildDate:"2020-01-18T23:27:49Z", GoVersion:"go1.13.5", Compiler:"gc", Platform:"linux/amd64"}
CentOSの場合
CentOSの場合はyum
でインストールできるようにリポジトリを追加します。
$ cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
# Set SELinux in permissive mode (effectively disabling it)
$ setenforce 0
$ sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
インストールしていきます。
$ yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
$ systemctl enable --now kubelet
正常にインストールできたか確認してみます。
# バージョン情報が表示されればOK
$ kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.2", GitCommit:"59603c6e503c87169aea6106f57b9f242f64df89", GitTreeState:"clean", BuildDate:"2020-01-18T23:27:49Z", GoVersion:"go1.13.5", Compiler:"gc", Platform:"linux/amd64"}
マスターサーバの初期化
kubeadm
コマンドを使って、マスターサーバを初期化します。
- Swapが有効になっていると初期化できないようなので、無効にしておきます。
- –pod-network-cidr=10.244.0.0/16 のオプションはflannel(後述)というKubernetes上の仮想ネットワークを構成するための設定となります。
多少時間がかかるため、気長に待ちましょう。
# SwapをOFF
$ sudo swapoff -a
# 初期化
$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16
...
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.0.201:6443 --token *********************** \
--discovery-token-ca-cert-hash sha256:****************************************************************
マスターサーバと通信するための設定と動作確認
マスターサーバの初期化が終了しました。
先程のログにかかれていますが、現在のログインユーザでKubernetesクラスタと通信するための設定を行います。
$ mkdir -p $HOME/.kube
$ sudo cp -f /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
kubectl version
でバージョンが表示されるかを確認します。
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.1", GitCommit:"d224476cd0730baca2b6e357d144171ed74192d6", GitTreeState:"clean", BuildDate:"2020-01-16T11:36:03Z", GoVersion:"go1.13.6", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.2", GitCommit:"59603c6e503c87169aea6106f57b9f242f64df89", GitTreeState:"clean", BuildDate:"2020-01-18T23:22:30Z", GoVersion:"go1.13.5", Compiler:"gc", Platform:"linux/amd64"}
flannelをデプロイ
Kubernetes上の仮想ネットワークを構成するためのコンポーネントをインストールします。
- ネット上に掲載されているflannelのインストールコマンドは現在では古い場合が多いことに注意!
- これは当ブログにも言えることです!!
- 2020-01-20現在は、以下のmasterブランチの構成情報ファイルが利用できました。
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
マスタノードにポッドをスケジュールできるようにする
kubeadm
で初期化したマスターサーバは、デフォルトの状態では「ノード」の役割を持ちません。
通常は「マスタサーバ」は余裕のある状況が望ましいですのですが、何度も言いますが今回は検証環境であるため、「ノード」の役割を兼任させてしまいます。
$ kubectl taint nodes --all node-role.kubernetes.io/master-
kubelet
サービスを有効化
「ノード」の役割を担当する kubelet
というサービスを、OS起動時にも自動的に立ち上がるようにしておきます。
$ sudo systemctl enable kubelet.service
ここまで行けばクラスタの構築は完了です。
Apacheサーバを立ち上げてみる
Kubernetesクラスタを使って、Apacheサーバを立ち上げてみます。
細かい説明は省略しますが以下のコマンドを実行してみます。
# Apacehサーバを立ち上げる
$ kubectl run --port 80 --image=httpd httpd
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/httpd created
# Apacheサーバが立ち上がっているかを確認する
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
httpd-785b97775d-nkbx7 1/1 Running 0 18s
# このままではサーバにはクラスタ外からはアクセスできないので、ポートフォワードして8080でアクセスできるようにする
$ kubectl port-forward httpd-785b97775d-nkbx7 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
Handling connection for 8080
ブラウザあるいはcurl
コマンドで http://localhost:8080
にアクセスしてみます。
$ curl localhost:8080
<html><body><h1>It works!</h1></body></html>
無事Webページが見れるはずです。
ひとこと
1台のKubernetesクラスタはどこまで死なずに稼働できるでしょうね。
試してみます。
ディスカッション
コメント一覧
まだ、コメントがありません