SMARTCAMP Engineer Blog

スマートキャンプ株式会社(SMARTCAMP Co., Ltd.)のエンジニアブログです。業務で取り入れた新しい技術や試行錯誤を知見として共有していきます。

KubeadmでのKubernetesクラスタ構築

f:id:mt_iri:20190129165559p:plain

スマートキャンプでインフラエンジニアをしている入山です。

みなさんはKubernetes(k8s)を知っていますか? Kubernetesは知らなくても、Dockerを知っている、またはローカルでの開発でDockerを使っているエンジニアの方は多いのではないでしょうか?

スマートキャンプではこれまで、ローカル環境では仮想コンテナ(docker)で開発を行い、テスト環境や本番環境はサーバー上へデプロイする方式でしたが、新規プロダクトではKubernetesを導入し、テスト環境や本番環境についてもアプリケーションを仮想コンテナでデプロイする方式に変更しました。

Kubernetesといえばマネージドサービス(Kubernetesを運用管理するアウトソーシングサービス)が主流であり、最近でもEKS東京リージョンのリリースが発表されましたが、新規プロダクトではノンマネージドでKubernetesを構築しました。(EKS東京リージョンを待ちきれませんでした。。。)

今回は、ノンマネージドでのKubernetesクラスタの構築について、紹介したいと思います!

Kubernetesとは

Kubernetesは、コンテナ化されたアプリケーションのデプロイ、スケーリング、管理を自動化するためのコンテナオーケストレーションツールです。 コンテナオーケストレーションツールを利用することにより、複数のホスト上で複数の仮想コンテナを一元的に管理することが簡単に実現できます。 これにより、仮想コンテナを利用した一定規模以上のプロダクション利用に耐えうるシステムが構築できるようになりました。

Kubernetesは、3大クラウドプロバイダ(google、Amazon、Microsoft)のマネージドサービスを筆頭に、コンテナオーケストレーションツールのデファクトスタンダードとして確固たる地位を獲得しています。

Kubernetes環境の選択肢

Kubernetesは、様々なプラットフォーム上にクラスタを構築することが可能で、大きく分けると以下3種類の構成/構築方法があります。

  • ローカルKubernetes(Minikube,Dockerなど)
    1台のローカルマシン上にオールインワン構成で手軽にKubernetesを構築(一部利用不可機能有り)
  • Kubernetes構築ツール(Kubeadm,Rancherなど)
    オンプレミスやクラウドサーバ上で複数ノードのKubernetesクラスタ構築に必要なコンポーネントのインストールや設定などを自動化
  • マネージドKubernetesサービス(EKS,GKE,AKSなど)
    クラウドサービス上でのKubernetesクラスタやノード管理、ロードバランサ連携などを簡単に利用可能

スマートキャンプでは従来よりインフラにAWSを使用しているのですが、新規プロダクトの環境構築時はEKSが東京リージョン未対応であったため、構築ツール(kubeadm)を利用してKubernetesクラスタを構築しました。

構築環境

今回は例として、以下のKubernetesクラスタをKubeadmを使用して構築していきます。 コンテナランタイムは、デフォルトのDockerを使用します。

  • 環境構成

    • AWS/EC2(ノンマネージド)
      • Master : 1台
      • Worker : 2台
  • 構築方法

    • Kubeadm
  • バージョン

    • OS : Ubuntu 16.04.5 LTS
    • Docker : 18.06.1-ce
    • kubeadm : v1.12.2
    • kubelet : v1.12.2
    • kubectl : v1.12.2
    • flannel : v0.10.0

Kubernetesクラスタ構築手順

Kubernetesクラスタは、MasterノードWorkerノードで構成されており、各ノードによって構築手順が多少異なります。

1. パッケージのインストール(対象:Master,Worker)

全ノードでDockerKubernetesのパッケージをインストールします。今回は、各パッケージのバージョンを指定してます。

  • Docker
sudo apt-get update && sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
sudo su -
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
add-apt-repository "deb https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") $(lsb_release -cs) stable"
exit
sudo apt-get update && sudo apt-get install -y docker-ce=18.06.1~ce~3-0~ubuntu
  • Kubernetes
sudo apt-get update && sudo apt-get install -y apt-transport-https curl
sudo su -
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
exit
sudo apt-get update && sudo apt-get install -y kubelet=1.12.2-00 kubeadm=1.12.2-00 kubectl=1.12.2-00

2. Masterノードのセットアップ(対象:Master)

  • Kubeadmの初期化(Masterの構築)

Masterとなる1台のノードで以下のコマンドを実行し、クラスタを構築します。

--pod-network-cidrオプションは、Podネットワーク(クラスタ内ネットワーク)で使用するアドオンの種別を選択します。今回は、Flannelを使用する為、--pod-network-cidr=10.244.0.0/16を指定しています。

--apiserver-advertise-addressオプションは、使用するIPアドレスを指定できます。今回はプライベートIPを指定します。指定しなければデフォルトゲートウェイのインターフェースが選択されます。

sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address 172.63.4.131

【コマンド実行結果例】

ubuntu@master:~$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address 172.63.4.131
I0129 06:18:37.035164   24995 version.go:236] remote version is much newer: v1.13.2; falling back to: stable-1.12
[init] using Kubernetes version: v1.12.5
[preflight] running pre-flight checks
        :
        :
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes master 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/

You can now join any number of machines by running the following on each node
as root:

  kubeadm join 172.63.4.131:6443 --token 8vij1a.g5cl58u5k4suh1v6 --discovery-token-ca-cert-hash sha256:7216e0860cfb9c8ad5d9e87afebe155b27c5107d80f68515af4eac34b8b33ce7
  • 認証ファイルの配置 kubectlは鍵による接続設定(鍵の配置)が必要となります。kubeadm init実行時に出力されている以下のコマンドを実行します。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

クラスタのノード状態を表示すると、以下のような結果が出力されます。

【ノード状態確認結果】

ubuntu@master:~$ kubectl get nodes
NAME     STATUS     ROLES    AGE   VERSION
master   NotReady   master   12m   v1.12.2

3. Workerノードのセットアップ(対象:Worker)

  • Kubernetesクラスタへの追加

WorkerをKubernetesクラスタに追加するために、Worker側でKubeadm joinコマンドを実行する必要があります。こちらのコマンドについても、Kubeadm initの実行結果に出力されています。

※環境毎に異なる為、出力されたコマンドを実行することに注意してください。

sudo kubeadm join 172.63.4.131:6443 --token 8vij1a.g5cl58u5k4suh1v6 --discovery-token-ca-cert-hash sha256:7216e0860cfb9c8ad5d9e87afebe155b27c5107d80f68515af4eac34b8b33ce7

【実行結果例】

ubuntu@worker1:~$ sudo kubeadm join 172.63.4.131:6443 --token 8vij1a.g5cl58u5k4suh1v6 --discovery-tok
en-ca-cert-hash sha256:7216e0860cfb9c8ad5d9e87afebe155b27c5107d80f68515af4eac34b8b33ce7
[preflight] running pre-flight checks
        :
        :
[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object "worker1" as an annotation

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the master to see this node join the cluster.

Master構築時に出力されたjoinコマンドは、以下のコマンドを実行することで再度出力することができます。

kubeadm token create --print-join-command

この時点でクラスタのノード状態を表示すると、以下のようにWorkerノードが追加されています。

【ノード状態確認結果】

ubuntu@master:~$ kubectl get nodes
NAME      STATUS     ROLES    AGE     VERSION
master    NotReady   master   26m     v1.12.2
worker1   NotReady   <none>   5m14s   v1.12.2
worker2   NotReady   <none>   3s      v1.12.2

4. Podネットワークのデプロイ(対象:Master)

上記のノード状態確認結果では、各ノードのSTATUSがNotReadyになっていますが、Kubernetesクラスタでは異なるノードのPod間で通信するための専用ネットワークを構築する必要があります。 Podネットワークも複数の選択肢がありますが、今回はFlannelを選択しています。以下のコマンドでデプロイします。

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

Flannelのデプロイが完了すると、各ノードの状態がReadyになり、運用可能な状態となります。最終的なノード状態は、以下の通りです。

ubuntu@master:~$ kubectl get nodes
NAME      STATUS   ROLES    AGE     VERSION
master    Ready    master   30m     v1.12.2
worker1   Ready    <none>   9m52s   v1.12.2
worker2   Ready    <none>   4m41s   v1.12.2

おまけ. 構築に失敗した場合

何かしらの理由でクラスタ構築に失敗した場合やクラスタ構築をやり直したい場合は、以下のコマンドを実行することで、kubeadm initkubeadm joinを実行する前の状態に戻すことが出来ます。

sudo kubeadm reset

以上で、Kubernetesクラスタの構築は完了です!

今後について

今回は、Kubernetes構築ツールを使用してノンマネーシドで構築しましたが、冒頭でも触れた通り2018/12/20にEKSが東京リージョンに対応しました。 Kubernetesをマネージドで構築することで、ロードバランサー連携やスケーリング、アップデートなど、クラスタの管理・運用が簡単且つ安全に行えるようになります。 今後、EKSでのKubernetes管理に移行していきたいと思っています!