Kubernetes (v1.5) を CentOS 7.3 に構築してコンテナをデプロイ可能にするまでの手順

本記事は、CentOS Linux release 7.3.1611 (Core) に対して Kubernetes をインストールするための 2017/05/28時点の作業ログを残すものです。初めて Kubernetes を使うにあたり改めて学んだことなどのメモも併記します。

2022年12月更新

現在では Kubernets を試す手段は多岐にわたり、マネージドサービスの Kubernetes (たとえば AWS の EKS や GCP の GKE) 、あるいは開発・検証用途であれば Docker Desktop に付属する Kubernetes や シングルバイナリで動作可能な minikube を利用すれば十分なので、わざわざ自身で Kubernetes を構築する必要はありません。

ですが、自身で Kubernetes をインストールすることで構成要素の全体像を把握することができるので、その後の Kubernets の運用を楽にしてくれるメリットが得られます。結果的には問題解決のスピードが早くなることもありますので、都合がつく方はぜひ一度挑戦してみてください。

その他の Kubernetes 関連記事はこちら: fand.jp Kubernetes | Web勉強ログ Hatena Bookmark Counter for https://fand.jp/tags/kubernetes/

動機と本記事の読者ターゲット

Dockerコンテナは便利で日々大活躍ですが、小規模利用だと docker-compose で必要十分でした。一方、Kubernetesなんかのオーケストレーションツールも盛り上がっていますね。

(2017/5/29 00:00 Google Trendsより)

この傾向だと他の追従を許さない感じですね。Kubernetes, Docker swarm, OpenShift いずれも CaaS (Container as a Service) の領域であるのに対し、Cloud Foundry は PaaS (Platform as a Service) なので直接対比するものではないのですが、規模感を並べてみただけです。

Kubernetesは興味がありつつも大袈裟なので敬遠していましたが、最近のトレンドを見てるとノータッチというわけにもいかないかと思い、セットアップしてみることにしました。

構築のゴール

  • Kubernetes クラスタを構築し、DockerHub等から取得したイメージをデプロイして動かすことができること。
  • 関連ソフトウェアの設定を通じてそれぞれがどのような役割をもって動いているのか理解すること。

動かすことだけが目的であれば kubeadm を使えばもっと楽できそうなのですが、理解が弱まってしまうので今回は利用しません。

kubeadmが何なのかは、この記事で学びました。

kubeadmが何をやっているのかみてみた - Qiita

※ デプロイまでをひとつの記事にまとめようと思いましたが、構築パートだけでそれなりの文章量になったのでデプロイパートは分割します。

本記事で取り扱わないこと

  • Kubernetesクラスタの運用
  • コンテナのデータ永続化
  • 商用環境を見据えたセキュリティ関連設定

… など。

今後やろうとしていること

  • Nodeがダウンしてもサービス継続できる運用の確認
  • プライベートRegistryの運用(Docker HubにイメージをPushしたくないもの用)
  • dashboardをインストールしてWebブラウザからクラスタ管理
  • prometheusなどを用いたメトリクスの収集とモニタリング

本記事執筆時点での構築環境条件

  • 物理マシン(VM)でMaster1台、Node2台を用意する。
  • ソフトウェアバージョンは以下のとおり。
SW Version note
CentOS 7.3.1611
Kubernetes v1.5.2
etcd 3.1.7 node のみで実行
Flanneld 0.7.0
Docker 1.12.6, build 1398f24/1.12.6 node のみで実行

MasterとNodeそれぞれで動くソフトウェアの配置は以下の通り。

No マシン インストール
1 Master Kubernetes, etcd, flannel, [docker-registry]
2 Node Kubernetes (Kubelet), flannel, docker

docker-registry は、今後の予定です。レポジトリ機能は、趣味の自宅サーバーレベルで構築すると運用コストが割に合わないので、外部サービスで済むならそれがよいかなと思っているところ。前向きに考えたいのは、Google Cloud Platform (GCP) の CONTAINER REGISTRY サービス (GCR) です。

Container Registry - 安全な非公開 Docker レジストリ  |  Container Registry  |  Google Cloud

サーバーのインストール作業

記事の立て付けは以下の流れで書いています。

  • 最初は、Master / Node での共通作業をする
  • Master サーバーでの設定をする
  • Node サーバーでの設定をする

Kubernetes の導入作業は基本的に Kubernetesマニュアル に倣っており、所々でコメントや調整を行っています。また、コマンドの実行は root ユーザーで実行しているものとします。

共通作業

# vi /etc/hosts
10.0.4.30  kube00
10.0.4.31  kube01
10.0.4.32  kube02

DNSサーバーでもいいのか詳細調べていませんが、Kubernetes はホスト名で解決をするため、という根拠だった気がします。Kubernetesマニュアル上もそうなっているので、とりあえず従います。

(より高度化のためには DNS Pods を使うことになるのかな?ここはとりあえず保留。)

DNS for Services and Pods - Kubernetes

ほか、好みで yum install をします。

# yum -y install bash-completion tcpdump chrony wget git

Dockerインストール用レポジトリの設定

# vi /etc/yum.repos.d/virt7-docker-common-release.repo

[virt7-docker-common-release]
name=virt7-docker-common-release
baseurl=http://cbs.centos.org/repos/virt7-docker-common-release/x86_64/os/
gpgcheck=0

Kubernetes関連ソフトウェアのインストール

# yum -y install --enablerepo=virt7-docker-common-release kubernetes etcd flannel

セキュリティ関連機能の無効化

SELinuxおよびFirewalldを停止します。

# getenforce
Disabled

この通りDisabledになっていない場合は、

# setenforce 0

Firewalldの停止

# systemctl disable firewalld
# systemctl stop firewalld

セキュリティ無効化に関する補足(スルーしてもよい)

マニュアル上は以下の通りです。

> setenforce 0
> systemctl disable iptables-services firewalld
> systemctl stop iptables-services firewalld

firewalld だけ止めれば、iptables も全て無効化になっています。(iptables -L で確認)

昔ながらの iptables の操作は不要になっていて、iptables をバックエンドとする Firewalld という関係になっているようです。最低限のポートだけあけたい場合、firewall-cmd で以下のように許可ポートを追加していきます。

// 例
# firewall-cmd --permanent --add-port=8080/tcp
# firewall-cmd --permanent --add-port=2379/tcp
# firewall-cmd --permanent --add-port=5000/tcp
// 確認
# cat /etc/firewalld/zones/public.xml

但し、上記例のポートだけだと追々失敗しますので、もう少し追加が必要です。

Masterサーバーでのインストール

Masterサーバーでのみの作業です。だいたい終わって閉まっているので、個別に行うインストールは以下のみです。

# yum -y install kubernetes

設定は後述します。

Nodeサーバーでのインストール作業

Nodeサーバーでのみの作業です。だいたい終わって閉まっているので、個別に行うインストールは以下のみです。

Docker が入っていなければ入れておきます。

# yum -y install docker

設定は後述します。

サーバーの設定作業

マスタの設定内容

Kubernetesでは、/etc/kubernetes/ ディレクトリ以下に各種設定ファイルがインストールされています。マスターサーバー側で変更が必要なのはapiserverファイルとconfigファイル、controller-managerファイルの3つ。

別途RSA鍵の用意も必要のようです。opensslコマンドを使用してkubernetesのAPI認証に使用される鍵ファイルを/etc/kubernetes/serviceaccount.keyとして作成しておきます。

# sudo openssl genrsa -out /etc/kubernetes/serviceaccount.key 2048

以降、見出しに記載している設定ファイルを修正していきます。全設定ファイルを記述すると冗長なので、変更対象部分のみを記載します。

[注]

  • ここまでは # で rootユーザーでの実行コマンドを意味してきましたが、設定ファイルの部分ではコメントアウトを意味しますので、よしなに読み替えてください。
  • kube00 の文字列が頻繁に出てきますが、最初に hosts で設定した通りMasterサーバーのホスト名です。こちらも各環境にあわせて読み替えてください。

/etc/kubernetes/config

#KUBE_MASTER="--master=http://127.0.0.1:8080"
KUBE_MASTER="--master=http://kube00:8080"

/etc/kubernetes/kubelet

#KUBELET_HOSTNAME="--hostname-override=127.0.0.1"
KUBELET_HOSTNAME="--hostname-override=kube00"

/etc/kubernetes/apiserver

#KUBE_API_ADDRESS="--insecure-bind-address=127.0.0.1"
KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0"

#KUBE_API_PORT="--port=8080"
#KUBE_API_PORT="--insecure-port=8080"

#KUBE_ETCD_SERVERS="--etcd-servers=http://127.0.0.1:2379"
KUBE_ETCD_SERVERS="--etcd-servers=http://kube00:2379"

KUBE_API_ARGS="--service_account_key_file=/etc/kubernetes/serviceaccount.key"

/etc/kubernetes/controller-manager

#KUBE_CONTROLLER_MANAGER_ARGS=""
KUBE_CONTROLLER_MANAGER_ARGS="--service_account_private_key_file=/etc/kubernetes/serviceaccount.key"

/etc/etcd/etcd.conf

ついで etcd です。KubernetesやFlanneldはその設定管理にetcdを使用するため、まずはetcdの設定を行ってサービスを起動します。etcdのデフォルト設定ではローカルホストからしかetcdにアクセスできないようになっているため、ETCD_LISTEN_CLIENT_URLS の値を修正します。

#ETCD_LISTEN_CLIENT_URLS="http://localhost:2379"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"

etcdctlでflannelが利用するネットワーク周りの設定

次に、仮想ネットワークを利用するためのflannelの設定を行います。まず、etcdのコマンドラインクライアントであるetcdctlコマンドを使ってflannelが使用する仮想ネットワークのIPアドレスを指定します。

# etcdctl mk /atomic.io/network/config '{"Network":"172.30.0.0/16", "SubnetLen":24, "Backend":{"Type":"vxlan"} }'

補足:/atomic.io/network/config はOSの実際のディレクトリではなく、etcd管理上のディレクトリです。物理的にディレクトリが作成されるわけではありません。

Error (Firewalld が起動したまま、あるいは必要ポートへの接続ができないため)

Errorの参考情報です。

Error:  client: etcd cluster is unavailable or misconfigured; error #0: dial tcp 127.0.0.1:4001: getsockopt: connection refused
; error #1: dial tcp 127.0.0.1:2379: getsockopt: connection refused

error #0: dial tcp 127.0.0.1:4001: getsockopt: connection refused
error #1: dial tcp 127.0.0.1:2379: getsockopt: connection refused

このエラーが発生した状態でこのあとのステップを続けると、最後の起動で失敗しました。途中記載したセキュリティ設定に関する部分の繰り返しになりますが、

# systemctl disable firewalld
# systemctl stop firewalld

マニュアルの通りFirewallを無効化して、このあと同じように作成すると、

# etcdctl mk /atomic.io/network/config '{"Network":"172.30.0.0/16", "SubnetLen":24, "Backend":{"Type":"vxlan"} }'
{"Network":"172.30.0.0/16", "SubnetLen":24, "Backend":{"Type":"vxlan"} }

成功します。Errorに出ているポート番号を許可設定すればよいと思いますが、初のKubernetes利用においては今後も他の弊害が出てくるかもしれないので素直に無効化しました。

なお、 /atomic.io は何かというと /etc/sysconfig/flanneldFLANNEL_ETCD_PREFIXとして設定されているディレクトリ名です。Kubernetesマニュアルでは以下の記述になっています。

systemctl start etcd
etcdctl mkdir /kube-centos/network
etcdctl mk /kube-centos/network/config "{ \\"Network\\": \\"172.30.0.0/16\\", \\"SubnetLen\\": 24, \\"Backend\\": { \\"Type\\": \\"vxlan\\" } }"

違いは、FLANNEL_ETCD_PREFIXに影響するディレクトリ名と、ネットワークでしょうか。PREFIXは変えるメリットが分からないのでそのまま設定、ネットワークは 172.17.0.0/16 だと標準のDockerネットワークでも同じアドレス帯だったと思うので、マニュアルに倣って変更しておくことにします。

なお、/atomic.io を作成しない状態で flanneld を起動しようとすると失敗することが分かります。

# etcdctl ls
/registry

# systemctl restart flanneld
 ...
flanneld-start[xxxx]: E0528 02:14:50.718371    7816 network.go:102] failed to retrieve network config: 100: Key not found (/atomic.io) [xxxx]

関連サービスの起動とサービス登録 (Master)

一通りの設定を終えたら、再起動とサービス登録をします。

Start the appropriate services on master:
for SERVICES in etcd kube-apiserver kube-controller-manager kube-scheduler flanneld; do
    systemctl restart $SERVICES
    systemctl enable $SERVICES
    systemctl status $SERVICES
done

Error: Failed to start Flanneld overlay address etcd agent.

上で少し書きましたが、etcdctl mk /atomic.io/network/config '{"Network":"172.30.0.0/16"}' の実行に失敗した状態で進めると、こんなエラーが。オーバーレイネットワークの作成に失敗しているためです。

May 28 00:08:34 kube00.yourdomain.local systemd: Started Kubernetes Scheduler Plugin.
May 28 00:08:34 kube00.yourdomain.local systemd: Starting Kubernetes Scheduler Plugin...

Job for flanneld.service failed because a timeout was exceeded. See "systemctl status flanneld.service" and "journalctl -xe" for details.
Created symlink from /etc/systemd/system/multi-user.target.wants/flanneld.service to /usr/lib/systemd/system/flanneld.service.
Created symlink from /etc/systemd/system/docker.service.requires/flanneld.service to /usr/lib/systemd/system/flanneld.service.
● flanneld.service - Flanneld overlay address etcd agent
   Loaded: loaded (/usr/lib/systemd/system/flanneld.service; enabled; vendor preset: disabled)
   Active: activating (auto-restart) (Result: timeout) since Sun 2017-05-28 00:10:05 EDT; 77ms ago
 Main PID: 6648 (code=exited, status=0/SUCCESS)

May 28 00:10:05 kube00.yourdomain.local systemd: Failed to start Flanneld overlay address etcd agent.
May 28 00:10:05 kube00.yourdomain.local systemd: Unit flanneld.service entered failed state.
May 28 00:10:05 kube00.yourdomain.local systemd: flanneld.service failed.

せっかく途中まで Firewalld を設定したのだから、最後まで…と思いつつも、オフィシャルドキュメント上ではOffにするよう記述もあることから、切り分け単純化のために無効化しました。

Disable the firewall on the master and all the nodes, as docker does not play well with other firewall rule managers. CentOS won’t let you disable the firewall as long as SELinux is enforcing, so that needs to be disabled first.
via CentOS | Kubernetes

ノードの設定内容

コンテナを稼動させるノードの設定です。コンテナ稼動ノードではetcdは不要で、DockerおよびKubernetes、Flanneldパッケージを利用します。

一応、etcdが無効化されている(あるいはインストールされていない)ことを確認する。

# systemctl status etcd
● etcd.service - Etcd Server
   Loaded: loaded (/usr/lib/systemd/system/etcd.service; disabled; vendor preset: disabled)
   Active: inactive (dead)

/etc/kubernetes/kubelet

KUBELET_HOSTNAME パラメータではそのノードのホスト名を指定しますが、これは空欄にしておくことで、そのホストで設定されているhostnameが利用されるとのこと。

#KUBELET_ADDRESS="--address=127.0.0.1"
KUBELET_ADDRESS="--address=0.0.0.0"

#KUBELET_HOSTNAME="--hostname-override=127.0.0.1"
KUBELET_HOSTNAME="--hostname-override="
                                   # 指定をしなければ起動しているホスト名を利用するらしい

#KUBELET_API_SERVER="--api-servers=http://127.0.0.1:8080"
KUBELET_API_SERVER="--api-servers=http://kube00:8080"

/etc/sysconfig/flanneld

Flanneldについては、デフォルトではローカルホスト上のetcdを参照しようとするため、設定ファイルを編集してマスターサーバー上のetcdを参照するよう変更します。ファイル内のFLANNEL_ETCD部分を、マスターサーバーを参照するよう変更します。

# etcd url location.  Point this to the server where etcd runs
#FLANNEL_ETCD="<http://127.0.0.1:2379>"
FLANNEL_ETCD="<http://kube00:2379>"

関連サービスの起動とサービス登録 (Node)

一通りの設定を終えたら、再起動とサービス登録をします。

for SERVICES in kube-proxy kubelet flanneld docker; do
    systemctl restart $SERVICES
    systemctl enable $SERVICES
    systemctl status $SERVICES
done

kubectl

Kubernetesを操作するクライアント kubectl を設定します。ここは、rootではなく一般のユーザーで同様に実施できました。パスワード設定などもここでできるようですが割愛します。

$ kubectl config set-cluster default-cluster --server=http://kube00:8080
$ kubectl config set-context default-context --cluster=default-cluster --user=default-admin
$ kubectl config use-context default-context

テスト

$ kubectl cluster-info

実行結果

$ kubectl config set-cluster default-cluster --server=http://kube00:8080
Cluster "default-cluster" set.

$ kubectl config set-context default-context --cluster=default-cluster --user=default-admin
Context "default-context" set.

$ kubectl config use-context default-context
Switched to context "default-context".

$ kubectl cluster-info
Kubernetes master is running at <http://kube00:8080>

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

$kubectl get nodes
NAME                      STATUS    AGE
kube01.yourdomain.local   Ready     10h
kube02.yourdomain.local   Ready     10h

まとめ

ここまでのステップでクラスタの構築が完了し、コンテナをデプロイできる状態になりました。このあと、いくつかのサービスをデプロイして運用を確認しようと思っています。

いまのところ、docker-compose に慣れすぎて、まだ yml の書き方を始め、いろいろと戸惑うところがあります。

また Kubernetes が何をやってくれるのか理解不足なのもあり、Pod や Namespace との関係、Deployment, Service の違い、その他用語など、慣れなければならないことが多そうです。

補足

etcd とは

ホスト間でキー・バリューを共有するためのKVS。etcdctl ls とコマンドを打つと、データの実態を確認することができる。使ってみて気づいた点。

  • KVSのデータはディレクトリ構造で管理されている
  • ディレクトリという表現ではあるがLinuxの実際のディレクトリは別物

オーバーレイネットワーク作成のために etcdctl mk /xxx と実行した内容を参照することができる。

Reference