Carpe Diem

備忘録

Kubernetes を使ったマルチホスト環境でのクラスタを構築する【基礎編】

概要

Kubernetesを使ってDockerのクラスタを構築します。Kubernetesを使うことで以下のような本番環境を意識したシステムを構築できます。

  • フェイルオーバー(コンテナが異常終了したことを検知し再起動させる)
  • スケーリング(起動しているコンテナの数を自由に変更できる)
  • ロードバランス(複数のコンテナにリクエストを振り分けて負荷分散する)
  • サービスディスカバリ(サービスへのルーティングを自動で提供する)

この構築は長いので記事自体も複数に分けて進めます。

アーキテクチャ

コンポーネント 説明
apiserver kubernetesを操作するためのAPIを提供する
controller-manager コンテナの状態管理やノードの管理と言った各種管理作業を行う
kube-proxy コンテナへのネットワークルーティングおよび負荷分散を行う
scheduler 各ノードに対しコンテナの割り当てなどを行う
kubelet 各ノード上でのコンテナ作成/削除やボリュームの割り当てなどを行う
kubectl API経由でKubenetesを操作するためのクライアントツール

図に表すと以下です。

f:id:quoll00:20180525101412p:plain

ref: Introduction to Kubernetes Architecture

また各ホストは以下の役割とします。

ホスト名 IP 役割
master 192.168.33.10 マスターノード
node1 192.168.33.100 子ノード
node2 192.168.33.101 子ノード

環境

  • Vagrant 1.8.1
  • CentOS 7.2.1511
  • Docker 1.9.0
  • Kubernetes 1.2.0
  • etcd 2.2.5
  • flannel 0.5.3

今回は各ツールのパッケージが全て提供されているCentOS7で構築します。

事前準備

簡単のため各サーバのファイアウォールSELinuxを無効化します。

# systemctl disable firewalld

SELinuxの修正

# vim /etc/sysconfig/selinux
・・・
SELINUX=permissive
・・・

また各ホスト名もユニークである必要があるので、/etc/hostnameを上記の表の通りに変更します。

最後に/etc/hostsにホスト名とIPを紐付けます。そうでないとkubeletがホスト名からIPを取得できません。

完了したら再起動します。

# reboot

マスターノードの設定

主に必要なパッケージは以下です。

  • docker
  • kubernetes-master
  • kubernetes-client
  • etcd
  • flannel

上記のパッケージを以下のコマンドでインストールします。

# yum install etcd kubernetes flannel

dockerサービスの自動起動化をします。

# systemctl start docker
# systemctl enable docker

etcdの設定

/etc/etcd/etcd.conf

ETCD_NAME=default
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="http://localhost:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://0.0.0.0:2379"

ETCD_LISTEN_CLIENT_URLSETCD_ADVERTISE_CLIENT_URLSlocalhostのままだと他のノードがアクセス出来ないので変更します。

起動&自動起動設定をします。

# systemctl start etcd
# systemctl enable etcd

Kubernetesの設定

/etc/kubernetes/config

KUBE_LOGTOSTDERR="--logtostderr=true"
KUBE_LOG_LEVEL="--v=0"
KUBE_ALLOW_PRIV="--allow-privileged=false"
KUBE_MASTER="--master=http://192.168.33.10:8080"

KUBE_MASTERをマスターサーバのIPにします。

/etc/kubernetes/apiserver

KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0"
KUBE_ETCD_SERVERS="--etcd-servers=http://192.168.33.10:2379"
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16"
KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"
KUBE_API_ARGS=""

KUBE_API_ADDRESSを0.0.0.0に設定、KUBE_ETCD_SERVERSをマスターサーバのIPに変更します。

完了したらサービスを起動します。

# for SERVICES in kube-apiserver kube-controller-manager kube-scheduler; do \
systemctl restart $SERVICES && \
systemctl enable $SERVICES; done

動作確認します。

# curl -s -L http://192.168.33.10:8080/version
{
  "major": "1",
  "minor": "2",
  "gitVersion": "v1.2.0",
  "gitCommit": "738b7603b042dcda7a5ba419ab0e7f40a617080c",
  "gitTreeState": "clean"
}

ポートも確認します。

# ss -untlp | grep -E "kube|etcd"
tcp    LISTEN     0      128    192.168.33.10:2379                  *:*                   users:(("etcd",pid=2466,fd=6))
tcp    LISTEN     0      128    127.0.0.1:2380                  *:*                   users:(("etcd",pid=2466,fd=5))
tcp    LISTEN     0      128    192.168.33.10:8080                  *:*                   users:(("kube-apiserver",pid=2514,fd=31))
tcp    LISTEN     0      128      :::10251                :::*                   users:(("kube-scheduler",pid=2568,fd=13))
tcp    LISTEN     0      128      :::10252                :::*                   users:(("kube-controller",pid=2541,fd=10))

kube-apiserverとetcdがLISTENしてます。大丈夫ですね。

子ノードの設定

主に必要なパッケージは以下です。

  • docker
  • kubernetes-node
  • kubernetes-client
  • flannel

上記のパッケージを以下のコマンドでインストールします。

# yum install kubernetes-node flannel

dockerサービスの自動起動化をします。

# systemctl start docker
# systemctl enable docker

kubernetesの設定

/etc/kubernetes/config

KUBE_LOGTOSTDERR="--logtostderr=true"
KUBE_LOG_LEVEL="--v=0"
KUBE_ALLOW_PRIV="--allow-privileged=false"
KUBE_MASTER="--master=http://192.168.33.10:8080"

KUBE_MASTERにマスターのIPを指定します。

/etc/kubernetes/kubelet

KUBELET_ADDRESS="--address=0.0.0.0"
KUBELET_API_SERVER="--api-servers=http://192.168.33.10:8080"
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"
KUBELET_ARGS="--register-node=true"

KUBELET_ADDRESSを0.0.0.0に設定、KUBELET_API_SERVERをマスターに。KUBELET_ARGSにオプションを追記します。

完了したら各サービスを再起動します。

# for SERVICES in kubelet kube-proxy; do \
systemctl restart $SERVICES && \
systemctl enable $SERVICES; done

サービスが動いているか確認します。

# ss -untlp | grep kube
tcp    LISTEN     0      128    127.0.0.1:10248                 *:*                   users:(("kubelet",pid=24082,fd=4))
tcp    LISTEN     0      128    127.0.0.1:10249                 *:*                   users:(("kube-proxy",pid=24110,fd=10))
tcp    LISTEN     0      128      :::10250                :::*                   users:(("kubelet",pid=24082,fd=8))
tcp    LISTEN     0      128      :::10255                :::*                   users:(("kubelet",pid=24082,fd=22))
tcp    LISTEN     0      128      :::4194                 :::*                   users:(("kubelet",pid=24082,fd=14))

ノードからマスターのetcdにアクセスできるか確認します。

# curl -s -L http://192.168.33.10:2379/version
{"etcdserver":"2.2.5","etcdcluster":"2.2.0"}

大丈夫ですね。

動作確認

全部の設定が完了するとマスターからノードが確認できます。

# kubectl get node
NAME      STATUS    AGE
node1     Ready     6m
node2     Ready     25s

次回はflannelを使ってマルチホストでDockerコンテナが通信できるovarlay networkを構築します。

ソース