こんにちは。サイオステクノロジー 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.1053/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.1443/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 がリリースされたため、機会があれば新しいバージョンでも検証を実施してみようと思います。