k8s上にDockerプライベートレジストリ構築

開発してるとDockerのイメージをpushするところって迷うじゃないですか。
AWSで作っていればECR、GCPの場合にはGCRを使えばよいわけですが、家のサーバで開発しているときは？

まぁGCRやECRを使ってもよいのですが、近いところに欲しいですよね。
GCRを使う場合はこちらを参考にどうぞ。
[オンプレのk8sのDockerレジストリにGCRを使う](https://qiita.com/murata-tomohide/items/891059ab645173d1e7f2)

Dockerのレジストリはhttpをしゃべるのでそんなに構築は難しくないみたいです。公式のDockerImageも用意されているのでそれを使えば一瞬さ？

でもk8sと同じサーバだと止まったときにデプロイできなくなるし、なんだかんだでせめて別サーバorクラウドなんじゃないかと、うっすら感じてはいる。

※httpsで通信できる必要があり〼。(insecureにすることでhttpでも可能ですが逆に面倒です。)

# tl;dr

k8sのクラスタにDocker registryを展開して、そこにpush＆k8sプロビジョニングします。

# Docker registryをk8sのyamlで作成する。

ここに公式イメージがある。
https://hub.docker.com/_/registry
レジストリだけ。GUIはない。


## k8s マニフェストyaml作成

registryのバージョンは2.7.1にした。ホストの`/kube/docker-registry-data`が `/var/lib/registry`にマウントされる。
envで認証周りの環境変数を渡す。

```yaml:docker-registry.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: docker-registry
  labels:
    app: docker-registry
spec:
  replicas: 1
  selector:
    matchLabels:
      app: docker-registry
  template:
    metadata:
      labels:
        app: docker-registry
    spec:
      containers:
      - name: docker-registry
        image: registry:2.7.1
        env:
          - name: REGISTRY_AUTH
            value: htpasswd
          - name: REGISTRY_AUTH_HTPASSWD_PATH
            value: "/var/lib/registry/auth/htpasswd"
          - name: REGISTRY_AUTH_HTPASSWD_REALM
            value: "Registry Realm"
          - name: REGISTRY_HTTP_HOST
            value: "https://docker.deroris.net"
        ports:
        - containerPort: 5000
        volumeMounts:
        - name: registry
          mountPath: /var/lib/registry
      volumes:
      - name: registry
        hostPath:
          type: Directory
          path: /kube/docker-registry-data
---
kind: Service
apiVersion: v1
metadata:
  name: docker-registry
spec:
  ports:
  - name: "http-port"
    protocol: TCP
    port: 80
    targetPort: 5000
  selector:
    app: docker-registry

```


## htpasswdの設定

↑でhtpasswd形式の認証にしたので、htpasswdファイルを作成する。

**注意** htpasswdファイルはbcryptオンリーで、registry:2.7からhtpasswdコマンドも同梱されなくなった模様。

適当なサーバでbcrypt形式のhtpasswdファイルを作成する。
リファレンス: https://httpd.apache.org/docs/2.4/programs/htpasswd.html

ホストのサーバでマウント先で直接作った。

```bash

[root@deroris auth]# pwd
/kube/docker-registry-data/auth
[root@deroris auth]# /usr/local/httpd/bin/htpasswd -cB ./htpasswd oreore
New password:
Re-type new password:
Adding password for user oreore
[root@deroris auth]# cat htpasswd
oreore:$2y$05$VVPZkdkwbBHdUlLfCEuWGO3UMVgdQ5HVgRNKoQ3HjKypJpFr6DhEO
```


# リバプロの設定する。

手を抜いて一番フロントにいるApacheからk8sのServiceに直接続した。（良い子のみんなはやったらだめだぞ）
Ingress使っている人はちゃんとそれで設定してください。443に来たものをレジストリの80に流せばおｋです。


```apache

# docker.deroris.net
<VirtualHost *:443>
    ServerName docker.deroris.net

    SSLEngine on
    SSLProxyEngine on
    SSLHonorCipherOrder on
    SSLProtocol All -SSLv2 -SSLv3
    SSLCipherSuite !3DES:!aNULL:EDH+HIGH:ECDH+HIGH:-AES128:-3DES:-DSS:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA
    SSLCertificateFile /etc/letsencrypt/live/deroris.net/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/deroris.net/privkey.pem

    ProxyRequests Off
    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>
    ProxyPass / http://10.103.17.215/
    ProxyPassReverse / http://10.103.17.215/
    ProxyPreserveHost On
</VirtualHost>
```

別ホストからつながるか確認。とりあえずなんかかえってくればよかろう。

```
murata:~ $ curl https://docker.deroris.net/v2/
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":null}]}
```


# push, pullできるか確認

動作確認しましょ。

## docker login

別ホストからログイン

```
murata:~ $ docker login docker.deroris.net
Username: oreore
Password:
WARNING! Your password will be stored unencrypted in /home/murata/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
```

## pull/push

適当なイメージをpullしてpush

```
murata:~ $ docker image pull fedora
Using default tag: latest
latest: Pulling from library/fedora
4c69497db035: Pull complete
Digest: sha256:ee55117b3058f2f12961184fae4b9c392586e400487626c6bd0d15b4eae94ecc
Status: Downloaded newer image for fedora:latest
docker.io/library/fedora:latest
murata:~ $ docker push docker.deroris.net/orega-fedora
The push refers to repository [docker.deroris.net/orega-fedora]
3b53a1a1ef4a: Pushed
latest: digest: sha256:829948d9a54ca9926c7fa01a976bbeccf38d66e85b558ca61f4b589246ab2d26 size: 529
```

これで上がっているはず。

ホストOSでディレクトリができているのが確認できる。

```
[root@deroris repositories]# pwd
/kube/docker-registry-data/docker/registry/v2/repositories
[root@deroris repositories]# ll
合計 0
drwxr-xr-x 5 root root 55  7月  7 18:34 orega-fedora
drwxr-xr-x 5 root root 55  7月  7 18:28 ubu
[root@deroris repositories]# ll orega-fedora/
合計 0
drwxr-xr-x 3 root root 20  7月  7 18:34 _layers
drwxr-xr-x 4 root root 35  7月  7 18:34 _manifests
drwxr-xr-x 2 root root  6  7月  7 18:34 _uploads
```


# k8sにユーザー設定

ここまではただのDockerレジストリの構築。
k8sのデプロイで利用するにはk8sが↑のレジストリに接続できる必要がある。

これを参考にk8sにレジストリの認証情報を設定してみよう。
https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/

適当にk8s用のdocker configを作る。configファイルをそのまま使うので、新しく作ったほうがいい。

```
╭─murata@deroris ~
╰─$ DOCKER_CONFIG=~/k8s-docker.config docker login docker.deroris.net
Username: oreore
Password:
WARNING! Your password will be stored unencrypted in /home/murata/k8s-docker.config/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
```

secretを作成する。

```
╭─murata@deroris ~
╰─$ kubectl create secret generic k8s-user \
    --from-file=.dockerconfigjson=/home/murata/k8s-docker.config/config.json \
    --type=kubernetes.io/dockerconfigjson
secret/k8s-user created
```

できてる。

```
╭─murata@deroris ~
╰─$ kubectl get secret
NAME                  TYPE                                  DATA   AGE
default-token-8bwmk   kubernetes.io/service-account-token   3      119m
k8s-user              kubernetes.io/dockerconfigjson        1      48s
```

こんな感じで先ほどあげたイメージを上げてみよう。
imageに先ほどのレジストリのイメージを指定、imagePullSecretsにkubectl create secretした名前を入れる。

```
cat <<EOF | kubectl apply -f -
kind: Deployment
apiVersion: apps/v1
metadata:
  name: fedora
spec:
  replicas: 1
  selector:
    matchLabels:
      app: fedora
  template:
    metadata:
      labels:
        app: fedora
    spec:
      containers:
      - args:
        image: docker.deroris.net/orega-fedora:latest
        imagePullPolicy: Always
        name: fedora
        command: ["sleep","3600"]
      imagePullSecrets:
        - name: k8s-user
EOF
```

ちゃんとfedoraちゃんのpodが動いている。

```
╭─murata@deroris ~
╰─$ kubectl get all
NAME                                   READY   STATUS    RESTARTS   AGE
pod/docker-registry-77599d7bc9-44rgv   1/1     Running   0          88m
pod/fedora-7c4d977b8f-v4cqj            1/1     Running   0          73s

NAME                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/docker-registry   ClusterIP   10.103.17.215   <none>        80/TCP    129m

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/docker-registry   1/1     1            1           129m
deployment.apps/fedora            1/1     1            1           73s

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/docker-registry-695f6cfdfc   0         0         0       93m
replicaset.apps/docker-registry-75d44c887b   0         0         0       129m
replicaset.apps/docker-registry-77599d7bc9   1         1         1       95m
replicaset.apps/docker-registry-fd6788bb4    0         0         0       91m
replicaset.apps/fedora-7c4d977b8f            1         1         1       73s
```

describe してみてもちゃんと作ったイメージを使っているね。

```
╭─murata@deroris ~
╰─$ kubectl describe pod/fedora-7c4d977b8f-v4cqj
Name:         fedora-7c4d977b8f-v4cqj
Namespace:    reg-docker
Priority:     0
Node:         deroris.net/***.***.***.***
Start Time:   Tue, 07 Jul 2020 19:13:14 +0900
Labels:       app=fedora
              pod-template-hash=7c4d977b8f
Annotations:  cni.projectcalico.org/podIP: 10.244.0.73/32
              cni.projectcalico.org/podIPs: 10.244.0.73/32
Status:       Running
IP:           10.244.0.73
IPs:
  IP:           10.244.0.73
Controlled By:  ReplicaSet/fedora-7c4d977b8f
Containers:
  fedora:
    Container ID:  docker://8a8ef69c98bc56df757a83d7fc75cdbe45187310cfaf5eafa98817e914f6ce92
    Image:         docker.deroris.net/orega-fedora:latest
    Image ID:      docker-pullable://docker.deroris.net/orega-fedora@sha256:829948d9a54ca9926c7fa01a976bbeccf38d66e85b558ca61f4b589246ab2d26
    Port:          <none>
    Host Port:     <none>
    Command:
      sleep
      3600
    State:          Running
      Started:      Tue, 07 Jul 2020 19:13:15 +0900
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-8bwmk (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-8bwmk:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-8bwmk
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age   From                  Message
  ----    ------     ----  ----                  -------
  Normal  Scheduled  110s  default-scheduler     Successfully assigned reg-docker/fedora-7c4d977b8f-v4cqj to deroris.net
  Normal  Pulling    109s  kubelet, deroris.net  Pulling image "docker.deroris.net/orega-fedora:latest"
  Normal  Pulled     109s  kubelet, deroris.net  Successfully pulled image "docker.deroris.net/orega-fedora:latest"
  Normal  Created    109s  kubelet, deroris.net  Created container fedora
  Normal  Started    109s  kubelet, deroris.net  Started container fedora
```


# 終わりに。

- proxyとしても動作できるようで、docker-hubのプロキシをローカルネットワーク内に置くこともできそう。
- ストレージにはローカルのほかにs3やgcs, azureなども使える模様。
- 認証の設定が入るので気軽に自前するのはよくないと思う。
- ほんとはpv,pvcを使ったほうがいい。
- 自身のk8sとは別のホストを使ったほうがいいと思う。

→あれ？GCRとかECR、せめてdocker-hub使ったほうがいいんじゃないかな・・・

ローカルのネットワーク内にたてる場合には、、、まぁあってもいいかもよ。。。

公式
https://docs.docker.com/registry/