はじめに
今回は、実際に手を動かしてkubernetesを理解していきましょう。まずはコンテナとkubernetesによるコンテナオーケストレーションについて説明します。その後、kubernetesクラスタを構築していきます。構築ができたら、実際にコンテナをクラスタ上で動かしてみます。
コンテナとは
コンテナは仮想化方式の1つとされています。アプリケーションの実行に必要なファイル群をコンテナという形でパッケージングして、ホストOSのカーネルを共有しつつユーザ空間でリソースを分離することで仮想的に分離された環境を生成し、アプリケーションを実行します。この実行環境はホストOSからは通常のプロセスとして扱われます。
この仕組みには、ハイパーバイザー型仮想化などの方法に比べて、以下のような利点があります。
- 高速な起動/停止
- 最小限のリソース消費
- 再現性の保証(Immutable Infrastructure)
これらの点により、構成管理やスケーリングに適したアプリケーション実行環境が実現されています。
Kubernetesとは
Kubernetesは、前述したコンテナをクラスタとして管理・実行する基盤(コンテナオーケストレータ)です。複数のノード(サーバ)をクラスタとして統合し、コンテナを各ノードに相互に通信可能な状態で配置して実行します。それだけではなく、コンテナを実行するノードの割り当て・計画実行、サービスの状態の自律的な制御など、拡張性/可用性の高いアーキテクチャを提供します。
コンテナオーケストレータの中でも、特にKubernetesは2つの特徴があります。
- 宣言的なコードによる自律的なインフラ運用
- 拡張可能な構成
「宣言的なコードとしての自律的なインフラ」とは、インフラにおけるすべての構成とその運用がコードによって表記されることを指します。Kubernetesは宣言されたコード通りの状態(アプリケーションコンテナの数や各リソースのエンドポイントの指定など)を保つための動作を自動で行います。加えて、コンテナやノードに障害が発生した際の対処や高負荷時の自動スケールアップ、ブルーグリーンデプロイやカナリアリリースなどのデプロイパターンまでコードとして表現できるため、多くの運用プロセスの自動化が可能になります。
「拡張可能な構成」とは、kubernetesの持つ様々なリソースを外部のサービスと連携させることで、ユーザ自身が高機能な構成をカスタマイズできることを指します。現在、kubernetesはCI/CD(継続的インテグレーション・デプロイメント)や監視・ロギング、セキュリティなど、多くのソリューションがサードパーティのOSSとして提供されています。ユーザーはこれらを必要に応じて使用し、各自の目的に沿ったインフラストラクチャーを構築できます。このようなkubernetesをとりまく様々なサービスを総称して「kubernetes ecosystem」と呼びます
以上のような特徴により、拡張性/可用性の高いアプリケーション基盤を実現しています。
kubernetesのインストール
以降では、実際に手を動かしながら、kubernetesを理解していきましょう。
構築する環境について
今回は、下記の環境でkubernetesクラスタを構築し、下図のような構成を目指します。
- サーバ台数: 3台 (コントロールプレーン1台、ワーカー2台)
- マシンスペック: vCPU x 2、メモリ 4 GB (Google Compute Engine e2-medium インスタンス)
- OS: Ubuntu 20.04LTS
この構成について、少し詳しく見てみましょう。
kubernetesはコントロールプレーンと複数のワーカーでクラスタを構成します。コントロールプレーンはkubernetesの管理サーバーとして振る舞い、ワーカーにアプリケーションをデプロイします。このコントロールプレーンはHA構成をとることも可能ですが、今回は単一構成とします。
続いて、kubernetesの内部を構成するコンポーネントを簡単に紹介します。kube-apiserverは、その名の通りkubernetesのAPIサーバであり、kubernetesクラスタの中心です。ユーザがコンテナを作成したり一覧したりする場合に、このkube-apiserverにリクエストします。
kube-apiserverがリクエストを受けて、実際にデータを読み書きするデータストアがetcdです。kube-controller-managerはコンテナ起動数の保持やローリングデプロイの実行など、運用に関する自律的な管理を行います。ユーザがコンテナを作成したり削除したりするのと同じように、kube-apiserverに対してアクセスしながらこれを実現します。
kube-schedulerは、作成されたコンテナをどのノードに配置するかを決定します。kubeletは各ノードに常駐するプロセスです。kube-apiserverの情報に基づいて、ノード上でコンテナランタイムにリクエストしてコンテナの状態を管理します。実際にコンテナを作成するのはコンテナランタイムです。ここではcontainerdを採用しています。
コンポーネントが多く少し複雑な構成に思えますが、インストールツールを利用すれば簡単に構築できます。それでは、実際にやってみましょう。
コンテナランタイムのインストール(コントロールプレーン、ワーカー)
コントロールプレーン、ワーカーの環境に、コンテナランタイムのcontainerdをインストールします。
まず、環境設定を行います。以下のコマンド群を実行してください。
01 | cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf |
07 | sudo modprobe br_netfilter |
09 | cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf |
10 | net.bridge.bridge-nf-call-iptables = 1 |
11 | net.ipv4.ip_forward = 1 |
12 | net.bridge.bridge-nf-call-ip6tables = 1 |
続いて、コンテナランタイムのcontainerdをインストールします。以下のコマンド群を実行してください。
1 | sudo apt-get update && sudo apt-get install -y containerd |
2 | sudo mkdir -p /etc/containerd |
3 | containerd config default | sudo tee /etc/containerd/config.toml |
4 | sudo systemctl restart containerd |
以上で、コントロールプレーン、ワーカーの環境にコンテナランタイムがインストールできました。
コントロールプレーンのセットアップ
続いて、コントロールプレーンの環境のセットアップを行います。
kubeadm、kubelet、kubectlのインストール(コントロールプレーン、ワーカー)
まず、Kubernetesのインストールツールであるkubeadmをインストールします。kubeadmはKubernetesコミュニティが公式に提供している簡易な構築ツールです。Kubernetesを構成するコンポーネントや証明書、各種設定ファイルを自動で作成し、素早くKubernetesクラスタを作成できます。 加えて、Kubernetesのノードコンポーネントであるkubelet、コマンドラインツールであるkubectlのインストールをします。
以下のコマンド群を実行してください。
1 | sudo apt-get update && sudo apt-get install -y apt-transport-https curl |
3 | cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list |
7 | sudo apt-get install -y kubelet kubeadm kubectl |
8 | sudo apt-mark hold kubelet kubeadm kubectl |
コントロールプレーンの起動
kubeadmを使用してコントロールプレーンを起動します。以下のコマンドを実行してください。
1 | sudo kubeadm init --pod-network-cidr=192.168.0.0/16 |
コマンド実行後、下記のように表示されれば成功です。
01 | [init] Using Kubernetes version: v1.20.4 |
03 | Your Kubernetes control-plane has initialized successfully! |
04 | To start using your cluster, you need to run the following as a regular user: |
06 | sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config |
07 | sudo chown $(id -u):$(id -g) $HOME/.kube/config |
08 | Alternatively, if you are the root user, you can run: |
09 | export KUBECONFIG=/etc/kubernetes/admin.conf |
10 | You should now deploy a pod network to the cluster. |
11 | Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: |
13 | Then you can join any number of worker nodes by running the following on each as root: |
14 | kubeadm join 10.146.0.22:6443 --token rob5u6.id7c9nj028eacutg \ |
15 | --discovery-token-ca-cert-hash sha256:5e746b01ceb1d459ffd7a7758e07f699a817e67784640f78aa |
このときに最後に表示されるコマンドは、ワーカーをコントロールプレーンに登録するコマンドです。後ほどワーカーの環境で使用するので、どこかにメモしておきましょう。
1 | kubeadm join 10.146.0.22:6443 --token rob5u6.id7c9nj028eacutg \ |
2 | --discovery-token-ca-cert-hash sha256:5e746b01ceb1d459ffd7a7758e07f699a817e67784640f78aa |
加えて、kubectlを使用可能にするため、以下のコマンドを実行します。
2 | sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config |
3 | sudo chown $(id -u):$(id -g) $HOME/.kube/config |
以上で、コントロールプレーンのセットアップは完了です。
ワーカーのセットアップ
続いて、ワーカー環境のセットアップを行います。
kubeadm、kubelet、kubectlのインストール
ワーカーの環境にも同様に、kubeadm、kubelet、kubectlをインストールします。 以下のコマンド群を実行してください。
1 | sudo apt-get update && sudo apt-get install -y apt-transport-https curl |
6 | sudo apt-get install -y kubelet kubeadm kubectl |
7 | sudo apt-mark hold kubelet kubeadm kubectl |
ワーカーのコントロールプレーンへの接続
次に、kubeadmコマンドを使用してワーカーの起動およびコントロールプレーンに接続を行います。
先ほどメモした以下のコマンドを2台のワーカーの環境で実行してください。
1 | sudo kubeadm join 10.146.0.22:6443 --token rob5u6.id7c9nj028eacutg --discovery-token-ca-cert-hash sha256:5e746b01ceb1d459ffd7a7758e07f699a817e67784640f78aae7710dc5ab77e0 |
コマンド実行後、下記のように表示されれば成功です。
1 | [preflight] Running pre-flight checks |
3 | This node has joined the cluster: |
4 | * Certificate signing request was sent to apiserver and a response was received. |
5 | * The Kubelet was informed of the new secure connection details. |
6 | Run 'kubectl get nodes' on the control-plane to see this node join the cluster. |
ワーカーがクラスターに接続されました。この段階で、kube-proxyがワーカーに自動的に配置されます。
以上で、ワーカーのセットアップは完了です。これでkubernetesクラスターができました。
ネットワークプラグインのインストールと接続確認
クラスタにワーカーを登録できたら、kubectlコマンドkubectl get nodesを使用してワーカーの情報を取得してみましょう。
2 | NAME STATUS ROLES AGE VERSION |
3 | control-plane NotReady control-plane,master 15m v1.20.4 |
4 | worker-1 NotReady <none> 4m41s v1.20.4 |
5 | worker-2 NotReady <none> 24s v1.20.4 |
表示を見るとSTATUSがNotReadyになっており、このままではkubernetesはオーケストレーションを始めることができません。これは、ノード間でネットワークが隔離され、ノード間の各コンテナが相互に通信できなくなっているためです。これを可能にするのがネットワークプラグイン(CNIプラグイン)です。今回は、CNIプラグインにCalicoを使用します。
以下のコマンドをコントロールプレーンで実行してください。
そして、もう一度kubectl get nodesをしてみましょう。STATUSがReadyになっていることが確認できます。
2 | NAME STATUS ROLES AGE VERSION |
3 | control-plane Ready control-plane,master 17m v1.20.4 |
4 | worker-1 Ready <none> 6m57s v1.20.4 |
5 | worker-2 Ready <none> 2m40s v1.20.4 |
以上で、kubernetesの環境構築は終了です。
Podを作成してコンテナを動かす
kubernetesの環境構築ができたので、実際にkubernetes上でアプリケーションを実行してみましょう。ここで、Podと呼ばれるリソースが登場します。
Podはコンテナを管理するリソースで、デプロイにおける最小単位です。1つ以上のコンテナによって構成されます。はじめに、リソースを定義するマニフェストを見てみましょう。
このマニフェストは、YAMLと呼ばれる形式で記述されています。各項目について解説すると、以下のようになります。
- apiVersion: kubernetes APIのバージョン
- kind: リソースの種類
- metadata: リソースの名前等
- spec: containersではコンテナ名やイメージ、コマンドを指定
これをnginx.yamlとして保存し、クラスタにデプロイしてみましょう。まず、kubectl get podsを実行して、まだ環境にPodがないことを確認します。
2 | No resources found in default namespace. |
次に、マニフェストnginx.yamlを使用してPodをデプロイします。マニフェストを適用する際には、kubectl applyを使用します。
1 | $ kubectl apply -f nginx.yaml |
kubectl get podsを実行すると、デプロイされたPodを確認できます。
2 | NAME READY STATUS RESTARTS AGE |
さらにkubectl describe pod nginxを実行すると、Podの詳しい情報を確認できます。
01 | $ kubectl describe pod nginx |
05 | Node: worker-2/10.146.0.26 |
06 | Start Time: Sun, 28 Feb 2021 08:39:01 +0000 |
08 | Annotations: cni.projectcalico.org/podIP: 192.168.133.195/32 |
09 | cni.projectcalico.org/podIPs: 192.168.133.195/32 |
19 | Image ID: docker.io/library/nginx@sha256:6fff55753e3b34e36e24e37039ee9eae1fe38a642 |
20 | 0d8ae16ef37c92d1eb26699 |
24 | Started: Sun, 28 Feb 2021 08:39:02 +0000 |
29 | /var/run/secrets/kubernetes.io/serviceaccount from default-token-7xdpg (ro) |
38 | Type: Secret (a volume populated by a Secret) |
今回は、nginxをデプロイしました。nginxがホストしているIPがkubectl describe pod nginxの結果にあるIP:に記載されているので、そのIPをcurlしてみましょう。
05 | <title>Welcome to nginx!</title> |
10 | font-family: Tahoma, Verdana, Arial, sans-serif; |
15 | <h1>Welcome to nginx!</h1> |
16 | <p>If you see this page, the nginx web server is successfully installed and |
17 | working. Further configuration is required.</p> |
18 | <p>For online documentation and support please refer to |
20 | Commercial support is available at |
22 | <p><em>Thank you for using nginx.</em></p> |
nginxのレスポンスが表示されたら成功です。Podの正常動作を確認できました。kubectl execコマンドを使うと、Pod内でコマンドを実行できます。
1 | $ kubectl exec nginx -it -- /bin/sh |
3 | bin dev home lib64 mnt proc run srv tmp var |
4 | boot etc lib media opt root sbin sys usr |
kubectl deleteコマンドを使うと、デプロイしたPodを削除できます。
1 | $ kubectl delete pod nginx |
ほかにも、Podのログを取得するkubectl logsなどのコマンドがあります。興味のある方は試してみてください。
おわりに
今回は、kubernetesを学ぶ上で基本的な概念であるコンテナとkubernetesの概要から、実際に手を動かしてkuberenetesの構築とPodのハンズオンを行いました。次回からは、サービスやデプロイメントなど、その他のリソースを見ていきます。お楽しみに。