Kubernetes on CentOS on ESXi 環境を構築してみた


概要

これまでは GKE 環境を使って Kubernetes で遊んでいましたが、Kubernetes 自体の動きを見てみたいこともあり、手元にクラスタを構築しました。

kubeadm を使って、CentOS 上に Kubernetes クラスタを構築し、ダッシュボードの導入まで行いました。メモを兼ねて手順を紹介します。


システム構成

タイトル通り「Kubernetes on CentOS on ESXi」の構成となっており、ESXi 自体は Intel NUC で動いています。

  • Kubeadm 1.9.6
  • Kubernetes 1.9
  • CentOS 7.4
  • VMware ESXi 6.0
  • Intel NUC6i5SYH

f:id:yuu2634:20180325183441p:plain


0. 事前確認

今回は、Master 1台、Worker Node 2台の構成。(仮想CPU2コア・メモリ4GB × 3台)

ひとまず作って動かすことを優先するため、kubeadm で構築。


参考にした公式ドキュメント: Installing kubeadm | Kubernetes


1. サーバ共通部分の構築

CentOS を用意し、NIC やネットワーク周りが正常に動作していることを確認。yum update なども済ませておく。

ポート開放は後回しとして、Docker をインストール。
Installing kubeadm | Kubernetes - Installing Docker

# yum install -y docker
# systemctl enable docker && systemctl start docker

Kubernetes 用のリポジトリを追加。

# vi /etc/yum.repos.d/kubernetes.repo

[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-$basearch
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

Kubeadm, Kubelet, Kubectl をインストール。

# yum install -y kubelet kubeadm kubectl
# systemctl enable kubelet && systemctl start kubelet

SELinux を無効化。(未対応らしい)

# setenforce 0
# vi /etc/selinux/config

SELINUX=enforcing
      ↓
SELINUX=disabled

iptables のバイパスを避けるパラメータ追加。

# echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.d/kubernetes.conf
# echo "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.d/kubernetes.conf
# sysctl -p

Cgroup Driver が、Docker とKubelet で一致していることを確認。

# docker info | grep -i cgroup
→systemd

# grep -i cgroup /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
→systemd

swap が有効になっている場合は無効化。/etc/fstab の記載も削る。

# swapoff -a
# vi /etc/fstab

/etc/hosts に自サーバのホスト名を追記。

# vi /etc/hosts

192.168.xxx.yyy kube-master


2. サーバクローン

今回は ESXi を利用しているため、VMware 自身の機能でサーバを複製する。

f:id:yuu2634:20171215220801p:plain

2台複製し、ホスト名・IPアドレス・hosts の修正をしておく。

念のため、MACアドレスが重複していない(再生成されている)ことも確認。


3. Master 構築

1台を選定し、Master としてセットアップを進める。

序盤にスキップした firewalld の設定を追加。
Installing kubeadm | Kubernetes - Check required ports

# firewall-cmd --add-port=6443/tcp --zone=public --parmanent
# firewall-cmd --add-port=2379-2380/tcp --zone=public --parmanent
# firewall-cmd --add-port=10250/tcp --zone=public --parmanent
# firewall-cmd --add-port=10251/tcp --zone=public --parmanent
# firewall-cmd --add-port=10255/tcp --zone=public --parmanent


本題の Kubernetes クラスタを作成。

--pod-network-cidr は Kubernetes で利用するネットワーク指定でデフォルトのまま。--apiserver-advertise-address は kube-apiserver 用アドレス指定。ここでは master サーバ自身の IP とする。

# kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=192.168.xxx.yyy


無事に構築できたことを確認し、kubeadm join …… のコマンドを控えておく。

Your Kubernetes master has initialized successfully!

(中略)

You can now join any number of machines by running the following on each node
as root:

  kubeadm join --token aaaa.bbbbbb 192.168.xxx.yyy:6443 --discovery-token-ca-cert-hash sha256:zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz


普段使うユーザに切り替え、kubectl の接続設定を反映。

$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

$ kubectl cluster-info
Kubernetes master is running at https://10.0.xxx.yyy:6443


4. Pod ネットワーク構築

Using kubeadm to Create a Cluster | Kubernetes - (3/4) Installing a pod network

今回は Flannel を利用するため、yml ファイルを一旦ダウンロード。

$ curl https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml -o kube-flannel.yml


利用する NIC 名を command: の末尾に追記。

$ vi kube-flannel.yml
      containers:
      - name: kube-flannel
        image: quay.io/coreos/flannel:v0.9.1-amd64
        command: [ "/opt/bin/flanneld", "--ip-masq", "--kube-subnet-mgr", "--iface=ens160" ]


編集済みの yml ファイルを適用。kube-dnsRunning になれば完了。

$ kubectl apply -f kube-flannel.yml

$ kubectl get pod -n kube-system | grep kube-dns
kube-dns-6f4fd4bdf-vmtnx                3/3       Running   0          2d

$ kubectl cluster-info
Kubernetes master is running at https://10.0.xxx.yyy:6443
KubeDNS is running at https://10.0.xxx.yyy:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy


5. Worker Node 構築

先ほどクローンしたサーバの状態からスタート。

今度は Worker Node 用の設定を追加。
Installing kubeadm | Kubernetes - Check required ports

# firewall-cmd --add-port=10250/tcp --zone=public --parmanent
# firewall-cmd --add-port=10255/tcp --zone=public --parmanent
# firewall-cmd --add-port=30000-32767/tcp --zone=public --parmanent


Master 構築時に提示されたコマンドだけでノード追加完了。

# kubeadm join --token aaaa.bbbbbb 192.168.xxx.yyy:6443 --discovery-token-ca-cert-hash sha256:zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz


kubectl から結果を確認。

$ kubectl get node
NAME            STATUS    ROLES     AGE       VERSION
kube-master     Ready     master    2d        v1.9.6
kube-worker01   Ready     <none>    2d        v1.9.6

同様に2台目の Worker Node も追加。


6. Kubernetes Dashboard 導入

Kubernetes Dashboard - README.md に従ってデプロイするだけ。

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml

$ kubectl get service -n kube-system
NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE
kubernetes-dashboard   ClusterIP   10.103.221.252   <none>        443/TCP         2d


ClusterIP には外から直接アクセスできないため、ローカルプロキシを作成。

$ kubectl proxy


この状態で http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/ にアクセス。

f:id:yuu2634:20180326205840p:plain

クラスタ情報取得のため、ログインを求められる。


7. Dashboard 用ユーザ作成

Creating sample user · kubernetes/dashboard Wiki を参考に yaml ファイルを作成して設定追加。

まずはユーザ作成。

$ cat <<EOF >admin-user.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kube-system
EOF

$ kubectl create -f admin-user.yaml


ロールを割り当て。

$ cat <<EOF >admin-user_role.yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kube-system
EOF

$ kubectl create -f admin-user_role.yaml


アクセストークンを取得。最後の token: 部分だけコピーして、Dashboard に貼り付け。

$ kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')

token:      eyJhbhp(略)o700OSpvTT9zlBsu-b35lzXGBRHzv5g_RA


ダッシュボードが見えるようになった。かっこいい。

f:id:yuu2634:20180326211451p:plain


7. Dashboard を NodePort 化

毎度 kubectl proxy するのも手間なので、NodePort からアクセスできるようにする。
Accessing Dashboard 1.7.X and above · kubernetes/dashboard Wiki

Service の設定を編集。

$ kubectl -n kube-system edit service kubernetes-dashboard


エディタが開くので type: 欄を修正して上書き保存。

  type: ClusterIP
   ↓
  type: NodePort


Service を確認すると NodePort が付与された。

$ kubectl get service -n kube-system
NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE
kube-dns               ClusterIP   10.96.0.10       <none>        53/UDP,53/TCP   2d
kubernetes-dashboard   NodePort    10.103.221.252   <none>        443:32701/TCP   2d


これにより https://<MasterのIPアドレス>:32701 でアクセス可能となった。
Google Chrome だと証明書エラーで開けない場合があるので、Firefox からアクセス。


まとめ

  • kubeadm を利用して CentOS 上に Kubernetes クラスタを構築しました
  • Dashboard のデプロイ&初期設定&NodePort 対応を行いました

自宅に一つ Kubernetes を用意することで、費用を気にせずコンテナ立て放題・yaml 検証可能な環境が整いました。

CoreOS も試したいと考えているため、近い内にノードとしてクラスタに追加予定です。