sagantaf

メモレベルの技術記事を書くブログ。

Kubernetesクラスタ構築(オンプレ/Ubuntu)

はじめに

以前、KubernetesをDocker for Macを使って構築してみました。(下の記事)

sagantaf.hatenablog.com


今回は、Ubuntu環境にKubernetesクラスタを構築したいと思います。

Ubuntu16.04, 18.04どちらも構築できることを確認済みです。

なお、クラウドのマネジメントサービスは使わず、手動で構築する手順になっており、master01およびnode01というホスト名の2台のUbuntu環境にて構築します。



1. Masterの構築

1-1. 環境のクリーンアップ

クリーンな環境でインストールするためにまずは下記を実施します。

  • dockerをアンインストール
sudo apt purge docker-ce docker-ce-cli docker
  • etcdをアンインストール

  インストールされているかを確認し、あればアンインストールを実行します。

dpkg -l | grep etcd
sudo apt purge etcd
  • /var/lib/etcd の削除

  中身を削除します。ない場合はスキップでOKです。


1-2. Dockerのインストールと初期設定

docker-ceをインストールします。

sudo apt install docker-ce=18.06.2~ce~3-0~ubuntu
docker --version # インストールされたことの確認

注意)Dockerのバージョンが新しすぎると、Kubernetesが対応していないため、エラーになります。公式ページで対応しているバージョンを確認してください。

[https://kubernetes.io/:title]

上記のバージョンでインストールした場合は下記の出力になります。

Docker version 18.06.2-ce, build 6d37f41


次にcgroupの設定を確認します。

/etc/docker/daemon.jsonのファイルが下記のようになっていることを確認し、なっていなければ編集して合わせます。

{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}

編集した場合は、設定を反映させるために、dockerデーモンを再起動します。

sudo systemctl daemon-reload
sudo systemctl restart docker


1-3. Kubernetesに必要なライブラリのインストール

まずは、必要なライブラリをインストールします。

sudo apt update && sudo apt install -y apt-transport-https curl

Kubernetesリポジトリ取得し、kubeadm, kubelet, kubectlをインストールします。

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -

sudo su -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
exit

sudo apt update && sudo apt install -y kubelet kubeadm kubectl


これでKubernetesクラスタを構築するための準備が整いました。


1-4. Kubernetesクラスタの構築

まずは、メモリのswap機能をoffにします。これを実行しないとkubeletを起動できません。

sudo swapoff -a

swap onの状態でkubeletを起動しようとすると下記のようなエラーが発生します。kubeletはswap機能をサポートしていないそうです。

error: failed to run Kubelet: Running with swap on is not supported, please disable swap! or set --fail-swap-on flag to false. 


swapをoffにしたら、いよいよクラスタの構築です。

下記のコマンドを実行します。ネットワークも自動で設定するためにflannelを考慮したオプションを指定しています。

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.xxx.xxx:6443 --token XXXXXX.XXXXXXXXXXXX \
    --discovery-token-ca-cert-hash sha256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX


上記の出力の通り、kubernetesの設定ファイルをコピーし、権限を設定します。

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

sudo chown $(id -u):$(id -g) $HOME/.kube/config

これを実行しないとkubectlコマンドが使えないので注意してください。

また、出力の最後の部分(kubeadm join xxx.xxx.xxx.xxx:6443 ~)をメモっておいてください。node追加時に必要になります。


下記のコマンドでmasterとして追加されたことを確認できます。

kubectl get nodes

出力は下記のようになるかと思います。

NAME       STATUS     ROLES    AGE   VERSION
master01   NotReady   master   15m   v1.16.1

この時、STATUSはNotReadyのままになっていますが、これからネットワーク設定をしてReadyにしていきます。


1-5. flannelを使ったネットワーク設定

上述の通り、この時点ではmasterの状態はNotReadyのままであるため、ネットワークの設定を実施する必要があります。

まずは、ネットワークファイルを設定します。

sudo su -
echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables
exit

そしてインターネット経由でflannelのyamlファイルを取得し、kubernetes環境に適用します。

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

1分以内にはPodの起動が完了し、Ready状態になるはずです。

NAME       STATUS   ROLES    AGE   VERSION
master01   Ready    master   17m   v1.15.0


以上でMasterの設定は完了です。次は実際のコンテナが動くNodesの設定です。


2. Nodeの構築

途中まではMasterと同じです。


2-1. 環境のクリーンアップ

# dockerをアンインストール
sudo apt purge docker-ce docker-ce-cli docker
# etcdをアンインストール
dpkg -l | grep etcd
sudo apt purge etcd
# `/var/lib/etcd` の削除


2-2. Dockerのインストールと初期設定

# dockerのインストール
sudo apt install docker-ce=18.06.2~ce~3-0~ubuntu
docker --version # インストールされたことの確認

# daemon.jsonの確認
cat /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}

# 必要であればdockerの再起動
sudo systemctl daemon-reload
sudo systemctl restart docker


2-3. Kubernetesに必要なライブラリのインストール

sudo apt update && sudo apt install -y apt-transport-https curl

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -

sudo su -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
exit

sudo apt update && sudo apt install -y kubelet kubeadm kubectl


2-4. Nodeの追加

ここもMasterと同じく、まずメモリのswap機能をoffにします。

sudo swapoff -a

また、一度でもnode追加をしたことがある機器を再利用している場合は、下記のコマンドでリセットしておかないと正常に稼働しません。

sudo kubeadm reset


その後、Masterのkubeadm initコマンドの最後に出力されたkubeadm joinコマンドでnodeの追加を実施します。

sudo kubeadm join 192.168.xxx.xxx:6443 --token xxxxxx.xxxxxxxxxxxx     --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxx

上記はxxxで記載していますが、実際には英数字が入ります。
注意)上記のコマンドはmasterのtokenを利用しています。そのため、Masterの設定から時間が立っている場合は、tokenが期限切れになっていることがあります。その場合はMasterにて以下を実行してtokenを再発行してください。

kubeadm token create

発行されたtokenにコマンドを書き換えて実行します。


問題なくkubeadm joinコマンドが完了したら、Masterにて追加されていることが確認できます。

kubectl get nodesコマンドを実行して結果を確認してみてください。

NAME       STATUS   ROLES    AGE     VERSION
node01     Ready    <none>   4m23s   v1.15.0
master01   Ready    master   124m    v1.15.0

もしSTATUSがNotReadyになっていた場合は、Nodeの/etc/hostsファイルに自身のIPアドレスとホスト名が記載されていない可能性があります。

記載されていなかった場合は、追加して、再度STATUSを確認するとReadyになっているはずです。


これでNodeの追加が完了しました。


2-5. 「network plugin is not ready: cni config uninitialized」というエラーが出た場合には

Node追加時に上記のエラーが出た場合は、flannelの設定ファイルを編集する必要があります。CNIプラグインのバグだそうです。
参考URL:

[BUG REPORT] cni config uninitialized after updating to v1.16.0 · Issue #1799 · kubernetes/kubeadm · GitHub

sudo systemctl status kubeletを実行することでより詳細なエラーを確認できます。

対応としては、/etc/cni/net.d/10-flannel.conflist のファイルに"cniVersion": "0.3.1"を追加すれば、数秒でエラーが解消されます。


ファイル全体は下記のようになります。

{
  "name": "cbr0",
  "cniVersion": "0.3.1",
  "plugins": [
    {
      "type": "flannel",
      "delegate": {
        "hairpinMode": true,
        "isDefaultGateway": true
      }
    },
    {
      "type": "portmap",
      "capabilities": {
        "portMappings": true
      }
    }
  ]
}


3. クラスタの確認

3-1. 補完機能の追加

確認していく前に、コマンドを楽に打てるように補完機能を追加します。

下記のコマンドを実行することで、kubectlコマンドの様々な指定を補完してくれるようになります。

sudo apt install bash-completion
echo "source <(kubectl completion bash)" >> ~/.bashrc


3-2. MasterやNodeを確認

kubectlコマンドで追加したMasterやNodeの状態を確認していきます。

下記のコマンドは今までも出現してきましたが、Masterを含む物理ホストの情報を表示できます。

kubectl get nodes -o=wide

オプションを付けることで、より詳細な情報を確認できます。

出力は下記のようになります。

NAME       STATUS     ROLES    AGE   VERSION   INTERNAL-IP       EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
node01     NotReady   <none>   11m   v1.15.0   192.168.xxx.xxx   <none>        Ubuntu 16.04 LTS     4.4.0-21-generic    docker://18.9.0
node02     NotReady   <none>   15m   v1.15.0   192.168.xxx.xxx   <none>        Ubuntu 16.04.6 LTS   4.4.0-21-generic    docker://18.9.7
master01   Ready      master   42m   v1.15.2   192.168.xxx.xxx   <none>        Ubuntu 18.04.2 LTS   4.15.0-43-generic   docker://18.9.7


クラスタの基本情報を表示するには、下記のコマンドを使います。

kubectl cluster-info

出力は下記のようになります。

Kubernetes master is running at https://192.168.xxx.xxx:6443
KubeDNS is running at https://192.168.xxx.xxx:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.


それぞれのNodeの詳細を確認するには、下記のコマンドを使います。

kubectl describe nodes node01

出力は長いので割愛します。


おまけ:Nodeを削除するには

Nodeを削除するには、正しい手順を踏む必要があります。

無闇にコンテナを削除したり、ネットワークから切り離したりすると、クラスタ全体が正常に稼働しなくなる可能性があります。

手順としてはkubectl drainコマンドでスケジューリングの対象から外した後に、kubectl deleteを実行して削除します。

# 対象のNodeをDrainする
kubectl drain node01
# ShedulingDisabledになっていることを確認する
kubectl get nodes
# 削除する
kubectl delete node node01
# nodeが表示されなくなっていることを確認する
kubectl get nodes

※コマンドは全てMasterで実行します。


まとめ

以上が、オンプレミス環境のUbuntu環境にKubernetesクラスタを構築する方法です。

合わせてクラスタの確認方法やNodeの削除方法も載せておきました。

次は、このKubernetesの環境をRancherで管理する方法を書き残しておこうと思います。(2019/10/13追記 書き残しました。下記です。)

sagantaf.hatenablog.com

参考文献

Docker/Kubernetes 実践コンテナ開発入門

Docker/Kubernetes 実践コンテナ開発入門

こちらの本は、KubernetesだけではなくDockerについての説明もあります。Dockerをこれから学ぶ人はもちろん、すでに習得している人の復習としても使えます。Kubernetesの部分は、細かく詳細を説明しているのではなく、まずは触って実際に構築してみて理解していく内容になっているため、初学者にとって進めやすく、おすすめです。

しくみがわかるKubernetes Azureで動かしながら学ぶコンセプトと実践知識

しくみがわかるKubernetes Azureで動かしながら学ぶコンセプトと実践知識

こちらの本はAzureを使ってKubernetesを解説している本になりますが、基本的な説明から実用的な可用性や保守性などにフォーカスした説明もあります。実際にシステムを本番導入する上で非常に役に立つ内容になっているため、おすすめです。