2019年版・Kubernetesクラスタ構築入門

「Kubernetes」は2014年の登場以来順調に利用者を増やしており、現在ではコンテナ管理ツールのデファクトスタンダードとなっている。新機能や関連ツールなどの開発も活発だ。そこで本記事では、ここ最新導入されたKubernetesの新機能や特徴を紹介するとともに、導入ツール「kubeadm」による最新版Kubernetesの環境構築方法を紹介する。

Kubernetesとは

Kubernetesについては以前にも紹介しているが、ここで改めてその概要や背景にある技術について簡単ではあるが紹介しておこう。

Kubernetesは、複数台のコンピュータをネットワークで接続した「クラスタ環境」を使い、「ノード」と呼ばれるクラスタ内のコンピュータ上で実行されるサーバーソフトウェアを管理するソフトウェアシステムだ(図1)。

図1 Kubernetesは複数台のコンピュータを組み合わせてソフトウェアを実行させるプラットフォームとなる
図1 Kubernetesは複数台のコンピュータを組み合わせてソフトウェアを実行させるプラットフォームとなる

最近ではコンピュータの低価格化により、少数の超高性能なコンピュータでシステムを構築するよりも、低価格でそれなりの性能のコンピュータを多数組み合わせてシステムを構築するほうがコストパフォーマンス的に優位なことが多い。また、冗長にシステムを構築することで、一部のコンピュータが故障した場合でもほかのコンピュータがその役割を肩代わりしてシステム全体では正常動作を続けられるような構成が現実的に可能だということが証明されている。Kubernetesはこうした構成のクラスタを構築するのに向いており、特に最近注目されているマイクロサービスアーキテクチャとの相性も良いため、採用例が増えている。

なお、Kubernetesは、基本的には複数台のコンピュータを組み合わせて構築したクラスタ環境で利用する。テストや実験のために1台のみでクラスタを構築することも可能ではあるものの、この場合Kubernetesクラスタを構築するメリットはほぼない。

Kubernetesとコンテナ

さて、このように多数のコンピュータを組み合わせてシステムを構築する場合、使用するすべてのコンピュータをすべて完全に同一のハードウェアでそろえようとすると、運用コストが高くなることが見込まれる。運用開始時にすべて同一のハードウェアでそろえることは難しくないが、たとえば一定期間の経過後に故障したハードウェアを取り替えたり、追加でハードウェアを投入したりするといったことはよくある話だ。その場合、完全に同一のハードウェアを入手することが難しくなっている可能性がある。また、より高性能なコンピュータを追加したいといったケースもあるだろう。さらに、ハードウェアだけでなくOS/カーネルのバージョンについても、異なるものが混在できるほうが好ましい。そこでKubernetesでは、「コンテナ」という技術を使い、ソフトウェアの実行環境をハードウェアやOSに依存しないようにしている。

コンテナというと一般的には物を入れる箱のようなイメージだが、ここではあらかじめ指定された以外のリソースにアクセスできないように制限をかけてアプリケーションを実行する仕組みをコンテナ技術と呼び、閉じ込めたリソースをコンテナと呼ぶ(図2)。

図2 Kubernetesで利用する「コンテナ」の概念
図2 Kubernetesで利用する「コンテナ」の概念

箱(コンテナ)の中にアプリケーションの実行に必要なすべてのプログラムやライブラリ、設定ファイル、各種リソースなどを閉じ込めて、プログラムからはコンテナ内にあるものしか利用できない、といったものをイメージしてもらうと分かりやすいだろう。また、コンテナ技術ではコンテナで使用するプログラムや各種設定ファイル、依存ライブラリなどを「イメージファイル」として管理することで、容易に必要なリソースを配布する仕組みも用意されている。

コンテナを使ってアプリケーションを実行させる場合、そのアプリケーションは基本的にコンテナ外のリソースにアクセスすることができない。つまりコンテナを利用することでハードウェアやOSのバージョン、インストールされているライブラリといったコンテナ外の環境に影響されずにアプリケーションを実行できるようになり、結果的にアプリケーションのハードウェアやOSへの依存性を減らすことができる。

こういったコンテナ技術は複数が開発されており、Kubernetesも特定のコンテナ技術に依存しないように開発されているが、多くのKubernetes環境では現在主流となっているコンテナ技術である「Docker」と組み合わせて運用されている。

Dockerではイメージファイルを共有・公開する「DockerHub」というサービスも提供されている。ここではApache HTTP ServerやNGINX、MySQLといったよく使われるアプリケーションのイメージファイルが公開されており、これらを利用することで簡単にコンテナを用意できる。

なお、コンテナではOSのカーネルだけは共有するため、カーネルのバージョンやカーネルビルド時の設定などの影響は受けるものの、多くの場合でこの影響は小さい。

Kubernetesのアーキテクチャと基本的な動作

Kubernetesでは、実行するアプリケーションや各種設定などは「リソースオブジェクト(resource object)」(単に「リソース」などとも呼ばれる)という単位で定義・管理する。主なリソースとしては表1のものがあり、たとえば使用するコンテナや実行するプログラムは「Pod」というリソースで定義・管理する。

表1 Kubernetesで利用できる代表的なリソースオブジェクト
名称 説明
Pod 使用するコンテナや実行するプログラムを定義する
Deployment Podの管理方法を定義する
Job 非定常的に処理を実行するジョブを定義する
CronJob 定期的に実行されるジョブを定義する
Service ネットワークサービスを定義する
ConfigMap コンテナで使用される各種設定リソースを定義する
Secret コンテナで使用される各種設定リソースを定義する
Volume コンテナに割り当てるストレージを定義する
Namespace 管理のための名前空間を定義する

Kubernetesが標準で提供するリソースの一覧はAPIドキュメントで確認できる。また、独自のリソースを定義して利用することもできる。

Kubernetesでは、「マニフェスト(manifest)」と呼ばれる形式で各種リソースを定義する。マニフェストは木(ツリー)構造で表現できるデータであり、たとえばコマンドラインツール「kubectl」ではYAML形式で記述されたマニフェストを元にリソースの作成や削除、変更といった操作を行える。

kubectlの使い方についてはドキュメントを参照して欲しいが、たとえば、DockerHubで公開されている「httpd」コンテナイメージを利用してApache HTTP Serverを実行させるには、まず次のようなマニフェストファイルを用意する。

apiVersion: v1
kind: Pod
metadata:
  name: httpd
  labels:
    app: httpd
spec:
  containers:
  - name: httpd
    image: httpd:2.4
    ports:
    - containerPort: 80
      name: http

このファイルを指定して「kubectl apply -f <マニフェストファイル>」コマンドを実行することでPodリソースが作成され、その内容に応じて以下のような処理が実行される。

  1. 設定に応じてコンテナを作成するクラスタノードを決定する
  2. そのクラスタノード上にコンテナ作成のためのイメージファイルをダウンロードする
  3. コンテナを作成しIPアドレスやストレージなどのリソースを割り当てる
  4. コンテナ内で指定されたプログラムを実行する

また、作成したコンテナを削除するには「kubectl delete -f <マニフェストファイル>」コマンドを実行すれば良い。

この一連の作業はすべてKubernetesによって自動的に行われるため、明示的にマニフェストで指定しない限りはどのノード上でプログラムが動作するのか、またIPアドレスなどのリソースがどのように割り当てられるかといった情報を事前に知ることはできない。そのため、コンテナ間の通信や外部からのコンテナへの通信は「Service」と呼ばれる、ネットワークルーティングを管理するためのリソースを使って制御することになる。

Kubenetesのここ最近の機能強化

Kubernetesで2015年7月にバージョン1.0がリリースされ、基本的な機能がほぼ完成した。その後性能向上や管理機能の強化などが続けられているが、ここ最近で安定扱いとなった大きな新機能としては次が挙げられる。

  • ロールベースのアクセス制御機能「RBAC」(バージョン1.8)
  • IPVS(IP Virtual Server)によるネットワークルーティング(バージョン1.11)
  • クラスタ内でのDNSサーバー「CoreDNS」の採用(バージョン1.11)
  • クラスタ構築ツール「kubeadm」(バージョン1.13)

今回はこの中でも、Kubernetesクラスタを構築するためのツールである「kubeadm」について紹介していく。

Kubernetesクラスタを構築する

昨今では設定済みのKubernetesクラスタを提供するクラウドサービスも多くあるが、いっぽうで自ら管理しているサーバーでアプリケーションを実行したいという需要もあるだろう。その場合、自前でKubernetesクラスタを構築する必要がある。Kubernetesクラスタの環境構築についてはいくつかの方法があり、Kubernetes公式ドキュメントでは構築方法を選ぶためのガイドページも用意されているが、自ら管理しているサーバーで構築するための代表的な方法としては以下が挙げられる。

  • Linuxディストリビューションで提供されているKubernetes関連パッケージを使用
  • 構築ツール「minikube」を利用
  • 構築ツール「conjure-up」を利用
  • 構築ツール「Tectonic」を使用
  • 構築ツール「kubeadm」を利用

Linuxディストリビューションで提供されているKubernetes関連パッケージを使う例については以前の記事で紹介している。こちらはやや古い情報となるが、現在でもおおむね同じ手順で作業が可能だ。ただし、Linuxディストリビューションによっては提供されているKubernetes関連パッケージのバージョンが古い場合がある点には注意が必要だ。たとえば記事執筆時のKubernetesの最新バージョンは1.13系だが、CentOS 7で提供されているパッケージは2016年にリリースされたバージョン1.5系をベースとしたものでかなり古い。Debian Linuxでは開発版(unstable)でのみの提供となっており、2017年リリースのバージョン1.7系がベースだ。Fedoraでは比較的新しいバージョンのパッケージが提供されているが、それでもFedora 29(2018年11月リリース)で提供されているのはv1.10ベースのパッケージとなっている。

「Minikube」を利用する方法は、以前『簡単にローカルKubernetes環境を構築できるツール「Minikube」』という記事で紹介したが、こちらはVirtualBoxなどの仮想化ソフトウェアを使ってローカルマシン上にテスト用にKubernetes環境を作るもので、複数台構成のクラスタを作るのには適していない。

conjure-up」はUbuntuなどで推奨されている方法で(Ubuntuのドキュメント)、conjure-upという環境構築ツールを使ってKubernetesのインストール作業を自動で行うというものだ。

また、「Tectonic」はCoreOSが提供しているKubernetesディストリビューションで、10ノードまでのクラスタであれば無料で利用できる。商用ソリューションということで独自の管理機能なども提供されている。

最後の「kubeadm」は、Kubernetesが提供しているKubernetes環境構築ツールだ(公式ドキュメント)。対応するOSがUbuntu 16.04以上、Debian 9(Stretch)、CentOS 7、Red Hat Enterprise Linux 7、Fedora 25/26などと幅広く、また公式ツールということで、最新バージョンのKubernetes環境のインストールが可能という特徴がある。「kubeadm」というコマンドラインツールで操作を行う点と、多数のインストールオプションがあるためにやや難しい印象もあるが、ポイントさえ押さえてしまえば比較的容易にクラスタを構築できる。

ということで、以下ではこのkubeadmを使ったKubernetesクラスタ構築の流れを紹介していく。

kubeadmを使ったKubernetesクラスタ構築

kubeadmは2016年9月にリリースされたKubernetes 1.4から導入されたツールで、2017年3月にリリースされたKubernetes 1.6でベータ扱いに、2018年12月にリリースされたKubernetes 1.13で主要機能がGA(General Availability、一般利用可能)というステータスとなっている。

Kubernetes環境を構築する際には、クラスタを構成する各ノードに「kubelet」や「flanneld」といったノード管理用コンポーネントをインストールし、さらにクラスタ管理用のノード(マスターノード)には「apiserver」や「controller-manager」、「scheduler」といったKubernetesクラスタの管理用コンポーネントやetcdといった設定管理用のデータベースをインストールする必要がある。kubeadmではこれらの作業を簡単なオプション指定のみで実行でき、さらに各種設定も自動で実行できる。

Kubernetesの動作要件

Kubernetesクラスタを構築する際の各クラスタノードのハードウェアおよびOS要件として、ドキュメントでは次が挙げられている。

  • Ubuntu 16.04以降/Debian 9/CentOS 7/Red Hat Enterprise Linux 7/Fedora 25および26/HypriotOS v1.0.1以降/Container Linux
  • メモリ2GB以上
  • 2CPU以上

ドキュメントではMACアドレスや「product_uuid」(カーネルによって生成されるシステム固有のID)、ホスト名が各ホストで重複せずユニークであるという条件も記載されているが、一般的な環境ではこれらが重複することはないのであまり気にしなくても良いだろう。なお、これらは以下のようにして確認できる。

↓product_uuidの確認
# cat /sys/class/dmi/id/product_uuid
7A2619D2-5B38-4E54-B506-DE16F4A0A126

↓MACアドレスの確認
# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 9c:a3:ba:2d:c4:75 brd ff:ff:ff:ff:ff:ff
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 9c:a3:ba:2c:92:bb brd ff:ff:ff:ff:ff:ff
  
  

ホスト名については、そのホスト名から対応するIPアドレスを取得できるよう設定されている必要がある。DNSサーバーで適切な設定を行っておくか、もしくは/etc/hostsファイルにホスト名と割り当てているIPアドレスの組を追加しておこう。

これに加えて、swapを無効にしておく必要もある。swapを無効にするにはいくつかのやり方があるが、/etc/fstabファイルを編集してtypeが「swap」になっている行をコメントアウトし再起動するのが確実だ。

たとえば次の例では、「UUID=36f795f8-cb44-49c2-8e05-95c306653c28」で始まる行がswapに関する設定なので、この行の先頭に「#」を入れてコメントアウトしている。

UUID=910f9791-4af2-4831-81a5-5fa187c38ac1 /               ext4    errors=remount-ro 0       1
# swap was on /dev/vda2 during installation
#UUID=36f795f8-cb44-49c2-8e05-95c306653c28 none            swap    sw

「swapoff -a」コマンドでもswapを無効化できるが、この場合システムを再起動すると再度swapが有効になってしまうので注意したい。

# swapoff -a

ネットワークブリッジを通過するパケットに対しiptablesルールを適用するかどうかを指定するカーネルパラメータ「net.bridge.bridge-nf-call-iptables」も次のように確認しておこう。

$ cat /proc/sys/net/bridge/bridge-nf-call-iptables
0

もし上記のように「0」と表示されたら、次のようにしてこれを1に設定しておく。

# echo net.bridge.bridge-nf-call-iptables = 1 > /etc/sysctl.d/99-bridge-nf-call-iptables
# sysctl -p /etc/sysctl.d/99-bridge-nf-call-iptables 

Kubernetesでは複数のコンテナ技術がサポートされており、別途使用するコンテナソフトウェアやランライムインターフェイス(CRI)を用意する必要がある。Dockerのほか「containerd」や「cri-o」、「frakti」といったコンテナ技術がサポートされているが、今回はKubernetesがデフォルトで対応しているDockerを利用することにする。Kubernetesのインストール前に、クラスタの各ノードにDockerをインストールしておこう。たとえばDebianやUbuntuでは、次のようにしてDockerをインストールできる。

↓Debian/Ubuntuの場合
# apt-get install docker.io

↓CentOS 7の場合
# yum install docker

↓Fedoraの場合
# dnf install docker

↓Dockerサービスの起動
# systemctl start docker

なお、Debianでは安定版パッケージとして提供されているDockerのバージョンがやや古いため、テスト版(testing)のパッケージを導入すると良いだろう。テスト版のDockerを導入するには、デフォルトでは安定版のパッケージを使用するよう設定ファイルを作成したうえで、テスト版を利用するための設定ファイルを追加する。

↓デフォルトで安定版を使用するよう指定
# touch /etc/apt/apt.conf.d/99target
# echo 'APT::Default-Release "stable";' >> /etc/apt/apt.conf.d/99target
↓testing版のリポジトリを追加
# echo deb http://ftp.jp.debian.org/debian testing main contrib non-free > /etc/apt/sources.list.d/testing.list

この状態で「apt-get update」コマンドを実行後、「docker.io/testing」のようにパッケージ名を指定して「apt-get install」コマンドを実行することで、テスト版のDockerをインストールできる。

# apt-get install docker.io/testing
# systemctl start docker

また、記事執筆時点ではCentOS 7で提供されているDockerの最新版には不具合があり、Kubernetesと組み合わせた際に正常に動作しない問題があるようだ(KubernetesのIssueトラッカー)。次のように「docker -v」コマンドを実行した場合に「build 07f3374/1.13.1」と表示された場合、問題が発生する可能性がある。

# docker -v
Docker version 1.13.1, build 07f3374/1.13.1

この問題は、次のように「yum downgrade」コマンドを実行して古いバージョンのものに入れ替えることで対処できる。

# yum downgrade docker-1.13.1-75.git8633870.el7.centos.x86_64 docker-client-1.13.1-75.git8633870.el7.centos.x86_64 docker-common-1.13.1-75.git8633870.el7.centos.x86_64

Kubernetesで使用するネットワーク

Kubernetesでは独自の仮想ネットワークが使用されるが、この仮想ネットワークで使用されるIPアドレスがほかのネットワークとは重複しないよう、クラスタ構築時に適切な設定を行っておく必要がある。重複の可能性があるネットワークとしては、各クラスタノードが物理的に接続しているネットワークや、Dockerが使用する仮想ネットワークがある。

物理的に接続しているネットワークについては分かりやすいが、見落としやすいのがDockerが使用する仮想ネットワークだ。Dockerではデフォルトで仮想ネットワークに接続するためのネットワークブリッジを作成する。このネットワークブリッジの情報は、次のようにして確認できる。

↓作成されているネットワークを確認する
# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
d4f3dad8b55e        bridge              bridge              local
de5453c22f2a        host                host                local
915b1fed6369        none                null                local

↓「bridge」という名前のネットワークの詳細を確認する
# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "d4f3dad8b55ed65e649c8c162f47a1ad8f2b117dcb9c70afd69cebce4080f208",
        "Created": "2019-02-20T19:08:28.981013324+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

この例では、使用する仮想ネットワークとして「172.17.0.0/16」が設定されている。この場合、Kubernetesで「172.17.0.0/16」に含まれるIPアドレスを使用しようとすると問題が発生することがある。そのため、後述するように別のIPアドレス範囲を使用するよう明示的に設定することをおすすめする。

kubeadmおよび必要なコンポーネントのインストール

kubeadmでKubernetesクラスタを構築するには、まずクラスタを構成するすべてのノードにkubeadmをインストールする必要がある。kubeadmは、Googleが提供しているパッケージリポジトリ経由でインストールできる。

DebianやUbuntuなどdeb形式のパッケージを利用する場合、次のようにしてGPG鍵のダウンロードと設定ファイルの追加を行えば良い。

↓GPG鍵のダウンロードとインストール
# wget https://packages.cloud.google.com/apt/doc/apt-key.gpg
# apt-key add apt-key.gpg
OK

↓aptコマンドでHTTPSを利用可能にする「apt-transport-https」をインストール
# apt-get install -y apt-transport-https

↓リポジトリを利用するための設定ファイルを作成
# echo deb https://apt.kubernetes.io/ kubernetes-xenial main > /etc/apt/sources.list.d/kubernetes.list
# apt-get update
kubeadmおよびkubectlのインストール
# apt-get install kubeadm kubectl

CentOS 7やFedoraの場合、まず「/etc/yum.repos.d/kubernetes.repo」として次のような設定ファイルを作成する。

[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg

続いてyumコマンド(Fedoraの場合はdnfコマンド)でkubeadmパッケージをインストールする。

# yum install kubeadm

 なお、このリポジトリではKubernetesを操作するためのコマンドラインインターフェイスである「kubectl」が同名のパッケージで提供されている。マスターノードにはこちらもインストールをしておこう。

# apt-get install kubectl
もしくは
# yum install kubectl

ファイアウォールの設定

クラスタの設定を行う前に、各クラスタノードのファイアウォール設定を変更し適切にKubernetesが使用するパケットを許可するよう設定しておこう。Kubernetesがどのポートを使用するかはドキュメントに記載されているが、クラスタ内から表2、3のポートへのアクセスを許可しておけば良い。

表2 マスターノードで許可するポート
ポート番号 使用するプログラム
6443 Kubernetes API server
2379、2380 etcd
10250 kubelet
10251 kube-scheduler
10252 kube-controller-manager
表3 マスターノード以外のノードで許可するポート
ポート番号 使用するプログラム
10250 kubelet
30000~32767 NodePort

なお、もしクラスタ内でプライベートなネットワークを利用できる場合、そのプライベートネットワークからのパケットをすべて許可するよう設定しても良いだろう。その場合、Kubernetesでは実際にそのプライベートなネットワークに割り当てられているIPアドレスに加えて、Kubernetesが使用する仮想ネットワークのIPアドレスも許可する発信元として指定しておく必要がある。

たとえばファイアウォールの設定をfirewalldで行っており、クラスタノードとなる各ホストが「192.168.1.0/24」というネットワークに接続されており、Kubernetesが使用する仮想ネットワークが「10.128.0.0/16」の場合、次のようにこれらを「trusted」ゾーンとして指定すれば良い。

# firewall-cmd --zone trusted --add-source 10.128.0.0/16 --permanent
# firewall-cmd --zone trusted --add-source 192.168.1.0/24 --permanent
# firewall-cmd --reload

マスターノードのセットアップ

kubeadmのインストールが完了したら、続いてマスターノードで「kubeadm init」コマンドを実行しセットアップを行っていく。kubeadm initコマンドでは、以下のような処理を自動的に実行できる。

  • Kubernetesの各種コンポーネントを実行するのに必要な条件を満たしているかのチェック
  • ノードやコンテナの管理を行う「kubelet」の設定と起動
  • 各種公開鍵や証明書の作成
  • Kubernetesで使用される設定ファイルの作成
  • etcd、apiserver、controller-manager、schedulerといったコンポーネントをコンテナ上で起動
  • 各種設定をクラスタ内に格納
  • クラスタ内にノードを追加するのに必要なトークンの生成
  • corednsやkube-proxyといったアドオンを起動

なお、これらの詳細や指定できるコマンドラインオプションは「kubeadm init --help」コマンドを実行することで確認できる。

「kubeadm init」コマンドではいくつかのオプションが用意されている(表4)。ホストに複数のネットワークインターフェイスが接続されており、片方のネットワークインターフェイス経由でしかほかのクラスタノードと通信できない場合は「--apiserver-advertise-address」オプションで他ノードと接続できるネットワークインターフェイスに割り当てられているIPアドレスを指定する。また、KubernetesのPod(コンテナ)に割り当てるIPアドレス範囲は「--pod-network-cidr」オプションで指定できる。前述のとおり、これはほかの既存ネットワークで使用されるIPアドレスとは重複しないものを設定しておこう。

表4 「kubeadm init」コマンドで指定できる主なオプション
オプション 説明
--apiserver-advertise-address apiserverが待ち受けを行うIPアドレスを指定
--dry-run 実際の設定作業を行わず、チェック作業のみを行う
--kubernetes-version インストールするKubernetesのバージョンを指定する
--node-name ノード名を指定する
--pod-network-cidr Podに割り当てるIPアドレスの範囲を指定する。任意のものが指定できるが、既存のネットワークとは重複しない必要がある
--service-cidr Serviceで使用するIPアドレス範囲を指定する(デフォルトは「10.96.0.0/12」)
--service-dns-domain DNSで使用するドメイン名を指定する(デフォルトは「cluster.local」)

たとえばほかのクラスタノードと接続されているネットワークインターフェイスに「192.168.1.100」というIPアドレスが割り当てられており、またPodに割り当てるIPアドレス範囲を「10.128.0.0/16」とする場合、次のように実行する。

# kubeadm init --apiserver-advertise-address=192.168.1.100 --pod-network-cidr=10.128.0.0/16

さて、kubeadm initコマンドを実行すると、そのホストの環境がKubernetesの動作に必要な条件を満たしているかがチェックされ、もし問題が見つかった場合はその旨が表示される。その場合、その指示に従って必要な対処を行い、その後「kubeadm reset」コマンドを実行して設定をリセットしてから再度kubeadm initコマンドを実行する。

# kubeadm reset

また、設定に成功すれば次のようなメッセージが表示されるはずだ。

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 192.168.1.100:6443 --token 4f2l52.00o3b9d3tw7i4wgv --discovery-token-ca-cert-hash sha256:bc993e1898329a4a5ebd2c4a9b0f6d8766bce00ac850f439ca7cc8cb6c3e9897

ここで、最後に「kubeadm join 192.168.1.100:6443 --token 4f2l52.00o3b9d3tw7i4wgv --discovery-token-ca-cert-hash sha256:bc993e1898329a4a5ebd2c4a9b0f6d8766bce00ac850f439ca7cc8cb6c3e9897」と表示されているが、これが非マスタノードをクラスタに参加させる際に実行するコマンドとなる。引数の「--token」および「--discoverty-token-ca-cert-hash」以下の部分は環境によって変わるので注意したい。

また、Kubernetesの設定フロントエンドであるkubectl向けの設定ファイルが/etc/kubernetes/admin.confとして作成されているので、これを次のようにしてKubernetesの管理に使用するユーザーのホームディレクトリにコピーする。

# mkdir -p ~<使用するユーザー>/.kube
# cp /etc/kubernetes/admin.conf ~<使用するユーザー>/.kube/config
# chown -R <使用するユーザー>:<使用するユーザー> ~<使用するユーザー>/.kube

これで、指定したユーザーでkubectlコマンドを使ってクラスタにアクセスできるようになる。たとえば「kubectl get node」コマンドを実行すると、ノードの状態を確認できるはずだ。

$ kubectl get node
NAME        STATUS     ROLES    AGE     VERSION
centos4x4   NotReady   master   3m49s   v1.13.3

なお、この時点ではまだネットワーク関連の設定が完了していないため、マスターノードは利用できない(NotReady)状態となっている。

続いて、コンテナ間の通信を行うための仮想ネットワークに関する設定を行っていく。仮想ネットワークとしてはいくつかのものが利用できるが、今回は一般的に利用されているflannelを利用することにする。flannelを利用するための設定ファイルはGitHub上で公開されているので、次のようにしてまずこれをダウンロードする。

$ wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

続いてこのファイルをエディタで開き、「net-conf.json: |」以下の「"Network"」の値を、kubeadm initコマンド実行時に「--pod-network-cidr」オプションで指定したものに変更する。先の例では「10.128.0.0/16」と指定していたので、次のようになる。

  net-conf.json: |
    {
      "Network": "10.128.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }

変更の保存後に次のように実行することでコンテナ内でflannelサービスが実行され、仮想ネットワークが利用できるようになる。

$ kubectl apply -f kube-flannel.yml

この状態で「kubectl get node」コマンドを実行すると、「STATUS」が「Ready」となり、ノードが利用できる状態になっていることが確認できる。

$ kubectl get node
NAME        STATUS   ROLES    AGE   VERSION
centos4x4   Ready    master   15m   v1.13.3

なお、このネットワーク設定を行った後にkubeadm resetコマンドを実行してクラスタを作り直す場合、以下のようにして作成された「flannel.1」や「cni0」という仮想ネットワークインターフェイスを先に削除しておく必要がある。

# ip link delete cni0
# ip link delete flannel.1

非マスターノードのセットアップ

マスターノードのセットアップが完了したら、続いてほかのクラスタ参加ノードの設定もおこなっていこう。クラスタに参加させたいノードで、次のように「kubeadm join」コマンドを実行する。

$  kubeadm join <マスターノードのIPアドレス>:6443 --token <トークン> --discovery-token-ca-cert-hash <証明書ハッシュ>

ここで使用するトークンや証明書ハッシュはマスターノードでのkubeadm initコマンド実行時に表示されたものを指定すれば良い。また、この作業はクラスタに参加させるすべてのノードで実行する必要がある。

なお、トークンには有効期限があり、通常は24時間で利用できなくなる。もしトークンが失効した場合や分からなくなった場合、マスターノードで「kubeadm token create --print-join-command」コマンドを実行するとトークンが再生成されて表示される。

# kubeadm token create --print-join-command
kubeadm join 192.168.1.100:6443 --token vd0nbk.sjs8o1046t4ox2ro --discovery-token-ca-cert-hash sha256:bc993e1898329a4a5ebd2c4a9b0f6d8766bce00ac850f439ca7cc8cb6c3e9897

最後にマスターノードで次のように「kubectl get node」コマンドを実行し、ノードがクラスタに参加したことを確認しておこう。

$ kubectl get node
NAME        STATUS   ROLES    AGE     VERSION
centos00    Ready    <none>   6m17s   v1.13.3
centos4x4   Ready    master   17m     v1.13.3

簡単にクラスタ構築はできる一方でトラブルシューティングは大変

このように、kubeadmでは各ノード「kubeadm init」や「kubeadm join」といったコマンドを実行するだけでクラスタの構築が行える。ただし、これらは各Linuxディストリビューションが公式にサポートしているわけではないため、不具合等が発生する可能性がある点には注意したい。また、Kubernetesでは複雑なルーティングを行うため、ファイアウォール関連の設定も難しい。もしネットワーク関連で問題が発生したら、一度ファイアウォールを無効にして試すと行った問題の切り分けを行うことをおすすめする。