AWSでCentOS 7にKubernetes 1.11をkubeadmでインストール

お勉強のため、AWSにkubeadmでKubernetesをインストールしたメモ。

CentOS 7.5
Docker CE 17.03.2
Kubernetes 1.11.0

## 前提

スクラッチでインストールする方法やその他いろいろ方法があるが、kubeadmを使ってインストールする。

[Creating a single master cluster with kubeadm](https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/)

Master1台とNode2台の計3台構成でインストールすることにする。
各マシンの要件としては2GBのメモリと2コアとあるが、インスタンスタイプはt2.smallにする（CPU数が要件に達していないので本当はt2.mediumにした方がよい）。

|役割|ホスト名|インスタンスタイプ|
|---|---|---|
|Master|k8s-master|t2.small|
|Node|k8s-node1|t2.small|
|Node|k8s-node2|t2.small|

## クラスター作成の流れ

Dockerやkubeadmなどのインストールについては、MasterとNodeで共通なので、

1. MasterノードにDocker、kubeadm、kubelet、kubectlなどをインストール
1. Masterノードのマシンを複製してNodeのマシンを2台作成
1. kubeadmによるクラスターの作成

という流れで実施する。

## EC2インスタンスの作成の事前準備

### VPCの作成

（参考）
[0から始めるAWS入門①：VPC編](https://qiita.com/hiroshik1985/items/9de2dd02c9c2f6911f3b)

AWSコンソールでVPCを作成する。

|項目|値|
|---|---|
|名前タグ|k8s-vpc（任意）|
|IPv4 CIDRブロック|10.0.0.0/16|
|IPv6 CIDRブロック|なし|
|テナンシー|デフォルト|

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/5cdccb82-b363-17ed-5f2c-13e1bde76ab4.png)

### サブネットの作成

作成したVPCにサブネットを作成する。

|項目|値|
|---|---|
|名前タグ|k8s-subnet（任意）|
|VPC|（前のステップで作成したVPC）|
|アベイラビリティーゾーン|指定なし|
|IPv4 CIDRブロック|10.0.0.0/24|

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/2c684a63-1d0c-c609-dcbf-43f311dd3a9d.png)

### インターネットゲートウェイの作成

インターネットゲートウェイを作成する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/a9d4345c-2439-5c7f-92e0-dfc06790cbde.png)

作成したインターネットゲートウェイをVPCにアタッチする。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/9e6e91b5-612a-d5fd-2ca7-ad93537a3deb.png)

### ルートテーブルの追加

このままではまだインターネットから接続できないので、ルートテーブルを修正する。作成したVPCへのルートテーブルを選択し、設定を追加して保存する。

|送信先|ターゲット|
|---|---|
|0.0.0.0/0|（前のステップで作成したインターネットゲートウェイ）|

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/1d53193a-0052-09b9-1b15-932e7a79e642.png)

### セキュリティグループの作成

作成したVPCにセキュリティグループを作成する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/26ee3c24-f77e-152f-3485-c7d601a53ee9.png)

インバウンドのルールで、セキュリティグループ内の接続を許可するルールと、SSHを許可する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/e82815e5-05a8-79dd-efba-3c16f572f3d9.png)

## Masterマシンの作成

### EC2インスタンスの作成

（参考）
[0から始めるAWS入門②：EC2編](https://qiita.com/hiroshik1985/items/f078a6a017d092a541cf)

EC2インスタンスを作成する。
AMIは「CentOS 7 (x86_64) - with Updates HVM」を使用する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/884c70d9-357d-109e-2208-3ad5da026110.png)

インスタンスタイプはt2.smallにする。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/d80f08fa-9bed-2d89-03b2-2639ddf15841.png)

事前に作成したVPCを指定する。グローバルIPの自動割り当てを有効にする。

|項目|値|
|---|---|
|ネットワーク|（事前に作成したVPC）|
|サブネット|（事前に作成したサブネット）|
|自動割り当てパブリックIP|有効化|

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/457e9863-9244-ed8a-bed5-19a4a35287b0.png)

ストレージはどれくらい必要かわからないが、40GBで作成。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/cc4ec86d-27e9-5e48-a528-8ae281a18406.png)

Nameタグを追加しておく。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/7d319e1f-1d49-3b2c-8283-6011428814a2.png)

事前に作成したセキュリティグループを指定する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/48202417-b5d3-0c0b-e7ef-1c24b29d032d.png)

設定を確認して、作成する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/0b768205-3363-c410-9b72-aaa33ea05121.png)

### OS更新

作成したインスタンスにSSHログインし、OSを更新する。

```
$ sudo yum update
```

### hostname変更

以下のリンク先を参考に、ホスト名を更新する。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/linux-static-hostname-rhel7-centos7/

hostnamectlコマンドでホスト名を更新する。

```
$ sudo hostnamectl set-hostname --static k8s-master
```

再起動時にcloud.initでホスト名が変更されないようにするため、`/etc/cloud/cloud.cfg`を編集し、

```
$ sudo vi /etc/cloud/cloud.cfg
```

以下を追加する。

```
preserve_hostname: true
```

`/etc/hosts`でホスト名が解決できるようにしておく。

```
$ sudo vi /etc/hosts
```

```
10.0.0.33 k8s-master
```

一度再起動して、ログインし直す。

```
$ sudo reboot
```

### Dockerのインストール

CentOS標準でインストール可能なDockerはバージョンが古いので、Docker公式の手順に従ってDocker CEをインストールする。

https://docs.docker.com/install/linux/docker-ce/centos/

前提パッケージをインストールする。

```
$ sudo yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2
```

Docker CEのリポジトリをセットアップする。

```
$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
```

インストール可能なバージョンを確認する。

```
$ sudo yum list docker-ce --showduplicates | sort -r
```

推奨となっている17.03を指定してインストールする。バージョンを指定する場合は、同時にdocker-ce-selinuxも指定して`--setopt=obsoletes=0`オプションを指定してあげる必要がある。

（参考）
https://github.com/docker/for-linux/issues/20
https://github.com/moby/moby/issues/33930

```
$ sudo yum install -y --setopt=obsoletes=0 docker-ce-17.03.2.ce docker-ce-selinux-17.03.2.ce
```

DockerデーモンをOS起動時に自動起動するよう設定し、起動する。

```
$ sudo systemctl enable docker && sudo systemctl start docker
```

### kubeadmのインストール

以下の手順に従いkubeadmをインストールする。

https://kubernetes.io/docs/tasks/tools/install-kubeadm/

ここからはrootで作業する。

```
$ sudo -i
```

リポジトリを追加する。

```
# cat <<EOF > /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
EOF
```

SELinuxを無効化する。

```
# setenforce 0
```

再起動後もSELinuxが無効になるように設定する。

```
# vi /etc/sysconfig/selinux
```

```
#SELINUX=enforcing
SELINUX=permissive
```

kubelet、kubeadm、kubectlをインストールする。

```
# yum install -y kubelet kubeadm kubectl
```

kubeletデーモンをOS起動時に自動起動するよう設定し、起動する。

```
# systemctl enable kubelet && systemctl start kubelet
```

`net.bridge.bridge-nf-call-iptables`が`1`であることを確認する。`1`であったので特に何もしない。

```
[root@k8s-master ~]# sysctl -n net.bridge.bridge-nf-call-iptables
1
[root@k8s-master ~]#
```

cgroup driverが一致しているかを確認する。しかし`cgroup-driver`がそもそも定義されていないように見えるので、何もしない。

```
[root@k8s-master ~]# docker info | grep -i cgroup
Cgroup Driver: cgroupfs
[root@k8s-master ~]# cat /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
# Note: This dropin only works with kubeadm and kubelet v1.11+
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
EnvironmentFile=-/etc/sysconfig/kubelet
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS
[root@k8s-master ~]#
```

v1.11の新機能であるIPVSによるロードバランシングを使用できるようにするため、必要なカーネルモジュールをロードする。

```
# modprobe -v ip_vs
# modprobe -v ip_vs_rr
# modprobe -v ip_vs_wrr
# modprobe -v ip_vs_sh
```

再起動後もカーネルモジュールがロードされるようにする。

https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/system_administrators_guide/sec-persistent_module_loading

`/etc/modules-load.d/ip_vs.conf`を作成し、モジュールを列挙する。

```
# vi /etc/modules-load.d/ip_vs.conf
```

```:/etc/modules-load.d/ip_vs.conf
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
```

ここまでで前提ソフトウェアのインストールは完了なので、一旦マシンを停止する。

```
# shutdown -h now
```

## Nodeマシンの作成

### AMIイメージの作成

AWSコンソールで、MasterマシンからAMIを作成する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/65413679-de67-69c7-47fa-af38e8c2f5e1.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/d8dd02b1-6bb8-ffa1-d089-be4fecc9f964.png)

### EC2インスタンスの作成

作成したAMIから2台のEC2インスタンスを作成する。

- インスタンスタイプの選択
  - t2.smallを選択
- インスタンス詳細の設定
  - 事前に作成したVPCを指定
  - 事前に作成したサブネットを指定
  - 自動割り当てパブリックIPを有効化
- ストレージの追加
  - 40GBの汎用SSDをルートに割り当て
- タグの追加
  - Name=k8s-node1/2を追加
- セキュリティグループの設定
  - 事前に作成したセキュリティグループを選択

以下の作業は2台のNodeマシンそれぞれに対して実施する。

### ホスト名の変更

（Node1）

```
$ sudo hostnamectl set-hostname --static k8s-node1
```

（Node2）

```
$ sudo hostnamectl set-hostname --static k8s-node2
```

`/etc/hosts`を修正する。この作業はMasterに対しても実施する。

```:/etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

10.0.0.33 k8s-master
10.0.0.129 k8s-node1
10.0.0.84 k8s-node2
```

## kubeadmによるクラスターの作成

マシンの前提準備が整ったので、ここからkubeadmでクラスターの作成を行う。以下の手順に従う。

https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/

### Masterの初期化

Masterマシンで、Pod network add-on（今回はcalicoを使う）に応じたcidrを指定して初期化する。

（k8s-masterで実施）

```
$ sudo -i
# kubeadm init --pod-network-cidr=192.168.0.0/16
```

```
[root@k8s-master ~]# kubeadm init --pod-network-cidr=192.168.0.0/16
I0629 07:56:25.611847    2184 feature_gate.go:230] feature gates: &{map[]}
[init] using Kubernetes version: v1.11.0
[preflight] running pre-flight checks
I0629 07:56:25.643552    2184 kernel_validator.go:81] Validating kernel version
I0629 07:56:25.643612    2184 kernel_validator.go:96] Validating kernel config
[preflight/images] Pulling images required for setting up a Kubernetes cluster
[preflight/images] This might take a minute or two, depending on the speed of your internet connection
[preflight/images] You can also perform this action in beforehand using 'kubeadm config images pull'
[kubelet] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[preflight] Activating the kubelet service
[certificates] Generated ca certificate and key.
[certificates] Generated apiserver certificate and key.
[certificates] apiserver serving cert is signed for DNS names [k8s-master kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 10.0.0.33]
[certificates] Generated apiserver-kubelet-client certificate and key.
[certificates] Generated sa key and public key.
[certificates] Generated front-proxy-ca certificate and key.
[certificates] Generated front-proxy-client certificate and key.
[certificates] Generated etcd/ca certificate and key.
[certificates] Generated etcd/server certificate and key.
[certificates] etcd/server serving cert is signed for DNS names [k8s-master localhost] and IPs [127.0.0.1 ::1]
[certificates] Generated etcd/peer certificate and key.
[certificates] etcd/peer serving cert is signed for DNS names [k8s-master localhost] and IPs [10.0.0.33 127.0.0.1 ::1]
[certificates] Generated etcd/healthcheck-client certificate and key.
[certificates] Generated apiserver-etcd-client certificate and key.
[certificates] valid certificates and keys now exist in "/etc/kubernetes/pki"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/admin.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/kubelet.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/controller-manager.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/scheduler.conf"
[controlplane] wrote Static Pod manifest for component kube-apiserver to "/etc/kubernetes/manifests/kube-apiserver.yaml"
[controlplane] wrote Static Pod manifest for component kube-controller-manager to "/etc/kubernetes/manifests/kube-controller-manager.yaml"
[controlplane] wrote Static Pod manifest for component kube-scheduler to "/etc/kubernetes/manifests/kube-scheduler.yaml"
[etcd] Wrote Static Pod manifest for a local etcd instance to "/etc/kubernetes/manifests/etcd.yaml"
[init] waiting for the kubelet to boot up the control plane as Static Pods from directory "/etc/kubernetes/manifests"
[init] this might take a minute or longer if the control plane images have to be pulled
[apiclient] All control plane components are healthy after 43.002143 seconds
[uploadconfig] storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.11" in namespace kube-system with the configuration for the kubelets in the cluster
[markmaster] Marking the node k8s-master as master by adding the label "node-role.kubernetes.io/master=''"
[markmaster] Marking the node k8s-master as master by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object "k8s-master" as an annotation
[bootstraptoken] using token: s7cx0z.3bjs1lz5vyv7v5im
[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.0.0.33:6443 --token s7cx0z.3bjs1lz5vyv7v5im --discovery-token-ca-cert-hash sha256:1f84300a56b03c40ba9f6048e5d8e6ac0c8ccea77849c42b4c548a1f1abc784f

[root@k8s-master ~]#
```

コンソールに出力された`kubeadm join`コマンドは後で使うのでコピーしておく。

なお、エラーになったとかでkubeadmコマンドをやり直したい場合は`kubeadm reset`でリセット可能。

### kubectlのセットアップ

一般ユーザーで以下を実行する。

（k8s-masterで実施）

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

もし、rootユーザーでkubectlを実行する場合は以下のコマンドで環境変数をセットする。

```
# export KUBECONFIG=/etc/kubernetes/admin.conf
```

### Pod network add-onのインストール

Pod network add-onはcalicoを使う。以下の手順の「Installing with the Kubernetes API datastore—50 nodes or less」に従う。

https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/calico

```
$ kubectl apply -f \
  https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/rbac-kdd.yaml
```

```
$ kubectl apply -f \
  https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml
```

ノードがReadyになるのを待つ。

```
[centos@k8s-master ~]$ kubectl get nodes
NAME         STATUS    ROLES     AGE       VERSION
k8s-master   Ready     master    13m       v1.11.0
[centos@k8s-master ~]$
```

### Nodeをクラスターに追加

各ノードで先ほど表示された`kubeadm join`コマンドをrootユーザーで実行する。

（k8s-node1/k8s-node2で実施）

```
[root@k8s-node1 ~]# kubeadm join 10.0.0.33:6443 --token s7cx0z.3bjs1lz5vyv7v5im --discovery-token-ca-cert-hash sha256:1f84300a56b03c40ba9f6048e5d8e6ac0c8ccea77849c42b4c548a1f1abc784f
[preflight] running pre-flight checks
I0629 08:13:03.564865    2178 kernel_validator.go:81] Validating kernel version
I0629 08:13:03.564968    2178 kernel_validator.go:96] Validating kernel config
[discovery] Trying to connect to API Server "10.0.0.33:6443"
[discovery] Created cluster-info discovery client, requesting info from "https://10.0.0.33:6443"
[discovery] Requesting info from "https://10.0.0.33:6443" again to validate TLS against the pinned public key
[discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server "10.0.0.33:6443"
[discovery] Successfully established connection with API Server "10.0.0.33:6443"
[kubelet] Downloading configuration for the kubelet from the "kubelet-config-1.11" ConfigMap in the kube-system namespace
[kubelet] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[preflight] Activating the kubelet service
[tlsbootstrap] Waiting for the kubelet to perform the TLS Bootstrap...
[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object "k8s-node1" as an annotation

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

Run 'kubectl get nodes' on the master to see this node join the cluster.
[root@k8s-node1 ~]#
```

```
[root@k8s-node2 ~]# kubeadm join 10.0.0.33:6443 --token s7cx0z.3bjs1lz5vyv7v5im --discovery-token-ca-cert-hash sha256:1f84300a56b03c40ba9f6048e5d8e6ac0c8ccea77849c42b4c548a1f1abc784f
[preflight] running pre-flight checks
I0629 08:13:51.375427    2155 kernel_validator.go:81] Validating kernel version
I0629 08:13:51.375528    2155 kernel_validator.go:96] Validating kernel config
[discovery] Trying to connect to API Server "10.0.0.33:6443"
[discovery] Created cluster-info discovery client, requesting info from "https://10.0.0.33:6443"
[discovery] Requesting info from "https://10.0.0.33:6443" again to validate TLS against the pinned public key
[discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server "10.0.0.33:6443"
[discovery] Successfully established connection with API Server "10.0.0.33:6443"
[kubelet] Downloading configuration for the kubelet from the "kubelet-config-1.11" ConfigMap in the kube-system namespace
[kubelet] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[preflight] Activating the kubelet service
[tlsbootstrap] Waiting for the kubelet to perform the TLS Bootstrap...
[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object "k8s-node2" as an annotation

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

Run 'kubectl get nodes' on the master to see this node join the cluster.
[root@k8s-node2 ~]#
```

追加したノードがReadyになったことを確認する。

```
[centos@k8s-master ~]$ kubectl get nodes
NAME         STATUS    ROLES     AGE       VERSION
k8s-master   Ready     master    18m       v1.11.0
k8s-node1    Ready     <none>    2m        v1.11.0
k8s-node2    Ready     <none>    1m        v1.11.0
[centos@k8s-master ~]$
```

以上でクラスターの作成は完了。

## 稼働確認

Nginxのコンテナをデプロイしてアクセスしてみる。

### Nginxのデプロイ

以下のyamlファイルを作成する。簡単のためサービスはNodePortで公開する。

```yaml:nginx-depoyment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
```

```yaml:nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
```

リソースを作成する。

```
$ kubectl apply -f nginx-deployment.yaml
$ kubectl apply -f nginx-service.yaml
```

Podが稼働していることを確認する。

```
[centos@k8s-master ~]$ kubectl get po -o wide
NAME                     READY     STATUS    RESTARTS   AGE       IP            NODE
nginx-67594d6bf6-wbtck   1/1       Running   0          42s       192.168.2.6   k8s-node2
nginx-67594d6bf6-zdbff   1/1       Running   0          42s       192.168.1.5   k8s-node1
[centos@k8s-master ~]$
```

サービスのポートを確認する。

```
[centos@k8s-master ~]$ kubectl get svc -o wide
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE       SELECTOR
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP        2d        <none>
nginx        NodePort    10.110.164.204   <none>        80:31123/TCP   7m        app=nginx
[centos@k8s-master ~]$
```

### セキュリティグループの修正

外からのアクセスをSSHしか許可していなかったので、AWSコンソールでセキュリティグループのインバウンドルールを編集し、確認したServiceのポート（上記例では31123）へのアクセスを許可する。

ブラウザでいずれかのノードの上記のポートアクセスすると、Nginxの画面が表示される。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/86449/15614d0d-995e-e026-7453-148a0f36e3a1.png)

以上で稼働確認は終了。

## （参考）ノードをクラスターから除去

例えば、k8s-node2ノードをクラスターから除去する場合は以下の手順を実施する。

Masterノードで以下を実行。

```
$ kubectl drain k8s-node2 --delete-local-data --force --ignore-daemonsets
$ kubectl delete node k8s-node2
```

```
[centos@k8s-master ~]$ kubectl get nodes
NAME         STATUS    ROLES     AGE       VERSION
k8s-master   Ready     master    13h       v1.11.0
k8s-node1    Ready     <none>    12h       v1.11.0
k8s-node2    Ready     <none>    12h       v1.11.0
[centos@k8s-master ~]$ kubectl drain k8s-node2 --delete-local-data --force --ignore-daemonsets
node/k8s-node2 cordoned
WARNING: Ignoring DaemonSet-managed pods: calico-node-z5mxp, kube-proxy-vcs9q
[centos@k8s-master ~]$ kubectl get nodes
NAME         STATUS                     ROLES     AGE       VERSION
k8s-master   Ready                      master    13h       v1.11.0
k8s-node1    Ready                      <none>    12h       v1.11.0
k8s-node2    Ready,SchedulingDisabled   <none>    12h       v1.11.0
[centos@k8s-master ~]$ kubectl delete node k8s-node2
node "k8s-node2" deleted
[centos@k8s-master ~]$ kubectl get nodes
NAME         STATUS    ROLES     AGE       VERSION
k8s-master   Ready     master    13h       v1.11.0
k8s-node1    Ready     <none>    12h       v1.11.0
[centos@k8s-master ~]$
```

Node側では`kubeadm reset`を実施する。

```
# kubeadm reset
```

```
[root@k8s-node2 ~]# kubeadm reset
[reset] WARNING: changes made to this host by 'kubeadm init' or 'kubeadm join' will be reverted.
[reset] are you sure you want to proceed? [y/N]: y
[preflight] running pre-flight checks
[reset] stopping the kubelet service
[reset] unmounting mounted directories in "/var/lib/kubelet"
[reset] removing kubernetes-managed containers
[reset] cleaning up running containers using crictl with socket /var/run/dockershim.sock
[reset] failed to list running pods using crictl: exit status 1. Trying to use docker instead[reset] no etcd manifest found in "/etc/kubernetes/manifests/etcd.yaml". Assuming external etcd
[reset] deleting contents of stateful directories: [/var/lib/kubelet /etc/cni/net.d /var/lib/dockershim /var/run/kubernetes]
[reset] deleting contents of config directories: [/etc/kubernetes/manifests /etc/kubernetes/pki]
[reset] deleting files: [/etc/kubernetes/admin.conf /etc/kubernetes/kubelet.conf /etc/kubernetes/bootstrap-kubelet.conf /etc/kubernetes/controller-manager.conf /etc/kubernetes/scheduler.conf]
[root@k8s-node2 ~]#
```