kun432's blog

Alexaなどスマートスピーカーの話題中心に、Voiceflowの日本語情報を発信してます。たまにAWSやkubernetesなど。

〜スマートスピーカーやVoiceflowの記事は右メニューのカテゴリからどうぞ。〜

kubeadm on Vagrantでマルチマスターやってみた②

2020/3/15追記: kubeadm init後のmasterの状態と--upload-certsについて、id:endu-lucy 様にコメントを頂き、再度確認したところご指摘どおりでした。内容を修正しました。ご指摘ありがとうございました!

ちょっと間が開きましたが続きです。

前回、一通りのサーバをVagrantで用意したのでいよいよクラスタを作っていきます。環境おさらい。

f:id:kun432:20200224235455p:plain

controller-0

まずはmasterの1台目となるcontroller-0から。まずcontroller-0にsshでログインします。

$ vagrant ssh controller-0

kubeadm initでクラスタを初期化します。vagrantユーザで実行するのでsudoをお忘れなく。

$ sudo kubeadm init \
  --control-plane-endpoint="10.240.0.40:6443" \
  --apiserver-advertise-address="10.240.0.10" \
  --kubernetes-version="v1.17.3" \
  --pod-network-cidr="192.168.0.0/16" \
  --upload-certs | sudo tee -a /etc/kubernetes/kubeadm-init.result

少しだけ解説

  • --kubernetes-versionはstableを指定している場合がありますが、バージョンコントロールは自分であるということで厳密にバージョン指定しています。
  • --apiserver-advertise-addressはノードのIPアドレスを指定します。Vagrantでは10.0.2.15というNATインタフェースがあるのですが、これはVMからホストを経由してインターネットに抜けるためのインタフェースであり、ノード間の通信には使えません。kubeadm initするとこのインタフェースがデフォルトでapiserverにbindされてしまうため、明示的に指定しています。
  • --control-plane-endpointはmasterの負荷分散代表IPアドレスとなる、haproxyのIPとポートを指定します。
  • --pod-network-cidrは、Calicoのデフォルトである192.168.0.0/16を指定しています。これがpodに払い出されるIPアドレスになります。
  • --upload-certsで、2台め以降のmasterをjoinさせる場合に必要となる証明書をsecretに保存します。これにより、証明書の受け渡しが不要になります。
  • 出力結果が後で必要になるのでteeでファイルに出力しています。

ズラッとログが流れます。

W0309 15:26:39.649323   21845 validation.go:28] Cannot validate kube-proxy config - no validator is available
W0309 15:26:39.649374   21845 validation.go:28] Cannot validate kubelet config - no validator is available
[init] Using Kubernetes version: v1.17.3
[preflight] Running pre-flight checks
[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] Starting the kubelet
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [controller-0 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 10.240.0.10 10.240.0.40]
[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 "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [controller-0 localhost] and IPs [10.240.0.10 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [controller-0 localhost] and IPs [10.240.0.10 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-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"
W0309 15:26:45.391175   21845 manifests.go:214] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
W0309 15:26:45.392823   21845 manifests.go:214] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC"
[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 19.508153 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.17" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
9bad123e7d9a2f08532be35d84cd003021104421c5b5ba7a7d0239326101386a
[mark-control-plane] Marking the node controller-0 as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node controller-0 as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: cytl2k.i235yw3fiitpehgh
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane 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 the control-plane node running the following command on each as root:

  kubeadm join 10.240.0.40:6443 --token cytl2k.i235yw3fiitpehgh \
    --discovery-token-ca-cert-hash sha256:45de4e89c9f663d716dda514fda815a23e869f55fd18b68efef19afa10e6f82b \
    --control-plane --certificate-key 9bad123e7d9a2f08532be35d84cd003021104421c5b5ba7a7d0239326101386a

Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
"kubeadm init phase upload-certs --upload-certs" to reload certs afterward.

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 10.240.0.40:6443 --token cytl2k.i235yw3fiitpehgh \
    --discovery-token-ca-cert-hash sha256:45de4e89c9f663d716dda514fda815a23e869f55fd18b68efef19afa10e6f82b

Your Kubernetes control-plane has initialized successfully!と表示されていれば一旦はOKです。vagrantの場合、確認しておくべきなのはapiserverのbindアドレスです。ここが必ず10.0.2.15ではなく10.240.0.Xのアドレスになっていることを確認してください。

$ ps auxw | grep apiserver
root     10726  5.6 16.7 495072 316048 ?       Ssl  14:22   0:11 kube-apiserver --advertise-address=10.240.0.10 ・・・

では、kubeadm initの出力結果に従って設定を行っていきます。kubectlコマンドが実行できるようにKUBECONFIGの設定を行います。kubeadmi init で出力された/etc/kubernetes/admin.confをvagrantユーザの.kube/configとしてコピーします。

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

コマンドが実行できるか試してみましょう。kubectl get node でノードの状態を確認してみます。

$ kubectl get node
NAME           STATUS   ROLES    AGE     VERSION
controller-0  Not Ready    master   2m15s   v1.17.3

controller-0がmasterになっています。STATUSがNotReadyとなっていますが、CNIの設定を行っていないためですので問題ありません。では、続いてCNIの設定を行います。CNIは今回Calicoを使います。Calicoもバージョンはコントロールしたいと思うので、現在の最新版であるv3.13のmanifestをダウンロードしてきてkubectl applyします。

$ curl https://docs.projectcalico.org/v3.13/manifests/calico.yaml -o calico-v3.13.yaml
$ kubectl apply -f calico-v3.13.yaml
configmap/calico-config created
customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created
clusterrole.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrolebinding.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrole.rbac.authorization.k8s.io/calico-node created
clusterrolebinding.rbac.authorization.k8s.io/calico-node created
daemonset.apps/calico-node created
serviceaccount/calico-node created
deployment.apps/calico-kube-controllers created
serviceaccount/calico-kube-controllers created

再度kubectlでnodeの状態を見てみるとReadyになりました。もしなっていない場合は-wをつけてkubectl get nodeを実行して待ってみてください。

$ kubectl get node
NAME           STATUS   ROLES    AGE     VERSION
controller-0   Ready    master   4m34s   v1.17.3

では現時点で立ち上がっているpodを見てみましょう。

$ kubectl get pod
No resources found in default namespace.

何も出ませんね。というのも、kubernetesにはnamespaceの概念があり、namespaceごとにリソースを分けることができます。デフォルトだとdefaultというname spaceが選択されているので何も見えません。そこで--all-namespacesをつけてすべてのnamespacesをまたいでpodを見てみましょう。

$ kubectl get pod --all-namespaces
NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-68dc4cf88f-7rvrd   1/1     Running   0          35s
kube-system   calico-node-6f84m                          1/1     Running   0          35s
kube-system   coredns-6955765f44-s7pvx                   1/1     Running   0          4m3s
kube-system   coredns-6955765f44-wm9lq                   1/1     Running   0          4m3s
kube-system   etcd-controller-0                          1/1     Running   0          4m17s
kube-system   kube-apiserver-controller-0                1/1     Running   0          4m18s
kube-system   kube-controller-manager-controller-0       1/1     Running   0          4m18s
kube-system   kube-proxy-56kmh                           1/1     Running   0          4m2s
kube-system   kube-scheduler-controller-0                1/1     Running   0          4m18s

いくつか立ち上がっていてRunningになっていますね!ちなみにkube-systemというnamespaceはデフォルトでkubernetesが使うシステム的なnamespaceのようです。calicoのpodもあがっていますね。

1台目のmasterの構築はこれで完了ですが、残り2台のmasterのための準備を行います。

/etc/kubernetesの下に作成されている以下の証明書等のファイルをtarで固めます。

$ cd /
$ sudo tar cvfz /Vagrant/master-pki.tar.gz \
   /etc/kubernetes/pki/ca.crt \
   /etc/kubernetes/pki/ca.key \
   /etc/kubernetes/pki/sa.key \
   /etc/kubernetes/pki/sa.pub \
   /etc/kubernetes/pki/front-proxy-ca.crt \
   /etc/kubernetes/pki/front-proxy-ca.key \
   /etc/kubernetes/pki/etcd/ca.crt \
   /etc/kubernetes/pki/etcd/ca.key \
   /etc/kubernetes/admin.conf

出力先はVagrantfileで設定した共有ディレクトリにします。これで残りのmasterからも参照できるというわけですね。

では引き続き残りのmasterの構築を行います。

controller-1/controller-2

残り2台のmasterの構築手順は同じです。順次実施してください。

まずsshでログインします。

$ vagrant ssh controller-1

先程1台目のmasterで取得したtarファイルを同じ場所に展開します。

$ cd /
$ sudo tar xvfz /Vagrant/master-pki.tar.gz

準備はOKです。ではクラスタに追加します。masterの1台目でkubeadm initの出力に以下のような出力があったと思います。

  kubeadm join 10.240.0.40:6443 --token cytl2k.i235yw3fiitpehgh \
    --discovery-token-ca-cert-hash sha256:45de4e89c9f663d716dda514fda815a23e869f55fd18b68efef19afa10e6f82b \
    --control-plane --certificate-key 9bad123e7d9a2f08532be35d84cd003021104421c5b5ba7a7d0239326101386a

似たような出力があったと思いますが、--control-planeがついている方がmaster追加用のコマンドになります。このコマンドを実行するだけでmasterの追加ができちゃうのですね。では早速やっていきたいところですが、一つだけオプションを追加しましょう。

masterでkubeadm initを実行したときに以下のオプションを付けています。

--apiserver-advertise-address="10.240.0.10" \

masterのときにも説明したとおり、これはVagrantの場合のworkaroundなのですが、2台目以降のmasterを追加する場合も必要になります。これをつけないとうまくいきません。ということで、このオプションのIPアドレスをそれぞれのmasterのIPアドレスに合わせて、追加します。

$  sudo kubeadm join 10.240.0.40:6443 --token cytl2k.i235yw3fiitpehgh \
    --discovery-token-ca-cert-hash sha256:45de4e89c9f663d716dda514fda815a23e869f55fd18b68efef19afa10e6f82b \
    --control-plane --certificate-key 9bad123e7d9a2f08532be35d84cd003021104421c5b5ba7a7d0239326101386a \
    --apiserver-advertise-address="10.240.0.11"

こちらもズラッとログが出ます。

[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
[preflight] Running pre-flight checks before initializing the new control plane instance
[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'
[download-certs] Downloading the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [controller-1 localhost] and IPs [10.240.0.11 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [controller-1 localhost] and IPs [10.240.0.11 127.0.0.1 ::1]
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [controller-1 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 10.240.0.11 10.240.0.40]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Valid certificates and keys now exist in "/etc/kubernetes/pki"
[certs] Using the existing "sa" key
[kubeconfig] Generating kubeconfig files
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/admin.conf"
[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"
W0309 15:36:38.896510   10210 manifests.go:214] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
W0309 15:36:38.903042   10210 manifests.go:214] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC"
[control-plane] Creating static Pod manifest for "kube-scheduler"
W0309 15:36:38.903777   10210 manifests.go:214] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC"
[check-etcd] Checking that the etcd cluster is healthy
[kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.17" ConfigMap in the kube-system namespace
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
[etcd] Announced new etcd member joining to the existing etcd cluster
[etcd] Creating static Pod manifest for "etcd"
[etcd] Waiting for the new etcd member to join the cluster. This can take up to 40s
{"level":"warn","ts":"2020-03-09T15:37:01.654Z","caller":"clientv3/retry_interceptor.go:61","msg":"retrying of unary invoker failed","target":"passthrough:///https://10.240.0.11:2379","attempt":0,"error":"rpc error: code = DeadlineExceeded desc = context deadline exceeded"}
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[mark-control-plane] Marking the node controller-1 as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node controller-1 as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]

This node has joined the cluster and a new control plane instance was created:

* Certificate signing request was sent to apiserver and approval was received.
* The Kubelet was informed of the new secure connection details.
* Control plane (master) label and taint were applied to the new node.
* The Kubernetes control plane instances scaled up.
* A new etcd member was added to the local/stacked etcd cluster.

To start administering your cluster from this node, 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

Run 'kubectl get nodes' to see this node join the cluster.

ちょっとwarningが出ていますが、一旦気にせず行きます。

masterの1台目でノードの状態を確認します。

$ kubectl get node
NAME           STATUS   ROLES    AGE   VERSION
controller-0   Ready    master   39m   v1.17.3
controller-1   Ready    master   29m   v1.17.3

controller-1が追加されてReadyになっていますね!

1台目と同じようにkubectlを使えるようにしておきましょう。

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

これで完了です。同じようにして3台目のmasterも追加してください。

次はworkerです。

worker-0/1/2

workerはすべて同じ手順になりますので、順次実行してください。

まずsshでログインします。

$ vagrant ssh worker-0

そしてkubeadm initで出力されていた以下コマンドを実行するだけです。

kubeadm join 10.240.0.40:6443 --token cytl2k.i235yw3fiitpehgh \
    --discovery-token-ca-cert-hash sha256:45de4e89c9f663d716dda514fda815a23e869f55fd18b68efef19afa10e6f82b

こちらは特にオプションを追加する必要はありません。早速実行します。

$ sudo kubeadm join 10.240.0.40:6443 --token cytl2k.i235yw3fiitpehgh \
    --discovery-token-ca-cert-hash sha256:45de4e89c9f663d716dda514fda815a23e869f55fd18b68efef19afa10e6f82b
W0309 16:15:36.331600    9954 join.go:346] [preflight] WARNING: JoinControlPane.controlPlane settings will be ignored when control-plane flag is not set.
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
[kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.17" ConfigMap in the kube-system namespace
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

以上です。workerはかんたんですね。masterでkubectlを実行してノードの状態を見てみましょう。

$ kubectl get node
NAME           STATUS   ROLES    AGE     VERSION
controller-0   Ready    master   49m     v1.17.3
controller-1   Ready    master   39m     v1.17.3
controller-2   Ready    master   4m48s   v1.17.3
worker-0       Ready    <none>   49s     v1.17.3

worker-0がReadyになっていますね。これでOKです。

あとは残りのworkerも同様に追加してください。最終的にこうなればOKです。

$ kubectl get node
NAME           STATUS   ROLES    AGE     VERSION
controller-0   Ready    master   51m     v1.17.3
controller-1   Ready    master   41m     v1.17.3
controller-2   Ready    master   6m49s   v1.17.3
worker-0       Ready    <none>   2m50s   v1.17.3
worker-1       Ready    <none>   49s     v1.17.3
worker-2       Ready    <none>   36s     v1.17.3

podを動かしてみる

とりあえずこれでマルチmasterなkubernetesクラスタが構築できました。ではここからサンプルを少し動かしてみましょう。kuberenetesのベーシックチュートリアルにあるnode.jsウェブアプリを動かしてみたいと思います。

controller-0に入ります。

$ kubectl run kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1 --port=8080
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/kubernetes-bootcamp created

ちょっとwarningが出ますが気にしないで進めます。podの状態を確認してみます。

$ kubectl get pod
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-765bf4c7b4-rq5ds   1/1     Running   0          61s

なんか動いてますね!では公開してアクセスできるようにします。

$ kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
service/kubernetes-bootcamp exposed
$ kubectl get service
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes            ClusterIP   10.96.0.1       <none>        443/TCP          75m
kubernetes-bootcamp   NodePort    10.103.19.224   <none>        8080:30771/TCP   3s

30771というのがノードに紐付けられたポート番号になります。これでworkerノードIP:ポート番号でアクセスできます。ブラウザからアクセスしてみましょう。

f:id:kun432:20200310014620p:plain

表示されていますね。workerノードのIPアドレスを変更しても表示されますので、内部的にロードバランシングされているということですね。

次にスケールアウトさせてみます。

$ kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1/1     1            1           21m
$ kubectl get rs
NAME                             DESIRED   CURRENT   READY   AGE
kubernetes-bootcamp-765bf4c7b4   1         1         1       21m

今はpodが1台だけ起動させるようになっています。これを4台に増やしてみます。

$ kubectl scale deployments/kubernetes-bootcamp --replicas=4
deployment.apps/kubernetes-bootcamp scaled
$  kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   2/4     4            2           23m

起動対象が4台になり現在2台になってます。残りの2台は起動中ですね。ちょっとまってから、podの状態を確認してみます。

$ kubectl get pods -o wide
NAME                                   READY   STATUS    RESTARTS   AGE   IP                NODE       NOMINATED NODE   READINESS GATES
kubernetes-bootcamp-765bf4c7b4-2z8sg   1/1     Running   0          76s   192.168.226.65    worker-1   <none>           <none>
kubernetes-bootcamp-765bf4c7b4-k6nc7   1/1     Running   0          76s   192.168.43.1      worker-0   <none>           <none>
kubernetes-bootcamp-765bf4c7b4-rq5ds   1/1     Running   0          25m   192.168.133.193   worker-2   <none>           <none>
kubernetes-bootcamp-765bf4c7b4-w8q6d   1/1     Running   0          76s   192.168.133.194   worker-2   <none>           <none>

はい、4台起動していて、それぞれのworkerにうまく分散されているのがわかるでしょうか。ブラウザで開いてみても違うpodにアクセスしてるのがわかるかと思います。

f:id:kun432:20200310015939p:plain f:id:kun432:20200310020053p:plain

最後にpodを1台停止してみましょう。

$ kubectl get pod
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-765bf4c7b4-2z8sg   1/1     Running   0          8m52s
kubernetes-bootcamp-765bf4c7b4-k6nc7   1/1     Running   0          8m52s
kubernetes-bootcamp-765bf4c7b4-rq5ds   1/1     Running   0          32m
kubernetes-bootcamp-765bf4c7b4-w8q6d   1/1     Running   0          8m52s
$ kubectl delete pod kubernetes-bootcamp-765bf4c7b4-rq5ds
pod "kubernetes-bootcamp-765bf4c7b4-rq5ds" deleted

もう一度podの状態を確認してみます。

$ kubectl get pod
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-765bf4c7b4-2z8sg   1/1     Running   0          10m
kubernetes-bootcamp-765bf4c7b4-jxjcl   1/1     Running   0          37s
kubernetes-bootcamp-765bf4c7b4-k6nc7   1/1     Running   0          10m
kubernetes-bootcamp-765bf4c7b4-w8q6d   1/1     Running   0          10m

また4台になっていますね。先程スケールアップした際に4台起動するのが理想という設定にしたので、1台が死んでもちゃんと4台になるようにまた起動するんですね、これは便利ですね。スクリーンショットは割愛しますが、停止したpodにアクセスしていたブラウザはリロードするとちゃんと別のpodが表示されていました。


ということで、kubeadmを使ったkubernetesクラスタ構築でした。hard wayに比べるとやっぱり楽ですね。もう少し自動化できるようにVagrantのプロビジョニングも修正していきます。

kubernetesクラスタができたので次回以降では色々試してみたいと思います。