Money Forward Developers Blog

株式会社マネーフォワード公式開発者向けブログです。技術や開発手法、イベント登壇などを発信します。サービスに関するご質問は、各サービス窓口までご連絡ください。

20230215130734

DockerHub Pull数制限の対策としてHarborを導入した話

はじめに

はじめまして、マネーフォワード サービス基盤本部 PlatformSREチームのshiyunyaです。

DockerHubの通常の有料プランには一日あたり5000件のPull数制限がありますが、先日その対応としてコンテナレジストリであるHarborを導入しました。

Harborとは、オープンソースのコンテナレジストリです。 主な特徴として、ロールベースアクセス制御・イメージの脆弱性スキャン・マルチテナント・レジストリのレプリケーションなどが挙げられます。

本記事では、Harborを導入した際の幾つかのポイントを紹介します。

Harbor導入における課題

Harborを導入し、運用する上で課題となる点は以下の通りです。

  1. 使用イメージのHarborへの保存
    • HarborからイメージをPullするためにはHarbor上にイメージが保存されている必要があります。
  2. 使用レジストリのHarborへの移行
    • 使用しているコンテナイメージのレジストリをDockerHubからHarborに置き換える必要があります。

マネーフォワードには数え切れないほどのサービスやその開発環境があります。 それらで使用されるDockerHubイメージ全てに対して上記の対応をするのは困難であり、今後の運用にも負担がかかります。

Harborの導入

アーキテクチャ

Deploying Harbor with High Availability via Helmという記事を参考にします。 図のHA pgSQLにはAuroraを使用します。 HA RedisとしてErastiCacheクラスタを使用しようとしましたが、HarborはRedisのtlsに対応していなかったためPod上のRedisを使用することにしました。 画像引用:Deploying Harbor with High Availability via Helm

導入手順

導入手順は以下のような流れです。

外部DBの構築

Harborのプロジェクトやユーザ、イメージなどのメタデータを保存する外部DBを構築します。 アーキテクチャで述べたように、Auroraを使用します。

Harborの構築

HarborのHelm Chartを用いてEKSクラスタに構築します。 外部DBを上記のAuroraに設定します。

Harbor ProjectのProxy Cache設定

Proxy Cacheを行うHarbor Projectを設定します。 Proxy Cacheとは、イメージPullのリクエスト時、該当イメージがなければ対象レジストリからイメージをPullし、保存してくれる機能です。 この機能によって、課題1「使用イメージのHarborへの保存」を解決できます。

今回はTerraformのHarbor Providerを用いてHarborの設定をします。 以下のように外部レジストリとしてDockerHubを指定することで、DockerHubのProxyとして使用することができます。

resource "harbor_project" "dockerhub" {
  name        = "dockerio"
  registry_id = harbor_registry.dockerhub.registry_id
}

resource "harbor_registry" "dockerhub" {
  provider_name = "docker-hub"
  name          = "docker-hub-mirror"
  endpoint_url  = "https://hub.docker.com"
  access_id     = var.dockerhub_user
  access_secret = var.dockerhub_token
}

resource "harbor_project"はHarbor内のコンテナイメージの管理単位であるProjectを作成します。 Project毎にProxy Cacheやアクセス制御の設定が可能です。 resource "harbor_registry"は、Proxy Cacheのターゲットレジストリである外部のエンドポイントを作成します。

ミラーレジストリの設定

EKSノード上のcontainerdにHarborをDockerHubのミラーレジストリとしての設定を加えます。 ミラーレジストリの設定により、containerdはDockerHubからのPullをHarborに置き換えてくれます。 これにより、課題2「使用レジストリのHarborへの移行」を解決できます。

我々はkarpenterを用いてEKSノードを管理しているため、AWSNodeTemplateを以下のように設定します。

apiVersion: karpenter.k8s.aws/v1alpha1
kind: AWSNodeTemplate
metadata:
  name: default
spec:

  ~~~~~~~~~~~~~~~ 省略 ~~~~~~~~~~~~~~~

  userData: |
    #!/bin/bash
    mkdir -p /etc/containerd/certs.d/docker.io/
    CONTAINERD_HOST_CONFIG_FILE_PATH="/etc/containerd/certs.d/docker.io/hosts.toml"
    cat > $CONTAINERD_HOST_CONFIG_FILE_PATH <<- EOM
    server = "https://docker.io"

    # harbor on test
    [host."https://<harbor host>/v2/dockerio"]
      capabilities = ["pull", "resolve"]
      override_path = true

    # DockerHub
    [host."https://registry-1.docker.io"]
      capabilities = ["pull", "resolve"]
    EOM

    cat $CONTAINERD_HOST_CONFIG_FILE_PATH

spec.userDataではノード起動時の実行スクリプトを設定します。 /etc/containerd/certs.d/docker.io/hosts.tomlにcontainerdにおけるDockerHubの接続先ホストの設定を流し込みます。 設定に関する詳細はこちらを参照ください。

対応結果

上記のようにHarborを導入し、開発環境・テスト環境においてHarborを使用するようにした結果、一日当たりのPull数は元々の1/25程度となりました!

おわりに

マネーフォワードのサービス基盤本部ではエンジニアを募集しています!! マネーフォワードの開発生産性を一緒に向上させていきましょう!

hrmos.co