スマートキャンプでインフラエンジニアをしている入山です。
みなさんは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台
- AWS/EC2(ノンマネージド)
構築方法
- 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)
全ノードでDockerとKubernetesのパッケージをインストールします。今回は、各パッケージのバージョンを指定してます。
- 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 init
やkubeadm join
を実行する前の状態に戻すことが出来ます。
sudo kubeadm reset
以上で、Kubernetesクラスタの構築は完了です!
今後について
今回は、Kubernetes構築ツールを使用してノンマネーシドで構築しましたが、冒頭でも触れた通り2018/12/20にEKSが東京リージョンに対応しました。 Kubernetesをマネージドで構築することで、ロードバランサー連携やスケーリング、アップデートなど、クラスタの管理・運用が簡単且つ安全に行えるようになります。 今後、EKSでのKubernetes管理に移行していきたいと思っています!