マルチノード環境へのKubernetesインストール

今回構築した環境は以下のようになります。
・ベアメタルサーバー
・HV:EXSi
・OS:CentOS 7
・kubernetes : v1.10.2
・ノード構成 : masternode 1台 + workernode 2台

実施内容は、
・kubernetesインストール
・Dashboardインストール
・テスト用Podデプロイ
・外部アクセス設定
になります。

# kubernetesインストール
大方は
[How to Install Kubernetes (k8s) 1.7 on CentOS 7 / RHEL 7](https://www.linuxtechi.com/install-kubernetes-1-7-centos7-rhel7/)
を参考にしましたが、そのままだとうまくいきませんでした。

**masternode構築**

```ruby:host名設定
hostnamectl set-hostname 'k8s-master'
exec bash
```
```ruby:SELinuxとfirewallの無効化
setenforce 0
systemctl stop firewalld
systemctl disable firewalld
```
※今回はいち早くkubernetesを触ってみたかったので、firewallをoffにしてしまいました。

リンク先だと、ここで「/etc/hosts」の編集をしていますが、これはスキップします。
理由は後程。

```ruby:Swapオフ
vi /etc/fstab
```
3行目(swap swap 書いている行)をコメントアウトor削除する。

ここで設定反映のためにrebootする。

デフォルトのCentOS7ではKubernetesパッケージは使用できないため、リポジトリの設定を行う。

```ruby:repoファイル作成
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
```

設定が終わったら、kubeadmとDockerのインストール、有効化を行う。

```
yum install kubeadm docker -y
systemctl restart docker && systemctl enable docker
systemctl  restart kubelet && systemctl enable kubelet
```

kubernetesの初期化とセットアップを行う。

```
kubeadm init
```

上記コマンド実行で、以下のような出力が得られる。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/255858/161a780a-f882-3a4c-1856-2811ff996ebd.png)

出力内に記載されているコマンドを実行する

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

しっかり構築されているかを確認

```
kubectl get nodes
```

結果が出力されたらOK!
ここで、

```
The connection to the server localhost:8080 was refused - did you specify the right host or port?    
```

が出力されたら、上記configコピー忘れ

デプロイされているPodの確認をする

```
kubectl get pods --all-namespaces   
```

kube-dnsが1つもデプロイされてない。
異なるホストのコンテナが相互に通信できるようにポッドネットワークをデプロイする必要があるらしい。

```ruby:ポッドネットワークのデプロイ
export kubever=$(kubectl version | base64 | tr -d '\n') 
kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$kubever"              
```

これでもう1回Podの確認をする
デプロイされているPodの確認をする

```
kubectl get pods --all-namespaces   
```

DNSも作成されている！
これでmaster node 構築完了。

**worker node構築**
初期設定はmaster nodeと同じ。

```ruby:host名設定
hostnamectl set-hostname 'k8s-master'
exec bash
```

```ruby:SELinuxとfirewallの無効化
setenforce 0
systemctl stop firewalld
systemctl disable firewalld
```

```ruby:Swapオフ
vi /etc/fstab
```

```ruby:kubernetes.repo作成
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
```

```ruby:kubeadmとdockerのインストール・有効化
yum install kubeadm docker -y
systemctl restart docker && systemctl enable docker
systemctl  restart kubelet && systemctl enable kubelet
```
```ruby:config作成
mkdir -p $HOME/.kube
vi $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
```
「$HOME/.kube/config」は、master nodeで作成されたconfigファイルを配置する。

そして、ノード参加をする。
参加するためのコマンドは、master nodeにて「kubeadm init」を実行した際に出力された、以下コマンドとなる。

```ruby:ノード参加
kubeadm join 192.168.11.114:6443 --token puhvv1.lgfvwgzljq63sndl --discovery-token-ca-cert-hash 
 sha256:ae212816cc3bdf83c3df92dd4dfc73b4ed5421376b273ce41fb6a030680fa0fe
```
tokenには有効期間があり、以下コマンドで再発行が可能。
master node構築から時間がたった場合は、再発行してからnode追加させる？

```ruby:token再発行
kubeadm token create  
```
node参加できているかを確認
```
kubectl get nodes
```
以下のような出力になればOK

```ruby:
NAME           STATUS    ROLES     AGE       VERSION                                                                 
k8s-master     Ready     master    1d        v1.10.2                                                                 
worker-node1   Ready     <none>    2m        v1.10.2                                                                 
worker-node2   Ready     <none>    11s       v1.10.2   
```

# Dashboardインストール
インストールは公式サイトの手順通りに実行でうまくいった。
[Kubernetes Dashboard](https://github.com/kubernetes/dashboard/blob/master/README.md)

```ruby:Dashboardインストール
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml 
```

Dashboardがデプロイされたが、外部サーバー/クライアントからアクセスできないため、アクセス可能にする。

```ruby:Proxy起動
kubectl proxy --address 0.0.0.0 --accept-hosts '.*'
```

これで以下URLで外部からアクセス可能となっている。
"http://{master nodeのIP}:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/"

そして、Dashboardへのアクセスにおいて、今回は以下のサイトを参考にして認証なしで操作できるようにした。
[DashboardへAdmin権限でサインイン](https://www.kaitoy.xyz/2017/10/31/retry-dashboard-on-k8s-cluster-by-kubeadm/)

以下のようなyamlファイルを作成し、

```ruby:
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: kubernetes-dashboard
  labels:
    k8s-app: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: kubernetes-dashboard
  namespace: kube-system
```

kubectlで実行する。

```ruby:
kubectl create -f dashboard-admin.yml
```

これで、「skip」ボタン押下で認証無しで入った場合もすべての操作ができるようになっている。

また、「/etc/hosts」に設定を加えなかった理由は、Dashbordが正常に動作しなかったためである。
デプロイまではうまくいくが、正常にアクセスができなかった。
「/etc/hosts」を削除して再構築したらうまくいったため、おそらく原因と思われる。

# テスト用Podデプロイ
今回はnginxコンテナをデプロイし、外部からアクセスさせる。
以下の内容で「deployment-example.yaml」を作成する。

```ruby:yamlファイル
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: deployment-example
spec:
  replicas: 2
  # Podのテンプレート(PodTemplate)
  template:
    metadata:
      labels:
        app: deployment-example
    spec:
      containers:
      - name: nginx
        image: nginx:1.10
        ports:
        - containerPort: 80
```

```ruby:デプロイ
kubectl create -f deployment-example.yaml --record
```
作成されたPodを確認する。

```ruby:Pod確認
kubectl get pods -o wide
```

以下のような出力となり、サーバー内からはアクセス可能となっている。

```ruby:
NAME                                  READY     STATUS    RESTARTS   AGE       IP          NODE
deployment-example-564f5cdb48-s475f   1/1       Running   0          15m       10.32.0.2   worker-node1
deployment-example-564f5cdb48-xf89b   1/1       Running   0          15m       10.40.0.0   worker-node2
```
```ruby:アクセス確認
curl -I http://10.32.0.2
```

しかし、これだけでは外部からアクセスできない。

#外部アクセス設定
外部アクセスのためのServiceをデプロイする。

```ruby:Serviceデプロイ
kubectl expose deployment deployment-example --type=LoadBalancer --name=my-service
```

```ruby:Serviceデプロイ確認
kubectl get services
```
```ruby:Serviceデプロイ確認出力
NAME         TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP      10.96.0.1     <none>        443/TCP        1d
my-service   LoadBalancer   10.105.35.2   <pending>     80:30590/TCP   6s
```

GKEなどだと、これで外部アクセスが可能になるらしい。
しかし、本環境だと、「EXTERNAL-IP」が「<pending>」となっていて、外部アクセス用IPが作成されていなく、アクセスできない。
詳細は
[Kubernetes の Service type LoadBalancer を手作業で作る](https://qiita.com/yuanying/items/704a173033410d882eea)
を参照。

そのため、上記のリンクに従い、外部からアクセス可能なように設定する。

```ruby:configファイル作成
cat << EOF > haproxy.cfg
global
    maxconn 256

defaults
    mode http
    timeout client     120000ms
    timeout server     120000ms
    timeout connect      6000ms

listen http-in
    bind *:80
    server k8s-master 192.168.11.114:30590
    server worker-node1 192.168.11.115:30590
    server worker-node2 192.168.11.116:30590
EOF
```
※host名、IPアドレス、Port番号は自環境用に修正してください。
※Port番号は、「kubectl get services」にて確認した番号

そして、HAProxyを起動する

```ruby:HAProxy起動
docker run -d --name haproxy -p 80:80 -v $(pwd)/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro haproxy:1.8
```

これにより、外部サーバー/クライアントからnginxにアクセス可能となっている。
URL:http://localhost/