Harbor with Rancher

# はじめに
今回はコンテナレジストリである Harbor を Rancher から Deploy します。
コンテナイメージの保存、公開をする際に利用するソフトウェアであるコンテナレジストリですが、
有名どころとしては docker registry や docker hub を利用されている方は多いと思います。
CNCF の１プロジェクトである Harbor には以下の機能を有しています。

* RBAC
* Web UI
* イメージの脆弱性スキャン

この他にも有用な機能がありますので、詳細は[公式 Harbor](https://goharbor.io/) のページで。

# 環境情報
docker-ce：18.09
kubernetes：1.17
Rancher：2.4.2
Longhorn：0.8.0
HARBOR：1.9.1

※以前の記事でも載せていますが、vagrant 上の CentOS でクラスタを組んでます。
※PV/PVC として Longhorn を利用しています
⇒構築は[こちら](https://qiita.com/t_ume/items/425f7c93e2e7cfaa7d1c)を参照ください。

# Deploy

早速 Deploy します。

Rancher の library catalog に含まれているので、「apps」⇒「起動」から Deploy します。

![qiita001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317159/0448e00d-20ef-04c2-e802-d32bd17608eb.jpeg)

テンプレートバージョンは「1.2.0」です。
名前、名前空間はデフォルトの「harbor」です。

![qiita002.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317159/11483eed-4cac-9f97-4558-0666f81f6f26.jpeg)

以下、指定していきます
※指定なしはデフォルトの値で

The Initial Password for Harbor Admin：admin ユーザのパスワードを指定します

Harbor Proxy Service Type：ingress
Ingress Hostname of Harbor：core.harbor.invalid（任意）
Ingress Hostname of Harbor Notary：notary.harbor.invalid（任意）
Select Your Harbor TLS Certificate：デフォルト（指定なし）
※Harbor への アクセス経路を指定します。
⇒今回は harbor へのアクセスの際に hosts ファイルに、指定した Hostname を登録します（Worker ノードを一台選出して登録します）

Enable Harbor Persistent Volume：はい
※k8s のデフォルトのストレージクラスに Longhorn を設定しています
※永続 Volume のサイズについては適宜指定してください（デフォルトでは各 5G x4 必要です）

![qiita003.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317159/8253d7ed-6f25-0e9f-266f-d66040cebf7f.jpeg)

15～30分ほどで Deploy 完了するかと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317159/c546e1f6-2efe-b611-e9e5-7afc58363ba5.png)

# Web UI
Deploy 完了したので実際に Web UI にアクセスします。
Web UI：https://core.harbor.invalid/



※今回は DNS への登録は行っていないため、アクセスする際はクライアント端末の hosts にレコードを追加しています。
ex) Windows の場合、「C:\Windows\System32\drivers\etc\hosts」に以下を追記

```
# 192.168.10.51 は worker#1 のアドレス
192.168.10.51 core.harbor.invalid
192.168.10.51 notary.harbor.invalid
```

Apps の Harbor から各エンドポイントも参照できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317159/d4dcbcd5-57b5-6d6c-e584-1291aab38efd.png)

ログイン画面が表示されるので、UserName に「admin」、Password に Deploy 時に指定したパスワードを入力してログインします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317159/075297f0-815c-89cb-f08c-4c401b16facf.png)

ログイン後は Project 一覧画面に遷移します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317159/49fc30d0-11e4-e7e1-c51b-2d37bfeacec2.png)

後工程で image push を試したいので、試験用に Porject を作成します。
「New Project」ボタンを押下し、以下で Project を作成します。

Project Name：sandbox (任意)
Access Level：チェック無し (デフォルト)
Count quota：-1 (デフォルト)
Storage quota：-1 (デフォルト)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317159/db59f382-bcd8-f9ea-cb0d-2d550660aa24.png)

Web UI からは他にもユーザ作成や作業履歴、各種タスクが実行できます。

# docker image push

作成した Project にコンテナイメージを push します。
まずは作業端末(docker インストール済み)に証明書を導入します。
※私の場合は Rancher & Controller/etcd サーバで実施しています。

Rancher の管理画面から、「リソース」⇒「シークレット」に証明書管理ページがあります。

Harbor を Deploy したときに自動で登録されている証明書が表示されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317159/669ae328-2233-9735-3490-da25b414e5d3.png)

対象の証明書(今回は harbor-harbor-ingress)を編集し、「CA Certificate」の内容をコピーしておきます。
※CA Certificate の内容は編集せずに「キャンセル」で抜けます

作業端末で以下作業実施します。

```bash:証明書登録
# 証明書配置ディレクトリを作成
# Ingress で登録した hostname と同名のディレクトリを作成
$ mkdir /etc/docker/certs.d/core.harbor.invalid

# 上記でコピーした CA Certificate の内容を以下ファイルに貼付けて保存する
$ vi /etc/docker/certs.d/core.harbor.invalid/ca.crt

# docker に反映させるため、docker サービスを再起動する
$ systemctl restart docker

```

再起動が完了したら準備は完了です。
今回は alpine イメージを取得(pull)し、harbor に登録(push)していきます。

```bash:harborにimageをpush
# alpine:edge イメージを取得
$ docker pull alpine:edge
edge: Pulling from library/alpine
・・・
Status: Downloaded newer image for alpine:edge
docker.io/library/alpine:edge

# harbor 登録用にタグ付けする
# image id 確認
$ docker images alpine:edge
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
alpine              edge                24cae4d038c0        3 weeks ago         5.58MB

# タグ付け
# docker tag <image id> <hostname>/<project name>/<image name>:<tag>
# project name は Web UI で登録したプロジェクト名を入力する
$ docker tag 24cae4d038c0 core.harbor.invalid/sandbox/alpine:edge
$ docker images core.harbor.invalid/sandbox/alpine:edge
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
core.harbor.invalid/sandbox/alpine   edge                24cae4d038c0        3 weeks ago         5.58MB

# image push 
# push する前に DNS 登録していないので、hosts にアドレスを登録する
$ echo 192.168.10.51 core.harbor.invalid >> /etc/hosts

# docker login
$ docker login -u admin core.harbor.invalid
Password: ★admin のパスワードを入力
・・・
Login Succeeded

# docker push 
$ docker push core.harbor.invalid/sandbox/alpine:edge
The push refers to repository [core.harbor.invalid/sandbox/alpine]
xxxx: Pushed
edge: digest: sha256:xxxx size: xxx

```

Web UI から確認すると、イメージが登録されていることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317159/d3eac7d2-1dfd-10ee-ea78-bb93d2de0a32.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317159/f71794e1-eee6-2f3e-9b05-350b644972b9.png)

# Pod Deploy
最後に登録した Image を使って Deploy をしてみましょう。
今回は DNS 登録を行っていないため、各 Worker の ```/etc/hosts``` に harbor のアドレスを登録します。

```bash:各workerで実行
# 今回は共通でworker#1のアドレスを指定
$ echo 192.168.10.51 core.harbor.invalid >> /etc/hosts
```

次に Rancher から registory の登録を行います。
「リソース」⇒「シークレット」⇒「レジストリ」と辿り、「レジストリ追加」ボタンを押下します。
以下入力内容でレジストリを登録します。

名前：harbor (任意)
アドレス：カスタム - core.harbor.invalid (harbor の URL を指定)
ユーザ名：admin
パスワード：harbor を Deploy 時に指定したパスワード

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317159/79d0f6a0-270c-d0a2-6920-9aa8ef66c029.png)

Pod を Deploy します。
※imagePullSecrets に登録したレジストリの名前を設定します。

```yaml:pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: alpine
  namespace: default
spec:
  containers:
  - image: core.harbor.invalid/sandbox/alpine:edge
    name: alpine
    tty: true
  imagePullSecrets:
  - name: harbor
```

```bash:pod_deploy
$ kubectl apply -f pod.yaml
pod/alpine created

$ kubectl get po
NAME                       READY   STATUS    RESTARTS   AGE
alpine                     1/1     Running   0          2m31s

$ kc describe po alpine
Name:               alpine
Namespace:          default
・・・
Containers:
  alpine:
    Container ID:   docker://xxxx
    Image:          core.harbor.invalid/sandbox/alpine:edge
    Image ID:       docker-pullable://core.harbor.invalid/sandbox/alpine@sha256:xxxx
・・・
Events:
  Type    Reason     Age        From               Message
  ----    ------     ----       ----               -------
  Normal  Scheduled  <unknown>  default-scheduler  Successfully assigned default/alpine to minion02
  Normal  Pulling    7m12s      kubelet, minion02  Pulling image "core.harbor.invalid/sandbox/alpine:edge"
  Normal  Pulled     7m11s      kubelet, minion02  Successfully pulled image "core.harbor.invalid/sandbox/alpine:edge"
  Normal  Created    7m11s      kubelet, minion02  Created container alpine
  Normal  Started    7m11s      kubelet, minion02  Started container alpine
```

# おわりに
証明書や DNS の登録に手間取りましたが、Deploy 事態は Rancher から簡単にできました。
docker registry には無い Web UI も使い勝手よく、イメージの削除なども簡単に行えるの便利かと思います。
Harbor の Image Scan や署名機能なども使っていけると実用的になるのかもしれませんね。