kubectlでThe connection to the server [IP]:[PORT] was refusedになったときの対処

## TL;DR

1. `kubectl get pods`で表題のエラーが帰ってくる場合は接続先の指定が誤っている
2. 指定している接続先は`kubectl config view`の`clusters > cluster > server`で確認できる
3. 接続先の指定は`kubectl config set-cluster [cluster-name] --server=https://[IP]:[PORT]`で書き換えられる


## 発生した事象

localでdocker-for-macを利用してKubernetesを動かしていたのですが、気がつくと`kubectl get nodes`で次のエラーを返すようになってしまっていました。

```console
$ kubectl get nodes
The connection to the server localhost:6443 was refused - did you specify the right host or port?
```

また、 `kubectl describe nodes`でもサーバーに接続されない旨のエラーが帰ってきてしまい、原因がすぐにはわかりませんでした。

```console
$ kubectl describe nodes
Unable to connect to the server: EOF
```

## 原因

configで指定しているクラスタの接続先が誤っていました。

```console
$ kubectl config view
apiVersion: v1
clusters:
- cluster:
    insecure-skip-tls-verify: true
    server: https://localhost:6443
  name: docker-for-desktop-cluster
```

何らかのタイミングでlocalhostに書き換えてしまっていたようです。

## 解決策

次の方法で解決します。

1. 接続すべきIPアドレスとポート番号を調査する
2. configを書き換える

### 接続すべきIPアドレスとポート番号の調査 

幸い、ローカルの環境なので手元で動いているDockerコンテナの情報は取得できます。まず、Kubernetesのsystem containerが見えるようにします。この操作はGUI上でできます。

<img width="612" alt="スクリーンショット 2019-04-29 0.48.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41266/28934974-af06-5d82-2689-c9b4a0ad725f.png">

最下段の`Show system containers (acvanced)`にチェックを付けてください。

次に、Dockerが待ち受けているポートを探します。今回は`docker ps --no-trunc`を実行し、コンテナの`COMMAND`を確認する方法で行います。実行するとすごい量のテキストが吐き出されるので、その中から目当ての`kube-apiserver`コマンドの引数 `--advertise-address`を見つけます。

```console
$ docker ps --no-trunc | grep 'advertise-address='
(lots of texts)
```

正直見つけにくいので、出力結果に対して検索機能を駆使して見つけたほうが楽だと思います。次のような文字列を探してください。=の右側の文字列(IPアドレスとポート番号)は環境によって異なります。

```console
--advertise-address=192.168.65.3 
--secure-port=6443
```

### configの書き換え

次のコマンドで書き換えます。

```console
$ kubectl config set-cluster docker-for-desktop-cluster \
--server=https://[IPADDR]:[PORT]
```

`docker-for-desktop-cluster`は自分が利用したいクラスタ名を入力してください。[IPADDR]と[PORT]は先程調べた値で書き換えてください。

## 確認

`kubectl get pods`で確認できます。次のようなメッセージが帰ってくる場合があります。

```console
$ kubectl get pods
No resources found.
```

これは単にまだ何のpodも無いだけで**正常です**。もし正しく設定できていない場合は冒頭のエラーメッセージが帰ってくる、どれだけ待っても何も帰ってこないといった事象が発生します。

## 参考

* [The connection to the server <host>:6443 was refused - did you specify the right host or port? - General Discussions - Discuss Kubernetes](https://discuss.kubernetes.io/t/the-connection-to-the-server-host-6443-was-refused-did-you-specify-the-right-host-or-port/552)
* [【kubectl】The connection to the server localhost:8080 was refused と叱られる - DRYな備忘録](http://otiai10.hatenablog.com/entry/2016/04/07/061601)
* [Hello Minikube - Kubernetes](https://kubernetes.io/docs/tutorials/hello-minikube/)
* [Running Kubernetes Locally via Docker - `kubectl get nodes` returns `The connection to the server localhost:8080 was refused - did you specify the right host or port?` · Issue #23726 · kubernetes/kubernetes](https://github.com/kubernetes/kubernetes/issues/23726)
* [Kubernetes "did you specify the right host or port?" - Qiita](https://qiita.com/pnpnd1111/items/cac6f9f33a25de06e3e9)
* ["Kubernetes is starting…" state never ends · Issue #2990 · docker/for-mac](https://github.com/docker/for-mac/issues/2990)
* [Kubernetes does not complete startup, "Kubernetes is starting" · Issue #1649 · docker/for-win](https://github.com/docker/for-win/issues/1649)
* [Docker for MacでKubernetes インストールからデプロイまで - Qiita](https://qiita.com/uni-3/items/a4f2afa0973bfc35b498)