kubeadm を使って Kubernetes v1.13 をインストールしてみた

こんにちは。サイオステクノロジー OSS サポート担当 Y です。

本日、新元号 “令和” が発表されました。

IT システムの構築や運用をされているエンジニアの皆様の中には、5月に向けた新元号対応の作業が始まっている方も多いのではないでしょうか。弊社のサポート部門にも、新元号発表前から各 OSS 製品やライブラリにおける元号変更に伴う影響有無等に関するお問い合わせを複数頂いております。

さて、新元号が発表されて間もない状況であり元号関連の情報を期待されていた方には申し訳ないのですが、残念ながら今回の記事は元号に関する内容ではありません。

今回は、kubeadm を利用して Kubernetes v1.13 をオンプレ環境の仮想マシン上にシングルノード構成でインストールしてみました。(※以下の内容は CentOS 7.6/kubeadm v1.13 にて検証しています。)

■はじめに

昨今のトレンドであるコンテナ技術において欠かすことができないコンテナオーケストレーションツールのデファクトスタンダードになっている Kubernetes ですが、Kubernetes クラスタを一から自分で構築するのにはそれなりの手間がかかってしまいます。

また、AWS, Azure, GCP 等の主要なクラウドサービスを利用すれば、そのような構築の手間をあまりかけずに Kubernetes を利用することも可能ですが、個人での検証や学習用として使うには少しハードルが高いと感じる方もいらっしゃるのではないでしょうか。

そこで今回は、(できるだけ) 簡単に Kubernetes をインストールする方法として、kubeadm というツールを使った (できるだけ) 簡単な Kubernetes のインストール方法を試してみました。

なお、今回の記事では可能な限りシンプルな構成とするために、1台の仮想マシン上にシングルノード構成の Kubernetes をインストールしています。

■OS (CentOS) の設定 (swap 無効化)

初めに、Kubernetes をインストールする OS (CentOS) 側の設定を実施します。

こちらのドキュメントに記載されている通り、kubeadm の要件として swap を無効にする必要があるため、swap を無効にします。

[root@kubeadm ~]# swapon -s
Filename                                Type            Size    Used    Priority
/dev/dm-1                               partition       1679356 0       -2
[root@kubeadm ~]# 
[root@kubeadm ~]# cat /proc/swaps 
Filename                                Type            Size    Used    Priority
/dev/dm-1                               partition       1679356 0       -2
[root@kubeadm ~]# 
[root@kubeadm ~]# cp -p /etc/fstab ~/fstab.backup
[root@kubeadm ~]# 
[root@kubeadm ~]# vim /etc/fstab 
[root@kubeadm ~]# 
[root@kubeadm ~]# diff -u ~/fstab.backup /etc/fstab ~/fstab.backup 
--- /etc/fstab  2019-02-13 15:42:07.093706842 +0900
+++ /root/fstab.backup  2018-12-04 15:35:52.479534688 +0900
@@ -8,4 +8,4 @@
 #
 /dev/mapper/centos-root /                       xfs     defaults        0 0
 UUID=0402849e-44c1-4846-8d8c-1f00c87e56db /boot                   xfs     defaults        0 0
-/dev/mapper/centos-swap swap                    swap    defaults        0 0
+#/dev/mapper/centos-swap swap                    swap    defaults        0 0
[root@kubeadm ~]# 
[root@kubeadm ~]# shutdown -r now


(再起動後)


[root@kubeadm ~]# swapon -s
[root@kubeadm ~]# 
[root@kubeadm ~]# cat /proc/swaps 
Filename                                Type            Size    Used    Priority

■Docker のインストール

次に、コンテナランタイムのインストールです。ドキュメントを参考に、Docker をインストールします。

(こちらのドキュメントに記載されている通り、Kubernetes では複数のコンテナランタイムを利用することが可能ですが、今回はデフォルトの Docker を利用します。)

[root@kubeadm ~]# yum install -y yum-utils device-mapper-persistent-data lvm2
Loaded plugins: fastestmirror, langpacks
Determining fastest mirrors
 * base: ftp.riken.jp
 * extras: ftp.riken.jp
 * updates: ftp.riken.jp


~(中略)~


Updated:
  lvm2.x86_64 7:2.02.180-10.el7_6.3                                                                     

Dependency Updated:
  device-mapper.x86_64 7:1.02.149-10.el7_6.3                                                            
  device-mapper-event.x86_64 7:1.02.149-10.el7_6.3                                                      
  device-mapper-event-libs.x86_64 7:1.02.149-10.el7_6.3                                                 
  device-mapper-libs.x86_64 7:1.02.149-10.el7_6.3                                                       
  lvm2-libs.x86_64 7:2.02.180-10.el7_6.3                                                                

Complete!
[root@kubeadm ~]# 
[root@kubeadm ~]# yum-config-manager \
>     --add-repo \
>     https://download.docker.com/linux/centos/docker-ce.repo
Loaded plugins: fastestmirror, langpacks
adding repo from: https://download.docker.com/linux/centos/docker-ce.repo
grabbing file https://download.docker.com/linux/centos/docker-ce.repo to /etc/yum.repos.d/docker-ce.repo
repo saved to /etc/yum.repos.d/docker-ce.repo
[root@kubeadm ~]# 
[root@kubeadm ~]# yum install -y docker-ce-18.06.2.ce
Loaded plugins: fastestmirror, langpacks
Loading mirror speeds from cached hostfile
 * base: ftp.riken.jp
 * extras: ftp.riken.jp
 * updates: ftp.riken.jp
Resolving Dependencies
--> Running transaction check
---> Package docker-ce.x86_64 0:18.06.2.ce-3.el7 will be installed
--> Processing Dependency: container-selinux >= 2.9 for package: docker-ce-18.06.2.ce-3.el7.x86_64
--> Running transaction check
---> Package container-selinux.noarch 2:2.74-1.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

========================================================================================================
 Package                    Arch            Version                     Repository                 Size
========================================================================================================
Installing:
 docker-ce                  x86_64          18.06.2.ce-3.el7            docker-ce-stable           41 M
Installing for dependencies:
 container-selinux          noarch          2:2.74-1.el7                extras                     38 k

Transaction Summary
========================================================================================================
Install  1 Package (+1 Dependent package)

Total download size: 41 M
Installed size: 168 M
Downloading packages:
(1/2): container-selinux-2.74-1.el7.noarch.rpm                                   |  38 kB  00:00:00     
warning: /var/cache/yum/x86_64/7/docker-ce-stable/packages/docker-ce-18.06.2.ce-3.el7.x86_64.rpm: Header V4 RSA/SHA512 Signature, key ID 621e9f35: NOKEY
Public key for docker-ce-18.06.2.ce-3.el7.x86_64.rpm is not installed
(2/2): docker-ce-18.06.2.ce-3.el7.x86_64.rpm                                     |  41 MB  00:00:06     
--------------------------------------------------------------------------------------------------------
Total                                                                   6.6 MB/s |  41 MB  00:00:06     
Retrieving key from https://download.docker.com/linux/centos/gpg
Importing GPG key 0x621E9F35:
 Userid     : "Docker Release (CE rpm) "
 Fingerprint: 060a 61c5 1b55 8a7f 742b 77aa c52f eb6b 621e 9f35
 From       : https://download.docker.com/linux/centos/gpg
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : 2:container-selinux-2.74-1.el7.noarch                                                1/2 
  Installing : docker-ce-18.06.2.ce-3.el7.x86_64                                                    2/2 
  Verifying  : docker-ce-18.06.2.ce-3.el7.x86_64                                                    1/2 
  Verifying  : 2:container-selinux-2.74-1.el7.noarch                                                2/2 

Installed:
  docker-ce.x86_64 0:18.06.2.ce-3.el7                                                                   

Dependency Installed:
  container-selinux.noarch 2:2.74-1.el7                                                                 

Complete!
[root@kubeadm ~]# 
[root@kubeadm ~]# mkdir /etc/docker
[root@kubeadm ~]# 
[root@kubeadm ~]# cat > /etc/docker/daemon.json  {
>   "exec-opts": ["native.cgroupdriver=systemd"],
>   "log-driver": "json-file",
>   "log-opts": {
>     "max-size": "100m"
>   },
>   "storage-driver": "overlay2",
>   "storage-opts": [
>     "overlay2.override_kernel_check=true"
>   ]
> }
> EOF
[root@kubeadm ~]# 
[root@kubeadm ~]# mkdir -p /etc/systemd/system/docker.service.d
[root@kubeadm ~]# 
[root@kubeadm ~]# systemctl daemon-reload
[root@kubeadm ~]# 
[root@kubeadm ~]# systemctl restart docker
[root@kubeadm ~]# 
[root@kubeadm ~]# systemctl status docker
* docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
   Active: active (running) since Thu 2019-03-07 11:56:19 JST; 4s ago
     Docs: https://docs.docker.com
 Main PID: 7422 (dockerd)
    Tasks: 21
   Memory: 44.7M
   CGroup: /system.slice/docker.service
           |-7422 /usr/bin/dockerd
           `-7431 docker-containerd --config /var/run/docker/containerd/containerd.toml

Mar 07 11:56:18 kubeadm.example.com dockerd[7422]: time="2019-03-07T11:56:18.305985178+09:00" leve...rpc
Mar 07 11:56:18 kubeadm.example.com dockerd[7422]: time="2019-03-07T11:56:18.306216582+09:00" leve...rpc
Mar 07 11:56:18 kubeadm.example.com dockerd[7422]: time="2019-03-07T11:56:18.306243704+09:00" leve...t."
Mar 07 11:56:18 kubeadm.example.com dockerd[7422]: time="2019-03-07T11:56:18.732774215+09:00" leve...ss"
Mar 07 11:56:19 kubeadm.example.com dockerd[7422]: time="2019-03-07T11:56:19.045417032+09:00" leve...e."
Mar 07 11:56:19 kubeadm.example.com dockerd[7422]: time="2019-03-07T11:56:19.071730599+09:00" leve...-ce
Mar 07 11:56:19 kubeadm.example.com dockerd[7422]: time="2019-03-07T11:56:19.072347884+09:00" leve...on"
Mar 07 11:56:19 kubeadm.example.com dockerd[7422]: time="2019-03-07T11:56:19.082319539+09:00" leve...TH"
Mar 07 11:56:19 kubeadm.example.com dockerd[7422]: time="2019-03-07T11:56:19.100100644+09:00" leve...ck"
Mar 07 11:56:19 kubeadm.example.com systemd[1]: Started Docker Application Container Engine.
Hint: Some lines were ellipsized, use -l to show in full.
[root@kubeadm ~]# 
[root@kubeadm ~]# systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.

■kubeadm, kubelet, kubectl のインストール

最後に、kubeadm, kubelet, kubectl のインストールです。

こちらのドキュメントを参考にしてインストールします。

[root@kubeadm ~]# cat  /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
> exclude=kube*
> EOF
[root@kubeadm ~]# 
[root@kubeadm ~]# setenforce 0
[root@kubeadm ~]# 
[root@kubeadm ~]# getenforce 
Permissive
[root@kubeadm ~]# 
[root@kubeadm ~]# sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
[root@kubeadm ~]# 
[root@kubeadm ~]# grep SELINUX /etc/selinux/config 
# SELINUX= can take one of these three values:
SELINUX=permissive
# SELINUXTYPE= can take one of three values:
SELINUXTYPE=targeted 
[root@kubeadm ~]# 
[root@kubeadm ~]# yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
Loaded plugins: fastestmirror, langpacks
Loading mirror speeds from cached hostfile
 * base: ftp.riken.jp
 * extras: ftp.riken.jp
 * updates: ftp.riken.jp
kubernetes/signature                                                             |  454 B  00:00:00     
Retrieving key from https://packages.cloud.google.com/yum/doc/yum-key.gpg
Importing GPG key 0xA7317B0F:
 Userid     : "Google Cloud Packages Automatic Signing Key "
 Fingerprint: d0bc 747f d8ca f711 7500 d6fa 3746 c208 a731 7b0f
 From       : https://packages.cloud.google.com/yum/doc/yum-key.gpg
Retrieving key from https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
kubernetes/signature                                                             | 1.4 kB  00:00:00 !!! 
kubernetes/primary                                                               |  45 kB  00:00:00     
kubernetes                                                                                      323/323


~(中略)~


Installed:
  kubeadm.x86_64 0:1.13.4-0         kubectl.x86_64 0:1.13.4-0         kubelet.x86_64 0:1.13.4-0        

Dependency Installed:
  conntrack-tools.x86_64 0:1.4.4-4.el7                cri-tools.x86_64 0:1.12.0-0                       
  kubernetes-cni.x86_64 0:0.6.0-0                     libnetfilter_cthelper.x86_64 0:1.0.0-9.el7        
  libnetfilter_cttimeout.x86_64 0:1.0.0-6.el7         libnetfilter_queue.x86_64 0:1.0.2-2.el7_2         
  socat.x86_64 0:1.7.3.2-2.el7                       

Complete!
[root@kubeadm ~]# 
[root@kubeadm ~]# systemctl enable --now kubelet
Created symlink from /etc/systemd/system/multi-user.target.wants/kubelet.service to /etc/systemd/system/kubelet.service.
[root@kubeadm ~]# 
[root@kubeadm ~]# sysctl --system
* Applying /usr/lib/sysctl.d/00-system.conf ...
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0
* Applying /usr/lib/sysctl.d/10-default-yama-scope.conf ...
kernel.yama.ptrace_scope = 0
* Applying /usr/lib/sysctl.d/50-default.conf ...
kernel.sysrq = 16
kernel.core_uses_pid = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.promote_secondaries = 1
net.ipv4.conf.all.promote_secondaries = 1
fs.protected_hardlinks = 1
fs.protected_symlinks = 1
* Applying /usr/lib/sysctl.d/60-libvirtd.conf ...
fs.aio-max-nr = 1048576
* Applying /etc/sysctl.d/99-sysctl.conf ...
* Applying /etc/sysctl.d/k8s.conf ...
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
* Applying /etc/sysctl.conf ...
[root@kubeadm ~]# 
[root@kubeadm ~]# sysctl -a 2>&1 | grep net.bridge.bridge-nf-call-ip
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1

これで、必要なパッケージ (コンポーネント) のインストールは完了です。

■Kubernetes の起動

それではいよいよ、Kubernetes を起動してみます。

ドキュメントを参考にしながら、先ほどインストールした kubeadm にいくつかのオプションを指定し、実行します。

[root@kubeadm ~]# kubeadm init --apiserver-advertise-address=10.1.1.146 --pod-network-cidr=10.244.0.0/16
[init] Using Kubernetes version: v1.13.4
[preflight] Running pre-flight checks
        [WARNING Firewalld]: firewalld is active, please ensure ports [6443 10250] are open or your cluster may not function correctly
        [WARNING Hostname]: hostname "kubeadm.example.com" could not be reached
        [WARNING Hostname]: hostname "kubeadm.example.com": lookup kubeadm.example.com on 10.11.0.2:53: no such host
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Activating the kubelet service
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [kubeadm.example.com localhost] and IPs [10.1.1.146 127.0.0.1 ::1]
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [kubeadm.example.com localhost] and IPs [10.1.1.146 127.0.0.1 ::1]
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [kubeadm.example.com kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 10.1.1.146]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 24.003562 seconds
[uploadconfig] storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.13" in namespace kube-system with the configuration for the kubelets in the cluster
[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object "kubeadm.example.com" as an annotation
[mark-control-plane] Marking the node kubeadm.example.com as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node kubeadm.example.com as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: y38n58.r4tb9ghfa6gzhnrt
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstraptoken] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstraptoken] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstraptoken] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstraptoken] creating the "cluster-info" ConfigMap in the "kube-public" namespace
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

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 10.1.1.146:6443 --token y38n58.r4tb9ghfa6gzhnrt --discovery-token-ca-cert-hash sha256:5ff37a169c562349c5badb6802539e9edcb1017c72012c5eeb1e6e5f035983df

“Your Kubernetes master has initialized successfully!” と出力されれば、起動完了です。ただし、実際に利用するためにはもう少し作業を実施する必要があります。

まず、Kubernetes 用の CLI ツールである kubectl で先ほど起動した Kubernetes サーバに接続 (コマンドを送信) できるように、環境変数 KUBECONFIG を設定します。

[root@kubeadm ~]# echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile 
[root@kubeadm ~]# . ~/.bash_profile 
[root@kubeadm ~]# 
[root@kubeadm ~]# echo $KUBECONFIG
/etc/kubernetes/admin.conf
[root@kubeadm ~]# 
[root@kubeadm ~]# kubectl get node
NAME                  STATUS     ROLES    AGE     VERSION
kubeadm.example.com   NotReady   master   3m58s   v1.13.4

(今回は root ユーザで kubectl を利用する想定ですが、一般ユーザで kubectl を利用する場合は代わりに以下の様なコマンドを実行します)

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

次に、Kubernetes クラスタ内のネットワーク (クラスタ内の Pod 間の通信を行うためのネットワーク) を構築するために、pod network add-on をインストールします。(複数の pod network add-on から選択することが可能ですが、今回は Flannel を利用します。)

[root@kubeadm ~]# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.extensions/kube-flannel-ds-amd64 created
daemonset.extensions/kube-flannel-ds-arm64 created
daemonset.extensions/kube-flannel-ds-arm created
daemonset.extensions/kube-flannel-ds-ppc64le created
daemonset.extensions/kube-flannel-ds-s390x created

最後に、Master Node に (システムコンポーネントではない) ユーザ作成の Pod をデプロイできるようにするために、Master Node に設定されている Taint の設定を外します。(デフォルトだと、ユーザ作成の Pod は Master Node にデプロイされません。今回は Master Node 1台のシングルノード構成であるため、この作業が必要です。)

[root@kubeadm ~]# kubectl taint nodes --all node-role.kubernetes.io/master-
node/kubeadm.example.com untainted
[root@kubeadm ~]# 

これで、全ての作業が完了です。

特に問題がなければ、kubectl コマンドを使って以下の様にバージョン情報やシステムコンポーネント (Pod) の情報を取得することができるはずです。

[root@kubeadm ~]# kubectl version
Client Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.4", GitCommit:"c27b913fddd1a6c480c229191a087698aa92f0b1", GitTreeState:"clean", BuildDate:"2019-02-28T13:37:52Z", GoVersion:"go1.11.5", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.4", GitCommit:"c27b913fddd1a6c480c229191a087698aa92f0b1", GitTreeState:"clean", BuildDate:"2019-02-28T13:30:26Z", GoVersion:"go1.11.5", Compiler:"gc", Platform:"linux/amd64"}
[root@kubeadm ~]# kubectl get all -n kube-system
NAME                                              READY   STATUS             RESTARTS   AGE
pod/coredns-86c58d9df4-5zxzt                      0/1     CrashLoopBackOff   25         100m
pod/coredns-86c58d9df4-pqmf8                      0/1     CrashLoopBackOff   25         100m
pod/etcd-kubeadm.example.com                      1/1     Running            0          99m
pod/kube-apiserver-kubeadm.example.com            1/1     Running            0          99m
pod/kube-controller-manager-kubeadm.example.com   1/1     Running            0          99m
pod/kube-flannel-ds-amd64-kbtvn                   1/1     Running            0          96m
pod/kube-proxy-rdkjm                              1/1     Running            0          100m
pod/kube-scheduler-kubeadm.example.com            1/1     Running            0          99m

NAME               TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
service/kube-dns   ClusterIP   10.96.0.10           53/UDP,53/TCP   100m

NAME                                     DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                     AGE
daemonset.apps/kube-flannel-ds-amd64     1         1         1       1            1           beta.kubernetes.io/arch=amd64     96m
daemonset.apps/kube-flannel-ds-arm       0         0         0       0            0           beta.kubernetes.io/arch=arm       96m
daemonset.apps/kube-flannel-ds-arm64     0         0         0       0            0           beta.kubernetes.io/arch=arm64     96m
daemonset.apps/kube-flannel-ds-ppc64le   0         0         0       0            0           beta.kubernetes.io/arch=ppc64le   96m
daemonset.apps/kube-flannel-ds-s390x     0         0         0       0            0           beta.kubernetes.io/arch=s390x     96m
daemonset.apps/kube-proxy                1         1         1       1            1                                       100m

NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/coredns   0/2     2            0           100m

NAME                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/coredns-86c58d9df4   2         2         0       100m

■動作確認

前述した方法で構築した Kubernetes クラスタを利用して NGINX コンテナを利用した動作検証を実施してみます。

今回は、以下の様なマニフェスト (YAML ファイル) を作成し、kubectl apply コマンドで適用します。

[root@kubeadm ~]# cat  ~/k8s-yaml/nginx-test.yaml
> apiVersion: v1
> kind: Service
> metadata:
>   name: nginx-test-service
>   labels:
>     app: nginx-test
> spec:
>   selector:
>     app: nginx-test
>   type: NodePort
>   ports:
>   - protocol: TCP 
>     port: 80
>     targetPort: 80
>     nodePort: 30080
> ---
> apiVersion: apps/v1
> kind: Deployment
> metadata:
>   name: nginx-test-deployment
> spec:
>   replicas: 3
>   selector:
>     matchLabels:
>       app: nginx-test
>   template:
>     metadata:
>       labels:
>         app: nginx-test
>     spec:
>       containers:
>       - name: nginx-container
>         image: nginx:1.15.9
>         ports:
>         - containerPort: 80
>         lifecycle:
>           postStart:
>             exec:
>               command:
>                 - /bin/sh
>                 - -c
>                 - echo "NGINX container!" > /usr/share/nginx/html/index.html && echo "Pod name is \$(hostname) ." >> /usr/share/nginx/html/index.html
> EOF
[root@kubeadm ~]# 
[root@kubeadm ~]# kubectl apply -f ~/k8s-yaml/nginx-test.yaml 
service/nginx-test-service created
deployment.apps/nginx-test-deployment created

マニフェストの詳細は割愛しますが、大雑把に説明すると以下の様な設定を実施しています。

・NGINX コンテナ (Pod) を 3つデプロイ。
・Kubernetes をインストールした仮想サーバの 30080番 port 宛の通信を、いずれかの NGINX コンテナの 80番 port に転送。

また、どの NGINX コンテナ (Pod) からのレスポンスであるかを判断できるように、Pod 名をレスポンス (index.html) に含めるようにしています。

デプロイが完了すると、各リソースの状態が以下の様になると思います。

[root@kubeadm ~]# kubectl get service
NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes           ClusterIP   10.96.0.1                443/TCP        38m
nginx-test-service   NodePort    10.106.224.109           80:30080/TCP   31s
[root@kubeadm ~]# 
[root@kubeadm ~]# kubectl get deployment
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
nginx-test-deployment   3/3     3            3           37s
[root@kubeadm ~]# 
[root@kubeadm ~]# kubectl get pod
NAME                                     READY   STATUS    RESTARTS   AGE
nginx-test-deployment-56fdfc565c-8n4mr   1/1     Running   0          39s
nginx-test-deployment-56fdfc565c-btx4x   1/1     Running   0          39s
nginx-test-deployment-56fdfc565c-v4gnd   1/1     Running   0          39s

それでは、実際に Kubernetes をインストールした仮想サーバの 30080番 port 宛てに HTTP リクエストを投げてみます。

[root@kubeadm ~]# curl -XGET https://10.1.1.146:30080/
NGINX container!
Pod name is nginx-test-deployment-56fdfc565c-v4gnd .
[root@kubeadm ~]# 
[root@kubeadm ~]# curl -XGET https://10.1.1.146:30080/
NGINX container!
Pod name is nginx-test-deployment-56fdfc565c-btx4x .
[root@kubeadm ~]# 
[root@kubeadm ~]# curl -XGET https://10.1.1.146:30080/
NGINX container!
Pod name is nginx-test-deployment-56fdfc565c-btx4x .
[root@kubeadm ~]# 
[root@kubeadm ~]# curl -XGET https://10.1.1.146:30080/
NGINX container!
Pod name is nginx-test-deployment-56fdfc565c-v4gnd .
[root@kubeadm ~]# 
[root@kubeadm ~]# curl -XGET https://10.1.1.146:30080/
NGINX container!
Pod name is nginx-test-deployment-56fdfc565c-8n4mr .
[root@kubeadm ~]# 
[root@kubeadm ~]# curl -XGET https://10.1.1.146:30080/
NGINX container!
Pod name is nginx-test-deployment-56fdfc565c-8n4mr .

すると、上記の様に正常に HTTP レスポンスが返ってきました。

何回かリクエストを実行すると、レスポンスに含まれている Pod 名が変わっている (複数の NGINX コンテナ宛てにリクエストが振り分けられている) ことも確認できます。

■まとめ

今回は、kubeadm を利用して “できるだけ” シンプルかつ簡単にシングルノード構成の Kubernetes クラスタを構築してみましたが、インストールから起動までそれなりの数の手順があり、”yum でインストールして systemctl で起動” 程のお手軽感ではありませんでした。

しかし、多少手間はかかってしまいますが、オンプレ環境の仮想サーバ上に Kubernetes をインストールして簡単な動作検証を実施することができました。仮想サーバ 1台のみで構築することができ、複数台の仮想サーバを用意する必要もありません。

今回の様なシングルノード構成の場合、Pod のスケジューリングやノード障害発生時の動作等、一部の機能の動作検証を実施することはできませんが、個人での検証や学習用途として試してみるのには丁度良いのではないでしょうか。

また、本記事を作成中に Kubernetes v1.14 がリリースされたため、機会があれば新しいバージョンでも検証を実施してみようと思います。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

2人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です