diff --git a/deploy/chart/euler_copilot/configs/rag/.env b/deploy/chart/euler_copilot/configs/rag/.env index ed3c3b2395296baa8231d66374de638f07311e63..031fc8f17f142fb3bd43449ac08be7d2d5573a7c 100644 --- a/deploy/chart/euler_copilot/configs/rag/.env +++ b/deploy/chart/euler_copilot/configs/rag/.env @@ -24,7 +24,7 @@ REDIS_PWD=${redis-password} TASK_RETRY_TIME=3 # Embedding Service -EMBEDDING_ENDPOINT={{ .Values.models.embedding.url }}/embeddings +EMBEDDING_ENDPOINT={{ .Values.models.embedding.url }}/v1/embeddings EMBEDDING_API_KEY={{ .Values.models.embedding.key }} EMBEDDING_MODEL_NAME={{ .Values.models.embedding.name }} diff --git a/deploy/chart/euler_copilot/templates/framework/framework.yaml b/deploy/chart/euler_copilot/templates/framework/framework.yaml index 5c04487f88f590dcb9895c408d57eb4f6a6b8c72..7fbc87b3ea2baca18b5b038c14f86903378a1f59 100644 --- a/deploy/chart/euler_copilot/templates/framework/framework.yaml +++ b/deploy/chart/euler_copilot/templates/framework/framework.yaml @@ -38,7 +38,7 @@ spec: fsGroup: 1001 containers: - name: framework - image: {{ default "hub.oepkgs.net/neocopilot/euler-copilot-framework:0.9.3-x86" .Values.euler_copilot.framework.image }} + image: {{ default "hub.oepkgs.net/neocopilot/euler-copilot-framework:0.9.4-x86" .Values.euler_copilot.framework.image }} imagePullPolicy: {{ default "IfNotPresent" .Values.globals.imagePullPolicy }} ports: - containerPort: 8002 @@ -140,4 +140,4 @@ spec: - name: framework-shared emptyDir: medium: Memory -{{- end -}} \ No newline at end of file +{{- end -}} diff --git a/deploy/chart/euler_copilot/templates/rag-web/rag-web.yaml b/deploy/chart/euler_copilot/templates/rag-web/rag-web.yaml index 2f6f515ae5008f567bd60f537c109b620972afe5..046e93f8cada995ba326c6e9c84eb2b4f14796d1 100644 --- a/deploy/chart/euler_copilot/templates/rag-web/rag-web.yaml +++ b/deploy/chart/euler_copilot/templates/rag-web/rag-web.yaml @@ -56,7 +56,7 @@ spec: automountServiceAccountToken: false containers: - name: rag-web - image: {{ default "hub.oepkgs.net/neocopilot/data_chain_web:0.9.3-x86" .Values.euler_copilot.rag_web.image }} + image: {{ default "hub.oepkgs.net/neocopilot/data_chain_web:0.9.4-x86" .Values.euler_copilot.rag_web.image }} imagePullPolicy: {{ default "IfNotPresent" .Values.globals.imagePullPolicy }} ports: - containerPort: 9888 diff --git a/deploy/chart/euler_copilot/templates/rag/rag.yaml b/deploy/chart/euler_copilot/templates/rag/rag.yaml index b75f7287d7f4995568b8a4e342944be665fbc386..78c593d2fb4dc68ae5cd2cab98a56c973f488bd7 100644 --- a/deploy/chart/euler_copilot/templates/rag/rag.yaml +++ b/deploy/chart/euler_copilot/templates/rag/rag.yaml @@ -37,7 +37,7 @@ spec: automountServiceAccountToken: false containers: - name: rag - image: {{ default "hub.oepkgs.net/neocopilot/data_chain_back_end:0.9.3-x86" .Values.euler_copilot.rag.image }} + image: {{ default "hub.oepkgs.net/neocopilot/data_chain_back_end:0.9.4-x86" .Values.euler_copilot.rag.image }} imagePullPolicy: {{ default "IfNotPresent" .Values.globals.imagePullPolicy }} ports: - containerPort: 9988 diff --git a/deploy/chart/euler_copilot/templates/web/web.yaml b/deploy/chart/euler_copilot/templates/web/web.yaml index f77ffd49b7243597fbb6fcede98243b5f1b7d21a..a47877529dd27a769918f9c8bd9e6c171829f33d 100644 --- a/deploy/chart/euler_copilot/templates/web/web.yaml +++ b/deploy/chart/euler_copilot/templates/web/web.yaml @@ -57,7 +57,7 @@ spec: fsGroup: 1001 containers: - name: web - image: {{ default "hub.oepkgs.net/neocopilot/euler-copilot-web:0.9.3-x86" .Values.euler_copilot.web.image }} + image: {{ default "hub.oepkgs.net/neocopilot/euler-copilot-web:0.9.4-x86" .Values.euler_copilot.web.image }} imagePullPolicy: {{ default "IfNotPresent" .Values.globals.imagePullPolicy }} ports: - containerPort: 8080 @@ -107,4 +107,4 @@ spec: - name: web-tmp emptyDir: medium: Memory -{{- end -}} \ No newline at end of file +{{- end -}} diff --git a/deploy/scripts/0-one-click-deploy/one-click-deploy.sh b/deploy/scripts/0-one-click-deploy/one-click-deploy.sh new file mode 100644 index 0000000000000000000000000000000000000000..a4f4247fe32253708e454c95c6afbeb456905dfc --- /dev/null +++ b/deploy/scripts/0-one-click-deploy/one-click-deploy.sh @@ -0,0 +1,157 @@ +#!/bin/bash + +# 增强颜色定义 +RESET='\033[0m' +BOLD='\033[1m' +RED='\033[31m' +GREEN='\033[32m' +YELLOW='\033[33m' +BLUE='\033[34m' +MAGENTA='\033[35m' +CYAN='\033[36m' +WHITE='\033[37m' +BG_RED='\033[41m' +BG_GREEN='\033[42m' + +# 带颜色输出的进度条函数 +colorful_progress() { + local current=$1 + local total=$2 + local cols=$(tput cols) + local progress=$((current*100/total)) + printf "${YELLOW}${BOLD}[进度]${RESET} ${BLUE}%3d%%${RESET} ${CYAN}[步骤 %d/%d]${RESET}\n" $progress $current $total +} + +# 获取主脚本绝对路径并切换到所在目录 +MAIN_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +cd "$MAIN_DIR" || exit 1 + +# 带错误检查的脚本执行函数 +run_script_with_check() { + local script_path=$1 + local script_name=$2 + local step_number=$3 + + # 前置检查:脚本是否存在 + if [ ! -f "$script_path" ]; then + echo -e "\n${RED}${BOLD}✗ 致命错误:${RESET}${YELLOW}${script_name}${RESET}${RED} 不存在 (路径: ${CYAN}${script_path}${RED})${RESET}" >&2 + exit 1 + fi + + echo -e "\n${BLUE}${BOLD}▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍" + echo -e "${WHITE}${BOLD}▶ 步骤 ${step_number}: ${script_name}${RESET}" + echo -e "${CYAN}🠖 执行路径:${YELLOW}${script_path}${RESET}" + + # 使用bash解释器执行并捕获输出 + if bash "$script_path" 2>&1; then + echo -e "\n${BG_GREEN}${WHITE}${BOLD} ✓ 成功 ${RESET} ${GREEN}${script_name} 执行成功!${RESET}" + else + echo -e "\n${BG_RED}${WHITE}${BOLD} ✗ 失败 ${RESET} ${RED}${script_name} 执行失败!${RESET}" >&2 + exit 1 + fi +} + +# 卸载所有组件 +uninstall_all() { + echo -e "\n${RED}${BOLD}⚠ 警告:此操作将永久删除所有组件和数据!${RESET}" + read -p "$(echo -e "${YELLOW}确认要继续吗?(y/n) ${RESET}")" confirm + + if [[ $confirm != "y" && $confirm != "Y" ]]; then + echo -e "${GREEN}取消卸载操作${RESET}" + return + fi + + echo -e "\n${CYAN}▸ 开始卸载所有Helm Release...${RESET}" + local RELEASES + RELEASES=$(helm list -n euler-copilot --short 2>/dev/null || true) + + if [ -n "$RELEASES" ]; then + echo -e "${YELLOW}找到以下Helm Release:${RESET}" + echo "$RELEASES" | awk '{print " ➤ "$0}' + for release in $RELEASES; do + echo -e "${BLUE}正在删除: ${release}${RESET}" + helm uninstall "$release" -n euler-copilot || echo -e "${RED}删除失败,继续执行...${RESET}" + done + else + echo -e "${YELLOW}未找到需要清理的Helm Release${RESET}" + fi + + echo -e "\n${CYAN}▸ 清理持久化存储...${RESET}" + local pvc_list + pvc_list=$(kubectl get pvc -n euler-copilot -o name 2>/dev/null || true) + + if [ -n "$pvc_list" ]; then + echo -e "${YELLOW}找到以下PVC资源:${RESET}" + echo "$pvc_list" | awk '{print " ➤ "$0}' + echo "$pvc_list" | xargs -n 1 kubectl delete -n euler-copilot || echo -e "${RED}删除失败,继续执行...${RESET}" + else + echo -e "${YELLOW}未找到需要清理的PVC${RESET}" + fi + + echo -e "\n${BG_GREEN}${WHITE}${BOLD} ✓ 完成 ${RESET} ${GREEN}所有资源已清理完成${RESET}" +} + +# 打印初始环境信息 +echo -e "\n${MAGENTA}${BOLD}✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧" +echo -e "${WHITE}${BOLD} Euler Copilot 一键部署系统 ${RESET}" +echo -e "${MAGENTA}✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧${RESET}" +echo -e "${CYAN}◈ 主工作目录:${YELLOW}${MAIN_DIR}${RESET}" + +# 总步骤数和当前步骤 +total_steps=8 +current_step=1 + +# ======================================================================== +# 步骤1: 环境检查 +# ======================================================================== +run_script_with_check "../1-check-env/check_env.sh" "环境检查" $current_step +colorful_progress $current_step $total_steps +((current_step++)) + +# ======================================================================== +# 步骤2: 基础设施处理 +# ======================================================================== +echo -e "\n${BLUE}${BOLD}▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍" +echo -e "${WHITE}${BOLD}▶ 步骤 ${current_step}: 基础设施处理${RESET}" + +if command -v k3s >/dev/null 2>&1 && command -v helm >/dev/null 2>&1; then + echo -e "${CYAN}🠖 检测到已安装 k3s 和 helm,执行环境清理...${RESET}" + uninstall_all +else + echo -e "${CYAN}🠖 开始安装基础工具...${RESET}" + run_script_with_check "../2-install-tools/install_tools.sh" "基础工具安装(k3s+helm)" $current_step +fi + +colorful_progress $current_step $total_steps +((current_step++)) + +# ======================================================================== +# 后续步骤 (3-8) +# ======================================================================== +steps=( + "../3-install-ollama/install_ollama.sh Ollama部署" + "../4-deploy-deepseek/deploy_deepseek.sh Deepseek模型部署" + "../5-deploy-embedding/deploy-embedding.sh Embedding服务部署" + "../6-install-databases/install_databases.sh 数据库集群部署" + "../7-install-authhub/install_authhub.sh Authhub部署" + "../8-install-EulerCopilot/install_eulercopilot.sh EulerCopilot部署" +) + +for step in "${steps[@]}"; do + script_path=$(echo "$step" | awk '{print $1}') + script_name=$(echo "$step" | awk '{sub($1 OFS, ""); print}') + run_script_with_check "$script_path" "$script_name" $current_step + colorful_progress $current_step $total_steps + ((current_step++)) +done + +# ======================================================================== +# 完成提示 +# ======================================================================== +echo -e "\n${BG_GREEN}${WHITE}${BOLD} ✦ 全部完成 ✦ ${RESET}" +echo -e "${GREEN}${BOLD}所有组件已成功部署!${RESET}" +echo -e "${YELLOW}请通过以下方式验证部署:" +echo -e " ➤ 检查所有Pod状态: kubectl get pods -n euler-copilot" +echo -e " ➤ 查看服务端点: kubectl get svc -n euler-copilot" +echo -e " ➤ 访问Web界面: http://<节点IP>:<服务端口>${RESET}" +echo -e "\n${MAGENTA}${BOLD}✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧✧${RESET}" diff --git a/deploy/scripts/1-check-env/check_env.sh b/deploy/scripts/1-check-env/check_env.sh new file mode 100644 index 0000000000000000000000000000000000000000..42173894183e93e07dada44629a3b54f6c32d0ce --- /dev/null +++ b/deploy/scripts/1-check-env/check_env.sh @@ -0,0 +1,250 @@ +#!/bin/bash + +# 颜色定义 +COLOR_INFO='\033[34m' # 蓝色信息 +COLOR_SUCCESS='\033[32m' # 绿色成功 +COLOR_ERROR='\033[31m' # 红色错误 +COLOR_RESET='\033[0m' # 重置颜色 + +function check_user { + if [[ $(id -u) -ne 0 ]]; then + echo -e "${COLOR_ERROR}[Error] 请以root权限运行该脚本!${COLOR_RESET}" + return 1 + fi + return 0 +} + +function check_version { + local current_version_id="$1" + local supported_versions=("${@:2}") # 从第二个参数开始为支持的版本 + + echo -e "${COLOR_INFO}[Info] 当前操作系统版本为:$current_version_id${COLOR_RESET}" + for version_id in "${supported_versions[@]}"; do + if [[ "$current_version_id" == "$version_id" ]]; then # 精确匹配 + echo -e "${COLOR_SUCCESS}[Success] 操作系统满足兼容性要求${COLOR_RESET}" + return 0 + fi + done + + echo -e "${COLOR_ERROR}[Error] 操作系统不满足兼容性要求,脚本将退出${COLOR_RESET}" + return 1 +} + +function check_os_version { + local id=$(grep -E "^ID=" /etc/os-release | cut -d '"' -f 2) + local version=$(grep -E "^VERSION_ID=" /etc/os-release | cut -d '"' -f 2) + + echo -e "${COLOR_INFO}[Info] 当前发行版为:$id${COLOR_RESET}" + + case $id in + "openEuler"|"bclinux") + local supported_versions=("22.03" "22.09" "23.03" "23.09" "24.03") + check_version "$version" "${supported_versions[@]}" + ;; + "InLinux") + local supported_versions=("23.12") + check_version "$version" "${supported_versions[@]}" + ;; + "FusionOS") + local supported_versions=("23") + check_version "$version" "${supported_versions[@]}" + ;; + "uos") + local supported_versions=("20") + check_version "$version" "${supported_versions[@]}" + ;; + "HopeOS") + local supported_versions=("V22") + check_version "$version" "${supported_versions[@]}" + ;; + *) + echo -e "${COLOR_ERROR}[Error] 发行版不受支持,脚本将退出${COLOR_RESET}" + return 1 + ;; + esac + return $? +} + +function check_hostname { + local current_hostname=$(cat /etc/hostname) + if [[ -z "$current_hostname" ]]; then + echo -e "${COLOR_ERROR}[Error] 当前操作系统未设置主机名,将进行主机名设置${COLOR_RESET}" + read -p "请输入主机名:" new_hostname + set_hostname "$new_hostname" + return $? + else + echo -e "${COLOR_INFO}[Info] 当前主机名为:$current_hostname${COLOR_RESET}" + echo -e "${COLOR_SUCCESS}[Success] 当前操作系统主机名已设置${COLOR_RESET}" + return 0 + fi +} + +function set_hostname { + if ! command -v hostnamectl &> /dev/null; then + echo -e "${COLOR_ERROR}[Error] hostnamectl 不存在,主机名设置可能不会持久生效${COLOR_RESET}" + echo "$1" > /etc/hostname + echo -e "${COLOR_SUCCESS}[Success] 手动设置主机名成功${COLOR_RESET}" + return 0 + fi + + if hostnamectl set-hostname "$1"; then + echo -e "${COLOR_SUCCESS}[Success] 主机名设置成功${COLOR_RESET}" + return 0 + else + echo -e "${COLOR_ERROR}[Error] 主机名设置失败${COLOR_RESET}" + return 1 + fi +} + +function check_dns { + echo -e "${COLOR_INFO}[Info] 检查DNS服务器设置${COLOR_RESET}" + if grep -q "^nameserver" /etc/resolv.conf; then + echo -e "${COLOR_SUCCESS}[Success] DNS服务器已配置${COLOR_RESET}" + return 0 + fi + + echo -e "${COLOR_ERROR}[Error] DNS服务器未配置${COLOR_RESET}" + read -p "请输入新的DNS服务器地址:" new_dns + set_dns "$new_dns" + return $? +} + +function set_dns { + if systemctl is-active --quiet NetworkManager; then + local net_ic=$(nmcli -t -f NAME con show --active | head -n 1) + if [[ -z "$net_ic" ]]; then + echo -e "${COLOR_ERROR}[Error] 未找到活跃网络连接${COLOR_RESET}" + return 1 + fi + + if nmcli con mod "$net_ic" ipv4.dns "$1" && nmcli con mod "$net_ic" ipv4.ignore-auto-dns yes; then + nmcli con down "$net_ic" && nmcli con up "$net_ic" + echo -e "${COLOR_SUCCESS}[Success] DNS设置成功${COLOR_RESET}" + return 0 + else + echo -e "${COLOR_ERROR}[Error] DNS设置失败${COLOR_RESET}" + return 1 + fi + else + cp /etc/resolv.conf /etc/resolv.conf.bak + echo "nameserver $1" >> /etc/resolv.conf + echo -e "${COLOR_SUCCESS}[Success] 手动设置DNS成功${COLOR_RESET}" + return 0 + fi +} + +function check_ram { + local RAM_THRESHOLD=16000 # 16GB + local current_mem=$(free -m | awk '/Mem/{print $2}') + + echo -e "${COLOR_INFO}[Info] 当前机器的RAM为:$current_mem MB${COLOR_RESET}" + if (( current_mem < RAM_THRESHOLD )); then + echo -e "${COLOR_ERROR}[Error] 内存容量不足 ${RAM_THRESHOLD} MB${COLOR_RESET}" + return 1 + fi + echo -e "${COLOR_SUCCESS}[Success] 内存容量满足要求${COLOR_RESET}" + return 0 +} + +function check_disk { + local DISK_THRESHOLD=50000 # 50GB + local PERCENT_THRESHOLD=85 # 85% + + read -r available size <<< $(df -m /var/lib | awk 'NR==2{print $4,$2}') + echo -e "${COLOR_INFO}[Info] 当前磁盘可用空间: ${available}MB, 总大小: ${size}MB${COLOR_RESET}" + + if (( available < DISK_THRESHOLD )); then + echo -e "${COLOR_ERROR}[Error] 磁盘可用空间不足 ${DISK_THRESHOLD} MB${COLOR_RESET}" + return 1 + fi + + local used_after=$(( size - (available - DISK_THRESHOLD) )) + local usage_percent=$(( used_after * 100 / size )) + + if (( usage_percent > PERCENT_THRESHOLD )); then + echo -e "${COLOR_ERROR}[Error] 部署后磁盘使用率将达 ${usage_percent}% (超过 ${PERCENT_THRESHOLD}%)${COLOR_RESET}" + return 1 + fi + + echo -e "${COLOR_SUCCESS}[Success] 磁盘空间满足要求${COLOR_RESET}" + return 0 +} + +function check_network { + echo -e "${COLOR_INFO}[Info] 检查网络连接...${COLOR_RESET}" + if ! command -v curl &> /dev/null; then + echo -e "${COLOR_INFO}[Info] 正在安装curl...${COLOR_RESET}" + yum install -y curl || { echo -e "${COLOR_ERROR}[Error] curl安装失败${COLOR_RESET}"; return 1; } + fi + + if ! curl -IsSf --connect-timeout 5 www.baidu.com &> /dev/null; then + echo -e "${COLOR_ERROR}[Error] 无法访问外部网络${COLOR_RESET}" + return 1 + fi + echo -e "${COLOR_SUCCESS}[Success] 网络连接正常${COLOR_RESET}" + return 0 +} + +function check_selinux { + local config_status=$(grep -E "^SELINUX=" /etc/selinux/config | awk -F'=' '{print $2}' | tr -d '"' | tr -d ' ') + local runtime_status=$(getenforce 2>/dev/null) + + if [[ "$runtime_status" == "Enforcing" ]]; then + echo -e "${COLOR_ERROR}[Error] SELinux当前处于强制模式${COLOR_RESET}" + read -p "是否禁用SELinux?(Y/n)" choice + case $choice in + [nN]) + echo -e "${COLOR_ERROR}[Error] 已保留SELinux设置${COLOR_RESET}" + return 1 + ;; + *) + sed -i 's/^SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config + setenforce 0 + echo -e "${COLOR_SUCCESS}[Success] SELinux已禁用${COLOR_RESET}" + ;; + esac + elif [[ "$config_status" == "enforcing" ]]; then + echo -e "${COLOR_ERROR}[Error] SELinux配置为强制模式(需重启生效)${COLOR_RESET}" + return 1 + fi + return 0 +} + +function check_firewall { + if systemctl is-active --quiet firewalld; then + echo -e "${COLOR_ERROR}[Error] FirewallD正在运行${COLOR_RESET}" + read -p "是否关闭防火墙?(Y/n)" choice + case $choice in + [nN]) + echo -e "${COLOR_ERROR}[Error] 已保留防火墙设置${COLOR_RESET}" + return 1 + ;; + *) + systemctl disable --now firewalld + echo -e "${COLOR_SUCCESS}[Success] 防火墙已关闭${COLOR_RESET}" + ;; + esac + else + echo -e "${COLOR_SUCCESS}[Success] 防火墙未运行${COLOR_RESET}" + fi + return 0 +} + +function main { + check_user || return 1 + check_os_version || return 1 + check_hostname || return 1 + check_dns || return 1 + check_ram || return 1 + check_disk || return 1 + check_network || return 1 + check_selinux || return 1 + check_firewall || return 1 + + echo -e "\n${COLOR_SUCCESS}#####################################" + echo -e "# 环境检查全部通过,可以开始部署 #" + echo -e "#####################################${COLOR_RESET}" + return 0 +} + +main diff --git a/deploy/scripts/2-install-tools/install_tools.sh b/deploy/scripts/2-install-tools/install_tools.sh new file mode 100644 index 0000000000000000000000000000000000000000..2ffd9754fb1c85de25dfe87c9bf2332c041f4836 --- /dev/null +++ b/deploy/scripts/2-install-tools/install_tools.sh @@ -0,0 +1,122 @@ +#!/bin/bash + +GITHUB_MIRROR="https://gh-proxy.com" +ARCH=$(uname -m) + +# 函数:显示帮助信息(更新版) +function help { + echo -e "用法:bash install_tools.sh [cn: 可选镜像参数]" + echo -e "示例:bash install_tools.sh # 使用默认设置安装" + echo -e " bash install_tools.sh cn # 使用国内镜像加速" +} + +function check_user { + if [[ $(id -u) -ne 0 ]]; then + echo -e "\033[31m[Error]请以root权限运行该脚本!\033[0m" + exit 1 + fi +} + +function check_arch { + case $ARCH in + x86_64) ARCH=amd64 ;; + aarch64) ARCH=arm64 ;; + *) + echo -e "\033[31m[Error]当前CPU架构不受支持\033[0m" + return 1 + ;; + esac + return 0 +} + +function install_k3s { + local k3s_version="v1.30.2+k3s1" + local image_name="k3s-airgap-images-$ARCH.tar.zst" + + # 根据架构确定二进制文件名 + local bin_name="k3s" + [[ $ARCH == "arm64" ]] && bin_name="k3s-arm64" + + # 构建下载URL + local k3s_bin_url="$GITHUB_MIRROR/https://github.com/k3s-io/k3s/releases/download/$k3s_version/$bin_name" + local k3s_image_url="$GITHUB_MIRROR/https://github.com/k3s-io/k3s/releases/download/$k3s_version/$image_name" + + echo -e "[Info] 下载K3s二进制文件(版本:$k3s_version)" + if ! curl -L "$k3s_bin_url" -o /usr/local/bin/k3s; then + echo -e "\033[31m[Error] K3s二进制文件下载失败\033[0m" + return 1 + fi + chmod +x /usr/local/bin/k3s + + echo -e "[Info] 下载K3s依赖镜像" + mkdir -p /var/lib/rancher/k3s/agent/images + if ! curl -L "$k3s_image_url" -o "/var/lib/rancher/k3s/agent/images/$image_name"; then + echo -e "\033[31m[Error] K3s依赖下载失败\033[0m" + return 1 + fi + + # 选择安装源 + local install_source="https://get.k3s.io" + [[ $1 == "cn" ]] && install_source="https://rancher-mirror.rancher.cn/k3s/k3s-install.sh" + + echo -e "[Info] 执行K3s安装脚本" + if ! curl -sfL "$install_source" | INSTALL_K3S_SKIP_DOWNLOAD=true sh -; then + echo -e "\033[31m[Error] K3s安装失败\033[0m" + return 1 + fi + + echo -e "\033[32m[Success] K3s ($k3s_version) 安装成功\033[0m" + return 0 +} + +function install_helm { + local helm_version="v3.15.3" + local file_name="helm-${helm_version}-linux-${ARCH}.tar.gz" + + # 根据镜像参数选择下载源 + local base_url="https://get.helm.sh" + [[ $1 == "cn" ]] && base_url="https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts/helm/v${helm_version#v}" + + echo -e "[Info] 下载Helm(版本:$helm_version)" + if ! curl -L "$base_url/$file_name" -o "$file_name"; then + echo -e "\033[31m[Error] Helm下载失败\033[0m" + return 1 + fi + + echo -e "[Info] 解压并安装Helm" + tar -zxvf "$file_name" --strip-components 1 -C /usr/local/bin "linux-$ARCH/helm" + chmod +x /usr/local/bin/helm + rm -f "$file_name" + + echo -e "\033[32m[Success] Helm ($helm_version) 安装成功\033[0m" + return 0 +} + +function main { + check_user + check_arch || exit 1 + + local use_mirror="" + [[ $1 == "cn" ]] && use_mirror="cn" + + # 安装K3s(如果尚未安装) + if ! command -v k3s &> /dev/null; then + install_k3s "$use_mirror" || exit 1 + else + echo -e "[Info] K3s 已经安装,跳过安装步骤" + fi + + # 安装Helm(如果尚未安装) + if ! command -v helm &> /dev/null; then + install_helm "$use_mirror" || exit 1 + else + echo -e "[Info] Helm 已经安装,跳过安装步骤" + fi + + echo -e "\n\033[32m=== 全部工具安装完成 ===\033[0m" + echo -e "K3s 版本:$(k3s --version | head -n1)" + echo -e "Helm 版本:$(helm version --short)" +} + +# 执行主函数,允许传递一个可选参数(cn) +main "$@" diff --git a/deploy/scripts/3-install-ollama/install_ollama.sh b/deploy/scripts/3-install-ollama/install_ollama.sh new file mode 100644 index 0000000000000000000000000000000000000000..77ea069b2e6e46ce16f1e367f6a4e583cbea4567 --- /dev/null +++ b/deploy/scripts/3-install-ollama/install_ollama.sh @@ -0,0 +1,118 @@ +#!/bin/bash +set -euo pipefail + +# 定义颜色代码 +RED='\e[31m' +GREEN='\e[32m' +YELLOW='\e[33m' +BLUE='\e[34m' +MAGENTA='\e[35m' +CYAN='\e[36m' +RESET='\e[0m' + +# 初始化全局变量 +OS_ID="" + +detect_os() { + echo -e "${BLUE}步骤1/4:检测操作系统...${RESET}" + if [ -f /etc/os-release ]; then + . /etc/os-release + OS_ID="${ID}" + echo -e "${GREEN}[信息] 检测到操作系统: $OS_ID${RESET}" + else + echo -e "${RED}[错误] 无法检测操作系统类型${RESET}" >&2 + exit 1 + fi +} + +install_dependencies() { + echo -e "${BLUE}步骤2/4:安装系统依赖...${RESET}" + case "$OS_ID" in + ubuntu|debian) + if ! apt-get update && apt-get install -y curl wget tar gzip jq; then + echo -e "${RED}[错误] APT依赖安装失败${RESET}" >&2 + exit 1 + fi + ;; + openEuler|centos|rhel|fedora) + if ! yum install -y curl wget tar gzip jq; then + echo -e "${RED}[错误] YUM依赖安装失败${RESET}" >&2 + exit 1 + fi + ;; + *) + echo -e "${RED}[错误] 不支持的发行版: $OS_ID${RESET}" >&2 + exit 1 + ;; + esac + echo -e "${GREEN}[信息] 系统依赖安装完成${RESET}" +} + +install_ollama() { + echo -e "${BLUE}步骤3/4:安装Ollama...${RESET}" + if command -v ollama &>/dev/null; then + echo -e "${GREEN}[信息] Ollama已安装,跳过安装步骤${RESET}" + return 0 + fi + + echo -e "${CYAN}[操作] 开始安装Ollama...${RESET}" + if ! curl -o ollama_install.sh https://ollama.ai/install.sh; then + echo -e "${RED}[错误] 下载安装脚本失败${RESET}" >&2 + exit 1 + fi + + # 替换镜像源 + if ! sed -i 's#https://github.com/#https://mirrors.tuna.tsinghua.edu.cn/github/#g' ollama_install.sh; then + echo -e "${YELLOW}[警告] 镜像源替换失败,继续尝试安装...${RESET}" + fi + + if ! sh ollama_install.sh; then + echo -e "${RED}[错误] Ollama安装失败${RESET}" >&2 + echo -e "${YELLOW}排查建议:" + echo "1. 检查脚本执行权限:ls -l ollama_install.sh" + echo "2. 查看安装日志:journalctl -u ollama -n 50${RESET}" + exit 1 + fi + echo -e "${GREEN}[信息] Ollama安装完成${RESET}" +} + +manage_service() { + echo -e "${BLUE}步骤4/4:配置Ollama服务...${RESET}" + local service_file="/etc/systemd/system/ollama.service" + + if [ ! -f "$service_file" ]; then + echo -e "${RED}[错误] Ollama服务文件不存在:$service_file${RESET}" >&2 + exit 1 + fi + + if ! grep -q "OLLAMA_HOST=0.0.0.0:11434" "$service_file"; then + echo -e "${CYAN}[操作] 配置服务监听地址...${RESET}" + if ! sed -i '/^\[Service\]/a Environment="OLLAMA_HOST=0.0.0.0:11434"' "$service_file"; then + echo -e "${RED}[错误] 服务文件修改失败${RESET}" >&2 + exit 1 + fi + systemctl daemon-reload + echo -e "${GREEN}[信息] 服务配置已更新${RESET}" + fi + + if systemctl is-active --quiet ollama; then + echo -e "${CYAN}[操作] 重启服务应用配置...${RESET}" + systemctl restart ollama + else + echo -e "${CYAN}[操作] 启动Ollama服务...${RESET}" + systemctl enable --now ollama + fi + + echo -e "${YELLOW}[状态] 等待服务初始化...${RESET}" + sleep 10 +} + +### 主执行流程 ### +echo -e "${MAGENTA}=== 开始Ollama安装 ===${RESET}" +{ + detect_os + install_dependencies + install_ollama + manage_service +} +echo -e "${MAGENTA}=== Ollama安装成功 ===${RESET}" diff --git a/deploy/scripts/4-deploy-deepseek/deploy_deepseek.sh b/deploy/scripts/4-deploy-deepseek/deploy_deepseek.sh new file mode 100644 index 0000000000000000000000000000000000000000..45d7e535b2de9a787d0c0ff7b16c054b345fa382 --- /dev/null +++ b/deploy/scripts/4-deploy-deepseek/deploy_deepseek.sh @@ -0,0 +1,154 @@ +#!/bin/bash +set -euo pipefail + +# 颜色定义 +GREEN='\033[0;32m' +RED='\033[0;31m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # 重置颜色 + +# 配置参数 +readonly MODEL_NAME="deepseek-llm-7b-chat" +readonly MODEL_URL="https://modelscope.cn/models/second-state/Deepseek-LLM-7B-Chat-GGUF/resolve/master/deepseek-llm-7b-chat-Q4_K_M.gguf" +readonly MODEL_FILE="deepseek-llm-7b-chat-Q4_K_M.gguf" +readonly MODELLEFILE="Modelfile" +readonly TIMEOUT_DURATION=45 + +check_service() { + echo -e "${BLUE}步骤1/5:检查服务状态...${NC}" + if ! systemctl is-active --quiet ollama; then + echo -e "${RED}Ollama服务未运行${NC}" + echo -e "${YELLOW}请先执行ollama-install.sh安装服务${NC}" + exit 1 + fi + echo -e "${GREEN}服务状态正常${NC}" +} + +download_model() { + echo -e "${BLUE}步骤2/5:下载模型文件...${NC}" + if [[ -f "$MODEL_FILE" ]]; then + echo -e "${GREEN}模型文件已存在,跳过下载${NC}" + return 0 + fi + + echo -e "${YELLOW}开始下载模型...${NC}" + + # 检查下载工具 + local download_cmd + if command -v wget &> /dev/null; then + download_cmd="wget --tries=3 --content-disposition -O '$MODEL_FILE' '$MODEL_URL'" + elif command -v curl &> /dev/null; then + download_cmd="curl -# -L -o '$MODEL_FILE' '$MODEL_URL'" + else + echo -e "${RED}错误:需要wget或curl来下载模型文件${NC}" + exit 1 + fi + + if ! eval "$download_cmd"; then + echo -e "${RED}模型下载失败,删除不完整文件...${NC}" + rm -f "$MODEL_FILE" + exit 1 + fi + + echo -e "${GREEN}模型下载完成(文件大小:$(du -h $MODEL_FILE | cut -f1))${NC}" +} + +create_modelfile() { + echo -e "${BLUE}步骤3/5:创建模型配置...${NC}" + cat > "$MODELLEFILE" < /dev/null; then + echo -e "${YELLOW}注意:jq未安装,响应解析可能受限,建议安装jq以获得更好的输出。${NC}" + fi + + local retries=3 + local interval=5 + local attempt=1 + + # 基础验证 + if ! ollama list | grep -qw "$MODEL_NAME"; then + echo -e "${RED}基础验证失败 - 未找到模型 $MODEL_NAME${NC}" + echo -e "${YELLOW}排查建议:" + echo "1. 检查服务状态:systemctl status ollama" + echo "2. 查看创建日志:journalctl -u ollama | tail -n 50${NC}" + exit 1 + fi + echo -e "${GREEN}基础验证通过 - 检测到模型: $MODEL_NAME${NC}" + + # API功能验证 + echo -e "${YELLOW}执行API测试(超时时间${TIMEOUT_DURATION}秒)...${NC}" + + while [ $attempt -le $retries ]; do + echo -e "${BLUE}尝试 $attempt: 发送测试请求...${NC}" + response=$(timeout $TIMEOUT_DURATION curl -s -X POST http://localhost:11434/api/generate \ + -d "{\"model\": \"$MODEL_NAME\", \"prompt\": \"你好,请说一首中文古诗\", \"stream\": false}") + + if [[ $? -eq 0 ]] && [[ -n "$response" ]]; then + echo -e "${GREEN}测试响应成功,收到有效输出:" + # 处理JSON解析 + if jq -e .response <<< "$response" &> /dev/null; then + jq .response <<< "$response" + else + echo "$response" + fi + return 0 + else + echo -e "${YELLOW}请求未得到有效响应${NC}" + ((attempt++)) + sleep $interval + fi + done + + echo -e "${RED}验证失败:经过 $retries 次重试仍未收到有效响应${NC}" + exit 1 +} + +### 主执行流程 ### +echo -e "${BLUE}=== 开始模型部署 ===${NC}" +{ + check_service + download_model + create_modelfile + create_model + verify_deployment +} +echo -e "${GREEN}=== 模型部署成功 ===${NC}" + +cat << EOF +${YELLOW}使用说明: +1. 启动交互模式:ollama run $MODEL_NAME +2. API访问示例: +curl -X POST http://localhost:11434/api/generate \\ +-d "{\\"model\\": \\"$MODEL_NAME\\", \\"prompt\\": \\"你好,介绍一下上海\\", \\"stream\\": false}" + +3. 流式对话模式: +curl http://localhost:11434/api/chat \\ +-d "{\\"model\\": \\"$MODEL_NAME\\", \\"messages\\": [{ \\"role\\": \\"user\\", \\"content\\": \\"你好\\" }]}" +EOF \ No newline at end of file diff --git a/deploy/scripts/5-deploy-embedding/deploy-embedding.sh b/deploy/scripts/5-deploy-embedding/deploy-embedding.sh new file mode 100644 index 0000000000000000000000000000000000000000..3294110ccf2be8465cdbe6433918a6c01c2cf86e --- /dev/null +++ b/deploy/scripts/5-deploy-embedding/deploy-embedding.sh @@ -0,0 +1,141 @@ +#!/bin/bash +set -euo pipefail + +# 颜色定义 +RED='\e[31m' +GREEN='\e[32m' +YELLOW='\e[33m' +BLUE='\e[34m' +NC='\e[0m' # 重置颜色 + +# 配置参数 +readonly MODEL_NAME="bge-m3" +readonly MODEL_URL="https://modelscope.cn/models/gpustack/bge-m3-GGUF/resolve/master/bge-m3-Q4_K_M.gguf" +readonly MODEL_FILE="bge-m3-Q4_K_M.gguf" +readonly MODELLEFILE="Modelfile" +readonly TIMEOUT_DURATION=45 + +check_service() { + echo -e "${BLUE}步骤1/4:检查服务状态...${NC}" + if ! systemctl is-active --quiet ollama; then + echo -e "${RED}[ERROR] Ollama服务未运行${NC}" + echo -e "${YELLOW}可能原因:" + echo "1. 服务未安装" + echo "2. 系统未启用服务" + echo -e "请先执行ollama-install.sh安装服务${NC}" + exit 1 + fi +} + +download_model() { + echo -e "${BLUE}步骤2/4:下载模型文件...${NC}" + if [[ -f "$MODEL_FILE" ]]; then + echo -e "${GREEN}[SUCCESS] 模型文件已存在,跳过下载${NC}" + return 0 + fi + + echo -e "${YELLOW}开始下载模型...${NC}" + if ! wget --tries=3 --content-disposition -O "$MODEL_FILE" "$MODEL_URL"; then + echo -e "${RED}[ERROR] 模型下载失败${NC}" + echo -e "${YELLOW}可能原因:" + echo "1. URL已失效(当前URL: $MODEL_URL)" + echo "2. 网络连接问题" + echo -e "3. 磁盘空间不足(当前剩余:$(df -h . | awk 'NR==2 {print $4}'))${NC}" + exit 1 + fi + echo -e "${GREEN}[SUCCESS] 模型下载完成(文件大小:$(du -h $MODEL_FILE | awk '{print $1}' ${NC}))" +} + +create_modelfile() { + echo -e "${BLUE}步骤3/4:创建模型配置...${NC}" + cat > "$MODELLEFILE" < response.txt + return 0 # 成功,无需打印响应 + else + ((ATTEMPT++)) + if [ $ATTEMPT -le $retries ]; then + sleep $INTERVAL + else + echo -e "${RED}[ERROR] 已达到最大尝试次数($retries),仍未收到响应${NC}" + return 1 + fi + fi + done +} + +### 主执行流程 ### +echo -e "${BLUE}=== 开始模型部署 ===${NC}" +{ + check_service + download_model + create_modelfile + create_model + verify_deployment +} +echo -e "${BLUE}=== 模型部署成功 ===${NC}" + +cat << EOF +${GREEN}使用说明:${NC} +1. 启动交互模式:ollama run $MODEL_NAME +2. API访问示例: +curl -k -X POST http://localhost:11434/v1/embeddings \\ +-H "Content-Type: application/json" \\ +-d '{"input": "The food was delicious and the waiter...", "model": "bge-m3", "encoding_format": "float"}' +EOF diff --git a/deploy/scripts/6-install-databases/install_databases.sh b/deploy/scripts/6-install-databases/install_databases.sh new file mode 100644 index 0000000000000000000000000000000000000000..474329e13895d70a0b33b9bdf992ec473f283db2 --- /dev/null +++ b/deploy/scripts/6-install-databases/install_databases.sh @@ -0,0 +1,120 @@ +#!/bin/bash +set -eo pipefail + +RED='\033[31m' +GREEN='\033[32m' +YELLOW='\033[33m' +BLUE='\033[34m' +NC='\033[0m' + +create_namespace() { + echo -e "${BLUE}==> 检查命名空间 euler-copilot...${NC}" + if ! kubectl get namespace euler-copilot &> /dev/null; then + kubectl create namespace euler-copilot || { + echo -e "${RED}命名空间创建失败!${NC}" + return 1 + } + echo -e "${GREEN}命名空间创建成功${NC}" + else + echo -e "${YELLOW}命名空间已存在,跳过创建${NC}" + fi +} + + +# 删除PVC和Helm Release +delete_pvcs() { + echo -e "${BLUE}==> 清理现有资源...${NC}" + + # 获取Helm Release列表 + local RELEASES + RELEASES=$(helm list -n euler-copilot --short | grep databases || true) + + # 删除所有关联的Helm Release + if [ -n "$RELEASES" ]; then + echo -e "${YELLOW}找到以下Helm Release,开始清理...${NC}" + for release in $RELEASES; do + echo -e "${BLUE}正在删除Helm Release: ${release}${NC}" + helm uninstall "$release" -n euler-copilot || echo -e "${RED}删除Helm Release失败,继续执行...${NC}" + done + else + echo -e "${YELLOW}未找到需要清理的Helm Release${NC}" + fi + + # 获取所有非mysql的PVC列表 + local pvc_list + pvc_list=$(kubectl get pvc -n euler-copilot -o name | grep -v 'persistentvolumeclaim/mysql-pvc' 2>/dev/null || true) + + # 删除PVC + if [ -n "$pvc_list" ]; then + echo -e "${YELLOW}找到以下PVC,开始清理...${NC}" + echo "$pvc_list" | xargs -n 1 kubectl delete -n euler-copilot || echo -e "${RED}PVC删除失败,继续执行...${NC}" + else + echo -e "${YELLOW}未找到需要清理的PVC${NC}" + fi + + echo -e "${GREEN}资源清理完成${NC}" +} + +helm_install() { + local target_dir="/home/euler-copilot-framework/deploy/chart" + echo -e "${BLUE}==> 进入部署目录...${NC}" + [ ! -d "$target_dir" ] && { + echo -e "${RED}错误:部署目录不存在 $target_dir${NC}" + return 1 + } + cd "$target_dir" + + echo -e "${BLUE}正在安装 databases...${NC}" + helm install databases -n euler-copilot ./databases || { + echo -e "${RED}Helm 安装 databases 失败!${NC}" + return 1 + } +} + +check_pods_status() { + echo -e "${BLUE}==> 等待初始化就绪(30秒)...${NC}" + sleep 30 + + local timeout=300 + local start_time=$(date +%s) + + echo -e "${BLUE}开始监控Pod状态(总超时时间300秒)...${NC}" + + while true; do + local current_time=$(date +%s) + local elapsed=$((current_time - start_time)) + + if [ $elapsed -gt $timeout ]; then + echo -e "${RED}错误:部署超时!${NC}" + kubectl get pods -n euler-copilot + return 1 + fi + + local not_running=$(kubectl get pods -n euler-copilot -o jsonpath='{range .items[*]}{.metadata.name} {.status.phase}{"\n"}{end}' | grep -v "Running") + + if [ -z "$not_running" ]; then + echo -e "${GREEN}所有Pod已正常运行!${NC}" + kubectl get pods -n euler-copilot + return 0 + else + echo "等待Pod就绪(已等待 ${elapsed} 秒)..." + echo "当前异常Pod:" + echo "$not_running" | awk '{print " - " $1 " (" $2 ")"}' + sleep 10 + fi + done +} + +main() { + create_namespace + delete_pvcs + helm_install + check_pods_status + + echo -e "\n${GREEN}=========================" + echo "Databases 部署完成!" + echo -e "=========================${NC}" +} + +trap 'echo -e "${RED}操作被中断!${NC}"; exit 1' INT +main "$@" diff --git a/deploy/scripts/7-install-authhub/install_authhub.sh b/deploy/scripts/7-install-authhub/install_authhub.sh new file mode 100644 index 0000000000000000000000000000000000000000..0ef7f18f35ffc6de71e25f3daf802e03e6285b74 --- /dev/null +++ b/deploy/scripts/7-install-authhub/install_authhub.sh @@ -0,0 +1,158 @@ +#!/bin/bash +set -eo pipefail + +RED='\033[31m' +GREEN='\033[32m' +YELLOW='\033[33m' +BLUE='\033[34m' +NC='\033[0m' + +SCRIPTS_DIR=/home/euler-copilot-framework/deploy/scripts/8-install-EulerCopilot +CHART_DIR=/home//euler-copilot-framework/deploy/chart + + +create_namespace() { + echo -e "${BLUE}==> 检查命名空间 euler-copilot...${NC}" + if ! kubectl get namespace euler-copilot &> /dev/null; then + kubectl create namespace euler-copilot || { + echo -e "${RED}命名空间创建失败!${NC}" + return 1 + } + echo -e "${GREEN}命名空间创建成功${NC}" + else + echo -e "${YELLOW}命名空间已存在,跳过创建${NC}" + fi +} + +delete_pvcs() { + echo -e "${BLUE}==> 清理现有资源...${NC}" + + local RELEASES + RELEASES=$(helm list -n euler-copilot --short | grep authhub || true) + + if [ -n "$RELEASES" ]; then + echo -e "${YELLOW}找到以下Helm Release,开始清理...${NC}" + for release in $RELEASES; do + echo -e "${BLUE}正在删除Helm Release: ${release}${NC}" + helm uninstall "$release" -n euler-copilot || echo -e "${RED}删除Helm Release失败,继续执行...${NC}" + done + else + echo -e "${YELLOW}未找到需要清理的Helm Release${NC}" + fi + + local pvc_list + pvc_list=$(kubectl get pvc -n euler-copilot -o name | grep 'persistentvolumeclaim/mysql-pvc' 2>/dev/null || true) + + if [ -n "$pvc_list" ]; then + echo -e "${YELLOW}找到以下PVC,开始清理...${NC}" + echo "$pvc_list" | xargs -n 1 kubectl delete -n euler-copilot || echo -e "${RED}PVC删除失败,继续执行...${NC}" + else + echo -e "${YELLOW}未找到需要清理的PVC${NC}" + fi + + echo -e "${GREEN}资源清理完成${NC}" +} + + +# 获取用户输入参数 +get_user_input() { + echo -e "${BLUE}请输入 Authhub的域名配置:${NC}" + echo + + read -p "Authhub的前端域名: " authhub_domain + if ! [[ "${authhub_domain}" =~ ^([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$ ]]; then + echo -e "${RED}错误:输入的AuthHub域名格式不正确${NC}" + exit 1 + fi + + if [[ -z "$authhub_domain" ]]; then + echo -e "${RED}错误:所有输入字段都不能为空${NC}" + exit 1 + fi +} + + +# 修改YAML配置文件的方法 +modify_yaml() { + echo -e "${BLUE}开始修改YAML配置文件...${NC}" + python "${SCRIPTS_DIR}/modify_eulercopilot_yaml.py" \ + "${CHART_DIR}/authhub/values.yaml" \ + "${CHART_DIR}/authhub/values.yaml" \ + --set "domain.authhub=${authhub_domain}" + + if [ $? -ne 0 ]; then + echo -e "${RED}错误:YAML文件修改失败${NC}" + exit 1 + fi + echo -e "${GREEN}YAML文件修改成功!${NC}" +} + + +helm_install() { + echo -e "${BLUE}==> 进入部署目录...${NC}" + [ ! -d "${CHART_DIR}" ] && { + echo -e "${RED}错误:部署目录不存在 ${CHART_DIR} ${NC}" + return 1 + } + cd "${CHART_DIR}" + + echo -e "${BLUE}正在安装 authhub...${NC}" + helm install authhub -n euler-copilot ./authhub || { + echo -e "${RED}Helm 安装 authhub 失败!${NC}" + return 1 + } +} + +# 检查Pod状态 +check_pods_status() { + echo -e "${BLUE}==> 等待初始化就绪(30秒)...${NC}" + sleep 30 # 初始等待时间 + + local timeout=300 + local start_time=$(date +%s) + + echo -e "${BLUE}开始监控Pod状态(总超时时间300秒)...${NC}" + + while true; do + local current_time=$(date +%s) + local elapsed=$((current_time - start_time)) + + if [ $elapsed -gt $timeout ]; then + echo -e "${RED}错误:部署超时!${NC}" + kubectl get pods -n euler-copilot + return 1 + fi + + # 检查所有Pod状态 + local not_running=$(kubectl get pods -n euler-copilot -o jsonpath='{range .items[*]}{.metadata.name} {.status.phase}{"\n"}{end}' | grep -v "Running") + + if [ -z "$not_running" ]; then + echo -e "${GREEN}所有Pod已正常运行!${NC}" + kubectl get pods -n euler-copilot + return 0 + else + echo "等待Pod就绪(已等待 ${elapsed} 秒)..." + echo "当前异常Pod:" + echo "$not_running" | awk '{print " - " $1 " (" $2 ")"}' + sleep 10 + fi + done +} + +# 主执行流程 +main() { + create_namespace + delete_pvcs + get_user_input + modify_yaml + helm_install + check_pods_status + + echo -e "\n${GREEN}=========================" + echo "Authhub 部署完成!" + echo -e "=========================${NC}" +} + +# 异常处理 +trap 'echo -e "${RED}操作被中断!${NC}"; exit 1' INT +main "$@" diff --git a/deploy/scripts/8-install-EulerCopilot/install_eulercopilot.sh b/deploy/scripts/8-install-EulerCopilot/install_eulercopilot.sh new file mode 100644 index 0000000000000000000000000000000000000000..3cb5f6edefc862c1719771cf5028e46480845159 --- /dev/null +++ b/deploy/scripts/8-install-EulerCopilot/install_eulercopilot.sh @@ -0,0 +1,235 @@ +#!/bin/bash + + + +# 颜色定义 +RED='\e[31m' +GREEN='\e[32m' +YELLOW='\e[33m' +BLUE='\e[34m' +NC='\e[0m' # 恢复默认颜色 + +SCRIPTS_DIR=/home/euler-copilot-framework_openeuler/deploy/scripts/8-install-EulerCopilot +CHART_DIR=/home//euler-copilot-framework_openeuler/deploy/chart +PLUGINS_DIR="/home/eulercopilot/sematics" + +get_eth0_ip() { + echo -e "${BLUE}获取 eth0 网络接口 IP 地址...${NC}" + local timeout=20 + local start_time=$(date +%s) + local interface="eth0" + + # 检查 eth0 是否存在,并等待其变为可用状态 + while [ $(( $(date +%s) - start_time )) -lt $timeout ]; do + if ip link show "$interface" > /dev/null 2>&1; then + break + else + sleep 1 + fi + done + + if ! ip link show "$interface" > /dev/null 2>&1; then + echo -e "${RED}错误:未找到网络接口 ${interface}${NC}" + exit 1 + fi + + # 获取 IP 地址 + host=$(ip addr show "$interface" | grep -w inet | awk '{print $2}' | cut -d'/' -f1) + + if [[ -z "$host" ]]; then + echo -e "${RED}错误:未能从接口 ${interface} 获取 IP 地址${NC}" + exit 1 + fi + + echo -e "${GREEN}使用网络接口:${interface},IP 地址:${host}${NC}" +} + + +## 获取 eth0 IP 地址 +#get_eth0_ip() { +# echo -e "${BLUE}获取网络接口 IP 地址...${NC}" +# local timeout=20 +# local start_time=$(date +%s) +# +# while [ $(( $(date +%s) - start_time )) -lt $timeout ]; do +# interface=$(ip -o link show | awk '/state UP/ {print $2}' | cut -d':' -f1 | head -1) +# [[ -n "$interface" ]] && break || sleep 1 +# done +# +# if [[ -z "$interface" ]]; then +# echo -e "${RED}错误:未找到可用网络接口${NC}" +# exit 1 +# fi +# +# host=$(ip addr show $interface | grep -w inet | awk '{print $2}' | cut -d'/' -f1) +# +# echo -e "${GREEN}使用网络接口:${interface},IP 地址:${host}${NC}" +#} + +# 获取用户输入参数 +get_user_input() { + echo -e "${BLUE}请输入 OAuth 客户端配置:${NC}" + read -p "Client ID: " client_id + read -s -p "Client Secret: " client_secret + echo + + read -p "Web前端域名: " eulercopilot_domain + if ! [[ "${eulercopilot_domain}" =~ ^([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$ ]]; then + echo -e "${RED}错误:输入的Copilot域名格式不正确${NC}" + exit 1 + fi + + read -p "Authhub的前端域名: " authhub_domain + if ! [[ "${authhub_domain}" =~ ^([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$ ]]; then + echo -e "${RED}错误:输入的AuthHub域名格式不正确${NC}" + exit 1 + fi + + if [[ -z "$client_id" || -z "$client_secret" || -z "$eulercopilot_domain" || -z "$authhub_domain" ]]; then + echo -e "${RED}错误:所有输入字段都不能为空${NC}" + exit 1 + fi +} + +# 创建必要目录 +create_directories() { + echo -e "${BLUE}检查并创建数据目录...${NC}" + if ! mkdir -p "${PLUGINS_DIR}"; then + echo -e "${RED}错误:无法创建目录 ${PLUGINS_DIR}${NC}" + exit 1 + fi + echo -e "${GREEN}目录已就绪:${PLUGINS_DIR}${NC}" +} + +# 安装前检查并删除已有部署 +check_and_delete_existing_deployment() { + echo -e "${YELLOW}检查是否存在已部署的euler-copilot...${NC}" + if helm list -n euler-copilot --short | grep -q "^euler-copilot$"; then + echo -e "${YELLOW}发现已存在的euler-copilot部署,正在删除...${NC}" + helm uninstall -n euler-copilot euler-copilot + + if [ $? -ne 0 ]; then + echo -e "${RED}错误:删除旧版euler-copilot失败${NC}" + exit 1 + fi + + echo -e "${YELLOW}等待旧部署清理完成(10秒)...${NC}" + sleep 10 + else + echo -e "${GREEN}未找到已存在的euler-copilot部署,继续安装...${NC}" + fi +} + +# 修改YAML配置文件的方法 +modify_yaml() { + echo -e "${BLUE}开始修改YAML配置文件...${NC}" + python "${SCRIPTS_DIR}/modify_eulercopilot_yaml.py" \ + "${CHART_DIR}/euler_copilot/values.yaml" \ + "${CHART_DIR}/euler_copilot/values.yaml" \ + --set "models.answer.url=http://$host:11434" \ + --set "models.answer.key=sk-123456" \ + --set "models.answer.name=deepseek-llm-7b-chat" \ + --set "models.answer.ctx_length=8192" \ + --set "models.answer.max_tokens=2048" \ + --set "models.embedding.url=http://$host:11434/embeddings" \ + --set "models.embedding.key=sk-123456" \ + --set "models.embedding.name=bge-m3" \ + --set "login.type=authhub" \ + --set "login.client.id=${client_id}" \ + --set "login.client.secret=${client_secret}" \ + --set "login.oidc.token_url=http://authhub-backend-service-authhub.euler-copilot.svc.cluster.local:11120/oauth2/token" \ + --set "login.oidc.user_url=http://authhub-backend-service-authhub.euler-copilot.svc.cluster.local:11120/oauth2/introspect" \ + --set "login.oidc.refresh_url=http://authhub-backend-service-authhub.euler-copilot.svc.cluster.local:11120/oauth2/refresh-token" \ + --set "login.oidc.redirect=https://${authhub_domain}/oauth2/authorize?client_id=${client_id}&redirect_uri=https://${eulercopilot_domain}/api/auth/login&scope=openid offline_access&access_type=offline&response_type=code&prompt=consent&state=235345&nonce=loser" \ + --set "domain.euler_copilot=${eulercopilot_domain}" \ + --set "domain.authhub=${authhub_domain}" + + if [ $? -ne 0 ]; then + echo -e "${RED}错误:YAML文件修改失败${NC}" + exit 1 + fi + echo -e "${GREEN}YAML文件修改成功!${NC}" +} + +# 进入Chart目录的方法 +enter_chart_directory() { + echo -e "${BLUE}进入Chart目录...${NC}" + cd "${CHART_DIR}" || { + echo -e "${RED}错误:无法进入Chart目录 ${CHART_DIR}${NC}" + exit 1 + } +} + +# 执行Helm安装的方法 +execute_helm_install() { + echo -e "${BLUE}开始部署EulerCopilot...${NC}" + helm install -n euler-copilot euler-copilot ./euler_copilot + + if [ $? -ne 0 ]; then + echo -e "${RED}错误:Helm安装失败${NC}" + exit 1 + fi + echo -e "${GREEN}Helm安装EulerCopilot成功!${NC}" +} + +check_pods_status() { + echo -e "${BLUE}==> 等待初始化就绪(30秒)...${NC}" + sleep 30 + + local timeout=300 + local start_time=$(date +%s) + + echo -e "${BLUE}开始监控Pod状态(总超时时间300秒)...${NC}" + + while true; do + local current_time=$(date +%s) + local elapsed=$((current_time - start_time)) + + if [ $elapsed -gt $timeout ]; then + echo -e "${RED}错误:部署超时!${NC}" + kubectl get pods -n euler-copilot + return 1 + fi + + # 修改核心检测逻辑:同时检查Phase和Ready状态 + local not_running=$( + kubectl get pods -n euler-copilot -o jsonpath='{range .items[*]}{.metadata.name} {.status.phase} {.status.conditions[?(@.type=="Ready")].status}{"\n"}{end}' \ + | awk '$2 != "Running" || $3 != "True" {print $1 " " $2}' + ) + + if [ -z "$not_running" ]; then + echo -e "${GREEN}所有Pod已正常运行!${NC}" + kubectl get pods -n euler-copilot + return 0 + else + echo "等待Pod就绪(已等待 ${elapsed} 秒)..." + echo "当前异常Pod:" + echo "$not_running" | awk '{print " - " $1 " (" $2 ")"}' + sleep 10 + return 1 + fi + done +} + +# 主函数执行各个步骤 +main() { + get_eth0_ip + get_user_input + create_directories + check_and_delete_existing_deployment + modify_yaml + enter_chart_directory + execute_helm_install + check_pods_status + + echo -e "\n${GREEN}==================================================${NC}" + echo -e "${GREEN} EulerCopilot 部署成功! ${NC}" + echo -e "${GREEN}==================================================${NC}" + echo -e "${YELLOW}插件目录:${PLUGINS_DIR}${NC}" + echo -e "${YELLOW}Chart目录位置:${CHART_DIR}${NC}" + echo -e "${YELLOW}Copilot前端访问地址:https://${eulercopilot_domain}${NC}" + echo -e "${YELLOW}AuthHub前端地址:https://${authhub_domain}${NC}" +} + +# 调用主函数 +main diff --git a/deploy/scripts/8-install-EulerCopilot/install_oidc_eulercopilot.sh b/deploy/scripts/8-install-EulerCopilot/install_oidc_eulercopilot.sh new file mode 100644 index 0000000000000000000000000000000000000000..832944e103a7095a356f4b8d483abfbc635784a7 --- /dev/null +++ b/deploy/scripts/8-install-EulerCopilot/install_oidc_eulercopilot.sh @@ -0,0 +1,151 @@ +#!/bin/bash + +# 颜色定义 +RED='\e[31m' +GREEN='\e[32m' +YELLOW='\e[33m' +BLUE='\e[34m' +NC='\e[0m' # 恢复默认颜色 + +# 路径变量定义 +CHART_DIR="/home/euler-copilot-framework/deploy/chart" +SCRIPTS_DIR="/home/euler-copilot-framework/deploy/scripts" +DATA_DIR="/home/eulercopilot/sematics" + +# 创建必要目录 +create_directories() { + echo -e "${BLUE}检查并创建数据目录...${NC}" + if ! mkdir -p "${DATA_DIR}"; then + echo -e "${RED}错误:无法创建目录 ${DATA_DIR}${NC}" + exit 1 + fi + echo -e "${GREEN}目录已就绪:${DATA_DIR}${NC}" +} + +# 安装前检查并删除已有部署 +check_and_delete_existing_deployment() { + echo -e "${YELLOW}检查是否存在已部署的euler-copilot...${NC}" + if helm list -n euler-copilot --short | grep -q "^euler-copilot$"; then + echo -e "${YELLOW}发现已存在的euler-copilot部署,正在删除...${NC}" + helm uninstall -n euler-copilot euler-copilot + + if [ $? -ne 0 ]; then + echo -e "${RED}错误:删除旧版euler-copilot失败${NC}" + exit 1 + fi + + echo -e "${YELLOW}等待旧部署清理完成(10秒)...${NC}" + sleep 10 + else + echo -e "${GREEN}未找到已存在的euler-copilot部署,继续安装...${NC}" + fi +} + +# 修改YAML配置文件的方法 +modify_yaml() { + echo -e "${BLUE}开始修改YAML配置文件...${NC}" + cd + python ${SCRIPTS_DIR}/8-install-EulerCopilot/modify_eulercopilot_yaml.py \ + "${CHART_DIR}/euler_copilot/values.yaml" \ + "${CHART_DIR}/euler_copilot/values.yaml" \ + --set "models.answer.url=http://120.46.78.178:8000" \ + --set "models.answer.key=sk-EulerCopilot1bT1WtG2ssG92pvOPTkpT3BlbkFJVruTv8oUe" \ + --set "models.answer.name=Qwen2.5-32B-Instruct-GPTQ-Int4" \ + --set "models.answer.ctx_length=8192" \ + --set "models.answer.max_tokens=2048" \ + --set "models.embedding.url=https://192.168.50.4:8001/embedding/v1" \ + --set "models.embedding.key=sk-123456" \ + --set "models.embedding.name=bge-m3" \ + --set "login.type=oidc" \ + --set "login.client.id=623c3c2f1eca5ad5fca6c58a" \ + --set "login.client.secret=5d07c65f44fa1beb08b36f90af314aef" \ + --set "login.oidc.token_url=https://omapi.test.osinfra.cn/oneid/oidc/token" \ + --set "login.oidc.user_url=https://omapi.test.osinfra.cn/oneid/oidc/user" \ + --set "login.oidc.redirect=https://omapi.test.osinfra.cn/oneid/oidc/authorize?client_id=623c3c2f1eca5ad5fca6c58a&redirect_uri=https://qa-robot-openeuler.test.osinfra.cn/api/auth/login&scope=openid+profile+email+phone+offline_access&complementation=phone&access_type=offline&response_type=code" \ + --set "domain.euler_copilot=qa-robot-eulercopilot.test.osinfra.cn" \ + + if [ $? -ne 0 ]; then + echo -e "${RED}错误:YAML文件修改失败${NC}" + exit 1 + fi + echo -e "${GREEN}YAML文件修改成功!${NC}" +} + +# 进入Chart目录的方法 +enter_chart_directory() { + echo -e "${BLUE}进入Chart目录...${NC}" + cd "${CHART_DIR}" || { + echo -e "${RED}错误:无法进入Chart目录 ${CHART_DIR}${NC}" + exit 1 + } +} + +# 执行Helm安装的方法 +execute_helm_install() { + echo -e "${BLUE}开始部署EulerCopilot...${NC}" + helm install -n euler-copilot euler-copilot ./euler_copilot + + if [ $? -ne 0 ]; then + echo -e "${RED}错误:Helm安装失败${NC}" + exit 1 + fi + echo -e "${GREEN}Helm安装成功!${NC}" +} + +# 检查Pod状态 +check_pods_status() { + echo -e "${BLUE}==> 等待初始化就绪(30秒)...${NC}" + sleep 30 # 初始等待时间 + + local timeout=300 + local start_time=$(date +%s) + + echo -e "${BLUE}开始监控Pod状态(总超时时间300秒)...${NC}" + + while true; do + local current_time=$(date +%s) + local elapsed=$((current_time - start_time)) + + if [ $elapsed -gt $timeout ]; then + echo -e "${RED}错误:部署超时!${NC}" + kubectl get pods -n euler-copilot + return 1 + fi + + # 检查所有Pod状态 + local not_running=$(kubectl get pods -n euler-copilot -o jsonpath='{range .items[*]}{.metadata.name} {.status.phase}{"\n"}{end}' | grep -v "Running") + + if [ -z "$not_running" ]; then + echo -e "${GREEN}所有Pod已正常运行!${NC}" + kubectl get pods -n euler-copilot + return 0 + else + echo "等待Pod就绪(已等待 ${elapsed} 秒)..." + echo "当前异常Pod:" + echo "$not_running" | awk '{print " - " $1 " (" $2 ")"}' + sleep 10 + fi + done +} + + + +# 主函数执行各个步骤 +main() { + create_directories + check_and_delete_existing_deployment + modify_yaml + enter_chart_directory + execute_helm_install + check_pods_status + + echo -e "\n${GREEN}==================================================${NC}" + echo -e "${GREEN} EulerCopilot 部署成功! ${NC}" + echo -e "${GREEN}==================================================${NC}" + echo -e "${YELLOW}插件目录:${DATA_DIR}${NC}" + echo -e "${YELLOW}Chart目录位置:${CHART_DIR}${NC}" + echo -e "${YELLOW}前端访问地址:https://qa-robot-eulercopilot.test.osinfra.cn${NC}" +} + +# 调用主函数 +main diff --git a/deploy/scripts/8-install-EulerCopilot/modify_eulercopilot_yaml.py b/deploy/scripts/8-install-EulerCopilot/modify_eulercopilot_yaml.py new file mode 100644 index 0000000000000000000000000000000000000000..fa87b90655c78b4a5419649d8dc040b04bac07bd --- /dev/null +++ b/deploy/scripts/8-install-EulerCopilot/modify_eulercopilot_yaml.py @@ -0,0 +1,60 @@ +import argparse +from ruamel.yaml import YAML +from ruamel.yaml.comments import CommentedMap + +def parse_value(value): + """智能转换值的类型""" + value = value.strip() + if value.lower() in ('true', 'false'): + return value.lower() == 'true' + try: + return int(value) + except ValueError: + try: + return float(value) + except ValueError: + pass + return value + +def set_nested_value(data, key_path, value): + """递归设置嵌套字典的值""" + keys = key_path.split('.') + current = data + for key in keys[:-1]: + if key not in current: + current[key] = CommentedMap() + current = current[key] + current[keys[-1]] = parse_value(value) + +def main(): + parser = argparse.ArgumentParser(description='YAML字段修改工具') + parser.add_argument('input', help='输入YAML文件路径') + parser.add_argument('output', help='输出YAML文件路径') + parser.add_argument('--set', action='append', + help='格式: path.to.key=value (可多次使用)', + metavar='KEY_PATH=VALUE') + + args = parser.parse_args() + + yaml = YAML() + yaml.preserve_quotes = True + yaml.indent(mapping=2, sequence=4, offset=2) + + # 读取YAML文件 + with open(args.input, 'r') as f: + data = yaml.load(f) + + # 处理所有--set参数 + if args.set: + for item in args.set: + if '=' not in item: + raise ValueError(f"Invalid format: {item}. Use KEY_PATH=VALUE") + key_path, value = item.split('=', 1) + set_nested_value(data, key_path, value) + + # 写入修改后的YAML + with open(args.output, 'w') as f: + yaml.dump(data, f) + +if __name__ == '__main__': + main() diff --git a/deploy/scripts/download_file.sh b/deploy/scripts/9-other-script/download_file.sh similarity index 100% rename from deploy/scripts/download_file.sh rename to deploy/scripts/9-other-script/download_file.sh diff --git a/deploy/scripts/get_log.sh b/deploy/scripts/9-other-script/get_log.sh similarity index 100% rename from deploy/scripts/get_log.sh rename to deploy/scripts/9-other-script/get_log.sh diff --git a/deploy/scripts/prepare_docker.sh b/deploy/scripts/9-other-script/prepare_docker.sh similarity index 100% rename from deploy/scripts/prepare_docker.sh rename to deploy/scripts/9-other-script/prepare_docker.sh diff --git a/deploy/scripts/check_env.sh b/deploy/scripts/check_env.sh deleted file mode 100644 index 02fc422c47d2e7ccfce434833e8f383d6658a477..0000000000000000000000000000000000000000 --- a/deploy/scripts/check_env.sh +++ /dev/null @@ -1,319 +0,0 @@ -#!/bin/bash - - -function check_user { - if [[ $(id -u) -ne 0 ]]; then - echo -e "\033[31m[Error]请以root权限运行该脚本!\033[0m"; - return 1; - fi - - return 0; -} - -function check_version { - current_version_id="$1"; - supported_version=("$@"); - - echo -e "[Info]当前操作系统版本为:$current_version_id"; - for version_id in "${supported_version[@]:1}" - do - if [[ $current_version_id =~ $version_id ]]; then - echo -e "\033[32m[Success]操作系统满足兼容性要求\033[0m"; - return 0; - fi - done; - - echo -e "\033[31m[Error]操作系统不满足兼容性要求,脚本将退出\033[0m"; - return 1; -} - -function check_os_version { - id=$(grep -E "^ID=" /etc/os-release | cut -d '"' -f 2); - version=$(grep -E "^VERSION_ID=" /etc/os-release | cut -d '"' -f 2); - - echo -e "[Info]当前发行版为:$id"; - if [[ $id =~ "openEuler" ]] || [[ $id =~ "bclinux" ]]; then - supported_version=( - "22.03" - "22.09" - "23.03" - "23.09" - "24.03" - ) - check_version $version "${supported_version[@]}"; - return $?; - fi - - if [[ $id =~ "InLinux" ]]; then - supported_version=( - "23.12" - ) - check_version $version "${supported_version[@]}"; - return $?; - fi - - if [[ $id =~ "FusionOS" ]]; then - supported_version=( - "23" - ) - check_version $version "${supported_version[@]}"; - return $?; - fi - - if [[ $id =~ "uos" ]]; then - supported_version=( - "20" - ) - check_version $version "${supported_version[@]}" - return $?; - fi - - if [[ $id =~ "HopeOS" ]]; then - supported_version=( - "V22" - ) - check_version $version "${supported_version[@]}" - return $?; - fi - - echo -e "\033[31m[Error]发行版不受支持,脚本将退出\033[0m"; - return 1; -} - -function check_hostname { - current_hostname=$(cat /etc/hostname); - if [[ -z "$current_hostname" ]]; - then - echo -e "\033[31m[Error]当前操作系统未设置主机名,将进行主机名设置\033[0m"; - read -p "主机名:" new_hostname; - set_hostname $new_hostname; - return $?; - else - echo -e "[Info]当前主机名为:$current_hostname"; - echo -e "\033[32m[Success]当前操作系统主机名已设置\033[0m"; - return 0; - fi -} - -function set_hostname { - echo -e "[Info]检查hostnamectl"; - if ! [[ -x "$(command -v hostnamectl)" ]]; then - echo -e "\033[31m[Error]hostnamectl程序不存在,主机名设置可能不会持久生效\033[0m"; - echo $1 > /etc/hostname; - echo -e "\033[32m[Success]手动设置主机名成功\033[0m"; - return 0; - fi - - echo -e "[Info]使用hostnamectl设置主机名"; - hostnamectl set-hostname $1; - echo -e "\033[32m[Success]手动设置主机名成功\033[0m"; - return 0; -} - -function check_dns { - echo -e "[Info]检查DNS服务器设置"; - nameserver_line=$(cat /etc/resolv.conf | grep nameserver | wc -l); - if [[ $nameserver_line -ne 0 ]]; then - echo -e "\033[32m[Success]DNS服务器已配置\033[0m"; - return 0; - fi - - echo -e "\033[31m[Error]DNS服务器未配置\033[0m"; - read -p "请输入新的" new_dns; - set_dns $new_dns; - return $?; -} - -function set_dns { - echo -e "[Info]检查NetworkManager"; - if [[ $(systemctl status NetworkManager | grep running) -ne 0 ]]; then - echo -e "\033[31m[Error]NetworkManager未启用,将直接编辑resolv.conf\033[0m"; - cp -f /etc/resolv.conf /etc/resolv.bak; - echo "nameserver $1" > /etc/resolv.conf; - echo -e "\033[32m[Success]手动设置DNS服务器成功\033[0m"; - return 0; - fi - - echo -e "[Info]NetworkManager已启用,使用nmcli进行DNS服务器配置"; - echo -e "[Info]将手动设置DNS地址,DNS地址将应用于第一块活跃网卡中"; - net_ic=$(nmcli -t -f NAME c show --active | head -1) - if [[ -z "$net_ic" ]]; then - echo -e "\033[31m[Error]NetworkManager无法检测到网卡,请确认网卡是否启用\033[0m"; - return 1; - fi - nmcli con mod $net_ic ipv4.ignore-auto-dns yes; - nmcli con mod $net_ic ipv4.dns "$1"; - if [[ $? -ne 0 ]]; then - echo -e "\033[31m[Error]使用NetworkManager设置DNS失败"; - return 1; - fi - return 0; -} - -function check_ram { - echo -e "[Info]检查RAM容量"; - RAM_THRESHOLD=16000; - - current_mem=$(free --mega | grep "Mem" | awk '{print $2}') - echo -e "[Info]当前机器的RAM为:$current_mem MB"; - if [[ $(expr $current_mem) -lt $RAM_THRESHOLD ]]; then - echo -e "\033[31m[Error]当前机器总RAM小于 $RAM_THRESHOLD MB\033[0m"; - return 1; - fi - echo -e "[Info]当前机器RAM符合要求"; - return 0; -} - -function check_disk { - echo -e "[Info]检查磁盘剩余空间"; - current_disk_info=$(df -BM --output=avail,size /var/lib | awk 'NR==2{print $0}') - current_disk_avaliable=$(echo $current_disk_info | awk '{print $1}' | grep -e "[0-9]*" -m 1 -o) - current_disk_size=$(echo $current_disk_info | awk '{print $2}' | grep -e "[0-9]*" -m 1 -o) - - PERCENT_THRESHOLD=0.85; - DISK_THRESHOLD=50000; - - if [[ $(expr $current_disk_avaliable) -lt $DISK_THRESHOLD ]]; then - echo -e "\033[31m[Error]当前机器磁盘空间小于 $DISK_THRESHOLD MB\033[0m"; - return 1; - fi - - current_percent=$(echo 1 - \($current_disk_avaliable - $DISK_THRESHOLD\) / $current_disk_size | bc -l); - if [[ $(echo "$current_percent > $PERCENT_THRESHOLD" | bc) -eq 1 ]]; then - echo -e "\033[31m[Error]当前机器在部署后磁盘占用率将大于 $(echo $PERCENT_THRESHOLD*100 | bc) %\033[0m"; - return 1; - fi - - echo -e "[Info]当前机器磁盘空间满足要求"; - return 0; -} - -function check_network { - echo -e "[Info]正在检查当前机器网络情况"; - # 检查curl是否已安装 - if ! command -v curl &> /dev/null; then - echo -e "\033[31m[Error]Curl不存在,将进行安装\033[0m"; - # 尝试使用yum安装curl - if yum install -y curl; then - echo -e "\033[32m[Success]Curl安装成功\033[0m"; - else - echo -e "\033[31m[Error]Curl安装失败\033[0m"; - return 1; - fi - else - echo -e "\033[32m[Success]Curl已存在\033[0m"; - fi - curl https://hub.oepkgs.net/neocopilot --connect-timeout 5 -s - if [[ $? -ne 0 ]]; then - echo -e "\033[31m[Error]当前机器网络无法连接至镜像仓库,请检查网络配置,或使用离线部署方案\033[0m"; - return 1; - fi - return 0; -} - -function check_selinux { - echo -e "[Info]检查SELinux情况"; - status=$(cat /etc/selinux/config | grep -e "^SELINUX=.*$" | cut -d "=" -f 2); - if [[ $status =~ "enforcing" ]]; then - echo -e "\033[31m[Error]SELinux已开启,可能会导致服务运行错误\033[0m"; - read -p "关闭SELinux?(Y/n)" choice; - case $choice in - [yY]) sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config; - setenforce 0; - if [[ $? -ne 0 ]]; then - echo -e "\033[31m[Error]自动关闭SELinux失败,请手动关闭后重试\033[0m"; - return 1; - fi - return 0; - ;; - - *) echo -e "\033[31m[Error]已终止执行,请手动关闭SELinux后重试\033[0m"; - return 1; - ;; - esac - fi - - echo -e "[Info]未开启SELinux"; - return 0; -} - -function check_firewall { - echo -e "[Info]检查防火墙情况"; - status=$(systemctl status firewalld | grep inactive); - if [[ $? -ne 0 ]]; then - echo -e "\033[31m[Error]FirewallD防火墙正在运行中\033[0m"; - read -p "关闭FirewallD?(Y/n)" choice; - - case $choice in - [yY]) systemctl stop firewalld; - systemctl disable firewalld; - if [[ $? -ne 0 ]]; then - echo -e "\033[31m[Error]FirewallD防火墙自动关闭失败,请手动关闭防火墙后重试\033[0m"; - return 1; - fi - echo -e "\033[32m[Success]FirewallD防火墙关闭成功\033[0m"; - return 0; - ;; - *) echo -e "\033[31m[Error]已终止执行,请手动关闭FirewallD防火墙后重试\033[0m"; - return 1; - ;; - esac - fi - - echo -e "[Info]未安装防火墙FirewallD"; - return 0; -} - - -function main { - check_user - if [[ $? -ne 0 ]]; then - return 1; - fi - - check_os_version - if [[ $? -ne 0 ]]; then - return 1; - fi - - check_hostname - if [[ $? -ne 0 ]]; then - return 1; - fi - - check_dns - if [[ $? -ne 0 ]]; then - return 1; - fi - - check_ram - if [[ $? -ne 0 ]]; then - return 1; - fi - - check_disk - if [[ $? -ne 0 ]]; then - return 1; - fi - - check_network - if [[ $? -ne 0 ]]; then - return 1; - fi - - check_selinux - if [[ $? -ne 0 ]]; then - return 1; - fi - - check_firewall - if [[ $? -ne 0 ]]; then - return 1; - fi - - echo -e "\033[32m[Success]部署环境检查通过\033[0m"; - return 0; -} - - -main diff --git a/deploy/scripts/deploy.sh b/deploy/scripts/deploy.sh new file mode 100644 index 0000000000000000000000000000000000000000..9c16036441c11a8e30e8fe942264b6bfeebe3352 --- /dev/null +++ b/deploy/scripts/deploy.sh @@ -0,0 +1,179 @@ +#!/bin/bash + + +# 顶层菜单 +show_top_menu() { + clear + echo "==============================" + echo " 主部署菜单 " + echo "==============================" + echo "0) 一键自动部署" + echo "1) 手动分步部署" + echo "2) 卸载所有组件并清除数据" + echo "3) 退出程序" + echo "==============================" + echo -n "请输入选项编号(0-3): " +} + +# 安装选项菜单(手动部署子菜单) +show_sub_menu() { + clear + echo "==============================" + echo " 手动分步部署菜单 " + echo "==============================" + echo "1) 执行环境检查脚本" + echo "2) 安装k3s和helm" + echo "3) 安装Ollama" + echo "4) 部署Deepseek模型" + echo "5) 部署Embedding模型" + echo "6) 安装数据库" + echo "7) 安装AuthHub" + echo "8) 安装EulerCopilot" + echo "9) 返回主菜单" + echo "==============================" + echo -n "请输入选项编号(0-9): " +} + +# 带错误检查的脚本执行函数 +run_script_with_check() { + local script_path=$1 + local script_name=$2 + + echo "--------------------------------------------------" + echo "开始执行:$script_name" + "$script_path" || { + echo -e "\n\033[31m$script_name 执行失败!\033[0m" + exit 1 + } + echo -e "\n\033[32m$script_name 执行成功!\033[0m" + echo "--------------------------------------------------" +} + +# 执行子菜单对应脚本 +run_sub_script() { + case $1 in + 1) + run_script_with_check "./1-check-env/check_env.sh" "环境检查脚本" + ;; + 2) + run_script_with_check "./2-install-tools/install_tools.sh" "k3s和helm安装脚本" + ;; + 3) + run_script_with_check "./3-install-ollama/install_ollama.sh" "Ollama安装脚本" + ;; + 4) + run_script_with_check "./4-deploy-deepseek/deploy_deepseek.sh" "Deepseek部署脚本" + ;; + 5) + run_script_with_check "./5-deploy-embedding/deploy-embedding.sh" "Embedding部署脚本" + ;; + 6) + run_script_with_check "./6-install-databases/install_databases.sh" "数据库安装脚本" + ;; + 7) + run_script_with_check "./7-install-authhub/install_authhub.sh" "AuthHub安装脚本" + ;; + 8) + run_script_with_check "./8-install-EulerCopilot/install_eulercopilot.sh" "EulerCopilot安装脚本" + ;; + 9) + echo "正在返回主菜单..." + return 2 # 特殊返回码表示返回上级菜单 + ;; + *) + echo -e "\033[31m无效的选项,请输入0-9之间的数字\033[0m" + return 1 + ;; + esac + return 0 +} + +# 卸载所有组件 +uninstall_all() { + echo -e "\033[31m警告:此操作将永久删除所有组件和数据!\033[0m" + read -p "确认要继续吗?(y/n) " confirm + + if [[ $confirm != "y" && $confirm != "Y" ]]; then + echo "取消卸载操作" + return + fi + + echo "开始卸载所有Helm Release..." + local RELEASES + RELEASES=$(helm list -n euler-copilot --short || true) + + # 删除所有关联的Helm Release + if [ -n "$RELEASES" ]; then + echo -e "${YELLOW}找到以下Helm Release,开始清理...${NC}" + for release in $RELEASES; do + echo -e "${BLUE}正在删除Helm Release: ${release}${NC}" + helm uninstall "$release" -n euler-copilot || echo -e "${RED}删除Helm Release失败,继续执行...${NC}" + done + else + echo -e "${YELLOW}未找到需要清理的Helm Release${NC}" + fi + + # 获取所有PVC列表 + local pvc_list + pvc_list=$(kubectl get pvc -n euler-copilot -o name 2>/dev/null || true) + + # 删除PVC + if [ -n "$pvc_list" ]; then + echo -e "${YELLOW}找到以下PVC,开始清理...${NC}" + echo "$pvc_list" | xargs -n 1 kubectl delete -n euler-copilot || echo -e "${RED}PVC删除失败,继续执行...${NC}" + else + echo -e "${YELLOW}未找到需要清理的PVC${NC}" + fi + + echo -e "${GREEN}资源清理完成${NC}" + echo -e "\033[32m所有组件和数据已成功清除\033[0m" +} + +# 手动部署子菜单循环 +manual_deployment_loop() { + while true; do + show_sub_menu + read -r sub_choice + run_sub_script "$sub_choice" + retval=$? + + if [ $retval -eq 2 ]; then # 返回主菜单 + break + elif [ $retval -eq 0 ]; then + echo "按任意键继续..." + read -r -n 1 -s + fi + done +} + +# 主程序循环 +while true; do + show_top_menu + read -r main_choice + + case $main_choice in + 0) + run_script_with_check "./0-one-click-deploy/one-click-deploy.sh" "一键自动部署" + echo -e "\n\033[33m请手动登录Authhub完成后续配置:" + echo "1. 访问Authhub管理界面" + echo "2. 创建新的应用授权" + echo "3. 更新EulerCopilot的配置文件\033[0m" + ;; + 1) + manual_deployment_loop + ;; + 2) + uninstall_all + echo "按任意键继续..." + read -r -n 1 -s + ;; + 3) + echo "退出部署系统" + exit 0 + ;; + *) + echo -e "\033[31m无效的选项,请输入0-3之间的数字\033[0m" + sleep 1 + ;; + esac +done diff --git a/deploy/scripts/install_tools.sh b/deploy/scripts/install_tools.sh deleted file mode 100644 index 58e4d4b6d3b95d6ca188e538acf907732bb43b05..0000000000000000000000000000000000000000 --- a/deploy/scripts/install_tools.sh +++ /dev/null @@ -1,173 +0,0 @@ -#/bin/bash - -GITHUB_MIRROR="https://gh-proxy.com"; -ARCH=$(uname -m); - -# 函数:显示帮助信息 -function help { - echo -e "用法:bash install_tools.sh [K3s版本] [Helm版本] [cn: 是否使用镜像站]"; - echo -e "示例:bash install_tools.sh v1.30.2+k3s1 仅安装K3s"; - echo -e " bash install_tools.sh v3.15.3 仅安装Helm"; - echo -e " bash install_tools.sh v1.30.2+k3s1 v3.15.3 安装K3s和Helm"; -} - -function check_user { - if [[ $(id -u) -ne 0 ]]; then - echo -e "\033[31m[Error]请以root权限运行该脚本!\033[0m" - exit 1; - fi -} - -function check_arch { - case $ARCH in - x86_64) - ARCH=amd64 - ;; - aarch64) - ARCH=arm64 - ;; - *) - echo -e "\033[31m[Error]当前CPU架构不受支持\033[0m" - return 1; - ;; - esac - return 0 -} - -function check_helm { - echo -e "[Info]测试与Helm官方网站之间的网络连通性" - curl https://get.helm.sh --connect-timeout 5 -s > /dev/null - if [[ $? -ne 0 ]]; then - echo -e "\033[31m[Error]无法连接至get.helm.sh\033[0m" - return 1 - fi - return 0 -} - -function install_k3s { - local image_name="k3s-airgap-images-$ARCH.tar.zst" - if [[ $ARCH = "amd64" ]]; then - local bin_name="k3s" - elif [[ $ARCH = "arm64" ]]; then - local bin_name="k3s-arm64" - fi - local k3s_bin_url="$GITHUB_MIRROR/https://github.com/k3s-io/k3s/releases/download/$k3s_version/${bin_name}" - local k3s_image_url="$GITHUB_MIRROR/https://github.com/k3s-io/k3s/releases/download/$k3s_version/${image_name}" - - echo -e "[Info]下载K3s二进制文件" - curl -L ${k3s_bin_url} -o /usr/local/bin/k3s - if [[ $? -ne 0 ]]; then - echo -e "\033[31m[Error]K3s二进制文件下载失败\033[0m" - return 1; - fi - chmod +x /usr/local/bin/k3s - - echo -e "[Info]下载K3s依赖" - mkdir -p /var/lib/rancher/k3s/agent/images - curl -L ${k3s_image_url} -o /var/lib/rancher/k3s/agent/images/${image_name} - if [[ $? -ne 0 ]]; then - echo -e "\033[31m[Error]K3s依赖下载失败\033[0m" - return 1; - fi - - echo -e "\033[32m[Success]K3s及其依赖下载成功\033[0m" - - bash -c "curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_SKIP_DOWNLOAD=true sh -" - if [[ $? -ne 0 ]]; then - echo -e "\033[31m[Error]K3s安装失败\033[0m"; - return 1; - fi - echo -e "\033[32m[Success]K3s安装成功\033[0m" - return 0; -} - -function install_helm { - local helm_version=$1 - local use_mirror=$2 - local file_name="helm-$helm_version-linux-$ARCH.tar.gz" - local url="" - - if [[ $use_mirror == "cn" ]]; then - url="https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts/helm/v$helm_version/$file_name" - else - url="${use_mirror:+$GITHUB_MIRROR/}https://get.helm.sh/$file_name" - fi - - echo -e "[Info]下载Helm" - curl -L $url -o $file_name - if [[ $? -ne 0 ]]; then - echo -e "\033[31m[Error]Helm下载失败\033[0m"; - return 1; - fi - - tar -zxvf $file_name --strip-components 1 -C /usr/local/bin linux-$ARCH/helm - chmod +x /usr/local/bin/helm - - echo -e "\033[32m[Success]Helm安装成功\033[0m" - return 0; -} - -function main { - if [[ $# -lt 1 || $# -gt 3 ]]; then - help - exit 1; - fi - - check_user - check_arch - if [[ $? -ne 0 ]]; then - exit 1; - fi - - local k3s_version="" - local helm_version="" - local use_mirror="" - - for arg in "$@"; do - if [[ $arg == v*+k3s1 ]]; then - k3s_version=$arg - elif [[ $arg =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - helm_version=$arg - else - echo "未知的参数: $arg" - exit 1 - fi - done - # 检查 K3s 是否已安装 - if [[ -n $k3s_version ]]; then - if command -v k3s &>/dev/null; then - echo -e "[Info]K3s 已经安装,无需再次安装"; - else - install_k3s "$k3s_version" "$use_mirror" - if [[ $? -ne 0 ]]; then - return 1; - fi - fi - fi - - # 检查 Helm 是否已安装 - if [[ -n $helm_version ]]; then - if command -v helm &>/dev/null; then - echo -e "[Info]Helm 已经安装,无需再次安装"; - else - check_helm - if [[ $? -ne 0 ]]; then - return 1; - fi - install_helm "$helm_version" "$use_mirror" - if [[ $? -ne 0 ]]; then - return 1; - fi - fi - fi - - # 如果两个都需要安装,但至少有一个已安装,则不执行任何操作 - if [[ -n $k3s_version && -n $helm_version ]]; then - if ! (command -v k3s &>/dev/null) || ! (command -v helm &>/dev/null); then - echo -e "[Info]K3s 或 Helm 已经安装,无需再次安装"; - return 1; - fi - fi -} - -main "$@" diff --git "a/docs/user-guide/\351\203\250\347\275\262\346\214\207\345\215\227/\347\275\221\347\273\234\347\216\257\345\242\203\344\270\213\351\203\250\347\275\262\346\214\207\345\215\227.md" "b/docs/user-guide/\351\203\250\347\275\262\346\214\207\345\215\227/\347\275\221\347\273\234\347\216\257\345\242\203\344\270\213\351\203\250\347\275\262\346\214\207\345\215\227.md" index 8bf2dfd42d4fe63b512385a60359af6ccfa0005a..379523a697dfc736b7ba396efa14101b80228d36 100644 --- "a/docs/user-guide/\351\203\250\347\275\262\346\214\207\345\215\227/\347\275\221\347\273\234\347\216\257\345\242\203\344\270\213\351\203\250\347\275\262\346\214\207\345\215\227.md" +++ "b/docs/user-guide/\351\203\250\347\275\262\346\214\207\345\215\227/\347\275\221\347\273\234\347\216\257\345\242\203\344\270\213\351\203\250\347\275\262\346\214\207\345\215\227.md" @@ -1,398 +1,200 @@ -# 网络环境部署指南 +# EulerCopilot 智能助手部署指南 -## 介绍 +版本信息 +当前版本:v0.9.4 +更新日期:2025年2月19日 -openEuler Copilot System 是一款智能问答工具,使用 openEuler Copilot System 可以解决操作系统知识获取的便捷性,并且为OS领域模型赋能开发者及运维人员。作为获取操作系统知识,使能操作系统生产力工具 (如 A-Ops / A-Tune / x2openEuler / EulerMaker / EulerDevOps / StratoVirt / iSulad 等),颠覆传统命令交付方式,由传统命令交付方式向自然语义进化,并结合智能体任务规划能力,降低开发、使用操作系统特性的门槛。 +## 概述 -### 主要组件介绍 +EulerCopilot 是一款智能问答工具,使用 EulerCopilot 可以解决操作系统知识获取的便捷性,并且为OS领域模型赋能开发者及运维人员。作为获取操作系统知识,使能操作系统生产力工具 (如 A-Ops / A-Tune / x2openEuler / EulerMaker / EulerDevOps / StratoVirt / iSulad 等),颠覆传统命令交付方式,由传统命令交付方式向自然语义进化,并结合智能体任务规划能力,降低开发、使用操作系统特性的门槛。 + +本指南提供基于自动化脚本的EulerCopilot智能助手系统部署说明,支持一键自动部署和手动分步部署两种方式。 + +### 组件介绍 | 组件 | 端口 | 说明 | | ----------------------------- | --------------- | -------------------- | | euler-copilot-framework | 8002 (内部端口) | 智能体框架服务 | | euler-copilot-web | 8080 | 智能体前端界面 | | euler-copilot-rag | 9988 (内部端口) | 检索增强服务 | -| euler-copilot-vectorize-agent | 8001 (内部端口) | 文本向量化服务 | +| authhub-backend-service | 11120 (内部端口) | 鉴权服务后端 | +| authhub-web-service | 8000 | 鉴权服务前端 | | mysql | 3306 (内部端口) | MySQL数据库 | | redis | 6379 (内部端口) | Redis数据库 | +| minio | 9000 (内部端口) 9001(外部部端口) | minio数据库 | +| mongo | 27017 (内部端口) | mongo数据库 | | postgres | 5432 (内部端口) | 向量数据库 | | secret_inject | 无 | 配置文件安全复制工具 | -## 环境要求 - ### 软件要求 - -| 类型 | 版本要求 | 说明 | -|------------| -------------------------------------|--------------------------------------| +| 类型 | 版本要求 | 说明 | +|----------------| -------------------------------------|--------------------------------------| | 操作系统 | openEuler 22.03 LTS 及以上版本 | 无 | | K3s | >= v1.30.2,带有 Traefik Ingress 工具 | K3s 提供轻量级的 Kubernetes 集群,易于部署和管理 | -| Helm | >= v3.15.3 | Helm 是一个 Kubernetes 的包管理工具,其目的是快速安装、升级、卸载 openEuler Copilot System 服务 | +| Helm | >= v3.15.3 | Helm 是一个 Kubernetes 的包管理工具,其目的是快速安装、升级、卸载 EulerCopilot 服务 | | python | >=3.9.9 | python3.9.9 以上版本为模型的下载和安装提供运行环境 | - +--- ### 硬件要求 -| 类型 | 硬件要求 | -|----------------| -----------------------------| -| 服务器 | 1台 | -| CPU | 鲲鹏或x86_64,>= 32 cores | -| RAM | >= 64GB | -| 存储 | >= 500 GB | -| GPU | Tesla V100 16GB,4张 | -| NPU | 支持大模型推理的NPU卡或服务器 | +| 硬件资源 | 服务器(最小要求) | 服务器(推荐) | +|--------------|----------------------------|------------------------------| +| CPU | 4 核心 | 16 核心及以上 | +| RAM | 4 GB | 64 GB | +| 存储 | 32 GB | 500G | +| 大模型名称 | deepseek-llm-7b-chat | DeepSeek-R1-Llama-8B | +| 显存 (GPU) | 8 GB (NVIDIA RTX A4000, 1个) | 16 GB (NVIDIA A100, 2个) | -注意: -1. 若无 GPU 或 NPU 资源,建议通过调用 OpenAI 接口的方式来实现功能。(接口样例: 参考链接:[API-KEY的获取与配置](https://help.aliyun.com/zh/dashscope/developer-reference/acquisition-and-configuration-of-api-key?spm=a2c4g.11186623.0.0.30e7694eaaxxGa)) +**注意**: +1. 若无 GPU 或 NPU 资源,建议通过调用 OpenAI 接口的方式来实现功能。 2. 调用第三方 OpenAI 接口的方式不需要安装高版本的 python (>=3.9.9) -3. 英伟达 GPU 对 Docker 的支持必需要新版本 Docker (>= v25.4.0) 4. 如果k8s集群环境,则不需要单独安装k3s,要求version >= 1.28 +--- +### 网络要求: + - 可访问 hub.oepkgs.net + - 可访问 modelscope.cn + - 开放端口:80/443/ +--- ### 部署视图 ![部署图](./pictures/部署视图.png) -## 获取 openEuler Copilot System +--- +### 域名要求 +为确保 EulerCopilot 的正确部署和使用,请准备以下四个服务的域名:minio、authhub、eulercopilot。这些子域名需属于同一个主域名下,例如 `minio.test.com`、`authhub.test.com`、`eulercopilot.test.com` + +您可以通过两种方式来完成这项准备工作: -- 从 openEuler Copilot System 的官方Git仓库 [euler-copilot-framework](https://gitee.com/openeuler/euler-copilot-framework) 下载最新的部署仓库 +- **预先申请域名**:为每个服务(Minio、AuthHub、Euler Copilot)分别注册上述格式的子域名。 + +- **本地配置**:如果是在开发或测试环境中,您可以直接在本地Windows主机文件中进行配置。打开位于 `C:\Windows\System32\drivers\etc\hosts` 的文件,并添加相应的条目以映射这些子域名到本地或特定的IP地址,例如: +```bash +127.0.0.1 minio.test.com +127.0.0.1 authhub.test.com +127.0.0.1 eulercopilot.test.com +``` +## 快速开始 +### 一键部署 +#### 1. 获取部署脚本 + +- 从 EulerCopilot 的官方Git仓库 [euler-copilot-framework](https://gitee.com/openeuler/euler-copilot-framework) 下载最新的部署仓库 - 如果您正在使用 Kubernetes,则不需要安装 k3s 工具。 ```bash # 下载目录以 home 为例 cd /home ``` - ```bash -git clone https://gitee.com/openeuler/euler-copilot-framework.git +git clone https://gitee.com/openeuler/euler-copilot-framework.git -b feat/ds-func-call ``` - -## 环境准备 - -设备需联网并符合 openEuler Copilot System 的最低软硬件要求。确认服务器、硬件、驱动等准备就绪后,即可开始环境准备工作。为了顺利进行后续操作,请按照指引,先进入我 -们的脚本部署目录,并且按照提供的操作步骤和脚本路径依次执行,以确保初始化成功。 - ```bash -# 进入部署脚本目录 -cd /home/euler-copilot-framework/deploy/scripts && tree +cd /home/euler-copilot-framework/deploy/scripts ``` - +#### 2. 执行主部署脚本(需要root权限) ```bash -. -├── check_env.sh -├── download_file.sh -├── get_log.sh -├── install_tools.sh -└── prepare_docker.sh +./deploy.sh ``` +#### 3. 输入0进行一键自动部署 +```bash +============================== + 主部署菜单 +============================== +0) 一键自动部署 +1) 手动分步部署 +2) 卸载所有组件并清除数据 +3) 退出程序 +============================== +请输入选项编号(0-3): 0 +``` +--- +### 手动分步部署 -| 序号 | 步骤内容 | 相关指令 | 说明 | -|-------------- |----------|---------------------------------------------|------------------------------------------ | -|1| 环境检查 | `bash check_env.sh` | 主要对服务器的主机名、DNS、防火墙设置、磁盘剩余空间大小、网络、检查SELinux的设置 | -|2| 文件下载 | `bash download_file.sh` | 模型bge-reranker-large、bge-mixed-mode下载 | -|3| 安装部署工具 | `bash install_tools.sh v1.30.2+k3s1 v3.15.3 cn` | 安装helm、k3s工具。注意:cn的使用是使用镜像站,可以去掉不用 | -|4| 域名配置 | 需要准备4个域名`minio\authhub\eulercopilot\witchaind` | 预先申请域名或在 'C:\Windows\System32\drivers\etc\hosts' 下配置。必须是同根域名, 例如`minio.test.com`、`authhub.test.com`、`eulercopilot.test.com`、`witchaind.test.com` | -|5| 大模型准备 | 提供第三方 OpenAI 接口或基于硬件本都部署大模型 | 本地部署大模型可参考附录部分 | - - - -## 安装 - -您的环境现已就绪,接下来即可启动 openEuler Copilot System 的安装流程。 - -- 下载目录以home为例,进入 openEuler Copilot System 仓库的 Helm 配置文件目录 - - ```bash - cd /home/euler-copilot-framework && ll - ``` - - ```bash - total 28 - drwxr-xr-x 3 root root 4096 Aug 28 17:45 docs/ - drwxr-xr-x 5 root root 4096 Aug 28 17:45 deploy/ - ``` - -- 查看deploy的目录 - - ```bash - tree deploy - ``` - - ```bash - deploy/chart - ├── databases - │   ├── Chart.yaml - │   ├── configs - │   ├── templates - │   └── values.yaml - ├── authhub - │   ├── Chart.yaml - │   ├── configs - │   ├── templates - │   └── values.yaml - └── euler_copilot - ├── Chart.yaml - ├── configs - ├── templates - │   ├── NOTES.txt - │   ├── rag - │   ├── vectorize - │   └── web - └── values.yaml - ``` -- 创建命名空间 - - ```bash - kubectl create namespace euler-copilot - ``` - - 设置环境变量 - - ```bash - export KUBECONFIG=/etc/rancher/k3s/k3s.yaml - ``` - -### 1. 安装数据库 - -- 编辑 values.yaml - - ```bash - cd deploy/chart/databases - ``` - - ```bash - vim values.yaml - ``` - **填写说明:** - 1. **密码设置**:所有密码必须设置为数字与字母的组合,并请确认所有条目均已准确填写; - 2. **域名设置**:依据之前的域名配置,请正确填写 MinIO 的域名; - 3. **镜像标签调整**:根据系统架构,请相应地调整镜像标签(tag)。 - -- 安装数据库 - - ```bash - helm install -n euler-copilot databases . - ``` - -- 检查 Pod 的状态 - - ```bash - kubectl -n euler-copilot get pods - ``` - - ```bash - pgsql-deploy-databases-86b4dc4899-ppltc 1/1 Running 0 17d - redis-deploy-databases-f8866b56-kj9jz 1/1 Running 0 17d - minio-deploy-databases-6b8dfcdc5d-7d4td 1/1 Running 0 17d - mongo-deploy-databases-85c75cbb-v88r6 1/1 Running 0 17d - ``` - -- 问题定位 - - - 查看 Pod 的 日志 - - ```bash - kubectl -n euler-copilot logs minio-deploy-databases-6b8dfcdc5d-7d4td - ``` - - 进入 Pod - - ```bash - kubectl -n euler-copilot exec pgsql-deploy-databases-86b4dc4899-ppltc -- bash - ``` - ```bash - # 连接数据库 - psql -U postgres -d postgres - ``` - - 清除 PVC - - ```bash - kubectl -n euler-copilot get pvc - ``` - - ```bash - kubectl -n euler-copilot delete pvc minio-pvc-databases - ``` - - 更新配置 - ```bash - helm upgrade -n euler-copilot databases . - ``` - -### 2. 安装鉴权平台Authhub - -- 编辑 values.yaml - - ```bash - cd ../authhub - ``` - ```bash - vim values.yaml - ``` - **填写说明:** - 1. **密码设置**:所有密码必须设置为数字与字母的组合,并请确认所有条目均已准确填写; - 2. **域名设置**:依据之前的域名配置,请正确填写 authhub-web 的域名; - 3. **镜像标签调整**:根据系统架构,请相应地调整镜像标签(tag)。 - -- 安装 AuthHub - - ```bash - helm install -n euler-copilot authhub . - ``` - -- 查看 pod 状态 - - ```bash - kubectl -n euler-copilot get pods - ``` - - ```bash - NAME READY STATUS RESTARTS AGE - authhub-backend-deploy-authhub-64896f5cdc-m497f 2/2 Running 0 16d - authhub-web-deploy-authhub-7c48695966-h8d2p 1/1 Running 0 17d - pgsql-deploy-databases-86b4dc4899-ppltc 1/1 Running 0 17d - redis-deploy-databases-f8866b56-kj9jz 1/1 Running 0 17d - minio-deploy-databases-6b8dfcdc5d-7d4td 1/1 Running 0 17d - mongo-deploy-databases-85c75cbb-v88r6 1/1 Running 0 17d - ``` - -- 登录 AuthHub - - AuthHub 的域名以 为例,浏览器输入`https://authhub.test.com`,登录界面如下图所示: - - ![部署图](./pictures/authhub登录界面.png) - - **AuthHub 登录默认账号 `administrator`, 密码 `changeme`** - -- 创建应用eulercopilot - - ![部署图](./pictures/创建应用界面.png) - - 点击**创建应用**后,请按照以下示例填写相关信息: - - **应用名称**: eulercopilot - - **应用主页 URL**: https://eulercopilot.test.com - - **应用回调地址(登录后)**: https://eulercopilot.test.com/api/auth/login - - 点击**创建**,即可完成应用创建流程,系统将自动生成一个 **Client ID** 和 **Client Secret**。请保存好这对凭据,稍后在 `deploy/chart/euler_copilot/values.yaml` 配置文件中需要添加它们。 - - ![部署图](./pictures/创建应用成功界面.png) - -### 3. 安装 openEuler Copilot System - -- 编辑 values.yaml - - ```bash - cd ../euler_copilot - ``` - ```bash - vim values.yaml - ``` - **填写说明:** - - 1. **密码设置**:所有密码必须是数字与字母的组合,请确保所有条目均已准确无误地填写。 - 2. **域名配置**:请根据先前的域名设置,正确填写 eulercopilot 和 witchind 的对应域名。 - 3. **镜像标签调整**:依据系统的架构要求,适当调整容器镜像的标签(tag)。 - 4. **Volume挂载目录**:创建并指定正确的卷(volume)挂载路径。 - 5. **OIDC 设置**:完成 framework章节中 OIDC 的正确配置。 - 6. **插件部署(可选)**:如果选择部署插件,需配置用于Function Call的模型。注意,部署sglang时需要有GPU支持环境,详情请参阅附件。 - -- 安装 openEuler Copilot System - - ```bash - helm install -n euler-copilot service . - ``` - -- 查看 Pod 状态 - - ```bash - kubectl -n euler-copilot get pods - ``` - - 镜像拉取过程可能需要大约一分钟的时间,请耐心等待。部署成功后,所有 Pod 的状态应显示为 Running。 - - ```bash - NAME READY STATUS RESTARTS AGE - authhub-backend-deploy-authhub-64896f5cdc-m497f 2/2 Running 0 16d - authhub-web-deploy-authhub-7c48695966-h8d2p 1/1 Running 0 17d - pgsql-deploy-databases-86b4dc4899-ppltc 1/1 Running 0 17d - redis-deploy-databases-f8866b56-kj9jz 1/1 Running 0 17d - mysql-deploy-databases-57f5f94ccf-sbhzp 2/2 Running 0 17d - framework-deploy-service-bb5b58678-jxzqr 2/2 Running 0 16d - rag-deploy-service-5b7887644c-sm58z 2/2 Running 0 110m - vectorize-deploy-service-57f5f94ccf-sbhzp 2/2 Running 0 17d - web-deploy-service-74fbf7999f-r46rg 1/1 Running 0 2d - ``` - - **故障排查:** - - 当 Pod 状态显示为失败时,建议遵循以下步骤进行问题排查: - - 1. **获取集群事件信息** - - 为了更好地定位 Pod 失败的原因,请首先检查 Kubernetes 集群中的事件 (Events)。这可以提供有关 Pod 状态变化的上下文信息。 - - ```bash - kubectl get events -n euler-copilot - ``` - - 2. **验证镜像拉取状态** - - 确认容器镜像是否成功拉取。如果镜像未能正确加载,可能是由于网络问题或镜像仓库配置错误。 - - ```bash - k3s crictl images - ``` - - 3. **审查 Pod 日志** - - 检查相关 Pod 的日志,以寻找可能的错误信息或异常行为。这对于诊断应用程序级别的问题特别有用。 - - ```bash - kubectl logs rag-deploy-service-5b7887644c-sm58z -n euler-copilot - ``` - - 4. **评估资源可用性** - - 确保 Kubernetes 集群有足够的资源(如 CPU、内存和存储)来支持 Pod 的运行。资源不足可能导致镜像拉取失败或其他性能问题。 - - ```bash - kubectl top nodes - ``` - - 5. **确认 k3s 版本兼容性** - - 如果遇到镜像拉取失败且镜像大小为 0 的问题,请检查您的 k3s 版本是否符合最低要求(v1.30.2 或更高)。较低版本可能存在不兼容的问题。 - - ```bash - k3s -v - ``` - - 6. **检查 OIDC 设置** - - 审核 `values.yaml` 文件中关于框架的 OIDC 配置,确保身份验证和授权服务已正确设置,这对于集成外部认证服务至关重要。 +#### 步骤1:环境检查 +```bash +sudo ./deploy.sh +# 选择1 -> 1 进入手动分步部署 +============================== + 手动分步部署菜单 +============================== +1) 执行环境检查脚本 +2) 安装k3s和helm +3) 安装Ollama +4) 部署Deepseek模型 +5) 部署Embedding模型 +6) 安装数据库 +7) 安装AuthHub +8) 安装EulerCopilot +9) 返回主菜单 +============================== +请输入选项编号(0-9): +``` +#### 步骤2:输入选项编号(0-9),逐步部署 +--- +**注意事项** +1. 全程都需要保持互联网连接 +2. 首次模型下载可能耗时较长(约30-60分钟) +3. 在部署过程中,您需要提供 Authhub 域名和 EulerCopilot 域名。 +4. 请先通过浏览器访问 http://authhub.test.com 来手动创建 EulerCopilot 应用,并从生成的凭证中获取 client_id 和 client_secret。随后,请将这两个值准确无误地输入到部署控制台对应的位置。这样确保了在部署 EulerCopilot 之前,已正确配置其所需的认证信息。 + +![部署图](./pictures/authhub登录界面.png) +**AuthHub 登录默认账号 `administrator`, 密码 `changeme`** +创建应用EulerCopilot +![部署图](./pictures/创建应用界面.png) +点击**创建应用**后,请按照以下示例填写相关信息: +- **应用名称**: EulerCopilot +- **应用主页 URL**: https://eulercopilot.test.com +- **应用回调地址(登录后)**: https://eulercopilot.test.com/api/auth/login +- 点击**创建**,即可完成应用创建流程,系统将自动生成一个 **Client ID** 和 **Client Secret**。请保存好这对凭据,稍后在 `deploy/chart/euler_copilot/values.yaml` 配置文件中需要添加它们。 +![部署图](./pictures/创建应用成功界面.png) +5. 生产环境建议配置HTTPS证书 +### 卸载所有组件 +```bash +sudo ./deploy.sh +# 选择2进行完全卸载 +============================== + 主部署菜单 +============================== +0) 一键自动部署 +1) 手动分步部署 +2) 卸载所有组件并清除数据 +3) 退出程序 +============================== +请输入选项编号(0-3): 2 +``` +--- - ```bash - cat /home/euler-copilot-framework/deploy/chart/euler_copilot/values.yaml | grep oidc - ``` +## 故障排查 +- 查看组件日志: +```bash +kubectl logs -n euler-copilot +``` +- 重新部署单个组件: +```bash +# 示例:更新euler-copilot +cd /home/euler-copilot-framework/deploy/chart/euler-copilot +# 修改yaml +vim values.yaml +# 更新EulerCopilot +helm upgrade euler-copilot -n euler-copilot . +``` ## 验证安装 -恭喜您,**openEuler Copilot System** 已成功部署!为了开始您的体验,请在浏览器中输入 `https://您的EulerCopilot域名` 链接访问 openEuler Copilot System 的网页界面: +恭喜您,**EulerCopilot** 已成功部署!为了开始您的体验,请在浏览器中输入 `https://您的EulerCopilot域名` 链接访问 EulerCopilot 的网页界面: 首次访问时,您需要点击页面上的 **立即注册** 按钮来创建一个新的账号,并完成登录过程。 ![Web登录界面](./pictures/WEB登录界面.png) ![Web 界面](./pictures/WEB界面.png) -## 安装插件 - -详细信息请参考文档 [插件部署指南](./插件部署指南) - -## 构建专有领域智能问答 - -详细信息请参考文档 [本地资产库构建指南](./本地资产库构建指南.md) - +--- ## 附录 ### 大模型准备 - #### GPU 环境 -参考以下方式进行部署 +可直接使用部署的deepseek大模型参考以下方式进行部署 1. 下载模型文件: @@ -627,6 +429,58 @@ vim /home/euler-copilot-framework_openeuler/deploy/chart_ssl/traefik-secret.yaml kubectl apply -f traefik-secret.yaml ``` -#### 9. Pod 状态从 Running 变为 Pending 或 Completed +#### 9. 问题排查方法 + + 1. **获取集群事件信息** + + 为了更好地定位 Pod 失败的原因,请首先检查 Kubernetes 集群中的事件 (Events)。这可以提供有关 Pod 状态变化的上下文信息。 + + ```bash + kubectl get events -n euler-copilot + ``` + + 2. **验证镜像拉取状态** + + 确认容器镜像是否成功拉取。如果镜像未能正确加载,可能是由于网络问题或镜像仓库配置错误。 + + ```bash + k3s crictl images + ``` + + 3. **审查 Pod 日志** + + 检查相关 Pod 的日志,以寻找可能的错误信息或异常行为。这对于诊断应用程序级别的问题特别有用。 + + ```bash + kubectl logs rag-deploy-service-5b7887644c-sm58z -n euler-copilot + ``` + + 4. **评估资源可用性** + + 确保 Kubernetes 集群有足够的资源(如 CPU、内存和存储)来支持 Pod 的运行。资源不足可能导致镜像拉取失败或其他性能问题,或使得 Pod 状态从 Running 变为 Pending 或 Completed。可查看磁盘空间并保证至少有 30% 的可用空间。这有助于维持 Pod 的稳定运行状态。 + + ```bash + kubectl top nodes + ``` + + 5. **确认 k3s 版本兼容性** -Pod 状态变化可能是因为宿主机存储空间不足。使用 `df -h` 检查磁盘使用情况,并保证至少有 30% 的可用空间。这有助于维持 Pod 的稳定运行状态。 + 如果遇到镜像拉取失败且镜像大小为 0 的问题,请检查您的 k3s 版本是否符合最低要求(v1.30.2 或更高)。较低版本可能存在不兼容的问题。 + + ```bash + k3s -v + ``` + + 6. **检查配置** + + 审核 `values.yaml` 文件中关于 OIDC 配置和域名配置是否填写正确,确保配置无误后更新服务。 + + ```bash + cat /home/euler-copilot-framework/deploy/chart/euler_copilot + ``` + ```bash + vim values.yaml | grep oidc + ``` + ```bash + helm upgrade euler-copilot -n euler-copilot . + ```