前提
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をデプロイしてみました。
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
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になってる。これは、いかん!!
後の問題にも関連してくるのでまとめると、今のネットワークはこのようになっています
podのサブネットは10.244.0.0/16なんだけど、基本的にpodに直接アクセスするようなことはしないので気にしないでおこう。
kubernetes内のリソースについて名前解決を行うにはkube-dns(Service)にアクセスしなければなりません。Serviceまでアクセスしたらcorednsにリクエストが振られて名前解決できるわけです。
podのDNSの設定はデフォルトではノードの設定を引き継ぐので各ノードの設定を変えてあげます。そうすると先に試したようにクラスタ内のノードからでもPod間通信でも名前解決ができます。
こちらで紹介したように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に繋いだケータイからアクセスしてみましょう。
無事アクセスできました!
これでクラスタ内でも外でも自由にリクエストのやり取りができます。
さて、何のアプリを置こうかな。