feat(release): 统一版本与 embed 部署,推送 lghost/aiops 镜像

- resolve_version 统一二进制/Docker/K8s 版本解析
- docker-compose 简化为 mysql+redis+aiops 单应用容器
- 新增 release/docker push/kubernetes push 构建并推送 Docker Hub
- K8s deployment 镜像改为 lghost/aiops:<tag> 语义版本
This commit is contained in:
Logan.Li committed 2026-06-26 16:37:15 +08:00
1 parent 8be51ac514
commit 9f5ce249f1
6 files changed
+300 -160

No files matched your search

+3 -1
View File
@@ -9,6 +9,7 @@
ARG VERSION=dev ARG VERSION=dev
ARG BUILD_TIME=unknown ARG BUILD_TIME=unknown
ARG GIT_COMMIT=unknown
# ==================== Stage 1: Frontend Builder ==================== # ==================== Stage 1: Frontend Builder ====================
FROM node:20-alpine AS frontend-builder FROM node:20-alpine AS frontend-builder
@@ -31,6 +32,7 @@ FROM golang:1.24-alpine AS backend-builder
ARG VERSION ARG VERSION
ARG BUILD_TIME ARG BUILD_TIME
ARG GIT_COMMIT
WORKDIR /app WORKDIR /app
@@ -56,7 +58,7 @@ COPY --from=frontend-builder /app/dist/ static/
# 构建后端二进制(前端已嵌入,注入版本号) # 构建后端二进制(前端已嵌入,注入版本号)
# local 模式需 CGO(SQLite + redka/mattn-sqlite3)// Logan.Li # local 模式需 CGO(SQLite + redka/mattn-sqlite3)// Logan.Li
RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build \ RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build \
-ldflags="-w -s -X main.Version=${VERSION} -X main.BuildTime=${BUILD_TIME}" \ -ldflags="-w -s -X main.Version=${VERSION} -X main.BuildTime=${BUILD_TIME} -X main.GitCommit=${GIT_COMMIT}" \
-o aiops . -o aiops .
# ==================== Stage 3: Agent Builder ==================== # ==================== Stage 3: Agent Builder ====================
+2 -2
View File
@@ -1,6 +1,6 @@
# deployment.yaml — AIOps 应用 (embed 前端嵌入后端, 单容器单端口) # deployment.yaml — AIOps 应用 (embed 前端嵌入后端, 单容器单端口)
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# - 镜像 aiops:embed(前端通过 go:embed 内嵌进同一二进制) # - 镜像 lghost/aiops:<tag>(前端通过 go:embed 内嵌进同一二进制)
# - 单端口 8080 = API + WebSocket + 前端 SPA 静态资源 # - 单端口 8080 = API + WebSocket + 前端 SPA 静态资源
# - 配置优先级: 环境变量 > config.yaml > 默认值 (viper AutomaticEnv) # - 配置优先级: 环境变量 > config.yaml > 默认值 (viper AutomaticEnv)
# - 环境变量命名: 配置键 database.host → DATABASE_HOST (全大写, 点变下划线) # - 环境变量命名: 配置键 database.host → DATABASE_HOST (全大写, 点变下划线)
@@ -58,7 +58,7 @@ spec:
mountPath: /vol mountPath: /vol
containers: containers:
- name: aiops - name: aiops
image: 10.10.10.72/library/aiops:embed image: lghost/aiops:dev
imagePullPolicy: Always imagePullPolicy: Always
ports: ports:
- name: http - name: http
+1 -1
View File
@@ -75,7 +75,7 @@ spec:
mountPath: /vol mountPath: /vol
containers: containers:
- name: aiops - name: aiops
image: aiops:embed image: lghost/aiops:dev
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
ports: ports:
- containerPort: 8080 - containerPort: 8080
+10 -30
View File
@@ -1,14 +1,18 @@
# AIOps — 单应用 embed 容器(连接外部 MySQL/Redis,无内置数据库)
# 用法: VERSION=v1.0.1 docker compose -f docker-compose.k8s.yml up -d --build
# 署名 Logan.Li
services: services:
# ======================== Go 后端服务 (连接外部 MySQL/Redis) ======================== aiops:
backend: image: ${DOCKERHUB_IMAGE:-lghost/aiops}:${VERSION:-dev}
build: build:
context: . context: .
dockerfile: backend/Dockerfile dockerfile: Dockerfile.embed
args: args:
VERSION: ${VERSION:-dev} VERSION: ${VERSION:-dev}
BUILD_TIME: ${BUILD_TIME:-unknown} BUILD_TIME: ${BUILD_TIME:-unknown}
container_name: aiops-backend GIT_COMMIT: ${GIT_COMMIT:-unknown}
hostname: aiops-backend container_name: aiops
restart: unless-stopped restart: unless-stopped
ports: ports:
- "8080:8080" - "8080:8080"
@@ -16,32 +20,8 @@ services:
- ./backend/config.external.yaml:/app/config.yaml - ./backend/config.external.yaml:/app/config.yaml
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
healthcheck: healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"] test: ["CMD", "curl", "-f", "http://localhost:8080/version"]
interval: 30s interval: 30s
timeout: 10s timeout: 10s
retries: 3 retries: 3
start_period: 40s start_period: 40s
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
- aiops-network
# ======================== React 前端 + Nginx ========================
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
container_name: aiops-frontend
hostname: aiops-frontend
restart: unless-stopped
ports:
- "80:80"
depends_on:
backend:
condition: service_healthy
networks:
- aiops-network
networks:
aiops-network:
driver: bridge
+26 -31
View File
@@ -1,5 +1,9 @@
# AIOps Docker Compose — embed 单应用容器 + MySQL + Redis
# 访问: http://localhost:8080 (API + 前端 SPA 同一端口)
# 构建: VERSION=v1.0.1 ./run.sh docker up
# 署名 Logan.Li
services: services:
# ======================== MySQL 数据库 ========================
mysql: mysql:
image: mysql:8.0 image: mysql:8.0
container_name: aiops-mysql container_name: aiops-mysql
@@ -28,7 +32,6 @@ services:
networks: networks:
- aiops-network - aiops-network
# ======================== Redis 缓存 ========================
redis: redis:
image: redis:7-alpine image: redis:7-alpine
container_name: aiops-redis container_name: aiops-redis
@@ -47,24 +50,35 @@ services:
networks: networks:
- aiops-network - aiops-network
# ======================== Go 后端服务 ======================== aiops:
backend: image: ${DOCKERHUB_IMAGE:-lghost/aiops}:${VERSION:-dev}
build: build:
context: . context: .
dockerfile: backend/Dockerfile dockerfile: Dockerfile.embed
args: args:
VERSION: ${VERSION:-dev} VERSION: ${VERSION:-dev}
BUILD_TIME: ${BUILD_TIME:-unknown} BUILD_TIME: ${BUILD_TIME:-unknown}
container_name: aiops-backend GIT_COMMIT: ${GIT_COMMIT:-unknown}
hostname: aiops-backend container_name: aiops
hostname: aiops
restart: unless-stopped restart: unless-stopped
ports: ports:
- "8080:8080" - "8080:8080"
environment: environment:
- MODE=${MODE:-release} TZ: Asia/Shanghai
MODE: release
DATABASE_DRIVER: mysql
DATABASE_HOST: mysql
DATABASE_PORT: 3306
DATABASE_USER: ${MYSQL_USER:-aiops}
DATABASE_PASSWORD: ${MYSQL_PASSWORD:-CHANGE_ME}
DATABASE_DBNAME: ${MYSQL_DATABASE:-aiops}
REDIS_DRIVER: redis
REDIS_HOST: redis
REDIS_PORT: 6379
JWT_SECRET: ${JWT_SECRET:-aiops-jwt-secret-change-me}
volumes: volumes:
- ./backend/config.yaml:/app/config.yaml - aiops_uploads:/app/uploads
- ./backend/data:/app/data
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
depends_on: depends_on:
mysql: mysql:
@@ -72,37 +86,18 @@ services:
redis: redis:
condition: service_healthy condition: service_healthy
healthcheck: healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"] test: ["CMD", "curl", "-f", "http://localhost:8080/version"]
interval: 30s interval: 30s
timeout: 10s timeout: 10s
retries: 3 retries: 3
start_period: 40s start_period: 40s
dns:
- 127.0.0.11
- 114.114.114.114
- 223.5.5.5
networks:
- aiops-network
# ======================== React 前端 + Nginx ========================
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
container_name: aiops-frontend
hostname: aiops-frontend
restart: unless-stopped
ports:
- "80:80"
depends_on:
backend:
condition: service_healthy
networks: networks:
- aiops-network - aiops-network
volumes: volumes:
mysql_data: mysql_data:
redis_data: redis_data:
aiops_uploads:
networks: networks:
aiops-network: aiops-network:
+258 -95
View File
@@ -3,8 +3,8 @@
# AIOps 智能运维平台 - 统一启动脚本 # AIOps 智能运维平台 - 统一启动脚本
# 支持三种部署方式 + 本地开发模式: # 支持三种部署方式 + 本地开发模式:
# #
# 方式 1 — Docker Compose: # 方式 1 — Docker Compose (embed 单应用容器):
# ./run.sh docker up 构建+启动 (MySQL+Redis+Backend+Nginx) # ./run.sh docker up 构建+启动 (MySQL+Redis+AIOps)
# #
# 方式 2 — Kubernetes (embed 单容器): # 方式 2 — Kubernetes (embed 单容器):
# ./run.sh kubernetes deploy 构建镜像+全量部署 (embed 前端嵌入后端) # ./run.sh kubernetes deploy 构建镜像+全量部署 (embed 前端嵌入后端)
@@ -33,6 +33,7 @@ BACKEND_DIR="backend"
FRONTEND_DIR="frontend" FRONTEND_DIR="frontend"
BACKEND_BIN="aiops-server" BACKEND_BIN="aiops-server"
STANDALONE_BIN="aiops" STANDALONE_BIN="aiops"
DOCKERHUB_IMAGE="lghost/aiops"
# 日志配置 # 日志配置
MAX_LOG_FILES=3 MAX_LOG_FILES=3
@@ -433,11 +434,19 @@ ensure_go_path() {
fi fi
} }
# 解析编译版本号(显式 tag 优先,否则取 git describe)// Logan.Li # 判断参数是否像版本号 (v1.0.1 / 1.0.1) // Logan.Li
resolve_build_version() { looks_like_version() {
local v=$1
[[ "$v" =~ ^v[0-9] ]] || [[ "$v" =~ ^[0-9]+\.[0-9] ]]
}
# 统一版本解析:显式参数 > VERSION 环境变量 > git describe > dev // Logan.Li
resolve_version() {
local explicit="${1:-}" local explicit="${1:-}"
if [ -n "$explicit" ]; then if [ -n "$explicit" ]; then
BUILD_VERSION="$explicit" BUILD_VERSION="$explicit"
elif [ -n "${VERSION:-}" ]; then
BUILD_VERSION="$VERSION"
elif git describe --tags --always --dirty 2>/dev/null | grep -q .; then elif git describe --tags --always --dirty 2>/dev/null | grep -q .; then
BUILD_VERSION=$(git describe --tags --always --dirty 2>/dev/null) BUILD_VERSION=$(git describe --tags --always --dirty 2>/dev/null)
else else
@@ -445,6 +454,108 @@ resolve_build_version() {
fi fi
BUILD_TIME=$(date -u '+%Y-%m-%dT%H:%M:%SZ') BUILD_TIME=$(date -u '+%Y-%m-%dT%H:%M:%SZ')
GIT_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown") GIT_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
EMBED_IMAGE="${DOCKERHUB_IMAGE}:${BUILD_VERSION}"
export VERSION="$BUILD_VERSION"
export BUILD_TIME
export GIT_COMMIT
}
# 兼容旧函数名 // Logan.Li
resolve_build_version() {
resolve_version "$@"
}
# 跨平台 sed -i // Logan.Li
sed_inplace() {
local expr=$1
local file=$2
if [ "$OS" = "macos" ]; then
sed -i '' "$expr" "$file"
else
sed -i "$expr" "$file"
fi
}
# 构建 embed Docker 镜像(二进制/K8s/Docker Compose 共用)// Logan.Li
build_embed_image() {
local version_tag="${1:-}"
local no_cache="${2:-0}"
local do_push="${3:-0}"
if ! command -v docker &>/dev/null; then
error "Docker 未安装"
return 1
fi
resolve_version "$version_tag"
banner "========== 构建 embed 镜像 ($EMBED_IMAGE) =========="
clean_frontend_artifacts
clean_embed_static
export DOCKER_BUILDKIT=1
local build_args=(
-f Dockerfile.embed
--build-arg "VERSION=${BUILD_VERSION}"
--build-arg "BUILD_TIME=${BUILD_TIME}"
--build-arg "GIT_COMMIT=${GIT_COMMIT}"
--label "org.opencontainers.image.version=${BUILD_VERSION}"
-t "$EMBED_IMAGE"
-t "${DOCKERHUB_IMAGE}:dev"
.
)
if [ "$no_cache" -eq 1 ]; then
build_args=(--no-cache --pull "${build_args[@]}")
info "无缓存全量构建 (--no-cache --pull)"
fi
info "构建中(前端 + 后端 embed)..."
docker build "${build_args[@]}" || {
error "镜像构建失败"
return 1
}
local img_size
img_size=$(docker images "$EMBED_IMAGE" --format "{{.Size}}" | head -1)
success "镜像构建完成: $EMBED_IMAGE ($img_size)"
KUBERNETES_BUILT_IMAGE="$EMBED_IMAGE"
if [ "$do_push" -eq 1 ]; then
push_embed_image "$BUILD_VERSION" || return 1
fi
return 0
}
# 推送镜像到 Docker Hub // Logan.Li
push_embed_image() {
local version_tag="${1:-}"
resolve_version "$version_tag"
info "推送镜像到 Docker Hub..."
docker push "$EMBED_IMAGE" || {
error "推送失败: $EMBED_IMAGE(请先 docker login)"
return 1
}
if [ "$BUILD_VERSION" != "dev" ]; then
docker push "${DOCKERHUB_IMAGE}:dev" 2>/dev/null || true
fi
success "已推送: $EMBED_IMAGE"
return 0
}
# 更新 K8s deployment 中的镜像坐标 // Logan.Li
kubernetes_update_manifest_image() {
local image=$1
local files=(
"$KUBERNETES_MANIFEST_DIR/deployment.yaml"
"$KUBERNETES_MANIFEST_DIR/quick-deploy.yaml"
)
local f
for f in "${files[@]}"; do
[ -f "$f" ] || continue
sed_inplace "s|image: ${DOCKERHUB_IMAGE}:.*|image: ${image}|g" "$f"
sed_inplace "s|image: .*/aiops:.*|image: ${image}|g" "$f"
done
info "K8s manifest 镜像已更新为: $image"
} }
# 编译独立二进制(含 embed 前端,输出到项目根目录 ./aiops)// Logan.Li # 编译独立二进制(含 embed 前端,输出到项目根目录 ./aiops)// Logan.Li
@@ -589,6 +700,7 @@ detect_compose_cmd() {
cmd_docker() { cmd_docker() {
local action=${1:-help} local action=${1:-help}
shift || true
if ! command -v docker &> /dev/null; then if ! command -v docker &> /dev/null; then
error "Docker 未安装,请先安装 Docker" error "Docker 未安装,请先安装 Docker"
@@ -600,27 +712,38 @@ cmd_docker() {
error "Docker Compose 未安装 (需要 docker compose 插件或 docker-compose)" error "Docker Compose 未安装 (需要 docker compose 插件或 docker-compose)"
exit 1 exit 1
fi fi
# 自动从 git tag 获取版本号
GIT_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
BUILD_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
export VERSION="${GIT_TAG:-dev}"
export BUILD_TIME
info "使用: $DOCKER_COMPOSE"
info "版本: $VERSION (构建时间: $BUILD_TIME)"
# 启用 BuildKit 加速构建(cache mount 跨构建复用 go mod/apk 缓存)// Logan.Li # 解析可选版本号参数 (up v1.0.1 / push v1.0.1) // Logan.Li
local version_arg=""
local fresh_build=0
while [ $# -gt 0 ]; do
case "$1" in
fresh) fresh_build=1; shift ;;
tag)
shift
version_arg=${1:-}
shift
;;
*)
if looks_like_version "$1"; then
version_arg=$1
fi
shift
;;
esac
done
resolve_version "$version_arg"
export DOCKERHUB_IMAGE
info "使用: $DOCKER_COMPOSE"
info "版本: $BUILD_VERSION | 镜像: $EMBED_IMAGE"
export DOCKER_BUILDKIT=1 export DOCKER_BUILDKIT=1
export COMPOSE_DOCKER_CLI_BUILD=1 export COMPOSE_DOCKER_CLI_BUILD=1
info "BuildKit: 已启用 (增量编译 + 缓存复用)" info "BuildKit: 已启用 (增量编译 + 缓存复用)"
case "$action" in case "$action" in
up|upgrade|update) up|upgrade|update)
local fresh_build=0 banner "========== Docker Compose 启动/升级 ($BUILD_VERSION) =========="
if [ "${2:-}" = "fresh" ] || [ "$action" = "fresh" ]; then
fresh_build=1
fi
banner "========== Docker Compose 启动/升级 =========="
clean_frontend_artifacts
if [ "$fresh_build" -eq 1 ]; then if [ "$fresh_build" -eq 1 ]; then
info "全量重建镜像 (--no-cache)..." info "全量重建镜像 (--no-cache)..."
$DOCKER_COMPOSE build --no-cache $DOCKER_COMPOSE build --no-cache
@@ -630,21 +753,19 @@ cmd_docker() {
$DOCKER_COMPOSE up -d --build --force-recreate --remove-orphans $DOCKER_COMPOSE up -d --build --force-recreate --remove-orphans
fi fi
echo "" echo ""
# 清理历史 build cache 和悬空镜像,防止占满磁盘
info "清理历史构建缓存..." info "清理历史构建缓存..."
local before_prune=$(df -h / | awk 'NR==2{print $5}')
docker builder prune -f 2>/dev/null || true docker builder prune -f 2>/dev/null || true
docker image prune -f 2>/dev/null || true docker image prune -f 2>/dev/null || true
local after_prune=$(df -h / | awk 'NR==2{print $5}')
info "磁盘使用: ${before_prune} → ${after_prune}"
echo "" echo ""
info "等待服务就绪..." info "等待服务就绪..."
sleep 5 sleep 5
$DOCKER_COMPOSE ps $DOCKER_COMPOSE ps
echo "" echo ""
info "前端地址: http://localhost:80" info "访问地址: http://localhost:8080"
info "后端地址: http://localhost:8080" info "版本检查: http://localhost:8080/version"
info "健康检查: http://localhost:8080/health" ;;
push)
build_embed_image "$version_arg" 0 1 || exit 1
;; ;;
down) down)
info "停止 Docker Compose..." info "停止 Docker Compose..."
@@ -688,16 +809,15 @@ cmd_docker() {
cmd_docker up fresh cmd_docker up fresh
;; ;;
help|--help|-h) help|--help|-h)
echo "Docker Compose 部署命令:" echo "Docker Compose 部署命令 (embed 单容器 + MySQL + Redis):"
echo " ./run.sh docker up 增量构建 + 强制重建容器" echo " ./run.sh docker up 增量构建 + 启动"
echo " ./run.sh docker up fresh 无缓存全量重建镜像并启动" echo " ./run.sh docker up v1.0.1 指定版本构建"
echo " ./run.sh docker upgrade 同 up(升级别名)" echo " ./run.sh docker up fresh 无缓存全量重建"
echo " ./run.sh docker down 停止并移除容器" echo " ./run.sh docker push v1.0.1 构建并推送到 $DOCKERHUB_IMAGE"
echo " ./run.sh docker build 仅构建镜像" echo " ./run.sh docker down 停止并移除容器"
echo " ./run.sh docker restart 重启容器" echo " ./run.sh docker build 仅构建镜像"
echo " ./run.sh docker logs 查看实时日志" echo " ./run.sh docker logs 查看实时日志"
echo " ./run.sh docker ps 查看容器状态" echo " ./run.sh docker ps 查看容器状态"
echo " ./run.sh docker clean 清理构建缓存/无用镜像"
;; ;;
*) *)
error "未知 docker 子命令: $action" error "未知 docker 子命令: $action"
@@ -876,7 +996,6 @@ cmd_binary() {
# ============================================================ # ============================================================
KUBERNETES_NAMESPACE="devops" KUBERNETES_NAMESPACE="devops"
KUBERNETES_MANIFEST_DIR="$SCRIPT_DIR/deploy/kubernetes" KUBERNETES_MANIFEST_DIR="$SCRIPT_DIR/deploy/kubernetes"
KUBERNETES_IMAGE="aiops:embed"
KUBERNETES_NODE_PORT=30080 KUBERNETES_NODE_PORT=30080
KUBERNETES_BUILT_IMAGE="" KUBERNETES_BUILT_IMAGE=""
@@ -918,52 +1037,32 @@ load_image_to_cluster() {
warning "如集群无法拉取镜像,请手动推送: docker push <registry>/$image" warning "如集群无法拉取镜像,请手动推送: docker push <registry>/$image"
} }
# Kubernetes 构建镜像(upgrade 时无缓存 + 时间戳 tag 避免旧层残留)// Logan.Li # Kubernetes 构建镜像 // Logan.Li
cmd_kubernetes_build() { cmd_kubernetes_build() {
local no_cache=${1:-0} local version_tag=""
if ! command -v docker &>/dev/null; then local no_cache=0
error "Docker 未安装" local do_push=0
exit 1 while [ $# -gt 0 ]; do
fi case "$1" in
1|--no-cache|fresh) no_cache=1; shift ;;
push) do_push=1; shift ;;
tag)
shift
version_tag=${1:-}
shift
;;
*)
if looks_like_version "$1"; then
version_tag=$1
fi
shift
;;
esac
done
banner "========== 构建 embed 镜像 ==========" build_embed_image "$version_tag" "$no_cache" "$do_push" || return 1
clean_frontend_artifacts load_image_to_cluster "$KUBERNETES_BUILT_IMAGE"
clean_embed_static load_image_to_cluster "${DOCKERHUB_IMAGE}:dev"
local version
version=$(git describe --tags --abbrev=0 2>/dev/null || echo "dev")
local build_time
build_time=$(date -u +%Y-%m-%dT%H:%M:%SZ)
local image_tag
image_tag="${KUBERNETES_IMAGE}-$(date +%Y%m%d%H%M%S)"
info "镜像: $KUBERNETES_IMAGE (+ $image_tag)"
local build_args=(
-f Dockerfile.embed
--build-arg VERSION="$version"
--build-arg BUILD_TIME="$build_time"
-t "$KUBERNETES_IMAGE"
-t "$image_tag"
)
if [ "$no_cache" -eq 1 ]; then
build_args+=(--no-cache --pull)
info "无缓存全量构建 (--no-cache --pull)"
fi
build_args+=(.)
info "构建中(前端 + 后端 embed)..."
docker build "${build_args[@]}" || {
error "镜像构建失败"
exit 1
}
local img_size
img_size=$(docker images "$KUBERNETES_IMAGE" --format "{{.Size}}" | head -1)
success "镜像构建完成: $KUBERNETES_IMAGE ($img_size)"
load_image_to_cluster "$KUBERNETES_IMAGE"
load_image_to_cluster "$image_tag"
KUBERNETES_BUILT_IMAGE="$image_tag"
} }
# 读取 deployment.yaml 中的 replicas(默认 1)// Logan.Li # 读取 deployment.yaml 中的 replicas(默认 1)// Logan.Li
@@ -1020,8 +1119,10 @@ cmd_kubernetes() {
check_kubernetes_deps check_kubernetes_deps
banner "========== Kubernetes 部署 ($KUBERNETES_NAMESPACE) ==========" banner "========== Kubernetes 部署 ($KUBERNETES_NAMESPACE) =========="
# 1. 构建镜像 # 1. 构建镜像(支持 deploy v1.0.1)
cmd_kubernetes_build shift
cmd_kubernetes_build "$@"
kubernetes_update_manifest_image "$KUBERNETES_BUILT_IMAGE"
# 2. 部署基础设施 # 2. 部署基础设施
info "部署 Namespace + Secret + ConfigMap..." info "部署 Namespace + Secret + ConfigMap..."
@@ -1080,7 +1181,9 @@ cmd_kubernetes() {
live_replicas=$(kubernetes_live_replicas) live_replicas=$(kubernetes_live_replicas)
live_replicas=${live_replicas:-1} live_replicas=${live_replicas:-1}
ensure_cluster_mode_for_replicas "$live_replicas" ensure_cluster_mode_for_replicas "$live_replicas"
cmd_kubernetes_build 1 shift
cmd_kubernetes_build fresh "$@"
kubernetes_update_manifest_image "$KUBERNETES_BUILT_IMAGE"
info "更新 Deployment 镜像: $KUBERNETES_BUILT_IMAGE" info "更新 Deployment 镜像: $KUBERNETES_BUILT_IMAGE"
kubectl -n "$KUBERNETES_NAMESPACE" set image deployment/aiops aiops="$KUBERNETES_BUILT_IMAGE" --record kubectl -n "$KUBERNETES_NAMESPACE" set image deployment/aiops aiops="$KUBERNETES_BUILT_IMAGE" --record
kubectl -n "$KUBERNETES_NAMESPACE" rollout status deployment/aiops --timeout=180s kubectl -n "$KUBERNETES_NAMESPACE" rollout status deployment/aiops --timeout=180s
@@ -1108,7 +1211,13 @@ cmd_kubernetes() {
;; ;;
build|image) build|image)
cmd_kubernetes_build shift
cmd_kubernetes_build "$@"
;;
push)
shift
cmd_kubernetes_build push "$@"
;; ;;
status|ps) status|ps)
@@ -1189,9 +1298,10 @@ cmd_kubernetes() {
echo " ./run.sh kubernetes port-forward 端口转发到本机 8080" echo " ./run.sh kubernetes port-forward 端口转发到本机 8080"
echo "" echo ""
echo " ${YELLOW}镜像${NC}" echo " ${YELLOW}镜像${NC}"
echo " ./run.sh kubernetes build 仅构建 embed 镜像" echo " ./run.sh kubernetes build v1.0.1 构建 embed 镜像"
echo " ./run.sh kubernetes push v1.0.1 构建并推送到 $DOCKERHUB_IMAGE"
echo "" echo ""
echo " 镜像: $KUBERNETES_IMAGE" echo " 镜像仓库: $DOCKERHUB_IMAGE:<tag>"
echo " 命名空间: $KUBERNETES_NAMESPACE" echo " 命名空间: $KUBERNETES_NAMESPACE"
echo " NodePort: $KUBERNETES_NODE_PORT" echo " NodePort: $KUBERNETES_NODE_PORT"
;; ;;
@@ -1204,6 +1314,55 @@ cmd_kubernetes() {
esac esac
} }
# ============================================================
# 统一发版:git tag + 二进制 + Docker 镜像推送 + K8s manifest
# ============================================================
cmd_release() {
local version_tag=${1:-}
local skip_tag=${2:-}
if [ -z "$version_tag" ]; then
error "用法: ./run.sh release v1.0.1"
echo " 将依次: 打 git tag → 编译二进制 → 构建镜像 → 推送 $DOCKERHUB_IMAGE → 更新 K8s manifest"
exit 1
fi
if ! looks_like_version "$version_tag"; then
error "版本号格式无效: $version_tag (示例: v1.0.1)"
exit 1
fi
banner "========== 发版 $version_tag =========="
resolve_version "$version_tag"
if [ "$skip_tag" != "--skip-tag" ]; then
if git rev-parse "$version_tag" >/dev/null 2>&1; then
warning "git tag 已存在: $version_tag(跳过创建)"
else
git tag -a "$version_tag" -m "release $version_tag"
success "已创建 git tag: $version_tag"
fi
fi
build_standalone_binary "$version_tag" || exit 1
info "二进制版本:"
./"$STANDALONE_BIN" version
build_embed_image "$version_tag" 0 1 || exit 1
kubernetes_update_manifest_image "$EMBED_IMAGE"
echo ""
success "发版完成: $version_tag"
echo " 二进制: ./$STANDALONE_BIN version"
echo " 镜像: $EMBED_IMAGE"
echo " 推送: docker push $EMBED_IMAGE"
echo " Compose: ./run.sh docker up $version_tag"
echo " K8s: ./run.sh kubernetes upgrade $version_tag"
echo ""
if [ "$skip_tag" != "--skip-tag" ]; then
info "如需推送 git tag: git push origin $version_tag"
fi
}
# ============================================================ # ============================================================
# 帮助 # 帮助
# ============================================================ # ============================================================
@@ -1218,15 +1377,12 @@ cmd_help() {
echo " ./run.sh status 查看本地服务状态" echo " ./run.sh status 查看本地服务状态"
echo " ./run.sh logs 查看实时日志" echo " ./run.sh logs 查看实时日志"
echo "" echo ""
echo -e " ${CYAN}Docker 容器部署${NC}" echo -e " ${CYAN}Docker 容器部署 (embed 单容器)${NC}"
echo " ./run.sh docker up 增量构建 + 强制重建容器" echo " ./run.sh docker up 构建+启动 (MySQL+Redis+AIOps)"
echo " ./run.sh docker up fresh 无缓存全量重建并启动" echo " ./run.sh docker up v1.0.1 指定版本"
echo " ./run.sh docker upgrade 同 up(升级别名)" echo " ./run.sh docker push v1.0.1 构建并推送到 $DOCKERHUB_IMAGE"
echo " ./run.sh docker down 停止并移除容器" echo " ./run.sh docker down 停止容器"
echo " ./run.sh docker build 仅构建镜像" echo " ./run.sh docker logs 查看日志"
echo " ./run.sh docker restart 重启容器"
echo " ./run.sh docker logs 查看容器日志"
echo " ./run.sh docker ps 查看容器状态"
echo "" echo ""
echo -e " ${MAGENTA}Kubernetes 部署 (embed 单容器)${NC}" echo -e " ${MAGENTA}Kubernetes 部署 (embed 单容器)${NC}"
echo " ./run.sh kubernetes deploy 构建镜像 + 全量部署到 Kubernetes" echo " ./run.sh kubernetes deploy 构建镜像 + 全量部署到 Kubernetes"
@@ -1244,6 +1400,7 @@ cmd_help() {
echo -e " ${YELLOW}编译 & 独立二进制${NC}" echo -e " ${YELLOW}编译 & 独立二进制${NC}"
echo " ./run.sh build 编译独立二进制 ./$STANDALONE_BIN (仅根目录)" echo " ./run.sh build 编译独立二进制 ./$STANDALONE_BIN (仅根目录)"
echo " ./run.sh build tag v1.0.1 指定版本号编译" echo " ./run.sh build tag v1.0.1 指定版本号编译"
echo " ./run.sh release v1.0.1 发版:tag+二进制+镜像推送+K8s"
echo " ./run.sh binary upgrade 停服→清旧→重编译→后台启动(生产升级)" echo " ./run.sh binary upgrade 停服→清旧→重编译→后台启动(生产升级)"
echo " ./run.sh binary start|stop|status 进程管理" echo " ./run.sh binary start|stop|status 进程管理"
echo " ./run.sh binary [args] 前台启动(调试)" echo " ./run.sh binary [args] 前台启动(调试)"
@@ -1313,6 +1470,12 @@ main() {
cmd_kubernetes "$@" cmd_kubernetes "$@"
;; ;;
# 统一发版
release)
shift
cmd_release "$@"
;;
# 帮助 # 帮助
help|--help|-h) help|--help|-h)
cmd_help cmd_help