Phase 2 — Storage Validation¶
Validate Ceph block storage (RBD) and Ceph object storage (RGW/S3) before deploying any applications. Both must be confirmed working before GitLab install.
Environment¶
Full Ceph reference
See Ceph Infrastructure → for full details on monitors, RGW endpoints, CSI config, and troubleshooting.
| Component | Detail |
|---|---|
| Ceph RBD (block) | StorageClass csi-rbd-sc — default, used for PVCs |
| Ceph CephFS (filesystem) | StorageClass csi-cephfs-sc — used for RWX |
| Ceph RGW (S3 object) | http://100.115.1.11:7480 (also .12, .13 — all same port) |
| Ceph monitors | 100.115.1.11:6789, 100.115.1.12:6789, 100.115.1.13:6789 |
| Cluster ID | b8085298-5426-11f1-bd37-5000e63565cc |
Step 2.1 — Verify storage classes¶
Expected output (verified ✅):
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
csi-cephfs-sc cephfs.csi.ceph.com Delete Immediate true 13d
csi-rbd-sc (default) rbd.csi.ceph.com Delete Immediate true 13d
| Storage Class | Type | Access Mode | Use for |
|---|---|---|---|
csi-rbd-sc |
Ceph RBD block | RWO | Databases, Gitaly, Redis |
csi-cephfs-sc |
CephFS filesystem | RWX | Shared mounts |
Step 2.2 — Verify Ceph RGW endpoints¶
Ceph RGW (S3-compatible object storage) runs on port 7480 on all 3 monitor nodes, fronted by a HAProxy + Keepalived VIP at 100.115.1.10.
Test VIP first (primary — this is what all apps use):
result=$(curl -s --connect-timeout 3 -o /dev/null -w "%{http_code}" https://s3.mod.auh1.dev.dir)
echo "VIP 100.115.1.10 port 7480: HTTP ${result}"
# Expected: HTTP 200
Test individual nodes (for HA validation):
for ip in 100.115.1.11 100.115.1.12 100.115.1.13; do
echo "=== $ip ==="
result=$(curl -s --connect-timeout 3 -o /dev/null -w "%{http_code}" http://${ip}:7481)
echo " port 7481: HTTP ${result}"
done
Port 7481 on individual nodes
Once HAProxy is deployed, local Ceph RGW daemons listen on 7481 (HAProxy takes 7480).
The VIP 100.115.1.10:7480 is the only endpoint consumers should use.
Expected output (verified ✅):
VIP 100.115.1.10 port 7480: HTTP 200
=== 100.115.1.11 ===
port 7481: HTTP 200
=== 100.115.1.12 ===
port 7481: HTTP 200
=== 100.115.1.13 ===
port 7481: HTTP 200
Step 2.3 — Test S3 connectivity with credentials¶
Prerequisites
You need the Ceph RGW access_key and secret_key for your S3 user.
These are provided by the Ceph administrator or retrieved from the Ceph cluster.
export AWS_ACCESS_KEY_ID="<your-access-key>"
export AWS_SECRET_ACCESS_KEY="<your-secret-key>"
export RGW_ENDPOINT="https://s3.mod.auh1.dev.dir" # VIP — HAProxy + Keepalived across all 3 RGW nodes
Step 2.3a — List buckets (confirms auth works)¶
Step 2.3b — Create test bucket¶
aws s3 mb s3://test-connectivity \
--endpoint-url ${RGW_ENDPOINT} --no-verify-ssl
# Expected: make_bucket: test-connectivity
Step 2.3c — Upload a test file¶
echo "rgw test" | aws s3 cp - s3://test-connectivity/test.txt \
--endpoint-url ${RGW_ENDPOINT} --no-verify-ssl
Step 2.3d — Verify file is stored¶
aws s3 ls s3://test-connectivity \
--endpoint-url ${RGW_ENDPOINT} --no-verify-ssl
# Expected: 2026-06-03 22:27:49 9 test.txt
Step 2.3e — Cleanup test bucket¶
aws s3 rb s3://test-connectivity --force \
--endpoint-url ${RGW_ENDPOINT} --no-verify-ssl
# Expected:
# delete: s3://test-connectivity/test.txt
# remove_bucket: test-connectivity
Step 2.3f — Unset credentials¶
Full test verified ✅ on bastion1 — bucket create, upload, list, delete all successful.
Step 2.4 — Pre-create GitLab S3 buckets¶
Create all buckets GitLab needs before installing GitLab.
GitLab does not auto-create S3 buckets on startup — missing buckets cause CrashLoopBackOff.
export AWS_ACCESS_KEY_ID="<your-access-key>"
export AWS_SECRET_ACCESS_KEY="<your-secret-key>"
export RGW_ENDPOINT="https://s3.mod.auh1.dev.dir" # VIP — HAProxy + Keepalived across all 3 RGW nodes
for bucket in \
gitlab-artifacts \
gitlab-lfs \
gitlab-uploads \
gitlab-packages \
gitlab-registry \
gitlab-backups \
gitlab-backups-tmp; do
aws s3 mb s3://${bucket} \
--endpoint-url ${RGW_ENDPOINT} --no-verify-ssl \
2>/dev/null && echo "✅ created: ${bucket}" || echo "ℹ️ exists: ${bucket}"
done
# Verify all buckets exist
echo ""
echo "=== All GitLab buckets ==="
aws s3 ls --endpoint-url ${RGW_ENDPOINT} --no-verify-ssl | grep gitlab
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY RGW_ENDPOINT
Expected output:
✅ created: gitlab-artifacts
✅ created: gitlab-lfs
✅ created: gitlab-uploads
✅ created: gitlab-packages
✅ created: gitlab-registry
✅ created: gitlab-backups
✅ created: gitlab-backups-tmp
=== All GitLab buckets ===
2026-06-03 gitlab-artifacts
2026-06-03 gitlab-lfs
2026-06-03 gitlab-uploads
2026-06-03 gitlab-packages
2026-06-03 gitlab-registry
2026-06-03 gitlab-backups
2026-06-03 gitlab-backups-tmp
Step 2.5 — Create GitLab S3 Kubernetes secrets¶
These two secrets are required by the GitLab Helm chart before install.
Run from
bastion1 — any directory
export AWS_ACCESS_KEY_ID="<your-access-key>"
export AWS_SECRET_ACCESS_KEY="<your-secret-key>"
export RGW_ENDPOINT="https://s3.mod.auh1.dev.dir" # VIP — HAProxy + Keepalived across all 3 RGW nodes
# Secret 1: S3 connection for uploads, LFS, artifacts, packages
kubectl create secret generic gitlab-s3-connection \
-n gitlab \
--from-literal=connection="$(cat << CONNEOF
provider: AWS
region: us-east-1
aws_access_key_id: ${AWS_ACCESS_KEY_ID}
aws_secret_access_key: ${AWS_SECRET_ACCESS_KEY}
aws_signature_version: 4
host: 100.115.1.10
endpoint: ${RGW_ENDPOINT}
path_style: true
CONNEOF
)"
# Secret 2: S3 config for GitLab container registry blobs
kubectl create secret generic gitlab-registry-storage \
-n gitlab \
--from-literal=config="$(cat << REGEOF
s3:
bucket: gitlab-registry
accesskey: ${AWS_ACCESS_KEY_ID}
secretkey: ${AWS_SECRET_ACCESS_KEY}
regionendpoint: ${RGW_ENDPOINT}
region: us-east-1
pathstyle: true
secure: false
REGEOF
)"
# Verify
kubectl get secret gitlab-s3-connection gitlab-registry-storage -n gitlab
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY RGW_ENDPOINT
Summary checklist¶
- [x] Storage classes verified —
csi-rbd-sc(default) andcsi-cephfs-sc - [x] Ceph RGW reachable on all 3 nodes at port
7480 - [x] S3 credentials tested — bucket create/upload/delete working
- [ ] GitLab S3 buckets pre-created (7 buckets)
- [ ]
gitlab-s3-connectionsecret created ingitlabnamespace - [ ]
gitlab-registry-storagesecret created ingitlabnamespace