feat(objectstorage): add Aliyun OSS support and auto-detect provider in deploy workflows
Introduces Aliyun OSS as an alternative to MinIO; deploy scripts and CI workflows now read object_storage.provider from config and conditionally include or skip MinIO resources in both Docker Compose and k3s paths. Also adds ops scheduler domain and its migration tables. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -37,6 +37,21 @@ ensure_local_config() {
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_config_aliases() {
|
||||
local yaml yml
|
||||
for yaml in config.yaml config.local.yaml ops-config.yaml ops-config.local.yaml; do
|
||||
yml="${yaml%.yaml}.yml"
|
||||
if [[ ! -f "${SCRIPT_DIR}/${yaml}" && -f "${SCRIPT_DIR}/${yml}" ]]; then
|
||||
cp "${SCRIPT_DIR}/${yml}" "${SCRIPT_DIR}/${yaml}"
|
||||
echo "==> 已从 ${yml} 创建 ${yaml},供部署清单挂载使用。"
|
||||
fi
|
||||
done
|
||||
if [[ ! -f "${SCRIPT_DIR}/prompts.yml" && -f "${SCRIPT_DIR}/prompts.yaml" ]]; then
|
||||
cp "${SCRIPT_DIR}/prompts.yaml" "${SCRIPT_DIR}/prompts.yml"
|
||||
echo "==> 已从 prompts.yaml 创建 prompts.yml,供部署清单挂载使用。"
|
||||
fi
|
||||
}
|
||||
|
||||
env_value() {
|
||||
local key="$1" default_value="$2" value
|
||||
value="$(grep -E "^${key}=" "${SCRIPT_DIR}/.env" | tail -1 | cut -d= -f2- || true)"
|
||||
@@ -45,9 +60,130 @@ env_value() {
|
||||
printf '%s' "${value:-${default_value}}"
|
||||
}
|
||||
|
||||
config_file_path() {
|
||||
local base="$1"
|
||||
for file in "${SCRIPT_DIR}/${base}.yaml" "${SCRIPT_DIR}/${base}.yml"; do
|
||||
if [[ -f "${file}" ]]; then
|
||||
printf '%s' "${file}"
|
||||
return
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
read_object_storage_provider() {
|
||||
local provider="minio" file
|
||||
for file in "$(config_file_path config)" "$(config_file_path config.local)"; do
|
||||
if [[ -z "${file}" || ! -f "${file}" ]]; then
|
||||
continue
|
||||
fi
|
||||
local next
|
||||
next="$(
|
||||
awk '
|
||||
/^[[:space:]]*object_storage:[[:space:]]*$/ {
|
||||
in_section=1
|
||||
base=match($0, /[^[:space:]]/) - 1
|
||||
next
|
||||
}
|
||||
in_section {
|
||||
indent=match($0, /[^[:space:]]/) - 1
|
||||
if ($0 ~ /^[[:space:]]*$/ || $0 ~ /^[[:space:]]*#/) {
|
||||
next
|
||||
}
|
||||
if (indent <= base) {
|
||||
in_section=0
|
||||
next
|
||||
}
|
||||
if ($0 ~ /^[[:space:]]*provider[[:space:]]*:/) {
|
||||
value=$0
|
||||
sub(/^[[:space:]]*provider[[:space:]]*:[[:space:]]*/, "", value)
|
||||
sub(/[[:space:]]+#.*$/, "", value)
|
||||
gsub(/^["'\'']|["'\'']$/, "", value)
|
||||
print value
|
||||
}
|
||||
}
|
||||
' "${file}" | tail -1
|
||||
)"
|
||||
if [[ -n "${next}" ]]; then
|
||||
provider="${next}"
|
||||
fi
|
||||
done
|
||||
printf '%s' "$(printf '%s' "${provider}" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]')"
|
||||
}
|
||||
|
||||
use_minio_for_object_storage() {
|
||||
case "$(read_object_storage_provider)" in
|
||||
""|minio|mino)
|
||||
return 0
|
||||
;;
|
||||
aliyun|aliyun_oss|aliyun-oss|oss)
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
sync_k3s_config() {
|
||||
mkdir -p "${SCRIPT_DIR}/k3s/config"
|
||||
for name in config ops-config prompts; do
|
||||
local output="${name}.yaml"
|
||||
if [[ "${name}" == "prompts" ]]; then
|
||||
output="prompts.yml"
|
||||
fi
|
||||
local source=""
|
||||
for candidate in "${SCRIPT_DIR}/${name}.yaml" "${SCRIPT_DIR}/${name}.yml"; do
|
||||
if [[ -f "${candidate}" ]]; then
|
||||
source="${candidate}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ -n "${source}" ]]; then
|
||||
cp "${source}" "${SCRIPT_DIR}/k3s/config/${output}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
prepare_k3s_runtime_overlay() {
|
||||
local base_dir="$1"
|
||||
local runtime_dir="${SCRIPT_DIR}/.k3s-runtime"
|
||||
rm -rf "${runtime_dir}"
|
||||
mkdir -p "${runtime_dir}"
|
||||
|
||||
cp "$(config_file_path config.local)" "${runtime_dir}/config.local.yaml"
|
||||
cp "$(config_file_path ops-config.local)" "${runtime_dir}/ops-config.local.yaml"
|
||||
|
||||
cat > "${runtime_dir}/kustomization.yaml" <<EOF
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../$(basename "${base_dir}")
|
||||
|
||||
secretGenerator:
|
||||
- name: geo-rankly-app-secret
|
||||
behavior: merge
|
||||
files:
|
||||
- config.local.yaml=config.local.yaml
|
||||
- ops-config.local.yaml=ops-config.local.yaml
|
||||
|
||||
generatorOptions:
|
||||
disableNameSuffixHash: true
|
||||
EOF
|
||||
|
||||
printf '%s' "${runtime_dir}"
|
||||
}
|
||||
|
||||
deploy_compose() {
|
||||
ensure_config_aliases
|
||||
ensure_local_config "config.local.yaml" "config.local.yaml.example"
|
||||
ensure_local_config "ops-config.local.yaml" "ops-config.local.yaml.example"
|
||||
local compose_files=("-f" "docker-compose.yaml" "-f" "docker-compose.offline.yaml")
|
||||
local minio_enabled="true"
|
||||
if ! use_minio_for_object_storage; then
|
||||
compose_files+=("-f" "docker-compose.aliyun-oss.yaml")
|
||||
minio_enabled="false"
|
||||
fi
|
||||
|
||||
# ─── Step 1: 加载镜像 ───────────────────────────────────────────────────────
|
||||
echo "==> [1/3] 加载 Docker 镜像(可能需要几分钟)..."
|
||||
@@ -62,30 +198,46 @@ deploy_compose() {
|
||||
|
||||
# ─── Step 3: 启动服务 ───────────────────────────────────────────────────────
|
||||
echo "==> [3/3] 启动所有服务..."
|
||||
if [[ "${minio_enabled}" == "true" ]]; then
|
||||
echo " object_storage.provider=$(read_object_storage_provider),将部署 MinIO。"
|
||||
else
|
||||
echo " object_storage.provider=$(read_object_storage_provider),将跳过 MinIO。"
|
||||
export COMPOSE_PROFILES=""
|
||||
docker rm -f geo-minio geo-minio-init >/dev/null 2>&1 || true
|
||||
fi
|
||||
cd "${SCRIPT_DIR}"
|
||||
docker compose \
|
||||
-f docker-compose.yaml \
|
||||
-f docker-compose.offline.yaml \
|
||||
--env-file .env \
|
||||
up -d
|
||||
docker compose "${compose_files[@]}" --env-file .env up -d
|
||||
|
||||
echo ""
|
||||
echo "✅ Docker Compose 部署完成!"
|
||||
echo ""
|
||||
echo "服务状态:"
|
||||
docker compose -f docker-compose.yaml -f docker-compose.offline.yaml ps
|
||||
docker compose "${compose_files[@]}" ps
|
||||
echo ""
|
||||
echo "查看日志: docker compose -f docker-compose.yaml logs -f tenant-api"
|
||||
echo "停止服务: docker compose -f docker-compose.yaml down"
|
||||
echo "查看日志: docker compose ${compose_files[*]} logs -f tenant-api"
|
||||
echo "停止服务: docker compose ${compose_files[*]} down"
|
||||
echo "管理界面:"
|
||||
echo " Tenant Web: http://<server-ip>:$(env_value FRONTEND_PORT 18080)"
|
||||
echo " Ops Web: http://<server-ip>:$(env_value OPS_WEB_PORT 18082)"
|
||||
echo " RabbitMQ: http://<server-ip>:$(env_value RABBITMQ_MGMT_PORT 15673) (geo / geo_dev)"
|
||||
echo " MinIO: http://<server-ip>:$(env_value MINIO_CONSOLE_PORT 19001) ($(env_value MINIO_ROOT_USER minioadmin) / $(env_value MINIO_ROOT_PASSWORD minioadmin))"
|
||||
if [[ "${minio_enabled}" == "true" ]]; then
|
||||
echo " MinIO: http://<server-ip>:$(env_value MINIO_CONSOLE_PORT 19001) ($(env_value MINIO_ROOT_USER minioadmin) / $(env_value MINIO_ROOT_PASSWORD minioadmin))"
|
||||
fi
|
||||
}
|
||||
|
||||
deploy_k3s() {
|
||||
local kubectl_cmd="kubectl"
|
||||
local kustomize_dir="${SCRIPT_DIR}/k3s"
|
||||
local minio_enabled="true"
|
||||
|
||||
ensure_config_aliases
|
||||
ensure_local_config "config.local.yaml" "config.local.yaml.example"
|
||||
ensure_local_config "ops-config.local.yaml" "ops-config.local.yaml.example"
|
||||
|
||||
if ! use_minio_for_object_storage; then
|
||||
kustomize_dir="${SCRIPT_DIR}/k3s-aliyun-oss"
|
||||
minio_enabled="false"
|
||||
fi
|
||||
|
||||
if command -v k3s >/dev/null 2>&1; then
|
||||
echo "==> [1/3] 导入镜像到 k3s containerd..."
|
||||
@@ -100,7 +252,20 @@ deploy_k3s() {
|
||||
fi
|
||||
|
||||
echo "==> [2/3] 应用 k3s 清单..."
|
||||
${kubectl_cmd} apply -k "${SCRIPT_DIR}/k3s"
|
||||
sync_k3s_config
|
||||
kustomize_dir="$(prepare_k3s_runtime_overlay "${kustomize_dir}")"
|
||||
if [[ "${minio_enabled}" == "true" ]]; then
|
||||
echo " object_storage.provider=$(read_object_storage_provider),将部署 MinIO。"
|
||||
else
|
||||
echo " object_storage.provider=$(read_object_storage_provider),将跳过 MinIO。"
|
||||
${kubectl_cmd} -n geo-rankly delete statefulset minio --ignore-not-found
|
||||
${kubectl_cmd} -n geo-rankly delete service minio --ignore-not-found
|
||||
${kubectl_cmd} -n geo-rankly delete job minio-init --ignore-not-found
|
||||
for svc in tenant-api worker-generate kol-assist-worker scheduler; do
|
||||
${kubectl_cmd} -n geo-rankly set env "deployment/${svc}" OBJECT_STORAGE_ACCESS_KEY- OBJECT_STORAGE_SECRET_KEY- >/dev/null 2>&1 || true
|
||||
done
|
||||
fi
|
||||
${kubectl_cmd} apply -k "${kustomize_dir}"
|
||||
|
||||
echo "==> [3/3] 查看服务状态..."
|
||||
${kubectl_cmd} -n geo-rankly get pods,svc
|
||||
|
||||
@@ -159,12 +159,16 @@ echo " 镜像包大小: $(du -sh "${WORK_DIR}/images.tar" | cut -f1)"
|
||||
echo "==> [4/5] 打包部署文件"
|
||||
cp "${DEPLOY_DIR}/docker-compose.yaml" "${WORK_DIR}/"
|
||||
cp "${DEPLOY_DIR}/docker-compose.offline.yaml" "${WORK_DIR}/"
|
||||
cp "${DEPLOY_DIR}/docker-compose.aliyun-oss.yaml" "${WORK_DIR}/"
|
||||
cp "${DEPLOY_DIR}/config.yaml" "${WORK_DIR}/"
|
||||
cp "${DEPLOY_DIR}/ops-config.yaml" "${WORK_DIR}/"
|
||||
cp "${DEPLOY_DIR}/prompts.yml" "${WORK_DIR}/"
|
||||
cp "${DEPLOY_DIR}/.env.example" "${WORK_DIR}/"
|
||||
cp "${DEPLOY_DIR}/config.local.yaml.example" "${WORK_DIR}/"
|
||||
cp "${DEPLOY_DIR}/ops-config.local.yaml.example" "${WORK_DIR}/"
|
||||
cp "${DEPLOY_DIR}/scripts/load-and-start.sh" "${WORK_DIR}/deploy.sh"
|
||||
cp -R "${DEPLOY_DIR}/k3s" "${WORK_DIR}/k3s"
|
||||
cp -R "${DEPLOY_DIR}/k3s-aliyun-oss" "${WORK_DIR}/k3s-aliyun-oss"
|
||||
if [[ -f "${DEPLOY_DIR}/OFFLINE_PACKAGE.md" ]]; then
|
||||
cp "${DEPLOY_DIR}/OFFLINE_PACKAGE.md" "${WORK_DIR}/README.md"
|
||||
fi
|
||||
@@ -201,7 +205,10 @@ Files:
|
||||
images.tar
|
||||
docker-compose.yaml
|
||||
docker-compose.offline.yaml
|
||||
docker-compose.aliyun-oss.yaml
|
||||
.env.example
|
||||
config.local.yaml.example
|
||||
ops-config.local.yaml.example
|
||||
deploy.sh
|
||||
EOF
|
||||
|
||||
|
||||
Reference in New Issue
Block a user