k3dとLocal Registry

|前提環境            |                      |
|-------------------|----------------------|
| OS                |macOS Catalina 10.15.2|

| インストール済ソフト    |インストール方法                         |
|----------------------|--------------------------------------|
|Homebrew              |https://brew.sh/index_ja              |
|Visual Studio Code    |`brew cask install visual-studio-code`|
|Docker desktop 2.2.0.5|`brew cask install docker`            |
|kubernetes-cli 1.18.2 |`brew cask install kubernetes-cli`    |
|k3d 1.7.0             |`brew install k3d`                    |


# はじめに


k3dは一つのDocker環境上でマルチノードな軽量Kubernetes環境を稼動させるツールです。軽量Kubernetes環境の[k3s](https://rancher.com/docs/k3s/latest/en/architecture/)をコンテナ内で動かし、それを複数起動することでマルチノードを実現しています。コンテナの中でコンテナを動かす二重構造となり、外側がノード、内側がPodを構成します。
k3dを使って簡単に環境の作成＆削除ができますが、削除するとpullしたコンテナイメージごとリセットされてしまうので、再作成後にまたネットワークを介したpullが行われ余分な時間がかかってしまいます。

本稿では[k３dのレジストリに関する公式ドキュメント](https://github.com/rancher/k3d/blob/master/docs/registries.md)をベースに自分のPC上にlocal registryを作成する方法のあれこれをまとめます。



# 最終的にやりたいこと


- PC上に`k3d`を使ってコンパクトな`Kubernetes`環境を作成する
- PC上にローカルレジストリを立ててコンテナイメージのダウンロードのためのトラフィックを軽減する
- internetが使えない場所にPCを持っていってもKubernetes環境を使えるようにする


# コンテナRegistryについて


コンテナとして稼動させることが可能なレジストリツール、「registry」がDocker Hubに公開されています。
参考）他にも本格的なレジストリツールとして「[Harbor](https://goharbor.io/)」があります。

- Docker Hub/Registry  https://hub.docker.com/_/registry
- ドキュメント https://docs.docker.com/registry/
- source code https://github.com/docker/distribution

単純な起動方法は↓こんな感じです（Docker Hubのサイトに載ってます）。

```bash
$ docker run -d -p 5000:5000 --restart always --name registry registry:2
```


# No.1　k3dでlocal registryを作成する

k3dでk3sクラスタを作成すると同時に、local registryを作成することができます(下図のk3d-registry)。
ここで作成したlocal registryは自前でpushしたimageの取得元として使用します。
docker.io(Docker Hub)等の外部registryはk3sクラスタの各ノードにそれぞれpullされます。

<img width="698" alt="スクリーンショット 2020-04-23 13.33.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124599/a0c3799b-e512-1215-9e1f-e737af3643a2.png">

### 作成
- `k3d create`する際に`--enable-registry`を指定するとlocal registryが自動的に作成されます。
- 作成したRegistryは`k3d delete`すると停止＆削除されます。
- create時に`--registry-volume volume名`を指定し、delete時に`--keep-registry-volume`を指定するとコンテナimageを格納したvolumeは残り、次回のcreate時に再利用されます。

```
$ k3d create \
    --enable-registry \
    --registry-volume my-registry \
    --workers 2
```


<details><summary>クラスタ作成後の状態（クリックで開く）</summary><div>

指定した名前(my-registry)のVolumeが作成され、k3sのNode用コンテナとレジストリコンテナ(k3d-registry)が立ち上がります。

```
$ docker volume ls
DRIVER              VOLUME NAME
   :
local               k3d-k3s-default-images
local               my-registry

$ docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Ports}}"
NAMES                      IMAGE                PORTS
k3d-k3s-default-worker-1   rancher/k3s:v1.0.1   
k3d-k3s-default-worker-0   rancher/k3s:v1.0.1   
k3d-k3s-default-server     rancher/k3s:v1.0.1   0.0.0.0:6443->6443/tcp
k3d-registry               registry:2           0.0.0.0:5000->5000/tcp
```


k3sのNode内では、レジストリは`registry.local:5000`というmirror registryと認識されます。

```
$ docker exec k3d-k3s-default-server \
  cat /var/lib/rancher/k3s/agent/etc/containerd/config.toml
   :
[plugins.cri.registry.mirrors."registry.local:5000"]
  endpoint = ["http://registry.local:5000"]

$ docker exec k3d-k3s-default-server nslookup registry.local
Server:         127.0.0.11
Address:        127.0.0.11:53

Non-authoritative answer:

Non-authoritative answer:
Name:   registry.local
Address: 172.19.0.2
```

docker network上は以下の通り。

```
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
1b7b3c23ff23        bridge              bridge              local
896cb12f5c0c        host                host                local
d3fbe09b8f27        k3d-k3s-default     bridge              local
b5dbe20949f1        none                null                local

$ docker inspect k3d-k3s-default
   :
        "Containers": {
            "0694c00e6d488aefde9de70ec47b5d523e44d652d7b08be9332c2c7889e91c2a": {
                "Name": "k3d-k3s-default-worker-1",
                "EndpointID": "e10f44ab7bff2f02173558a7958ca6d8cc412bf90dc5bf4a577df260a14d99e0",
                "MacAddress": "02:42:ac:13:00:05",
                "IPv4Address": "172.19.0.5/16",
                "IPv6Address": ""
            },
            "6fb05a8847009ee0c1195e0a3999f90e93c5d0826a884e933d9c839af36b858b": {
                "Name": "k3d-registry",
                "EndpointID": "f4a60a8d934af27eaf2003e3accbf2ad3216b6ca665c84e7bc03cee6f8181330",
                "MacAddress": "02:42:ac:13:00:02",
                "IPv4Address": "172.19.0.2/16",
                "IPv6Address": ""
            },
            "84c0d86715aaf65578269f7ab84b094de4a112cc7e339534cf3075136634aba0": {
                "Name": "k3d-k3s-default-server",
                "EndpointID": "c8dcf9ca8c5d8cb9ac11efddcacc68a431bd431b4e8e90376ff26e87c20bfb74",
                "MacAddress": "02:42:ac:13:00:03",
                "IPv4Address": "172.19.0.3/16",
                "IPv6Address": ""
            },
            "a14218fbfac91d033e80adc644d0d6735a026a3748706f41e2d5d41c4256efdf": {
                "Name": "k3d-k3s-default-worker-0",
                "EndpointID": "a455e226accbd24fd1b30f3c354e63b2a25ff5b571ba68fbc581138077c89a6f",
                "MacAddress": "02:42:ac:13:00:04",
                "IPv4Address": "172.19.0.4/16",
                "IPv6Address": ""
            }
        }
   :
```

k3sクラスタ上のpodの状態

```
$ export KUBECONFIG="$(k3d get-kubeconfig --name='k3s-default')"
$ kubectl get pods -A
NAMESPACE     NAME                                      READY   STATUS      RESTARTS   AGE
kube-system   local-path-provisioner-58fb86bdfd-4sf67   1/1     Running     0          4m33s
kube-system   metrics-server-6d684c7b5-r2d9d            1/1     Running     0          4m33s
kube-system   helm-install-traefik-8dhqr                0/1     Completed   0          4m33s
kube-system   coredns-d798c9dd-cb77x                    1/1     Running     0          4m33s
kube-system   svclb-traefik-pbj7q                       3/3     Running     0          4m3s
kube-system   svclb-traefik-nvcnc                       3/3     Running     0          4m3s
kube-system   svclb-traefik-h9b82                       3/3     Running     0          4m3s
kube-system   traefik-65bccdc4bd-ntk55                  1/1     Running     0          4m3s
```
</div></details>

<details><summary>local registryを使う（クリックで開く）</summary><div>

自前のイメージをprivate registryにpushします。

```
$ docker build --tag my-nginx -<<EOF
FROM nginx
ENV HOGE fuge
EOF

$ docker tag my-nginx:latest localhost:5000/my-nginx:latest

$ docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}"
REPOSITORY                           TAG                 IMAGE ID
my-nginx                             latest              c8ea36ac903c
localhost:5000/my-nginx              latest              c8ea36ac903c
nginx                                latest              e791337790a6
   :

$ docker push localhost:5000/my-nginx
```

```
$ kubectl apply -f -<<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-test-registry
  labels:
    app: nginx-test-registry
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-test-registry
  template:
    metadata:
      labels:
        app: nginx-test-registry
    spec:
      containers:
      - name: nginx-test-registry
        image: registry.local:5000/my-nginx:latest
        ports:
        - containerPort: 80
EOF
```

```
$ kubectl get pods -l "app=nginx-test-registry"
NAME                                   READY   STATUS    RESTARTS   AGE
nginx-test-registry-6fb798cd48-ltngt   1/1     Running   0          100s
```
</div></details>


### 削除
```
$ k3d delete --keep-registry-volume
```
### 削除(完全)
```
$ k3d delete
```


# No.2　k3dでdocker.hubのcashe Registryを作成する

k3dでk3sクラスタを作成すると同時に、docker.io(Docker Hub)のキャッシュとして機能するlocal registryを作成することができます(下図のk3d-registry)。
docker.io(Docker Hub)以外の外部Registryのキャッシュにすることはできません。
また、このlocal registryには自前のimageをpushすることはできず、No.1のlocal registryと共存することもできません。

<img width="698" alt="スクリーンショット 2020-04-23 13.33.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124599/6c2a0b5c-2043-d0cf-c522-6485bd0f19bc.png">


### 作成
- `k3d create`する際に`--enable-registry`と`---enable-registry-cache`を指定すると docker.io(Docker Hub)のキャッシュが自動的に作成されます。
- 作成したRegistryは`k3d delete`すると停止＆削除されます。
- create時に`--registry-volume volume名`を指定し、delete時に`--keep-registry-volume`を指定するとコンテナimageを格納したvolumeは残り、次回のcreate時に再利用されます。

```
$ k3d create \
    --enable-registry \
    --enable-registry-cache \
    --registry-volume my-registry \
    --workers 2
```

<details><summary>クラスタ作成後の状態（クリックで開く）</summary><div>
指定した名前(my-registry)のVolumeが作成され、k3sのNode用コンテナとレジストリコンテナ(k3d-registry)が立ち上がります。

```
$ docker volume ls
DRIVER              VOLUME NAME
   :
local               k3d-k3s-default-images
local               my-registry

$ docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Ports}}"
NAMES                      IMAGE                PORTS
k3d-k3s-default-worker-1   rancher/k3s:v1.0.1   
k3d-k3s-default-worker-0   rancher/k3s:v1.0.1   
k3d-k3s-default-server     rancher/k3s:v1.0.1   0.0.0.0:6443->6443/tcp
k3d-registry               registry:2           0.0.0.0:5000->5000/tcp
```


k3sのNode内では、レジストリは`registry.local:5000`という名前で、docker.ioのmirror registryと認識されます。

```
$ docker exec k3d-k3s-default-server \
  cat /var/lib/rancher/k3s/agent/etc/containerd/config.toml
   :
[plugins.cri.registry.mirrors."docker.io"]
  endpoint = ["http://registry.local:5000"]

[plugins.cri.registry.mirrors."registry.local:5000"]
  endpoint = ["http://registry.local:5000"]

$ docker exec k3d-k3s-default-server nslookup registry.local
Server:         127.0.0.11
Address:        127.0.0.11:53

Non-authoritative answer:

Non-authoritative answer:
Name:   registry.local
Address: 172.20.0.2
```

docker network上は以下の通り。

```
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
1b7b3c23ff23        bridge              bridge              local
896cb12f5c0c        host                host                local
d3fbe09b8f27        k3d-k3s-default     bridge              local
b5dbe20949f1        none                null                local

$ docker inspect k3d-k3s-default
   :
        "Containers": {
            "07f97416207590dc235e3a41c3cd24203243282fdb6d3f86f21f982e56d24efc": {
                "Name": "k3d-k3s-default-server",
                "EndpointID": "8b6a4d0ffa4f4e410a0b57f3b73f728565d73c3eb1cae45907c6b83521978926",
                "MacAddress": "02:42:ac:14:00:03",
                "IPv4Address": "172.20.0.3/16",
                "IPv6Address": ""
            },
            "1261ead465cafe58bb8c05012f9b7cd9517987058d71757816e63d661f444339": {
                "Name": "k3d-k3s-default-worker-1",
                "EndpointID": "3d924f95cc0abafdd37bbe81a3e321aebfe391cac01a5997a9576cdf9f50031d",
                "MacAddress": "02:42:ac:14:00:05",
                "IPv4Address": "172.20.0.5/16",
                "IPv6Address": ""
            },
            "42cc1d880cdcbf81e95e0b55c02e16ab053f102a8d3a9b71b2cd651c58caa71f": {
                "Name": "k3d-registry",
                "EndpointID": "071fdb6f3350bbbec80310b76e69a0537346b4a18ad9fc2ff4ee88c2a68ecfdf",
                "MacAddress": "02:42:ac:14:00:02",
                "IPv4Address": "172.20.0.2/16",
                "IPv6Address": ""
            },
            "bbe78db02b568e9c0f806a371263c031ff22869fbfbf98ab2733b3746c6c4af6": {
                "Name": "k3d-k3s-default-worker-0",
                "EndpointID": "faacca93d48700b30720ba8f650e6db5afa2cabab0d64017957ae3b60d557f66",
                "MacAddress": "02:42:ac:14:00:04",
                "IPv4Address": "172.20.0.4/16",
                "IPv6Address": ""
            }
        },
   :
```

k3sクラスタ上のpodの状態

```
$ export KUBECONFIG="$(k3d get-kubeconfig --name='k3s-default')"
$ kubectl get pods -A
NAMESPACE     NAME                                      READY   STATUS      RESTARTS   AGE
kube-system   metrics-server-6d684c7b5-9c6j4            1/1     Running     0          5m11s
kube-system   local-path-provisioner-58fb86bdfd-xqz6m   1/1     Running     0          5m11s
kube-system   coredns-d798c9dd-pnjt8                    1/1     Running     0          5m11s
kube-system   helm-install-traefik-jqvwk                0/1     Completed   0          5m12s
kube-system   svclb-traefik-8q87s                       3/3     Running     0          4m14s
kube-system   svclb-traefik-2z8br                       3/3     Running     0          4m15s
kube-system   svclb-traefik-n9zr4                       3/3     Running     0          4m14s
kube-system   traefik-65bccdc4bd-6cznb                  1/1     Running     0          4m15s
```
</div></details>

### 削除
```
$ k3d delete --keep-registry-volume
```
### 削除(完全)
```
$ k3d delete
```

# No.3　自前でlocal registryとdocker.hub他のcasheを作成する

No.1,No.2のやりかたでは、キャッシュとprivate registryを両立することはできません。
外部レジストリ毎のキャッシュ、private registryを個別に作成してk3sクラスタから使用できるように設定します。

<img width="698" alt="スクリーンショット 2020-04-23 13.33.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124599/e3c92c5a-0f1d-b1df-b9cd-e11e76d0e233.png">


### 作成
- 外部レジストリ毎のキャッシュ、private registryを個別に作成します。
- 作成したregistryをk3sクラスタのnetworkに参加させる必要があります。`k3d create`によって自動的にnetworkが作成されますが、ここでは明示的に作成しています。
- imageファイルをPCの~/registry配下に保存されるようにしています。
- k3sクラスタ内では作成したregistryはmirrorsとして定義します。

```
$ docker network create -d bridge k3d-k3s-default \
    --label app=k3d --label cluster=k3s-default

$ makedir -p ~/registry/

$ docker run --name registry-private -d --restart=unless-stopped \
               -v ~/registry/private:/var/lib/registry \
               --net k3d-k3s-default \
               -p 5000:5000 registry:2

$ docker run --name registry-dockerHUB -d --restart=unless-stopped \
               -v ~/registry/dockerHUB:/var/lib/registry \
               --net k3d-k3s-default \
      -e REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io registry:2

$ docker run --name registry-k8s -d --restart=unless-stopped \
               -v ~/registry/k8s:/var/lib/registry \
               --net k3d-k3s-default \
      -e REGISTRY_PROXY_REMOTEURL=https://k8s.gcr.io registry:2

$ docker run --name registry-quay -d --restart=unless-stopped \
               -v ~/registry/quay:/var/lib/registry \
               --net k3d-k3s-default \
      -e REGISTRY_PROXY_REMOTEURL=https://quay.io registry:2

$ cat << EOF > ~/registry/registries.yaml
mirrors:
  "docker.io":
    endpoint:
    - http://registry-dockerHUB:5000
  "k8s.gcr.io":
    endpoint:
    - http://registry-k8s:5000
  "quay.io":
    endpoint:
    - http://registry-quay:5000
  "registry.local:5000":
    endpoint:
    - http://registry-private:5000
EOF

$ k3d create \
    --registries-file ~/registry/registries.yaml \
    --workers 2
```


<details><summary>クラスタ作成後の状態（クリックで開く）</summary><div>

```
$ docker volume ls
DRIVER              VOLUME NAME
   :
local               k3d-k3s-default-images

$ docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Ports}}"
NAMES                      IMAGE                PORTS
k3d-k3s-default-worker-1   rancher/k3s:v1.0.1   
k3d-k3s-default-worker-0   rancher/k3s:v1.0.1   
k3d-k3s-default-server     rancher/k3s:v1.0.1   0.0.0.0:6443->6443/tcp
registry-quay              registry:2           5000/tcp
registry-k8s               registry:2           5000/tcp
registry-dockerHUB         registry:2           5000/tcp
registry-private           registry:2           0.0.0.0:5000->5000/tcp

$ docker exec k3d-k3s-default-server \
  cat /var/lib/rancher/k3s/agent/etc/containerd/config.toml
   :
[plugins.cri.registry.mirrors."docker.io"]
  endpoint = ["http://registry-dockerHUB:5000"]

[plugins.cri.registry.mirrors."k8s.gcr.io"]
  endpoint = ["http://registry-k8s:5000"]

[plugins.cri.registry.mirrors."quay.io"]
  endpoint = ["http://registry-quay:5000"]

[plugins.cri.registry.mirrors."registry.local:5000"]
  endpoint = ["http://registry-private:5000"]

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
1b7b3c23ff23        bridge              bridge              local
896cb12f5c0c        host                host                local
d3fbe09b8f27        k3d-k3s-default     bridge              local
b5dbe20949f1        none                null                local

$ docker inspect k3d-k3s-default
   :
        "Containers": {
            "3062bc61543f350fae338b2cac818bc4d2e5aa3b347b79ead7f42a7d76cbb976": {
                "Name": "k3d-k3s-default-worker-0",
                "EndpointID": "d0525581b8f55c4039c249c1cee0bd5699b53ed7cbbd24046738eeb00d9acb0c",
                "MacAddress": "02:42:ac:15:00:07",
                "IPv4Address": "172.21.0.7/16",
                "IPv6Address": ""
            },
            "49710110bcafcac9e67d6f31e76a461c2d223f60858a4aa502d729d0dfbcdcaf": {
                "Name": "k3d-k3s-default-worker-1",
                "EndpointID": "6e678e3d754c59ffaf645befd7e6de580765e386b4a0470f49bb6d13aa689402",
                "MacAddress": "02:42:ac:15:00:08",
                "IPv4Address": "172.21.0.8/16",
                "IPv6Address": ""
            },
            "64d9e77c93f2ce493378fb0cf3af400e584c6822f60aaa38d1ae06776d15d9a8": {
                "Name": "registry-quay",
                "EndpointID": "c9deabf455cc009b76a37e7d2fd6a57c80ee67821e58f28172c5fdd360455d8c",
                "MacAddress": "02:42:ac:15:00:05",
                "IPv4Address": "172.21.0.5/16",
                "IPv6Address": ""
            },
            "7a387f6c183de72a500df1546bf8fa0d639b3c0f82f8a795da8f97b10f80ca00": {
                "Name": "k3d-k3s-default-server",
                "EndpointID": "eb8bed7866c25cebe130eb86a89909f5673f20faab804c4aff70dc3c4392ac59",
                "MacAddress": "02:42:ac:15:00:06",
                "IPv4Address": "172.21.0.6/16",
                "IPv6Address": ""
            },
            "81e2bb6491ed642d65d8de697745ce700d7d1688639e9f03c2dcef299d4d26b3": {
                "Name": "registry-k8s",
                "EndpointID": "a57e2f3f3af6243d00f0fb15df804db4e0ec06a877476d3834ccab929ac18871",
                "MacAddress": "02:42:ac:15:00:04",
                "IPv4Address": "172.21.0.4/16",
                "IPv6Address": ""
            },
            "c2c552ef6098039a73c38ba98d12039e97cabaec63cc3d887fa6fb23a1d89b94": {
                "Name": "registry-private",
                "EndpointID": "d260cb24e7818a4f25c913a402e0a338ac7833b8cd21bc0aae21935dcd40723d",
                "MacAddress": "02:42:ac:15:00:02",
                "IPv4Address": "172.21.0.2/16",
                "IPv6Address": ""
            },
            "d5793453b455794aeacad5d40eabf43e1e4c818950c8a2aa8b26469d484489d6": {
                "Name": "registry-dockerHUB",
                "EndpointID": "571bb13c3ec335c1a3aa307ea34e465242dfd049f19e13dfeca7a39f0336758e",
                "MacAddress": "02:42:ac:15:00:03",
                "IPv4Address": "172.21.0.3/16",
                "IPv6Address": ""
            }
        }
   :
```

k3sクラスタ上のpodの状態

```
$ export KUBECONFIG="$(k3d get-kubeconfig --name='k3s-default')"
$ kubectl get pods -A
kubectl get pods -A
NAMESPACE     NAME                                      READY   STATUS      RESTARTS   AGE
kube-system   metrics-server-6d684c7b5-hh7dk            1/1     Running     0          8m37s
kube-system   local-path-provisioner-58fb86bdfd-txxjv   1/1     Running     0          8m37s
kube-system   coredns-d798c9dd-pq6qh                    1/1     Running     0          8m37s
kube-system   helm-install-traefik-2c4l9                0/1     Completed   0          8m38s
kube-system   svclb-traefik-lpvgr                       3/3     Running     0          7m42s
kube-system   svclb-traefik-lfbxx                       3/3     Running     0          7m42s
kube-system   svclb-traefik-h4ql9                       3/3     Running     0          7m42s
kube-system   traefik-65bccdc4bd-x29wl                  1/1     Running     0          7m43s
```
</div></details>

<details><summary>local registryを使う（クリックで開く）</summary><div>

自前のイメージをprivate registryにpushします。

```
$ docker build --tag my-nginx -<<EOF
FROM nginx
ENV HOGE fuge
EOF

$ docker tag my-nginx:latest localhost:5000/my-nginx:latest

$ docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}"
REPOSITORY                           TAG                 IMAGE ID
my-nginx                             latest              c8ea36ac903c
localhost:5000/my-nginx              latest              c8ea36ac903c
nginx                                latest              e791337790a6
   :

$ docker push localhost:5000/my-nginx
```

```
$ kubectl apply -f -<<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-test-registry
  labels:
    app: nginx-test-registry
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-test-registry
  template:
    metadata:
      labels:
        app: nginx-test-registry
    spec:
      containers:
      - name: nginx-test-registry
        image: registry.local:5000/my-nginx:latest
        ports:
        - containerPort: 80
EOF
```

```
$ kubectl get pods -l "app=nginx-test-registry"
NAME                                   READY   STATUS    RESTARTS   AGE
nginx-test-registry-6fb798cd48-ltngt   1/1     Running   0          100s
```
</div></details>

### 削除

```
$ k3d delete
```

### 削除(作成したもの全て)

```
$ docker rm -f registry-quay registry-k8s registry-dockerHUB registry-private 
$ k3d delete
$ rm -rf ~/registry

#以下はNetworkが削除されなかった場合
$ docker network disconnect k3d-k3s-default registry-private
$ docker network disconnect k3d-k3s-default registry-dockerHUB
$ docker network disconnect k3d-k3s-default registry-k8s
$ docker network disconnect k3d-k3s-default registry-quay
$ docker network rm k3d-k3s-default
```


# No.4　local registryにdocker.hub他のimageを配置する
No.3の方法でやりたいことは実現できるのですが、registryをいくつも作らないといけません。
local registryを一つだけで全てを兼ねるようにします。


<img width="698" alt="スクリーンショット 2020-04-23 13.34.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124599/097564d1-2669-f3fd-9ceb-521e3ea98316.png">


### 作成
- 作成したregistryをk3sクラスタのnetworkに参加させる必要があります。`k3d create`によって自動的にnetworkが作成されますが、ここでは明示的に作成しています。
- imageファイルをPCの~/registry配下に保存されるようにしています。
- k3sクラスタ内では作成したregistryはmirrorsとして定義します。

```
$ docker network create -d bridge k3d-k3s-default \
    --label app=k3d --label cluster=k3s-default

$ makedir -p ~/registry/

$ docker run --name registry-private -d --restart=unless-stopped \
               -v ~/registry/private:/var/lib/registry \
               --net k3d-k3s-default \
               -p 5000:5000 registry:2

$ cat << EOF > ~/registry/registries.yaml
mirrors:
  "docker.io":
    endpoint:
    - http://registry-private:5000
  "k8s.gcr.io":
    endpoint:
    - http://registry-private:5000
  "quay.io":
    endpoint:
    - http://registry-private:5000
  "registry.local:5000":
    endpoint:
    - http://registry-private:5000
EOF

$ k3d create \
    --registries-file ~/registry/registries.yaml \
    --workers 2
```


<details><summary>クラスタ作成後の状態（クリックで開く）</summary><div>

```
$ docker volume ls
DRIVER              VOLUME NAME
   :
local               k3d-k3s-default-images

$ docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Ports}}"
NAMES                      IMAGE                PORTS
k3d-k3s-default-worker-1   rancher/k3s:v1.0.1   
k3d-k3s-default-worker-0   rancher/k3s:v1.0.1   
k3d-k3s-default-server     rancher/k3s:v1.0.1   0.0.0.0:6443->6443/tcp
registry-private           registry:2           0.0.0.0:5000->5000/tcp

$ docker exec k3d-k3s-default-server \
  cat /var/lib/rancher/k3s/agent/etc/containerd/config.toml
   :
[plugins.cri.registry.mirrors."docker.io"]
  endpoint = ["http://registry-private:5000"]

[plugins.cri.registry.mirrors."k8s.gcr.io"]
  endpoint = ["http://registry-private:5000"]

[plugins.cri.registry.mirrors."quay.io"]
  endpoint = ["http://registry-private:5000"]

[plugins.cri.registry.mirrors."registry.local:5000"]
  endpoint = ["http://registry-private:5000"]

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
1b7b3c23ff23        bridge              bridge              local
896cb12f5c0c        host                host                local
d3fbe09b8f27        k3d-k3s-default     bridge              local
b5dbe20949f1        none                null                local

$ docker inspect k3d-k3s-default
   :
        "Containers": {
            "73272ab8a2f604e1b15817342e89d71c5b3e719124ab5c9bcd9b4dd7ca5f3d0b": {
                "Name": "k3d-k3s-default-server",
                "EndpointID": "65146f7d73250887866cc548575c8974ee64ea582725d3459cc34df2a4b1475b",
                "MacAddress": "02:42:ac:16:00:03",
                "IPv4Address": "172.22.0.3/16",
                "IPv6Address": ""
            },
            "b55c1595485adc3590957459ffd60054a976552a9f4a4d708172f61165c20378": {
                "Name": "k3d-k3s-default-worker-0",
                "EndpointID": "e3adfba170bc313325f28327c619ce5cfb57e0aa6e957105bbdcc65430ab1b9f",
                "MacAddress": "02:42:ac:16:00:04",
                "IPv4Address": "172.22.0.4/16",
                "IPv6Address": ""
            },
            "cdbf6f96ed2b60984c74aa70d63b3a1e959c707555140a9f151cfa7ec30a2c2d": {
                "Name": "registry-private",
                "EndpointID": "ff43f8271069b9161fbf6516e4012746b01dfb17c8246174f308dd36007d0284",
                "MacAddress": "02:42:ac:16:00:02",
                "IPv4Address": "172.22.0.2/16",
                "IPv6Address": ""
            },
            "e91c0c65d427a1a1176dd640735bbc042b5f897ce92b918a363604cfb4f8b4ee": {
                "Name": "k3d-k3s-default-worker-1",
                "EndpointID": "5d4e1cc3cdf87c176d1fecc39eadf07b77d83611bca7d5853bc169fb6424357a",
                "MacAddress": "02:42:ac:16:00:05",
                "IPv4Address": "172.22.0.5/16",
                "IPv6Address": ""
            }
        }
   :
```

k3sクラスタ上のpodの状態

```
$ export KUBECONFIG="$(k3d get-kubeconfig --name='k3s-default')"
$ kubectl get pods -A
NAMESPACE     NAME                                      READY   STATUS      RESTARTS   AGE
kube-system   metrics-server-6d684c7b5-89l5j            1/1     Running     0          2m19s
kube-system   local-path-provisioner-58fb86bdfd-5wn9c   1/1     Running     0          2m19s
kube-system   helm-install-traefik-llgh8                0/1     Completed   0          2m21s
kube-system   coredns-d798c9dd-k8zp4                    1/1     Running     0          2m19s
kube-system   svclb-traefik-j2ccw                       3/3     Running     0          99s
kube-system   svclb-traefik-2glcm                       3/3     Running     0          99s
kube-system   svclb-traefik-pws9p                       3/3     Running     0          99s
kube-system   traefik-65bccdc4bd-wkn7k                  1/1     Running     0          99s
```
</div></details>

<details><summary>local registryを使う（クリックで開く）</summary><div>

```
$ docker pull nginx:latest
```

```
$ docker tag nginx:latest localhost:5000/nginx:latest
```

```
$ docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}"
REPOSITORY                           TAG                 IMAGE ID
nginx                                latest              ed21b7a8aee9
localhost:5000/nginx                 latest              ed21b7a8aee9
```
```
$ docker push localhost:5000/nginx
```

```
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-test-registry
  labels:
    app: nginx-test-registry
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-test-registry
  template:
    metadata:
      labels:
        app: nginx-test-registry
    spec:
      containers:
      - name: nginx-test-registry
        image: registry.local:5000/nginx:latest
        ports:
        - containerPort: 80
EOF

$ kubectl get pods -l "app=nginx-test-registry"
NAME                                  READY   STATUS    RESTARTS   AGE
nginx-test-registry-6464cff59-zpl9h   1/1     Running   0          20s
```
</div></details>


### 削除(registryを残して)
```
$ k3d delete
```
### 削除(作成したもの全て)
```
$ docker rm -f registry-private 
$ k3d delete
$ rm -rf ~/registry

#以下はNetworkが削除されなかった場合
$ docker network disconnect k3d-k3s-default registry-private
$ docker network rm k3d-k3s-default
```