kubernetesクラスタの初期設定（DNSの設定）

## 前提
https://qiita.com/ta_yaboo/items/1c86d1f94d0ffa0d9bae
https://qiita.com/ta_yaboo/items/ac8408b500052523fe9f
https://qiita.com/ta_yaboo/items/f442127db50385ba600a
これらで紹介した通り、raspberryPIを使ってkubernetesクラスタを構築したところまではよかったのだけれども、サーバーとして使うことはできない状態でした。

## 問題点
クリアしないといけない問題と解決方法は以下の通りです。
### クラスタ内で名前解決ができない
試しにnginxのコンテナを突っ込んだPodとServiceをデプロイしてみました。

```yaml:deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    run: label-nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      run: label-nginx
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      labels:
        run: label-nginx
    spec:
      containers:
      - image: nginx
        imagePullPolicy: Always
        name: nginx
        ports:
        - containerPort: 80
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
```
```yaml:service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  type: NodePort
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: label-nginx
```
```
$ kubectl apply -f manifest/sample/deployment.yaml 
deployment.extensions/nginx created
$ kubectl apply -f manifest/sample/service.yaml 
service/nginx created
```
しかしアクセスができません。

```
$ curl nginx
curl: (6) Could not resolve host: nginx
$ curl nginx.default.svc.cluster.local
curl: (6) Could not resolve host: nginx.default.svc.cluster.local
```
IPアドレスでならアクセスできます。

```
$ kubectl get svc
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes            ClusterIP   10.96.0.1       <none>        443/TCP          26d
nginx                 NodePort    10.99.135.187   <none>        80:32135/TCP     2m

$ curl 10.99.135.187
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
以下略
```
どうやら名前解決ができないようです。

podのdns設定はどうなっているのでしょうか？
試しにkube-proxyの設定など見てみましょう

```
$ kubectl get po -n kube-system
NAME                                   READY     STATUS    RESTARTS   AGE
coredns-78fcdf6894-725zx               1/1       Running   8          11d
coredns-78fcdf6894-p79bk               1/1       Running   8          11d
etcd-raspberrypi0                      1/1       Running   28         13d
kube-apiserver-raspberrypi0            1/1       Running   44         13d
kube-controller-manager-raspberrypi0   1/1       Running   28         13d
kube-flannel-ds-6w79w                  1/1       Running   13         13d
kube-flannel-ds-dtv9z                  1/1       Running   18         13d
kube-flannel-ds-gq29f                  1/1       Running   12         13d
kube-proxy-ljz2s                       1/1       Running   7          13d
kube-proxy-rjd2h                       1/1       Running   7          13d
kube-proxy-wd58n                       1/1       Running   8          13d
kube-scheduler-raspberrypi0            1/1       Running   28         13d
$ kubectl exec -it kube-proxy-ljz2s -n kube-system /bin/sh
# cat /etc/resolv.conf
nameserver 192.168.11.1
```

**あ！おうちのルーターがDNSになってる。これは、いかん！！**
後の問題にも関連してくるのでまとめると、今のネットワークはこのようになっています
<img width="463" alt="スクリーンショット 2018-10-13 13.55.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/250225/49c4baaf-9ff3-255d-abd4-1cdb66215446.png">
podのサブネットは10.244.0.0/16なんだけど、基本的にpodに直接アクセスするようなことはしないので気にしないでおこう。
kubernetes内のリソースについて名前解決を行うにはkube-dns（Service）にアクセスしなければなりません。Serviceまでアクセスしたらcorednsにリクエストが振られて名前解決できるわけです。

podのDNSの設定はデフォルトではノードの設定を引き継ぐので各ノードの設定を変えてあげます。そうすると先に試したようにクラスタ内のノードからでもPod間通信でも名前解決ができます。
[こちら](https://qiita.com/ta_yaboo/items/ac8408b500052523fe9f)で紹介したようにDNSの設定もDHCP（ルーター）から取るようにしていたのでルーターの設定でDNSサーバーのアドレスを手動設定にします。ルーターによって設定の仕方は異なりますが、BUFFALOのAirStationだと [Internet/LAN] > [LAN] にそのメニューがありました。
プライマリはこれまで通り、ルーターのアドレスにしてセカンダリにkube-dnsのアドレス（10.96.0.10）を設定しました。

念のため、全ノードと全Podを再起動して（Podの再起動は全てのPodをDeleteしました。通常Podを作成しているDeploymentやDaemonSetなど上位リソースが存在するのでPodを消しても自動で再作成されます。）もう一度試します。

```
$ curl nginx.default.svc.cluster.local
curl: (6) Could not resolve host: nginx.default.svc.cluster.local
```
あれ？？

```
$ nslookup nginx.default.svc.cluster.local
Server:		10.96.0.10
Address:	10.96.0.10#53

Name:	nginx.default.svc.cluster.local
Address: 10.99.135.187
```
なんでやねんw (ちなみにnslookupはこのためにインストールしました)
これで3日ほど悶々としたのですが、お手上げでした。
が、3日ほど経ったらなぜか繋がるようになりました。キャッシュが悪さしてたりしたのかな？？

### クラスタ外でも名前解決ができない
クラスタ内で名前解決できないんだから当然なんだけど。。。
先の設定でDNSサーバーの設定はできました。
が、クラスタ外からはネットワークセグメントが異なるのでアクセスできません。

最初はクラスタ外からはDNSはraspiのmasterのアドレスを設定してmasterでポートフォワードの設定してあげたらいいのかなと思ってたけど、もっと簡単な方法がありました。

それはルーターの経路情報(ルーティング)の設定です。
これまたBUFFALOのAirStationだと [Internet/LAN] > [経路情報] にそのメニューがありました。
宛先はServiceのネットワークなので、先ほど図に書いた通り、10.96.0.0/12 つまり、
10.96.0.0でサブネットマスクは255.240.0.0です。ゲートウェイはmasterの192.168.11.41です。
これでルーターがDNSへのリクエストをよしなにルーティングしてくれます。

では、ここはひとつwifiに繋いだケータイからアクセスしてみましょう。
![Screenshot_20181013-230937.png](https://qiita-image-store.s3.amazonaws.com/0/250225/9d776754-138d-f7ea-4483-6134733161a7.png)

無事アクセスできました！
これでクラスタ内でも外でも自由にリクエストのやり取りができます。
さて、何のアプリを置こうかな。