Kubernetes環境を構築して、実際にコンテナを動かしてみよう
![](https://thinkit.co.jp/sites/default/files/styles/main_image_730x/public/main_images/cl_kubernetes_study_cover_0.jpg?itok=Mo_EX1CE)
はじめに
今回は、実際に手を動かして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をインストールします。
まず、環境設定を行います。以下のコマンド群を実行してください。
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf overlay br_netfilter EOF sudo modprobe overlay sudo modprobe br_netfilter cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-ip6tables = 1 EOF sudo sysctl --system
続いて、コンテナランタイムのcontainerdをインストールします。以下のコマンド群を実行してください。
sudo apt-get update && sudo apt-get install -y containerd sudo mkdir -p /etc/containerd containerd config default | sudo tee /etc/containerd/config.toml sudo systemctl restart containerd
以上で、コントロールプレーン、ワーカーの環境にコンテナランタイムがインストールできました。
コントロールプレーンのセットアップ
続いて、コントロールプレーンの環境のセットアップを行います。
kubeadm、kubelet、kubectlのインストール(コントロールプレーン、ワーカー)
まず、Kubernetesのインストールツールであるkubeadmをインストールします。kubeadmはKubernetesコミュニティが公式に提供している簡易な構築ツールです。Kubernetesを構成するコンポーネントや証明書、各種設定ファイルを自動で作成し、素早くKubernetesクラスタを作成できます。 加えて、Kubernetesのノードコンポーネントであるkubelet、コマンドラインツールであるkubectlのインストールをします。
以下のコマンド群を実行してください。
sudo apt-get update && sudo apt-get install -y apt-transport-https curl curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list deb https://apt.kubernetes.io/ kubernetes-xenial main EOF sudo apt-get update sudo apt-get install -y kubelet kubeadm kubectl sudo apt-mark hold kubelet kubeadm kubectl
コントロールプレーンの起動
kubeadmを使用してコントロールプレーンを起動します。以下のコマンドを実行してください。
sudo kubeadm init --pod-network-cidr=192.168.0.0/16
コマンド実行後、下記のように表示されれば成功です。
[init] Using Kubernetes version: v1.20.4 .... 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 Alternatively, if you are the root user, you can run: export KUBECONFIG=/etc/kubernetes/admin.conf 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 10.146.0.22:6443 --token rob5u6.id7c9nj028eacutg \ --discovery-token-ca-cert-hash sha256:5e746b01ceb1d459ffd7a7758e07f699a817e67784640f78aa e7710dc5ab77e0
このときに最後に表示されるコマンドは、ワーカーをコントロールプレーンに登録するコマンドです。後ほどワーカーの環境で使用するので、どこかにメモしておきましょう。
kubeadm join 10.146.0.22:6443 --token rob5u6.id7c9nj028eacutg \ --discovery-token-ca-cert-hash sha256:5e746b01ceb1d459ffd7a7758e07f699a817e67784640f78aa e7710dc5ab77e0
加えて、kubectlを使用可能にするため、以下のコマンドを実行します。
mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
以上で、コントロールプレーンのセットアップは完了です。
ワーカーのセットアップ
続いて、ワーカー環境のセットアップを行います。
kubeadm、kubelet、kubectlのインストール
ワーカーの環境にも同様に、kubeadm、kubelet、kubectlをインストールします。 以下のコマンド群を実行してください。
sudo apt-get update && sudo apt-get install -y apt-transport-https curl curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list deb https://apt.kubernetes.io/ kubernetes-xenial main EOF sudo apt-get update sudo apt-get install -y kubelet kubeadm kubectl sudo apt-mark hold kubelet kubeadm kubectl
ワーカーのコントロールプレーンへの接続
次に、kubeadmコマンドを使用してワーカーの起動およびコントロールプレーンに接続を行います。
先ほどメモした以下のコマンドを2台のワーカーの環境で実行してください。
sudo kubeadm join 10.146.0.22:6443 --token rob5u6.id7c9nj028eacutg --discovery-token-ca-cert-hash sha256:5e746b01ceb1d459ffd7a7758e07f699a817e67784640f78aae7710dc5ab77e0
コマンド実行後、下記のように表示されれば成功です。
[preflight] Running pre-flight checks ... 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 control-plane to see this node join the cluster.
ワーカーがクラスターに接続されました。この段階で、kube-proxyがワーカーに自動的に配置されます。
以上で、ワーカーのセットアップは完了です。これでkubernetesクラスターができました。
ネットワークプラグインのインストールと接続確認
クラスタにワーカーを登録できたら、kubectlコマンドkubectl get nodesを使用してワーカーの情報を取得してみましょう。
$ kubectl get nodes NAME STATUS ROLES AGE VERSION control-plane NotReady control-plane,master 15m v1.20.4 worker-1 NotReady <none> 4m41s v1.20.4 worker-2 NotReady <none> 24s v1.20.4
表示を見るとSTATUSがNotReadyになっており、このままではkubernetesはオーケストレーションを始めることができません。これは、ノード間でネットワークが隔離され、ノード間の各コンテナが相互に通信できなくなっているためです。これを可能にするのがネットワークプラグイン(CNIプラグイン)です。今回は、CNIプラグインにCalicoを使用します。
以下のコマンドをコントロールプレーンで実行してください。
kubectl create -f https://docs.projectcalico.org/manifests/tigera-operator.yaml kubectl create -f https://docs.projectcalico.org/manifests/custom-resources.yaml
そして、もう一度kubectl get nodesをしてみましょう。STATUSがReadyになっていることが確認できます。
$ kubectl get nodes NAME STATUS ROLES AGE VERSION control-plane Ready control-plane,master 17m v1.20.4 worker-1 Ready <none> 6m57s v1.20.4 worker-2 Ready <none> 2m40s v1.20.4
以上で、kubernetesの環境構築は終了です。
Podを作成してコンテナを動かす
kubernetesの環境構築ができたので、実際にkubernetes上でアプリケーションを実行してみましょう。ここで、Podと呼ばれるリソースが登場します。
Podはコンテナを管理するリソースで、デプロイにおける最小単位です。1つ以上のコンテナによって構成されます。はじめに、リソースを定義するマニフェストを見てみましょう。
apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - image: nginx:1.17 name: nginx
このマニフェストは、YAMLと呼ばれる形式で記述されています。各項目について解説すると、以下のようになります。
- apiVersion: kubernetes APIのバージョン
- kind: リソースの種類
- metadata: リソースの名前等
- spec: containersではコンテナ名やイメージ、コマンドを指定
これをnginx.yamlとして保存し、クラスタにデプロイしてみましょう。まず、kubectl get podsを実行して、まだ環境にPodがないことを確認します。
$ kubectl get pods No resources found in default namespace.
次に、マニフェストnginx.yamlを使用してPodをデプロイします。マニフェストを適用する際には、kubectl applyを使用します。
$ kubectl apply -f nginx.yaml pod/nginx created
kubectl get podsを実行すると、デプロイされたPodを確認できます。
$ kubectl get pods NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 17s
さらにkubectl describe pod nginxを実行すると、Podの詳しい情報を確認できます。
$ kubectl describe pod nginx Name: nginx Namespace: default Priority: 0 Node: worker-2/10.146.0.26 Start Time: Sun, 28 Feb 2021 08:39:01 +0000 Labels: <none> Annotations: cni.projectcalico.org/podIP: 192.168.133.195/32 cni.projectcalico.org/podIPs: 192.168.133.195/32 Status: Running IP: 192.168.133.195 IPs: IP: 192.168.133.195 Containers: nginx: Container ID: containerd://ca0fbebe2e055407f4a03a23ebb2875a3000ca141d0efaa366e4f7f8447 834b8 Image: nginx:1.17 Image ID: docker.io/library/nginx@sha256:6fff55753e3b34e36e24e37039ee9eae1fe38a642 0d8ae16ef37c92d1eb26699 Port: <none> Host Port: <none> State: Running Started: Sun, 28 Feb 2021 08:39:02 +0000 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-7xdpg (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: default-token-7xdpg: Type: Secret (a volume populated by a Secret)
今回は、nginxをデプロイしました。nginxがホストしているIPがkubectl describe pod nginxの結果にあるIP:に記載されているので、そのIPをcurlしてみましょう。
$ curl 192.168.133.195 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
nginxのレスポンスが表示されたら成功です。Podの正常動作を確認できました。kubectl execコマンドを使うと、Pod内でコマンドを実行できます。
$ kubectl exec nginx -it -- /bin/sh # ls bin dev home lib64 mnt proc run srv tmp var boot etc lib media opt root sbin sys usr
kubectl deleteコマンドを使うと、デプロイしたPodを削除できます。
$ kubectl delete pod nginx pod "nginx" deleted
ほかにも、Podのログを取得するkubectl logsなどのコマンドがあります。興味のある方は試してみてください。
おわりに
今回は、kubernetesを学ぶ上で基本的な概念であるコンテナとkubernetesの概要から、実際に手を動かしてkuberenetesの構築とPodのハンズオンを行いました。次回からは、サービスやデプロイメントなど、その他のリソースを見ていきます。お楽しみに。
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- Project CalicoをKubernetesで使ってみる:構築編
- Kubernetes環境の選択肢
- Kubernetesの基礎
- Oracle Cloud Hangout Cafe Season5 #3「Kubernetes のセキュリティ」(2022年3月9日開催)
- Kubernetesアプリケーションのモニタリングことはじめ
- KubernetesのConfig&Storageリソース(その1)
- KubernetesのマニフェストをMagnumで実行する
- NGINX Ingress Controllerの柔軟なアプリケーション制御、具体的なユースケースと設定方法を理解する
- Oracle Cloud Hangout Cafe Season7 #1「Kubnernetes 超入門」(2023年6月7日開催)
- コンテナを効率的に運用・管理する標準ツール「Kubernetes」とは