はじめに
はじめまして、マネーフォワード サービス基盤本部 PlatformSREチームのshiyunyaです。
DockerHubの通常の有料プランには一日あたり5000件のPull数制限がありますが、先日その対応としてコンテナレジストリであるHarborを導入しました。
Harborとは、オープンソースのコンテナレジストリです。 主な特徴として、ロールベースアクセス制御・イメージの脆弱性スキャン・マルチテナント・レジストリのレプリケーションなどが挙げられます。
本記事では、Harborを導入した際の幾つかのポイントを紹介します。
Harbor導入における課題
Harborを導入し、運用する上で課題となる点は以下の通りです。
- 使用イメージのHarborへの保存
- HarborからイメージをPullするためにはHarbor上にイメージが保存されている必要があります。
- 使用レジストリの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程度となりました!
おわりに
マネーフォワードのサービス基盤本部ではエンジニアを募集しています!! マネーフォワードの開発生産性を一緒に向上させていきましょう!