Private Docker Registry(プライベートレジストリ) on Kubernetes

はじめに

以前下記の記事でdockerを用いて作成した,private docker registryをkubernetes cluster上にデプロイしてみます.

tenzen.hatenablog.com

ついでにストレージも以前下記記事でRookを用いて,作成したCeph-fsを用いてデータの永続化をします.

tenzen.hatenablog.com

また,今回サービスの公開でIngress Nginx Controllerを使用しました.

いつものことですが,本記事は以下の書籍を参考にさせてもらっています.

Kubernetes完全ガイド (impress top gear)

Kubernetes完全ガイド (impress top gear)

  • 作者:青山 真也
  • 発売日: 2018/09/21
  • メディア: 単行本(ソフトカバー)

Persistent Volumeの作成

Docker Registryでは以下の公式GitHubにあるような永続ストレージをサポートしています.

github.com

しかしながら,SQLには対応してないようなのでそこが少しイマイチかもしれません.Docker RegistryはDockerfileも公開されていないため自分でSQL対応させることも難しく,なんとかして欲しい気持ちではあります.

RookによりCeph-fsの構築が終わっているので,以下のようなマニフェスト「pvc.yaml」を作成して永続ボリュームの作成を行います.

kind: Namespace
apiVersion: v1
metadata:
  name: registry
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: registry-pvc
  namespace: registry
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 100Gi #set requests Volume size.
  storageClassName: csi-cephfs

デプロイします.

$ kubectl apply -f pvc.yaml
$
$ kubectl get pvc -n registry
NAME           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
registry-pvc   Bound    pvc-60116d0f-a6ec-47b4-a751-f2f5202e6e01   100Gi      RWX            csi-cephfs     10h

Private Docker Registryデプロイ

使用するイメージ自体はdockerで建てる時と変わらないですが,deploymentを用いてデプロイしていきます.以下のような「docker_registry_deployment.yaml」を作成してください.

deploymentでは回復性も考慮してReplica数3で作成しました.nginx ingress controllerを使用する際,今回バックエンドのサービスはClusterIPで構築していきます.NodePortでも構いません.

kind: Service
apiVersion: v1
metadata:
  name: pregistry-nodeport
  namespace: registry
spec:
  selector:
    app: pregistry
  type: ClusterIP
  ports:
  - protocol: TCP
    port: 5000
    targetPort: 5000
    name: registry-http
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pregistry-deployment
  namespace: registry
spec:
  replicas: 1
  selector:
    matchLabels:
      app: pregistry
  template:
    metadata:
      labels:
        app: pregistry
    spec:
      containers:
        - name: pregistry-container
          image: registry:2.7.1
          volumeMounts:
          - mountPath: "/var/lib/registry"
            name: registry-pvc
          ports:
          - containerPort: 5000
      volumes:
        - name: registry-pvc
          persistentVolumeClaim:
            claimName: registry-pvc
            readOnly: false

デプロイします.

$ kubectl apply -f docker_registry_deployment.yaml

Private Docker Registry Frontendのデプロイ

今回も前回と同様にWEBUIにdocker-registry-frontendを使用していきます. まず,以下のようなdocker-registry-frontendで使用する設定値をまとめたConfigMapのマニフェスト「docker_registry_configmap.yaml」を作成してください.pregistry_proxy_fqdnにはアクセスする際に使用する外部IPアドレスを設定してください.他にカスタマイズしたい設定がある場合はGitHubの公式リポジトリにある引数を使えば設定できます.

github.com

apiVersion: v1
kind: ConfigMap
metadata:
  name: pregistry-configmap
  namespace: registry
data:
  pregistry_host: pregistry-clusterip
  pregistry_port: "5000"
  pregistry_proxy_fqdn: "xxx.xxx.xxx.xxx"

次に,以下のような「docker_registry_frontend_deployment.yaml」を作成してください. 「Private Docker Registryのデプロイ」の章で行ったのと同様にバックエンドサービスにClusterIPを使用し,Replica数3でdeploymentを作成しています.

kind: Service
apiVersion: v1
metadata:
  name: pregistry-frontend-clusterip
  namespace: registry
spec:
  selector:
    app: pregistry-frontend
  type: ClusterIP
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80  
    name: registry-http-frontend
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pregistry-frontend-deployment
  namespace: registry
spec:
  replicas: 1
  selector:
    matchLabels:
      app: pregistry-frontend
  template: 
    metadata:
      labels: 
        app: pregistry-frontend
    spec:
      containers:
      - name: pregistry-frontend-container
        image: konradkleine/docker-registry-frontend:v2
        ports:
        - containerPort: 80
        env:
        - name: ENV_DOCKER_REGISTRY_HOST
          valueFrom:
              configMapKeyRef:
                name: pregistry-configmap
                key: pregistry_host
        - name: ENV_DOCKER_REGISTRY_PORT
          valueFrom:
              configMapKeyRef:
                name: pregistry-configmap
                key: pregistry_port
        - name: ENV_REGISTRY_PROXY_FQDN
          valueFrom:
            configMapKeyRef:
              name: pregistry-configmap
              key: pregistry_proxy_fqdn

デプロイしてください.

$ kubectl appluy -f docker_registry_frontend_deployment.yaml

Ingress Nginx Controller

Ingress Nginx Controllerとは

Ingress Nginx Controllerについては GitLab Runner on Kubernetesに敗北した話 - てんぜんの生存日誌で説明しましたので,概略図だけ貼っておきます.下記図ではServiceにNodeportを使用していますが,今回はClusterIPを使用しています.

nginx_ingress_resource
Ingress Nginx

Ingressリソースの実装

まずはじめにIngressリソースで使用するロードバランサとしてMetalLBを準備します.下記のGItHubリポジトリからマニフェストをダウンロードしてきてください.

さらに,下記のようなMetalLB用のconfigMapである「metallb_confingmap.yaml」を作成してください. 「xxx.xxx.xxx.xxx-xxx.xxx.xxx.xxx」にはロードバランサで使用するIPアドレスの範囲を指定してください.

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: metallb-ip-range
      protocol: layer2
      addresses:
      - xxx.xxx.xxx.xxx-xxx.xxx.xxx.xxx

ロードバランサの準備ができたので,Ingress Nginxを準備していきます. 下記のGitHubリポジトリからIngress Nginx用のマニフェストを2つダウンロードしてきます.

  1. mandatory.yaml github.com

  2. cloud-generic.yaml github.com

ダウンロードしてきたマニフェストで変更する部分は特にありません.

次に以下のような「registry_ingress.yaml」を作成します. 本来ならパスベースルーティングでspec.rules.http.paths.pathでパスを変えてルーティングが行えるのですが,docker registryがrootでのアクセスにしか対応してない模様です.また,docker-registry-frontendの方もリライトがうまく働かないようで,繋がりはしますがトップページにたどり着けませんでした. しかしながら,フロントもdocker registryもどちらも「/」で指定した場合でもなぜかちゃんとルーティングできました.(うまくいかなかったらhost名でルーティングしてください.)そのため下記マニフェストではどちらもパスが「/」になっています.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: pregistry-ingress
  namespace: registry
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: sample.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: pregistry-frontend-nodeport
          servicePort: 80
      - path: /
        backend:
          serviceName: pregistry-nodeport
          servicePort: 5000

デプロイします.

$ kubectl apply -f metallb.yaml
$ kubectl apply -f metallb_confingmap.yaml
$ kubectl apply -f mandatory.yaml
$ kubectl apply -f cloud-generic.yaml
$ kubectl apply -f registry_ingress.yaml

以上で終了です.ブラウザでIngressにおいて指定したホスト名(上記例ならsample.example.com)でアクセスすると Private Docker Registry(プライベートレジストリ)の構築 - てんぜんの生存日誌と同様にトップページが表示されるはずです.

docker-registry-frontend
Docker RegistryのWEBUI

おわりに

無理やり?kubernetesにPrivate Docker Registryを載せてみましたが,SQLに対応していなかったり,パスベースルーティングがうまくいかなかったりとあまり機能がないのが残念ではありました.

本格的にPrivate Container Registryを建てる場合はCNCFのIncubatingのプロジェクトの一つであるHarborがPrivate Container Registryとしては多機能(SQL対応,コンテナイメージの自動セキュリティチェックなど)で素晴らしいと思うのでそちらを使った方がいいと思います.

goharbor.io

では,またどこかでお会いしましょう.