はじめに
概要
本記事はCephの検証用環境をDockerで作成してみようという試みになります。また作成したCephのテストのためAWS-CLIの環境も一緒に用意しています。
本来Cephは各サービスが複数あることと、物理的に分けられた記憶領域が複数あることが求められます。ですが個人環境にそのような環境を用意することは難易度が高いです。そのためDockerを使って環境を作ることが真っ先に思い浮かびますが、ネット上に参考となる記事があまり見当たりませんでした。
そんな中Apache Polarisの公式リポジトリに非常に参考になるdocker-compose.ymlがありましたので、それをベースに作成してみました。
お断り
概要で述べた通り、本来cephの性能や利点を引き出すための構成になっていません。
とりあえずクリティカルなエラーがなく起動できるようにカスタムし、バケットの作成という簡単なテストしか行っていないため動作が安定しない可能性があります。
UUIDを.envに固定していたり、起動するとkeyringがホストPCに保存されるためセキュリティ面に留意してください。
TLDR
こちらのリポジトリをクローンしてcephフォルダで、docker compose upすると、環境が立ち上がります。
ディレクトリおよびファイル構成
以下のようにディレクトリとファイルを用意しています。
./
├ .env
├ docker-compose.yml
├ ceph/
│ └ ceph.conf
└ dockerfiles/
├ mgr/
│ └ Dockerfile
├ mon1/
│ ├ Dockerfile
│ └ entrypoint.sh
├ osd1/
│ └ Dockerfile
└ rgw1/
└ Dockerfile
Dockerfileおよび関連ファイル
各コンテナのビルドについて解説します。
mon1
mon向けのkeyringを作成しておきます。
entrypointではadmin向けとosdで使うkeyringの有無を確認したのち作成します。
FROM quay.io/ceph/ceph:v20.2.0
USER ceph
RUN ceph-authtool \
--create-keyring /var/lib/ceph/tmp/ceph.mon.keyring \
--gen-key -n mon. \
--cap mon 'allow *'
COPY entrypoint.sh /entrypoint.sh
#!/bin/sh
if [ ! -f "/etc/ceph/ceph.client.admin.keyring" ]; then
echo "Start creating keyrings (Frist time only)"
ceph-authtool \
--create-keyring /etc/ceph/ceph.client.admin.keyring \
--gen-key -n client.admin \
--cap mon 'allow *' \
--cap osd 'allow *' \
--cap mgr 'allow *' \
--cap mds 'allow *'
ceph-authtool \
--create-keyring /etc/ceph/ceph.client.bootstrap-osd.keyring \
--gen-key -n client.bootstrap-osd \
--cap mon 'profile bootstrap-osd' \
--cap mgr 'allow r'
else
echo "Skipping to create keyrings"
fi
exec "$@"
mgr
FROM quay.io/ceph/ceph:v20.2.0
RUN mkdir -p /var/lib/ceph/mgr/ceph-mgr
osd1
osd向けのkeyringを作成しておきます。
FROM quay.io/ceph/ceph:v20.2.0
USER ceph
RUN mkdir -p /var/lib/ceph/osd/ceph-0
RUN ceph-authtool \
--create-keyring /var/lib/ceph/osd/ceph-0/keyring \
--gen-key -n osd.0 \
--cap osd 'allow *' \
--cap mon 'allow profile osd'
rgw1
rgw向けのkeyringを作成しておきます。
FROM quay.io/ceph/ceph:v20.2.0
RUN mkdir -p /var/lib/ceph/radosgw/ceph-rgw1
RUN ceph-authtool \
--create-keyring /var/lib/ceph/radosgw/ceph-rgw1/keyring \
--gen-key -n client.rgw1 \
--cap osd 'allow *' \
--cap mon 'allow *'
docker-compose.ymlおよび関連ファイル
docker-compose.yml
長いですが、以下がdocker-compose.ymlです。
各コンテナにマウントしているcephフォルダには、ceph.confと、初回起動時に作成されるceph.client.admin.keyring, ceph.client.bootstrap-osd.keyringが入ります。
ceph.conf内のmon_hostにコンテナ名を指定すると、うまく起動しなかったのでnetworkを構成してコンテナ同士で使えるIPアドレスを割り当ててます。
networks:
ceph_network:
driver: bridge
ipam:
config:
- subnet: 172.30.0.0/16
services:
mon1:
build: dockerfiles/mon1
user: ceph
entrypoint: ["/entrypoint.sh"]
command:
- "/bin/sh"
- "-c"
- >-
ceph-authtool /var/lib/ceph/tmp/ceph.mon.keyring --import-keyring /etc/ceph/ceph.client.admin.keyring;
ceph-authtool /var/lib/ceph/tmp/ceph.mon.keyring --import-keyring /etc/ceph/ceph.client.bootstrap-osd.keyring;
monmaptool --create --add mon1 ${MON_IP} --fsid ${FSID} /var/lib/ceph/tmp/monmap --clobber;
ceph-mon --mkfs -i mon1 --monmap /var/lib/ceph/tmp/monmap --keyring /var/lib/ceph/tmp/ceph.mon.keyring;
ceph-mon -i mon1 -f -d;
environment:
MON_IP: ${MON_IP}
FSID: ${FSID}
volumes:
- ./ceph:/etc/ceph
networks:
ceph_network:
ipv4_address: 172.30.0.2
mgr:
build: dockerfiles/mgr
command:
- "/bin/sh"
- "-c"
- >-
ceph auth get-or-create mgr.mgr mon 'allow profile mgr' osd 'allow *' mds 'allow *' > /var/lib/ceph/mgr/ceph-mgr/keyring;
ceph-mgr -f -i mgr;
volumes:
- ./ceph:/etc/ceph
depends_on:
- mon1
ports:
- 8443:8443
networks:
ceph_network:
osd1:
pid: host
privileged: true
build: dockerfiles/osd1
environment:
OSD_UUID_1: ${OSD_UUID_1}
user: ceph
command:
- "/bin/sh"
- "-c"
- >-
ceph auth add osd.0 -i /var/lib/ceph/osd/ceph-0/keyring;
ceph osd new ${OSD_UUID_1} -n client.bootstrap-osd;
ceph-osd -i 0 --mkfs \
--osd-data /var/lib/ceph/osd/ceph-0 \
--osd-uuid ${OSD_UUID_1} \
--keyring /var/lib/ceph/osd/ceph-0/keyring;
ceph-osd -f -i 0;
volumes:
- ./ceph:/etc/ceph
depends_on:
- mon1
networks:
ceph_network:
rgw1:
build: dockerfiles/rgw1
environment:
MON_IP: ${MON_IP}
AWS_ACCESS_KEY_ID: ${RGW_ACCESS_KEY}
AWS_SECRET_ACCESS_KEY: ${RGW_SECRET_KEY}
command:
- "/bin/sh"
- "-c"
- >-
ceph auth get-or-create client.rgw1 mon 'allow rw' osd 'allow rwx';
ceph auth caps client.rgw1 mon 'allow rw' osd 'allow rwx';
ceph auth del client.rgw1;
ceph auth add client.rgw1 -i /var/lib/ceph/radosgw/ceph-rgw1/keyring;
radosgw-admin user create \
--uid="polaris-user" \
--display-name="Polaris User" \
--access-key="${RGW_ACCESS_KEY}" \
--secret-key="${RGW_SECRET_KEY}";
echo ">>> RGW user created (access=${RGW_ACCESS_KEY}, secret=${RGW_SECRET_KEY})";
radosgw -n client.rgw1 --rgw-frontends="beast port=7480" --foreground;
ports:
- "7480:7480" # RGW HTTP endpoint (S3)
- "7481:7481"
volumes:
- ./ceph:/etc/ceph
depends_on:
- osd1
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:7480"]
interval: 2s
timeout: 10s
retries: 10
start_period: 10s
networks:
ceph_network:
aws-cli:
image: amazon/aws-cli:2.33.8
depends_on:
rgw1:
condition: service_healthy
environment:
AWS_ACCESS_KEY_ID: ${RGW_ACCESS_KEY}
AWS_SECRET_ACCESS_KEY: ${RGW_SECRET_KEY}
AWS_ENDPOINT_URL: ${S3_ENDPOINT_URL}
AWS_REGION: ${S3_REGION}
entrypoint: "/bin/sh"
command:
- "-c"
- >-
tail -f /dev/null;
networks:
ceph_network:
ceph/ceph.conf
mon1コンテナに割り当てたIPアドレスをmon_hostに記載しています。
[global]
fsid = b2f59c4b-5f14-4f8c-a9b7-3b7998c76a0e
mon_initial_members = mon1
mon_host = 172.30.0.2
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx
osd_pool_default_size = 1
osd_pool_default_min_size = 1
osd_pool_default_pg_num = 333
osd_crush_chooseleaf_type = 1
mon_allow_pool_size_one= true
[mon.mon1]
mon_data = /var/lib/ceph/mon/ceph-mon1
mon_rocksdb_min_wal_logs = 1
mon_rocksdb_max_total_wal_size = 64M
mon_rocksdb_options = max_background_compactions=4;max_background_flushes=2
[client.rgw1]
host = ceph-rgw1
rgw_frontends = civetweb port=7480
.env
参考元のコメントにある通り、本来UUID等は再作成したほうがよいのですが、そのまま使っています。
S3_REGIONはcephにおいては動作に関係ないのですが、aws-cliコンテナの動作に関係する可能性があるため残しております。
LANG=en_US.utf8 # Default system locale used inside containers
TZ=UTC # Timezone used inside containers
MON_IP=172.30.0.2 # IP address of the monitor
RGW_ACCESS_KEY=POLARIS123ACCESS # Access key for Polaris S3 user
RGW_SECRET_KEY=POLARIS456SECRET # Secret key for Polaris S3 user
FSID=b2f59c4b-5f14-4f8c-a9b7-3b7998c76a0e # Unique cluster identifier (use `uuidgen` to regenerate)
OSD_UUID_1=80505106-0d32-4777-bac9-3dfc901b1273 # Unique OSD identifier (use `uuidgen` to regenerate)
S3_ENDPOINT_URL=http://rgw1:7480 # Internal endpoint for S3-compatible RGW service
S3_REGION=us-east-1 # S3 region name
動作確認
ビルドと初回起動
まずはビルドしましょう。
$ docker compose build
起動します。
$ docker compose up -d
初回起動ののち、cephフォルダに以下の2ファイルが作成されます。
- ceph.client.admin.keyring
- ceph.client.bootstrap-osd.keyring
起動状態を確認します。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
14ddce9f5e87 amazon/aws-cli:2.33.8 "/bin/sh -c 'tail -f…" 26 seconds ago Up 3 seconds iceberg-with-polaris-ceph-spark-in-docker-aws-cli-1
29706bc123bc iceberg-with-polaris-ceph-spark-in-docker-rgw1 "/bin/sh -c 'ceph au…" 26 seconds ago Up 25 seconds (healthy) 0.0.0.0:7480-7481->7480-7481/tcp, [::]:7480-7481->7480-7481/tcp iceberg-with-polaris-ceph-spark-in-docker-rgw1-1
386c3c640132 iceberg-with-polaris-ceph-spark-in-docker-mgr "/bin/sh -c 'ceph au…" 27 seconds ago Up 25 seconds 0.0.0.0:8443->8443/tcp, [::]:8443->8443/tcp iceberg-with-polaris-ceph-spark-in-docker-mgr-1
d9e2ec9bb1d1 iceberg-with-polaris-ceph-spark-in-docker-osd1 "/bin/sh -c 'ceph au…" 27 seconds ago Up 25 seconds iceberg-with-polaris-ceph-spark-in-docker-osd1-1
06492fac38d8 iceberg-with-polaris-ceph-spark-in-docker-mon1 "/entrypoint.sh /bin…" 27 seconds ago Up 25 seconds iceberg-with-polaris-ceph-spark-in-docker-mon1-1
動作確認
AWL-CLIコンテナに入ります。
docker exec -it 14ddce9f5e87 sh
バケットの作成をします。
$ aws s3 mb s3://test-bucket
make_bucket: test-bucket
作成したバケットを確認します。
$ aws s3 ls
2026-01-30 13:54:20 test-bucket
終わりに
次はSparkとPolarisも追加して、Iceberg環境を作ってみたいなと思っています。