kubeadmでAmazon Linux2にKubernetes1.17

[kubeadmでAmazon Linux2にKubernetes1.18を入れる場合はこちら](https://qiita.com/rururu_kenken/items/0a7434969ff2c28576eb)
[kubeadmでAmazon Linux2にKubernetes1.16を入れる場合はこちら](https://qiita.com/rururu_kenken/items/25ce39901c7cf264a839)
[kubeadmでAmazon Linux2にKubernetes1.15を入れる場合はこちら](https://qiita.com/rururu_kenken/items/298b2f09450a2ecc35fb)


**Master Node**

|    EC2　　 |    OS         | Kubernetes | Docker    | ホスト名  |
|:----------:|:-------------:|:----------:|:---------:|:---------:|
| t3.small　| Amazon Linux2  | 1.17.4     |18.09.9-ce |k8s-master|

2CPU、メモリ2GB以下の場合、kubeadm init実行時にエラーになります。
ディスクサイズはデフォルトの8G
Master NodeとWorker Nodeは同じVPC
Master NodeのIPアドレスは172.31.30.32

**Worker Node**

|    EC2　　 |    OS         | Kubernetes | Docker    | ホスト名  |
|:----------:|:-------------:|:----------:|:---------:|:---------:|
| t3.small   | Amazon Linux2 | 1.17.4     |18.09.9-ce |k8s-worker|

ディスクサイズは20G
Master NodeとWorker Nodeは同じVPC
Worker NodeのIPアドレスは172.31.28.255

## SELinux設定確認

```
$ getenforce

# 無効になっている
Disabled

```

## ホスト名の設定

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

## hostファイル編集

sudo vi /etc/hosts

```/etc/hosts.
# 以下の設定を追加
172.31.30.32 k8s-master
172.31.28.255 k8s-worker
```

## swap確認

```
$ free

# ないので何もしない。ある場合は「swapoff -a」
              total        used        free      shared  buff/cache   available
Mem:        2002344       75972     1573288         428      353084     1781640
Swap:             0           0           0
```

## Dockerインストール・設定

```
# amazon-linux-extras install -y docker=18.03.1のようにバージョン指定でインストールも可能
$ sudo amazon-linux-extras install -y docker=18.09.9

$ docker -v

Docker version 18.09.9-ce, build 039a7df

# dockerサービス起動
$ sudo systemctl start docker

# ログインしているユーザーをdockerグループに追加
$ sudo usermod -a -G docker $USER

# 確認コマンド
$ cat /etc/group | grep docker

docker:x:993:ec2-user

# ログアウトして、すぐに再ログイン
# exit

# Dockerの自動起動有効化
$ sudo systemctl enable docker

# cgroupdriverをsystemdに設定など
$ sudo tee /etc/docker/daemon.json <<EOF
{
  "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

$ sudo mkdir -p /etc/systemd/system/docker.service.d

# Restart Docker
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
```
## その他の設定

```
# sysctlでネットワークをブリッジできるようする
$ sudo tee /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

# カーネルパラメータを手動で反映
$ sudo sysctl --system

* Applying /etc/sysctl.d/00-defaults.conf ...
kernel.printk = 8 4 1 7
kernel.panic = 30
net.ipv4.neigh.default.gc_thresh1 = 0
net.ipv6.neigh.default.gc_thresh1 = 0
net.ipv4.neigh.default.gc_thresh2 = 15360
net.ipv6.neigh.default.gc_thresh2 = 15360
net.ipv4.neigh.default.gc_thresh3 = 16384
net.ipv6.neigh.default.gc_thresh3 = 16384
* 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 ...
* 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 /etc/sysctl.d/99-amazon.conf ...
kernel.sched_autogroup_enabled = 0
* Applying /etc/sysctl.d/99-sysctl.conf ...
* Applying /etc/sysctl.d/k8s.conf ...
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
* Applying /etc/sysctl.conf ...
```

## kubelet、kubeadm、kubectlインストール

「repo_gpgcheck=1」は「repo_gpgcheck=0」にする
[Got "repomd.xml signature could not be verified for kubernetes" error when installing Kubernetes from yum repo on Amazon Linux 2 #60134](https://github.com/kubernetes/kubernetes/issues/60134)

```
$ sudo sh -c "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=0
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
"
$ sudo yum install -y kubelet-1.17.4-0.x86_64 kubeadm-1.17.4-0.x86_64 kubectl-1.17.4-0.x86_64 --disableexcludes=kubernetes
```

## kubelet 起動

```
$ sudo systemctl enable kubelet && sudo systemctl start kubelet
```

## Master の初期化

```
# tcインストール
$ sudo yum install -y tc

# Flanelの場合
$ sudo kubeadm init --pod-network-cidr 10.244.0.0/16

# Calicoの場合
$ sudo kubeadm init --pod-network-cidr 192.168.0.0/16 
```

トークンには有効期限があり、通常は24時間で利用できなくなる。
トークンが失効した場合や分からなくなった場合、マスターノードで「kubeadm token create --print-join-command」コマンドを実行するとトークンが再生成されて表示される。

## kubectl 接続設定

```
$ 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

NAME         STATUS     ROLES    AGE     VERSION
k8s-master   NotReady   master   3m29s   v1.17.4

$ kubectl get cs

NAME                 STATUS    MESSAGE             ERROR
controller-manager   Healthy   ok                  
scheduler            Healthy   ok                  
etcd-0               Healthy   {"health":"true"}  

$ kubectl get pod --all-namespaces

NAMESPACE     NAME                                 READY   STATUS    RESTARTS   AGE
kube-system   coredns-6955765f44-bpdqr             0/1     Pending   0          3m52s
kube-system   coredns-6955765f44-xtc57             0/1     Pending   0          3m52s
kube-system   etcd-k8s-master                      1/1     Running   0          4m7s
kube-system   kube-apiserver-k8s-master            1/1     Running   0          4m7s
kube-system   kube-controller-manager-k8s-master   1/1     Running   0          4m7s
kube-system   kube-proxy-fnr6c                     1/1     Running   0          3m52s
kube-system   kube-scheduler-k8s-master            1/1     Running   0          4m7s
```

## Flannelの場合

[Super slow access to service IP from host (& host-networked pods) with Flannel CNI #1245](https://github.com/coreos/flannel/issues/1245)

```
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

$ kubectl get pod --all-namespaces

NAMESPACE     NAME                                 READY   STATUS    RESTARTS   AGE
kube-system   coredns-6955765f44-bpdqr             1/1     Running   0          6m6s
kube-system   coredns-6955765f44-xtc57             1/1     Running   0          6m6s
kube-system   etcd-k8s-master                      1/1     Running   0          6m21s
kube-system   kube-apiserver-k8s-master            1/1     Running   0          6m21s
kube-system   kube-controller-manager-k8s-master   1/1     Running   0          6m21s
kube-system   kube-flannel-ds-amd64-47ghl          1/1     Running   0          32s
kube-system   kube-proxy-fnr6c                     1/1     Running   0          6m6s
kube-system   kube-scheduler-k8s-master            1/1     Running   0          6m21s
```

## Calicoの場合

```
$ kubectl apply -f https://docs.projectcalico.org/v3.13/manifests/calico.yaml

$ kubectl get pod --all-namespaces

NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-788d6b9876-72fqg   1/1     Running   0          47s
kube-system   calico-node-p2svx                          1/1     Running   0          47s
kube-system   coredns-6955765f44-294gb                   1/1     Running   0          2m46s
kube-system   coredns-6955765f44-g4kcq                   1/1     Running   0          2m47s
kube-system   etcd-k8s-master                            1/1     Running   0          3m4s
kube-system   kube-apiserver-k8s-master                  1/1     Running   0          3m4s
kube-system   kube-controller-manager-k8s-master         1/1     Running   0          3m4s
kube-system   kube-proxy-92jgb                           1/1     Running   0          2m47s
kube-system   kube-scheduler-k8s-master                  1/1     Running   0          3m4s
```

```
$ kubectl get node

NAME         STATUS   ROLES    AGE     VERSION
k8s-master   Ready    master   7m30s   v1.17.4
```

# Worker Node

## 以下はMaster Nodeの手順を参照

Firewalld停止
SELinux設定確認
ホスト名の設定・・・sudo hostnamectl set-hostname k8s-worker
hostファイル編集
swap確認
Dockerインストール・設定
その他設定
kubelet、kubeadm、kubectlインストール
kubelet 起動

## クラスタに参加

```
# tcインストール
$ sudo yum install -y tc

# 「kubeadm token create --print-join-command」はMaster Nodeで実行
$ kubeadm token create --print-join-command

# 長いので「・・・」で省略
$ sudo kubeadm join 172.31.30.32:6443 --token ・・・
```

トークンには有効期限があり、通常は24時間で利用できなくなる。
トークンが失効した場合や分からなくなった場合、マスターノードで「kubeadm token create --print-join-command」コマンドを実行するとトークンが再生成されて表示される。

# Master Node

## kubectl コマンドで Node と Pod の状態を確認

```
$ kubectl get node

NAME         STATUS   ROLES    AGE   VERSION
k8s-master   Ready    master   30m   v1.17.4
k8s-worker   Ready    <none>   27s   v1.17.4
```

## Redisデプロイ・動作確認

```redis.yaml
apiVersion: v1
kind: Service
metadata:
  name: redis-svc
spec:
  ports:
    - port: 6379
      targetPort: 6379
  selector:
    app: redis
  clusterIP: None
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: redis.config
data:
  redis.conf: |
    requirepass password
    bind 0.0.0.0
---
apiVersion: apps/v1
kind: Deployment
metadata:
  # Deploymentの名前。Namespace内ではユニークである必要があります
  name: redis
spec:
  selector:
    matchLabels:
      app: redis
  # レプリカ数の指定
  replicas: 1
  # Podのテンプレート(PodTemplate)
  template:
    metadata:
      labels:
        # ラベル指定は必須
        app: redis
    spec:
      containers:
        - name: redis
          image: redis:5.0.5
          command: 
            - "redis-server"
            - "/redis-master/redis.conf"
          ports:
            - name: redis
              containerPort: 6379
          volumeMounts:
            - name: data
              mountPath: /redis-master-data
            - name: config
              mountPath: /redis-master
      volumes:
        - name: data
          emptyDir: {}
        - name: config
          configMap:
            name: redis.config
```

```
$ kubectl apply -f redis.yaml
$ kubectl run -it redis-cli --rm --image redis --restart=Never -- bash
If you don't see a command prompt, try pressing enter.
root@redis-cli:/data# redis-cli -c -h redis-svc -p 6379 -a password
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
redis-svc:6379> set a 1
OK
redis-svc:6379> get a
"1"
redis-svc:6379> exit
```

## Master 以外のノードに Role 設定

```
$ kubectl label node k8s-worker node-role.kubernetes.io/worker=

$ kubectl get node

NAME         STATUS   ROLES    AGE     VERSION
k8s-master   Ready    master   33m     v1.17.4
k8s-worker   Ready    worker   3m11s   v1.17.4
```

## Kubebernetes Dashboard

```
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml

# type: ClusterIP を type: NodePortに変更して保存
$ kubectl -n kubernetes-dashboard edit service kubernetes-dashboard

$ kubectl get svc --all-namespaces
NAMESPACE              NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                  AGE
default                kubernetes                  ClusterIP   172.16.130.1     <none>        443/TCP                  42m
kube-system            kube-dns                    ClusterIP   172.16.130.10    <none>        53/UDP,53/TCP,9153/TCP   42m
kubernetes-dashboard   dashboard-metrics-scraper   ClusterIP   172.16.130.60    <none>        8000/TCP                 5m50s
kubernetes-dashboard   kubernetes-dashboard        NodePort    172.16.130.183   <none>        443:30204/TCP            5m50s

$ vi dashboard-adminuser.yaml
```

```dashboard-adminuser.yaml:
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard
```

```
$ kubectl apply -f dashboard-adminuser.yaml

#トークン取得

$ kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}') | grep token: | awk '{print $2}'

# ブラウザでhttps://IPアドレス：30204/にアクセスして
# Tokenに取得したTokenを入力してダッシュボードにサインイン
```

## 参考URL

[kubeadmのインストール](https://kubernetes.io/ja/docs/setup/independent/install-kubeadm/)