大量更新

This commit is contained in:
zeaslity
2026-05-19 14:28:44 +08:00
parent a8f6bda703
commit 9fc3372fa3
5299 changed files with 423176 additions and 426690 deletions

View File

@@ -2,40 +2,41 @@
# 获取环境信息
/usr/local/bin/agent-wdd info all
cat /usr/local/etc/wdd/agent-wdd-config.yaml
/usr/local/bin/rmdc-watchdog-node info all
cat /usr/local/etc/wdd/rmdc-watchdog-node-config.yaml
# 手动执行全部的命令
/usr/local/bin/agent-wdd base ssh key
/usr/local/bin/agent-wdd base ssh config
/usr/local/bin/rmdc-watchdog-node base ssh key
/usr/local/bin/rmdc-watchdog-node base ssh config
/usr/local/bin/agent-wdd base tools
/usr/local/bin/agent-wdd base swap
/usr/local/bin/agent-wdd base firewall
/usr/local/bin/agent-wdd base selinux
/usr/local/bin/agent-wdd base sysconfig
/usr/local/bin/rmdc-watchdog-node base tools
/usr/local/bin/agent-wdd zsh cn
/usr/local/bin/rmdc-watchdog-node base swap
/usr/local/bin/rmdc-watchdog-node base firewall
/usr/local/bin/rmdc-watchdog-node base selinux
/usr/local/bin/rmdc-watchdog-node base sysconfig
/usr/local/bin/rmdc-watchdog-node zsh cn
# 首先需要下载所有的依赖!
/usr/local/bin/agent-wdd base docker local
/usr/local/bin/agent-wdd base dockercompose local
/usr/local/bin/rmdc-watchdog-node base docker local
/usr/local/bin/rmdc-watchdog-node base dockercompose local
# 仅在主节点执行
/usr/local/bin/agent-wdd base docker config
/usr/local/bin/agent-wdd base harbor install
/usr/local/bin/rmdc-watchdog-node base harbor install
# 主节点执行
# 安装octopus-agent
mv agent-wdd_linux_amd64 /usr/local/bin/agent-wdd
chmod +x /usr/local/bin/agent-wdd
mv rmdc-watchdog-node_linux_amd64 /usr/local/bin/rmdc-watchdog-node
chmod +x /usr/local/bin/rmdc-watchdog-node
mv rmdc-watchdog-node_linux_arm64 /usr/local/bin/rmdc-watchdog-node
chmod +x /usr/local/bin/rmdc-watchdog-node
# 主节点安装ssh-key
/usr/local/bin/agent-wdd base ssh config
/usr/local/bin/agent-wdd base ssh key
/usr/local/bin/rmdc-watchdog-node base ssh config
/usr/local/bin/rmdc-watchdog-node base ssh key
# 批量执行命令
host_list=(
@@ -55,15 +56,24 @@ done
# 复制 同步文件
export server=172.16.100.62
scp /usr/local/bin/agent-wdd root@${server}:/usr/local/bin/agent-wdd
ssh root@${server} "/usr/local/bin/agent-wdd base ssh config && /usr/local/bin/agent-wdd base ssh key"
scp /usr/local/bin/rmdc-watchdog-node root@${server}:/usr/local/bin/rmdc-watchdog-node
ssh root@${server} "/usr/local/bin/rmdc-watchdog-node base ssh config && /usr/local/bin/rmdc-watchdog-node base ssh key"
ssh root@${server} "echo yes"
# 安装docker-compose
mv docker-compose-linux-x86_64 /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
# ssh root@${server} "/usr/local/bin/agent-wdd base tools"
# 批量执行rmdc-watchdog-node的命令
ssh root@${server} "/usr/local/bin/rmdc-watchdog-node info all"
ssh root@${server} "cat /usr/local/etc/wdd/rmdc-watchdog-node-config.yaml"
ssh root@${server} "/usr/local/bin/rmdc-watchdog-node base swap"
ssh root@${server} "/usr/local/bin/rmdc-watchdog-node base firewall"
ssh root@${server} "/usr/local/bin/rmdc-watchdog-node base selinux"
ssh root@${server} "/usr/local/bin/rmdc-watchdog-node base sysconfig"
# APT代理加速
scp /root/wdd/apt-change.sh root@${server}:/root/wdd/apt-change.sh
@@ -84,6 +94,8 @@ scp /root/wdd/disk.sh root@${server}:/root/wdd/
ssh root@${server} "bash /root/wdd/disk.sh"
# master节点安装docker
export DOCKER_VERSION=24
bash /root/wdd/docker.sh
# 在线安装docker 通过APT代理
@@ -98,21 +110,15 @@ ssh root@${server} "docker compose version"
scp /root/wdd/docker-amd64-20.10.15.tgz root@${server}:/root/wdd/docker-amd64-20.10.15.tgz
scp /root/wdd/docker-compose-v2.18.0-linux-amd64 root@${server}:/root/wdd/
# 批量执行agent-wdd的命令
ssh root@${server} "/usr/local/bin/agent-wdd info all"
ssh root@${server} "cat /usr/local/etc/wdd/agent-wdd-config.yaml"
scp /root/wdd/docker-arm64-20.10.15.tgz root@${server}:/root/wdd/docker-arm64-20.10.15.tgz
scp /root/wdd/docker-compose-v2.18.0-linux-arm64 root@${server}:/root/wdd/
ssh root@${server} "/usr/local/bin/agent-wdd base swap"
ssh root@${server} "/usr/local/bin/agent-wdd base firewall"
ssh root@${server} "/usr/local/bin/agent-wdd base selinux"
ssh root@${server} "/usr/local/bin/agent-wdd base sysconfig"
ssh root@${server} "/usr/local/bin/agent-wdd base docker local"
ssh root@${server} "/usr/local/bin/agent-wdd base dockercompose local"
ssh root@${server} "/usr/local/bin/rmdc-watchdog-node base docker local"
ssh root@${server} "/usr/local/bin/rmdc-watchdog-node base dockercompose local"
# 仅在主节点执行
/usr/local/bin/agent-wdd base docker config
/usr/local/bin/rmdc-watchdog-node base docker config
# 下发docker的配置
scp /etc/docker/daemon.json root@${server}:/etc/docker/daemon.json
@@ -120,12 +126,12 @@ ssh root@${server} "cat /etc/docker/daemon.json"
ssh root@${server} "systemctl restart docker"
ssh root@${server} "docker info"
wget https://oss.demo.uavcmlc.com/cmlc-installation/tmp/nginx=1.27.0=2025-03-11=402.tar.gz && docker load < nginx=1.27.0=2025-03-11=402.tar.gz && docker run -it --rm harbor.cdcyy.com.cn/cmii/nginx:1.27.0
# 清理脚本
ssh root@${server} "rm /root/wdd/*.sh"
# 主节点执行 安装harbor仓库
/usr/local/bin/agent-wdd base harbor install
/usr/local/bin/rmdc-watchdog-node base harbor install
# 安装rke kubectl
mv /root/wdd/rke_linux-amd64 /usr/local/bin/rke
@@ -135,6 +141,13 @@ mv /root/wdd/kubectl_v1.30.14_amd64 /usr/local/bin/kubectl
chmod +x /usr/local/bin/kubectl
## arm64
mv /root/wdd/rke_linux-arm64 /usr/local/bin/rke
chmod +x /usr/local/bin/rke
mv /root/wdd/kubectl_v1.30.14_arm64 /usr/local/bin/kubectl
chmod +x /usr/local/bin/kubectl
# 安装 k8s-证书
mkdir /root/.kube
@@ -144,7 +157,7 @@ cp ./kube_config_cluster.yml /root/.kube/config
DEFAULT_HTTP_BACKEND_IP=$(kubectl -n ingress-nginx get svc default-http-backend -o jsonpath='{.spec.clusterIP}')
# master节点
curl -s "http://${DEFAULT_HTTP_BACKEND_IP}"x
curl -s "http://${DEFAULT_HTTP_BACKEND_IP}"
# worker节点
ssh root@"$server" "DEFAULT_HTTP_BACKEND_IP='$DEFAULT_HTTP_BACKEND_IP' bash -s" <<'EOF'

View File

@@ -1,84 +0,0 @@
#!/bin/bash
set -e
# 用户配置部分
DISK="/dev/sdb" # 要操作的物理磁盘(请根据实际情况修改)
MOUNT_PATH="/var/lib/docker" # 挂载点路径(目录会自动创建)
FS_TYPE="ext4" # 文件系统类型支持ext4/xfs默认ext4
#----------------------------------------------------------
# 核心逻辑(建议非必要不修改)
#----------------------------------------------------------
function check_prerequisites() {
# 必须root权限运行检查
[[ $EUID -ne 0 ]] && echo -e "\033[31m错误必须使用root权限运行此脚本\033[0m" && exit 1
# 磁盘存在性检查
[[ ! -b "$DISK" ]] && echo -e "\033[31m错误磁盘 $DISK 不存在\033[0m" && exit 1
# 文件系统类型校验
if [[ "$FS_TYPE" != "ext4" && "$FS_TYPE" != "xfs" ]]; then
echo -e "\033[31m错误不支持的磁盘格式 $FS_TYPE,仅支持 ext4/xfs\033[0m"
exit 1
fi
}
function prepare_disk() {
local partition="${DISK}1"
echo -e "\033[34m正在初始化磁盘分区...\033[0m"
parted "$DISK" --script mklabel gpt
parted "$DISK" --script mkpart primary 0% 100%
parted "$DISK" --script set 1 lvm on
partprobe "$DISK" # 确保系统识别新分区表
echo -e "\033[34m正在创建LVM结构...\033[0m"
pvcreate "$partition"
vgcreate datavg "$partition"
lvcreate -y -l 100%FREE -n lvdata datavg
}
function format_and_mount() {
echo -e "\033[34m格式化逻辑卷...\033[0m"
if [[ "$FS_TYPE" == "ext4" ]]; then
mkfs.ext4 -F "/dev/datavg/lvdata"
else
mkfs.xfs -f "/dev/datavg/lvdata"
fi
echo -e "\033[34m设置挂载配置...\033[0m"
mkdir -p "$MOUNT_PATH"
UUID=$(blkid -s UUID -o value "/dev/datavg/lvdata")
echo "UUID=$UUID $MOUNT_PATH $FS_TYPE defaults 0 0" | tee -a /etc/fstab >/dev/null
mount -a
}
function verify_result() {
echo -e "\n\033[1;36m最终验证结果\033[0m"
lsblk -f "$DISK"
echo -e "\n磁盘空间使用情况"
df -hT "$MOUNT_PATH"
}
# 主执行流程
check_prerequisites
prepare_disk
format_and_mount
verify_result
echo -e "\n\033[32m操作执行完毕请仔细核查上述输出信息\033[0m"
#请写一个shell脚本脚本前面有变量可以设置 物理磁盘名称 挂载点路径 磁盘格式化的形式,脚本实现如下的功能
#1.将物理磁盘的盘符修改为gpt格式
#2.将物理磁盘全部空间创建一个分区分区格式为lvm
#3.将分区分配给逻辑卷datavg
#4.将datavg所有可用的空间分配给逻辑卷lvdata
#5.将逻辑卷格式化为变量磁盘格式化的形式(支持xfs和ext4的格式,默认为ext4)
#6.创建变量挂载点路径
#7.写入/etc/fatab,将逻辑卷挂载到变量挂载点,执行全部挂在操作
#8.执行lsblk和df -TH查看分区是否正确挂载

View File

@@ -1,594 +0,0 @@
#!/usr/bin/env bash
# ==============================================================================
# Metadata
# ==============================================================================
# Author : Smith Wang (Refactor by ChatGPT)
# Version : 2.0.0
# License : MIT
# Description : Configure Docker APT repository (mirror) and install Docker on
# Ubuntu (18.04/20.04/22.04/24.04) with robust offline handling.
#
# Modules :
# - Logging & Error Handling
# - Environment & Dependency Checks
# - Public Network Reachability Detection
# - Docker GPG Key Installation (Online/Offline)
# - Docker APT Repo Configuration
# - Docker Installation & Service Setup
#
# Notes :
# - This script DOES NOT modify Ubuntu APT sources (/etc/apt/sources.list)
# - This script DOES NOT set APT proxy (assumed handled elsewhere)
# - If public network is NOT reachable and local GPG key is missing, script
# will NOT proceed (per your requirement).
#
# ShellCheck : Intended clean for bash v5+ with: shellcheck -x <script>
# ==============================================================================
set -euo pipefail
# ==============================================================================
# Global Constants
# ==============================================================================
readonly SCRIPT_NAME="$(basename "$0")"
readonly SCRIPT_VERSION="2.0.0"
# Default mirror for Docker repo (you asked: only focus on docker source)
readonly DEFAULT_DOCKER_APT_MIRROR="https://mirrors.aliyun.com/docker-ce/linux/ubuntu"
# Default keyring location (recommended by modern Ubuntu)
readonly DEFAULT_KEYRING_PATH="/etc/apt/keyrings/docker.gpg"
# Exit codes
readonly EC_OK=0
readonly EC_GENERAL=1
readonly EC_UNSUPPORTED_OS=10
readonly EC_DEPENDENCY=11
readonly EC_OFFLINE_NO_KEY=20
readonly EC_APT_FAILURE=30
# ==============================================================================
# Configurable Variables (Environment Overrides)
# ==============================================================================
# You may export these before running:
# DOCKER_VERSION="20.10" # or "20.10.15" (optional)
# DOCKER_APT_MIRROR="https://..."
# DOCKER_KEYRING_PATH="/root/wdd/docker.gpg"
# LOCAL_DOCKER_GPG="/path/to/docker.gpg" (optional)
# LOG_LEVEL="DEBUG|INFO|WARN|ERROR"
DOCKER_VERSION="${DOCKER_VERSION:-20.10}"
DOCKER_APT_MIRROR="${DOCKER_APT_MIRROR:-$DEFAULT_DOCKER_APT_MIRROR}"
DOCKER_KEYRING_PATH="${DOCKER_KEYRING_PATH:-$DEFAULT_KEYRING_PATH}"
LOCAL_DOCKER_GPG="${LOCAL_DOCKER_GPG:-/root/wdd/docker.gpg}"
LOG_LEVEL="${LOG_LEVEL:-INFO}"
# ==============================================================================
# Function Call Graph (ASCII)
# ==============================================================================
# main
# |
# +--> init_traps
# |
# +--> check_platform
# |
# +--> ensure_prerequisites
# |
# +--> detect_public_network
# | |
# | +--> can_fetch_url_head
# |
# +--> ensure_docker_gpg_key
# | |
# | +--> install_key_from_online
# | | |
# | | +--> require_cmd (curl, gpg)
# | |
# | +--> install_key_from_local
# |
# +--> configure_docker_repo
# |
# +--> install_docker_packages
# | |
# | +--> resolve_docker_version
# |
# +--> pin_docker_packages
# |
# +--> enable_docker_service
# ==============================================================================
# ==============================================================================
# Logging
# ==============================================================================
### Map log level string to numeric value.
### @param level_str string Level string (DEBUG/INFO/WARN/ERROR)
### @return 0 Always returns 0; outputs numeric level to stdout
### @require none
log_level_to_num() {
case "${1:-INFO}" in
DEBUG) echo 10 ;;
INFO) echo 20 ;;
WARN) echo 30 ;;
ERROR) echo 40 ;;
*) echo 20 ;;
esac
}
### Unified logger with level gating.
### @param level string Log level
### @param message string Message
### @return 0 Always returns 0
### @require date
log() {
local level="${1:?level required}"
shift
local message="${*:-}"
local now
now="$(date '+%F %T')"
local current_level_num wanted_level_num
current_level_num="$(log_level_to_num "$LOG_LEVEL")"
wanted_level_num="$(log_level_to_num "$level")"
if [ "$wanted_level_num" -lt "$current_level_num" ]; then
return 0
fi
# > Keep format stable for parsing by log collectors
printf '%s [%s] %s: %s\n' "$now" "$level" "$SCRIPT_NAME" "$message" >&2
}
# ==============================================================================
# Error Handling & Traps
# ==============================================================================
### Trap handler for unexpected errors.
### @param exit_code int Exit code from failing command
### @return 0 Always returns 0
### @require none
on_error() {
local exit_code="${1:-$EC_GENERAL}"
log ERROR "Unhandled error occurred (exit_code=${exit_code})."
exit "$exit_code"
}
### Trap handler for script exit.
### @param exit_code int Exit code
### @return 0 Always returns 0
### @require none
on_exit() {
local exit_code="${1:-$EC_OK}"
if [ "$exit_code" -eq 0 ]; then
log INFO "Done."
else
log WARN "Exited with code ${exit_code}."
fi
return 0
}
### Initialize traps (ERR/INT/TERM/EXIT).
### @return 0 Success
### @require none
init_traps() {
trap 'on_error $?' ERR
trap 'log WARN "Interrupted (SIGINT)"; exit 130' INT
trap 'log WARN "Terminated (SIGTERM)"; exit 143' TERM
trap 'on_exit $?' EXIT
}
# ==============================================================================
# Privilege Helpers
# ==============================================================================
### Run a command as root (uses sudo if not root).
### @param cmd string Command to run
### @return 0 Success; non-zero on failure
### @require sudo (if not root)
run_root() {
if [ "$(id -u)" -eq 0 ]; then
# shellcheck disable=SC2068
"$@"
else
# shellcheck disable=SC2068
sudo "$@"
fi
}
# ==============================================================================
# Dependency Checks
# ==============================================================================
### Ensure a command exists in PATH.
### @param cmd_name string Command name
### @return 0 If exists; 1 otherwise
### @require none
require_cmd() {
local cmd_name="${1:?cmd required}"
if ! command -v "$cmd_name" >/dev/null 2>&1; then
log ERROR "Missing dependency: ${cmd_name}"
return 1
fi
return 0
}
# ==============================================================================
# Platform Check
# ==============================================================================
### Check OS is Ubuntu and supported versions.
### @return 0 Supported; exits otherwise
### @require lsb_release, awk
check_platform() {
require_cmd lsb_release || exit "$EC_DEPENDENCY"
local distro version
distro="$(lsb_release -is 2>/dev/null || true)"
version="$(lsb_release -rs 2>/dev/null || true)"
if [ "$distro" != "Ubuntu" ]; then
log ERROR "Unsupported OS: ${distro}. This script supports Ubuntu only."
exit "$EC_UNSUPPORTED_OS"
fi
case "$version" in
18.04|20.04|22.04|24.04) ;;
*)
log ERROR "Unsupported Ubuntu version: ${version}. Supported: 18.04/20.04/22.04/24.04"
exit "$EC_UNSUPPORTED_OS"
;;
esac
log INFO "Platform OK: ${distro} ${version}"
}
# ==============================================================================
# APT Prerequisites
# ==============================================================================
### Install required packages for repository/key management and Docker installation.
### @return 0 Success; exits on apt failures
### @require apt-get
ensure_prerequisites() {
require_cmd apt-get || exit "$EC_DEPENDENCY"
log INFO "Installing prerequisites (does NOT modify APT sources or proxy)..."
# > apt update must work via your existing proxy+mirror scripts
if ! run_root apt-get update; then
log ERROR "apt-get update failed. Check APT proxy / mirror configuration."
exit "$EC_APT_FAILURE"
fi
# > Keep dependencies minimal; curl/gpg used only for online key fetch.
if ! run_root apt-get install -y ca-certificates gnupg lsb-release; then
log ERROR "Failed to install prerequisites."
exit "$EC_APT_FAILURE"
fi
log INFO "Prerequisites installed."
}
# ==============================================================================
# Public Network Reachability
# ==============================================================================
### Check whether we can fetch HTTP headers from a URL (lightweight reachability).
### @param test_url string URL to test
### @return 0 Reachable; 1 otherwise
### @require curl (optional; if missing returns 1)
can_fetch_url_head() {
local test_url="${1:?url required}"
if ! command -v curl >/dev/null 2>&1; then
log WARN "curl not found; cannot test public network reachability via HTTP."
return 1
fi
# > Use short timeout to avoid hanging in restricted networks
curl -fsSI --max-time 3 "$test_url" >/dev/null 2>&1
}
### Detect whether public network access is available for Docker key fetch.
### @return 0 Online; 1 Offline/Uncertain
### @require none
detect_public_network() {
local test_url="${DOCKER_APT_MIRROR%/}/gpg"
log INFO "Detecting public network reachability: HEAD ${test_url}"
if can_fetch_url_head "$test_url"; then
log INFO "Public network reachable for Docker mirror."
return 0
fi
log WARN "Public network NOT reachable (or curl missing). Will try local GPG key."
return 1
}
# ==============================================================================
# Docker GPG Key Management
# ==============================================================================
### Install Docker GPG key from online source (mirror).
### @param gpg_url string GPG URL
### @param keyring_path string Keyring output path
### @return 0 Success; non-zero on failure
### @require curl, gpg, install, mkdir, chmod
install_key_from_online() {
local gpg_url="${1:?gpg_url required}"
local keyring_path="${2:?keyring_path required}"
require_cmd curl || return 1
require_cmd gpg || return 1
# > Write to temp then atomically install to avoid partial files
local tmp_dir tmp_gpg
tmp_dir="$(mktemp -d)"
tmp_gpg="${tmp_dir}/docker.gpg"
log INFO "Fetching Docker GPG key online: ${gpg_url}"
curl -fsSL --max-time 10 "$gpg_url" | gpg --dearmor -o "$tmp_gpg"
run_root mkdir -p "$(dirname "$keyring_path")"
run_root install -m 0644 "$tmp_gpg" "$keyring_path"
run_root chmod a+r "$keyring_path" || true
rm -rf "$tmp_dir"
log INFO "Docker GPG key installed: ${keyring_path}"
return 0
}
### Install Docker GPG key from local file (offline-friendly).
### @param local_gpg_path string Local GPG file path
### @param keyring_path string Keyring output path
### @return 0 Success; 1 if local key missing; non-zero on other failures
### @require install, mkdir, chmod
install_key_from_local() {
local local_gpg_path="${1:?local_gpg_path required}"
local keyring_path="${2:?keyring_path required}"
if [ ! -f "$local_gpg_path" ]; then
log WARN "Local Docker GPG key not found: ${local_gpg_path}"
return 1
fi
run_root mkdir -p "$(dirname "$keyring_path")"
run_root install -m 0644 "$local_gpg_path" "$keyring_path"
run_root chmod a+r "$keyring_path" || true
log INFO "Docker GPG key installed from local: ${local_gpg_path} -> ${keyring_path}"
return 0
}
### Ensure Docker GPG key exists, using online if reachable; otherwise local-only.
### Offline policy: if local key missing -> DO NOT proceed (exit).
### @param is_online int 0 online; 1 offline
### @return 0 Success; exits with EC_OFFLINE_NO_KEY when offline and no local key
### @require none
ensure_docker_gpg_key() {
local is_online="${1:?is_online required}"
# > If keyring already exists, reuse it (idempotent)
if [ -f "$DOCKER_KEYRING_PATH" ]; then
log INFO "Docker keyring already exists: ${DOCKER_KEYRING_PATH}"
run_root chmod a+r "$DOCKER_KEYRING_PATH" || true
return 0
fi
# > Determine local key candidate paths (priority order)
local script_dir local_candidate
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ -n "$LOCAL_DOCKER_GPG" ]; then
local_candidate="$LOCAL_DOCKER_GPG"
elif [ -f "${script_dir}/docker.gpg" ]; then
local_candidate="${script_dir}/docker.gpg"
else
local_candidate=""
fi
local gpg_url
gpg_url="${DOCKER_APT_MIRROR%/}/gpg"
if [ "$is_online" -eq 0 ]; then
# Online: try online key fetch first; if fails, fallback to local if present.
log DEBUG "Online mode: attempt online key install, fallback to local."
if install_key_from_online "$gpg_url" "$DOCKER_KEYRING_PATH"; then
return 0
fi
if [ -n "$local_candidate" ] && install_key_from_local "$local_candidate" "$DOCKER_KEYRING_PATH"; then
return 0
fi
log ERROR "Failed to install Docker GPG key (online fetch failed and no usable local key)."
exit "$EC_DEPENDENCY"
fi
# Offline: strictly local only; if missing -> do not proceed
log INFO "Offline mode: install Docker GPG key from local only."
if [ -n "$local_candidate" ] && install_key_from_local "$local_candidate" "$DOCKER_KEYRING_PATH"; then
return 0
fi
log ERROR "Offline and local Docker GPG key is missing. Will NOT proceed (per policy)."
exit "$EC_OFFLINE_NO_KEY"
}
# ==============================================================================
# Docker Repo Configuration
# ==============================================================================
### Configure Docker APT repository list file.
### @return 0 Success; exits on apt update failures
### @require dpkg, lsb_release, tee, apt-get
configure_docker_repo() {
require_cmd dpkg || exit "$EC_DEPENDENCY"
require_cmd lsb_release || exit "$EC_DEPENDENCY"
require_cmd tee || exit "$EC_DEPENDENCY"
local codename arch list_file
codename="$(lsb_release -cs)"
arch="$(dpkg --print-architecture)"
list_file="/etc/apt/sources.list.d/docker.list"
log INFO "Configuring Docker APT repo: ${DOCKER_APT_MIRROR} (${codename}, ${arch})"
# > Only touch docker repo; do not touch system sources.list
run_root tee "$list_file" >/dev/null <<EOF
deb [arch=${arch} signed-by=${DOCKER_KEYRING_PATH}] ${DOCKER_APT_MIRROR} ${codename} stable
EOF
if ! run_root apt-get update; then
log ERROR "apt-get update failed after configuring Docker repo."
exit "$EC_APT_FAILURE"
fi
log INFO "Docker APT repo configured: ${list_file}"
}
# ==============================================================================
# Docker Installation
# ==============================================================================
### Resolve Docker package version string from APT cache.
### @param docker_version string Desired version ("20.10" or "20.10.15")
### @return 0 Success and echoes full apt version string; exits if not found
### @require apt-cache, awk, grep, sort, head
resolve_docker_version() {
local docker_version="${1:?docker_version required}"
require_cmd apt-cache || exit "$EC_DEPENDENCY"
require_cmd awk || exit "$EC_DEPENDENCY"
require_cmd grep || exit "$EC_DEPENDENCY"
require_cmd sort || exit "$EC_DEPENDENCY"
require_cmd head || exit "$EC_DEPENDENCY"
local resolved=""
# > apt-cache madison output includes epoch, keep it for apt-get install
if [[ "$docker_version" =~ ^[0-9]+\.[0-9]+$ ]]; then
# Pick newest patch/build for that major.minor
resolved="$(
apt-cache madison docker-ce \
| awk -F'|' '{gsub(/ /,"",$2); print $2}' \
| grep -E "^[0-9]+:${docker_version}([.-]|\~)" \
| sort -rV \
| head -1 || true
)"
elif [[ "$docker_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
resolved="$(
apt-cache madison docker-ce \
| awk -F'|' '{gsub(/ /,"",$2); print $2}' \
| grep -E "^[0-9]+:${docker_version}.*" \
| head -1 || true
)"
else
log ERROR "Invalid DOCKER_VERSION format: ${docker_version} (expect 20.10 or 20.10.15)"
exit "$EC_GENERAL"
fi
if [ -z "$resolved" ]; then
log ERROR "Cannot find Docker version '${docker_version}' from APT. Check repo/mirror and apt proxy."
exit "$EC_APT_FAILURE"
fi
echo "$resolved"
return 0
}
### Install Docker packages via APT.
### @return 0 Success; exits on failure
### @require apt-get, systemctl
install_docker_packages() {
require_cmd apt-get || exit "$EC_DEPENDENCY"
local full_version
full_version="$(resolve_docker_version "$DOCKER_VERSION")"
log INFO "Installing Docker packages: docker-ce=${full_version}"
# > Compose: use docker-compose-plugin (no curl downloading binaries)
if ! run_root apt-get install -y \
"docker-ce=${full_version}" \
"docker-ce-cli=${full_version}" \
"docker-ce-rootless-extras=${full_version}" \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin; then
log ERROR "Docker installation failed."
exit "$EC_APT_FAILURE"
fi
# > Optional: provide docker-compose legacy command compatibility
if ! command -v docker-compose >/dev/null 2>&1; then
if [ -x /usr/libexec/docker/cli-plugins/docker-compose ]; then
run_root ln -sf /usr/libexec/docker/cli-plugins/docker-compose /usr/local/bin/docker-compose || true
fi
fi
log INFO "Docker packages installed."
}
### Pin Docker packages to avoid unintended upgrades.
### @return 0 Success; non-zero on failures (non-fatal)
### @require apt-mark
pin_docker_packages() {
if ! command -v apt-mark >/dev/null 2>&1; then
log WARN "apt-mark not found; skip pinning."
return 0
fi
log INFO "Holding Docker packages (prevent auto-upgrade)..."
run_root apt-mark hold \
docker-ce docker-ce-cli docker-ce-rootless-extras containerd.io \
docker-buildx-plugin docker-compose-plugin >/dev/null 2>&1 || true
return 0
}
### Enable and start Docker service, then verify versions.
### @return 0 Success; exits on failure to enable docker
### @require systemctl, docker
enable_docker_service() {
require_cmd systemctl || exit "$EC_DEPENDENCY"
log INFO "Enabling and starting docker service..."
run_root systemctl enable --now docker
# > Verification should not hard-fail the whole script
if command -v docker >/dev/null 2>&1; then
docker --version || true
docker compose version || true
fi
if command -v docker-compose >/dev/null 2>&1; then
docker-compose --version || true
fi
log INFO "Docker service enabled."
}
# ==============================================================================
# Main
# ==============================================================================
### Main entrypoint.
### @return 0 Success; non-zero on failure
### @require none
main() {
init_traps
log INFO "Starting Docker installer (v${SCRIPT_VERSION})..."
check_platform
ensure_prerequisites
local is_online=1
if detect_public_network; then
is_online=0
fi
ensure_docker_gpg_key "$is_online"
configure_docker_repo
install_docker_packages
pin_docker_packages
enable_docker_service
log INFO "All tasks completed successfully."
exit "$EC_OK"
}
main "$@"

View File

@@ -1,24 +0,0 @@
# master节点
sudo apt update
sudo apt install -y apt-cacher-ng
systemctl status apt-cacher-ng
# worker节点
sudo tee /etc/apt/apt.conf.d/01proxy <<EOF
Acquire::http::Proxy "http://10.22.57.8:3142";
Acquire::https::Proxy "http://10.22.57.8:3142";
EOF
ssh root@${server} "printf '%s\n' \
'Acquire::http::Proxy \"http://10.22.57.8:3142\";' \
'Acquire::https::Proxy \"http://10.22.57.8:3142\";' \
| tee /etc/apt/apt.conf.d/01proxy >/dev/null"

View File

@@ -0,0 +1,132 @@
#!/bin/bash
set -euo pipefail
#----------------------------------------------------------
# 用户配置部分
#----------------------------------------------------------
DISKS=("/dev/vdb" "/dev/vdc" "/dev/vdd" "/dev/vde") # 4块物理磁盘
MOUNT_PATH="/var/lib/docker" # 挂载点路径(目录会自动创建)
FS_TYPE="ext4" # 文件系统类型(支持 ext4/xfs默认 ext4
VG_NAME="datavg" # 卷组名
LV_NAME="lvdata" # 逻辑卷名
#----------------------------------------------------------
# 核心逻辑(建议非必要不修改)
#----------------------------------------------------------
function check_prerequisites() {
# 必须 root 权限运行检查
[[ $EUID -ne 0 ]] && echo -e "\033[31m错误必须使用 root 权限运行此脚本\033[0m" && exit 1
# 文件系统类型校验
if [[ "$FS_TYPE" != "ext4" && "$FS_TYPE" != "xfs" ]]; then
echo -e "\033[31m错误不支持的磁盘格式 $FS_TYPE,仅支持 ext4/xfs\033[0m"
exit 1
fi
# 磁盘存在性检查
for disk in "${DISKS[@]}"; do
[[ ! -b "$disk" ]] && echo -e "\033[31m错误磁盘 $disk 不存在\033[0m" && exit 1
done
# 检查 VG / LV 是否已存在,避免误操作
if vgdisplay "$VG_NAME" >/dev/null 2>&1; then
echo -e "\033[31m错误卷组 $VG_NAME 已存在,请先检查环境\033[0m"
exit 1
fi
if lvdisplay "/dev/${VG_NAME}/${LV_NAME}" >/dev/null 2>&1; then
echo -e "\033[31m错误逻辑卷 /dev/${VG_NAME}/${LV_NAME} 已存在,请先检查环境\033[0m"
exit 1
fi
}
function prepare_disks() {
PARTITIONS=()
echo -e "\033[34m正在初始化磁盘分区...\033[0m"
for disk in "${DISKS[@]}"; do
echo -e "\033[34m处理磁盘: $disk\033[0m"
parted "$disk" --script mklabel gpt
parted "$disk" --script mkpart primary 0% 100%
parted "$disk" --script set 1 lvm on
partprobe "$disk"
# 兼容 nvme 和普通 sd/vd 设备命名
if [[ "$disk" =~ nvme ]]; then
partition="${disk}p1"
else
partition="${disk}1"
fi
# 等待分区节点出现
udevadm settle
sleep 1
[[ ! -b "$partition" ]] && echo -e "\033[31m错误分区 $partition 未识别成功\033[0m" && exit 1
PARTITIONS+=("$partition")
done
}
function create_lvm() {
echo -e "\033[34m正在创建 LVM 结构...\033[0m"
pvcreate "${PARTITIONS[@]}"
vgcreate "$VG_NAME" "${PARTITIONS[@]}"
lvcreate -y -l 100%FREE -n "$LV_NAME" "$VG_NAME"
}
function format_and_mount() {
local lv_path="/dev/${VG_NAME}/${LV_NAME}"
echo -e "\033[34m格式化逻辑卷...\033[0m"
if [[ "$FS_TYPE" == "ext4" ]]; then
mkfs.ext4 -F "$lv_path"
else
mkfs.xfs -f "$lv_path"
fi
echo -e "\033[34m设置挂载配置...\033[0m"
mkdir -p "$MOUNT_PATH"
UUID=$(blkid -s UUID -o value "$lv_path")
[[ -z "$UUID" ]] && echo -e "\033[31m错误未获取到逻辑卷 UUID\033[0m" && exit 1
# 避免重复写入 fstab
if ! grep -q "$UUID" /etc/fstab; then
echo "UUID=$UUID $MOUNT_PATH $FS_TYPE defaults 0 0" >> /etc/fstab
else
echo -e "\033[33m提示/etc/fstab 中已存在该 UUID跳过写入\033[0m"
fi
mount -a
}
function verify_result() {
echo -e "\n\033[1;36m最终验证结果\033[0m"
echo -e "\n\033[1;36m1. 查看块设备和 LVM 结构:\033[0m"
lsblk -f
echo -e "\n\033[1;36m2. 查看挂载结果:\033[0m"
df -hT "$MOUNT_PATH"
echo -e "\n\033[1;36m3. 查看 VG/LV 信息:\033[0m"
vgs
lvs
pvs
}
#----------------------------------------------------------
# 主执行流程
#----------------------------------------------------------
check_prerequisites
prepare_disks
create_lvm
format_and_mount
verify_result
echo -e "\n\033[32m操作执行完毕请仔细核查上述输出信息\033[0m"

View File

@@ -1,23 +0,0 @@
#!/bin/bash
nfs_data_path="/var/lib/docker/nfs_data"
#nfs_data_path="/data/nfs_data"
deploy_nfs_server(){
mkdir -p $nfs_data_path
chmod 777 $nfs_data_path
echo "${nfs_data_path} *(rw,no_root_squash,no_all_squash,sync)" >> /etc/exports
systemctl restart rpcbind
systemctl restart nfs-server
systemctl enable rpcbind
systemctl enable nfs-server
}
deploy_nfs_server
# docker login -u admin -p V2ryStr@ngPss 10.100.2.121:8033

View File

@@ -1,767 +0,0 @@
#!/bin/bash
###############################################################################
# NGINX Installation Script for China Mainland with Mirror Acceleration
###############################################################################
# @author Advanced Bash Shell Engineer
# @version 1.0.0
# @license MIT
# @created 2026-01-19
# @desc Production-grade NGINX installation script with China mirror support
# Supports Ubuntu 18.04/20.04/22.04/24.04 with version pinning
###############################################################################
###############################################################################
# GLOBAL CONSTANTS
###############################################################################
readonly SCRIPT_NAME="$(basename "${BASH_SOURCE[0]}")"
readonly SCRIPT_VERSION="1.0.0"
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Color codes for output
readonly COLOR_RED="\033[0;31m"
readonly COLOR_GREEN="\033[0;32m"
readonly COLOR_YELLOW="\033[1;33m"
readonly COLOR_BLUE="\033[0;34m"
readonly COLOR_RESET="\033[0m"
# Log levels
readonly LOG_LEVEL_DEBUG=0
readonly LOG_LEVEL_INFO=1
readonly LOG_LEVEL_WARN=2
readonly LOG_LEVEL_ERROR=3
# Default configuration
readonly DEFAULT_NGINX_VERSION="stable"
readonly DEFAULT_MIRROR="ustc"
readonly SUPPORTED_UBUNTU_VERSIONS=("18.04" "20.04" "22.04" "24.04")
# Mirror configurations (China mainland accelerated sources)
declare -A MIRROR_URLS=(
["aliyun"]="http://mirrors.aliyun.com/nginx"
["tsinghua"]="https://mirrors.tuna.tsinghua.edu.cn/nginx"
["ustc"]="https://mirrors.ustc.edu.cn/nginx/ubuntu"
["official"]="http://nginx.org"
)
declare -A MIRROR_KEY_URLS=(
["aliyun"]="http://mirrors.aliyun.com/nginx/keys/nginx_signing.key"
["tsinghua"]="https://mirrors.tuna.tsinghua.edu.cn/nginx/keys/nginx_signing.key"
["ustc"]="https://mirrors.ustc.edu.cn/nginx/keys/nginx_signing.key"
["official"]="https://nginx.org/keys/nginx_signing.key"
)
# Global variables
CURRENT_LOG_LEVEL="${LOG_LEVEL_INFO}"
NGINX_VERSION="${DEFAULT_NGINX_VERSION}"
MIRROR_SOURCE="${DEFAULT_MIRROR}"
FORCE_REINSTALL=false
DRY_RUN=false
###############################################################################
# ERROR HANDLING & TRAPS
###############################################################################
set -euo pipefail
IFS=$'\n\t'
###
### Cleanup function for graceful exit
### @param none
### @return void
### @require none
###
cleanup() {
local exit_code=$?
if [[ ${exit_code} -ne 0 ]]; then
log_error "脚本退出,错误码: ${exit_code}"
fi
# > Perform cleanup operations if needed
return "${exit_code}"
}
trap cleanup EXIT
trap 'log_error "用户中断脚本执行"; exit 130' INT TERM
###############################################################################
# LOGGING FUNCTIONS
###############################################################################
###
### Core logging function with level-based filtering
### @param log_level integer Log level (0-3)
### @param message string Message to log
### @param color string Color code for output
### @return void
### @require none
###
_log() {
local log_level=$1
local message=$2
local color=$3
local level_name=$4
if [[ ${log_level} -ge ${CURRENT_LOG_LEVEL} ]]; then
local timestamp
timestamp="$(date '+%Y-%m-%d %H:%M:%S')"
echo -e "${color}[${timestamp}] [${level_name}] ${message}${COLOR_RESET}" >&2
fi
}
###
### Debug level logging
### @param message string Debug message
### @return void
### @require none
###
log_debug() {
_log "${LOG_LEVEL_DEBUG}" "$1" "${COLOR_BLUE}" "调试"
}
###
### Info level logging
### @param message string Info message
### @return void
### @require none
###
log_info() {
_log "${LOG_LEVEL_INFO}" "$1" "${COLOR_GREEN}" "信息"
}
###
### Warning level logging
### @param message string Warning message
### @return void
### @require none
###
log_warn() {
_log "${LOG_LEVEL_WARN}" "$1" "${COLOR_YELLOW}" "警告"
}
###
### Error level logging
### @param message string Error message
### @return void
### @require none
###
log_error() {
_log "${LOG_LEVEL_ERROR}" "$1" "${COLOR_RED}" "错误"
}
###############################################################################
# VALIDATION FUNCTIONS
###############################################################################
###
### Check if script is running with root privileges
### @param none
### @return 0 if root, 1 otherwise
### @require none
###
check_root_privileges() {
if [[ ${EUID} -ne 0 ]]; then
log_error "此脚本必须以 root 身份运行,或使用 sudo 执行"
return 1
fi
log_debug "已确认具备 root 权限"
return 0
}
###
### Validate Ubuntu version compatibility
### @param none
### @return 0 if supported, 1 otherwise
### @require lsb_release command
###
validate_ubuntu_version() {
local ubuntu_version
# > Check if lsb_release exists
if ! command -v lsb_release &> /dev/null; then
log_error "未找到 lsb_release 命令,无法识别 Ubuntu 版本。"
return 1
fi
ubuntu_version="$(lsb_release -rs)"
log_debug "检测到 Ubuntu 版本: ${ubuntu_version}"
# > Validate against supported versions
local supported=false
for version in "${SUPPORTED_UBUNTU_VERSIONS[@]}"; do
if [[ "${ubuntu_version}" == "${version}" ]]; then
supported=true
break
fi
done
if [[ "${supported}" == false ]]; then
log_error "Ubuntu ${ubuntu_version} 不受支持。支持的版本: ${SUPPORTED_UBUNTU_VERSIONS[*]}"
return 1
fi
log_info "Ubuntu ${ubuntu_version} 受支持"
return 0
}
###
### Validate mirror source selection
### @param mirror_name string 镜像源 name
### @return 0 if valid, 1 otherwise
### @require none
###
validate_mirror_source() {
local mirror_name=$1
if [[ ! -v MIRROR_URLS["${mirror_name}"] ]]; then
log_error "无效的镜像源: ${mirror_name}"
log_info "可用镜像源: ${!MIRROR_URLS[*]}"
return 1
fi
log_debug "镜像源 '${mirror_name}' 有效"
return 0
}
###
### Check network connectivity to mirror
### @param mirror_url string URL to test
### @return 0 if reachable, 1 otherwise
### @require curl
###
check_mirror_connectivity() {
local mirror_url=$1
local timeout=10
log_debug "正在测试镜像连通性: ${mirror_url}"
if curl -sSf --connect-timeout "${timeout}" --max-time "${timeout}" \
"${mirror_url}" -o /dev/null 2>/dev/null; then
log_debug "镜像 ${mirror_url} 可访问"
return 0
else
log_warn "镜像 ${mirror_url} 不可访问"
return 1
fi
}
###############################################################################
# SYSTEM PREPARATION FUNCTIONS
###############################################################################
###
### Install required system dependencies
### @param none
### @return 0 on success, 1 on failure
### @require apt-get
###
install_dependencies() {
log_info "正在安装系统依赖..."
local dependencies=(
"curl"
"gnupg2"
"ca-certificates"
"lsb-release"
"ubuntu-keyring"
"apt-transport-https"
)
if [[ "${DRY_RUN}" == true ]]; then
log_info "[演练模式] 将会安装: ${dependencies[*]}"
return 0
fi
# > Update package index first
if ! apt-get update -qq; then
log_error "更新软件包索引失败"
return 1
fi
# > Install dependencies
if ! apt-get install -y -qq "${dependencies[@]}"; then
log_error "安装依赖失败"
return 1
fi
log_info "依赖安装完成"
return 0
}
###
### Remove existing NGINX installation if present
### @param none
### @return 0 on success or if not installed
### @require apt-get, dpkg
###
remove_existing_nginx() {
log_info "正在检查是否已安装 NGINX..."
if ! dpkg -l | grep -q "^ii.*nginx"; then
log_info "未发现已安装的 NGINX"
return 0
fi
if [[ "${FORCE_REINSTALL}" == false ]]; then
log_warn "NGINX 已安装。如需重装请使用 --force。"
return 1
fi
log_info "正在卸载已安装的 NGINX..."
if [[ "${DRY_RUN}" == true ]]; then
log_info "[演练模式] 将会卸载已安装的 NGINX"
return 0
fi
# > Stop NGINX service if running
if systemctl is-active --quiet nginx 2>/dev/null; then
systemctl stop nginx || true
fi
# > Remove NGINX packages
if ! apt-get remove --purge -y nginx nginx-common nginx-full 2>/dev/null; then
log_warn "部分 NGINX 软件包可能未能完全卸载(可忽略)"
fi
# > Clean up configuration files
apt-get autoremove -y -qq || true
log_info "已卸载现有 NGINX"
return 0
}
###############################################################################
# NGINX INSTALLATION FUNCTIONS
###############################################################################
###
### Import NGINX GPG signing key
### @param mirror_name string 镜像源 name
### @return 0 on success, 1 on failure
### @require curl, gpg
###
import_nginx_gpg_key() {
local mirror_name=$1
local key_url="${MIRROR_KEY_URLS[${mirror_name}]}"
local keyring_path="/usr/share/keyrings/nginx-archive-keyring.gpg"
log_info "正在导入 NGINX GPG 签名密钥(来源:${mirror_name}..."
if [[ "${DRY_RUN}" == true ]]; then
log_info "[演练模式] 将会从以下地址导入 GPG 密钥: ${key_url}"
return 0
fi
# > Remove old keyring if exists
[[ -f "${keyring_path}" ]] && rm -f "${keyring_path}"
# > Download and import GPG key
if ! curl -fsSL "${key_url}" | gpg --dearmor -o "${keyring_path}" 2>/dev/null; then
log_error "导入 GPG 密钥失败: ${key_url}"
return 1
fi
# > Verify the key was imported correctly
if ! gpg --dry-run --quiet --no-keyring --import --import-options import-show \
"${keyring_path}" &>/dev/null; then
log_error "GPG 密钥校验失败"
return 1
fi
# > Set proper permissions
chmod 644 "${keyring_path}"
log_info "GPG 密钥导入并校验成功"
return 0
}
###
### Configure NGINX APT repository
### @param mirror_name string 镜像源 name
### @return 0 on success, 1 on failure
### @require lsb_release
###
configure_nginx_repository() {
local mirror_name=$1
local mirror_url="${MIRROR_URLS[${mirror_name}]}"
local codename
codename="$(lsb_release -cs)"
local repo_file="/etc/apt/sources.list.d/nginx.list"
local keyring_path="/usr/share/keyrings/nginx-archive-keyring.gpg"
# > 不同镜像源目录结构可能不同:
# > - 官方/部分镜像:.../packages/ubuntu
# > - USTC.../ubuntu
local repo_base
case "${mirror_name}" in
ustc)
repo_base="${mirror_url}"
;;
*)
repo_base="${mirror_url}/packages/ubuntu"
;;
esac
log_info "正在配置 NGINX 软件源Ubuntu ${codename}..."
if [[ "${DRY_RUN}" == true ]]; then
log_info "[演练模式] 将会配置软件源deb [signed-by=${keyring_path}] ${repo_base} ${codename} nginx"
return 0
fi
# > Create repository configuration
local repo_config="deb [signed-by=${keyring_path}] ${repo_base} ${codename} nginx"
echo "${repo_config}" | tee "${repo_file}" > /dev/null
log_debug "已生成软件源配置文件:${repo_file}"
log_debug "软件源地址:${repo_base} ${codename}"
log_info "NGINX 软件源配置完成"
return 0
}
###
### Configure APT pinning preferences for NGINX
### @param none
### @return 0 on success
### @require none
###
configure_apt_pinning() {
local pref_file="/etc/apt/preferences.d/99nginx"
log_info "正在配置 APT Pin 优先级..."
if [[ "${DRY_RUN}" == true ]]; then
log_info "[演练模式] 将会配置 APT Pin 优先级"
return 0
fi
# > Create pinning configuration for priority
cat > "${pref_file}" <<EOF
Package: *
Pin: origin nginx.org
Pin: release o=nginx
Pin-Priority: 900
EOF
log_debug "APT Pin 配置写入:${pref_file}"
log_info "APT Pin 优先级配置完成"
return 0
}
###
### Install NGINX package
### @param version string NGINX version to install (stable/mainline/specific)
### @return 0 on success, 1 on failure
### @require apt-get
###
install_nginx_package() {
local version=$1
local package_spec="nginx"
log_info "正在安装 NGINX ${version}..."
# > Update package index with new repository
if [[ "${DRY_RUN}" == false ]]; then
if ! apt-get update -qq; then
log_error "更新软件包索引失败"
return 1
fi
fi
# > Handle version specification
if [[ "${version}" != "stable" && "${version}" != "mainline" ]]; then
# > Specific version requested
package_spec="nginx=${version}"
log_debug "安装指定版本:${package_spec}"
else
log_debug "从软件源安装:${version}"
fi
if [[ "${DRY_RUN}" == true ]]; then
log_info "[演练模式] 将会安装软件包:${package_spec}"
return 0
fi
# > Install NGINX
if ! DEBIAN_FRONTEND=noninteractive apt-get install -y -qq "${package_spec}"; then
log_error "安装 NGINX 失败"
return 1
fi
log_info "NGINX 安装完成"
return 0
}
###
### Verify NGINX installation
### @param none
### @return 0 on success, 1 on failure
### @require nginx
###
verify_nginx_installation() {
log_info "正在验证 NGINX 安装结果..."
# > Check if nginx binary exists
if ! command -v nginx &> /dev/null; then
log_error "未在 PATH 中找到 nginx 可执行文件"
return 1
fi
# > Get and display version
local nginx_version_output
nginx_version_output="$(nginx -v 2>&1)"
log_info "已安装: ${nginx_version_output}"
# > Test configuration
if ! nginx -t &>/dev/null; then
log_error "NGINX 配置文件校验失败"
return 1
fi
log_info "NGINX 安装验证通过"
return 0
}
###
### Enable and start NGINX service
### @param none
### @return 0 on success, 1 on failure
### @require systemctl
###
enable_nginx_service() {
log_info "正在设置 NGINX 开机自启并启动服务..."
if [[ "${DRY_RUN}" == true ]]; then
log_info "[演练模式] 将会启用并启动 NGINX 服务"
return 0
fi
# > Enable service to start on boot
if ! systemctl enable nginx &>/dev/null; then
log_error "设置 NGINX 开机自启失败"
return 1
fi
# > Start the service
if ! systemctl start nginx; then
log_error "启动 NGINX 服务失败"
return 1
fi
# > Verify service is running
if ! systemctl is-active --quiet nginx; then
log_error "NGINX 服务未处于运行状态"
return 1
fi
log_info "NGINX 服务已启用并启动"
return 0
}
###############################################################################
# MAIN ORCHESTRATION
###############################################################################
###
### Display usage information
### @param none
### @return void
### @require none
###
show_usage() {
cat <<EOF
Usage: ${SCRIPT_NAME} [选项]
NGINX 安装脚本(面向中国大陆镜像加速) v${SCRIPT_VERSION}
选项:
-v, --version VERSION 指定要安装的 NGINX 版本
stable/mainline/1.24.0/...
默认:${DEFAULT_NGINX_VERSION}
-m, --mirror MIRROR 选择镜像源
aliyun/tsinghua/ustc/official
默认:${DEFAULT_MIRROR}
-f, --force 若已安装则强制重装
-d, --dry-run 演练模式:仅展示将执行的操作,不真正执行
--debug 开启调试日志
-h, --help 显示帮助信息
示例:
# 使用默认镜像USTC安装稳定版
sudo ${SCRIPT_NAME}
# 使用清华镜像安装指定版本
sudo ${SCRIPT_NAME} --version 1.24.0 --mirror tsinghua
# 强制重装并开启调试
sudo ${SCRIPT_NAME} --force --debug
# 演练模式预览
sudo ${SCRIPT_NAME} --dry-run
支持的 Ubuntu 版本:
${SUPPORTED_UBUNTU_VERSIONS[*]}
可用镜像源:
${!MIRROR_URLS[*]}
EOF
}
###
### Parse command line arguments
### @param args array Command line arguments
### @return 0 on success, 1 on invalid arguments
### @require none
###
parse_arguments() {
while [[ $# -gt 0 ]]; do
case $1 in
-v|--version)
NGINX_VERSION="$2"
shift 2
;;
-m|--mirror)
MIRROR_SOURCE="$2"
shift 2
;;
-f|--force)
FORCE_REINSTALL=true
shift
;;
-d|--dry-run)
DRY_RUN=true
shift
;;
--debug)
CURRENT_LOG_LEVEL="${LOG_LEVEL_DEBUG}"
shift
;;
-h|--help)
show_usage
exit 0
;;
*)
log_error "未知参数: $1"
show_usage
exit 1
;;
esac
done
return 0
}
###
### Main installation workflow
### @param none
### @return 0 on success, 1 on failure
### @require all functions above
###
main() {
log_info "========================================="
log_info "NGINX 安装脚本 v${SCRIPT_VERSION}"
log_info "========================================="
# > Step 1: Pre-flight checks
log_info "步骤 1/8执行预检查..."
check_root_privileges || return 1
validate_ubuntu_version || return 1
validate_mirror_source "${MIRROR_SOURCE}" || return 1
# > Step 2: Check mirror connectivity
log_info "步骤 2/8检查镜像连通性..."
if ! check_mirror_connectivity "${MIRROR_URLS[${MIRROR_SOURCE}]}"; then
log_warn "主镜像不可用,尝试回退方案..."
# > Fallback to official if mirror fails
if [[ "${MIRROR_SOURCE}" != "official" ]]; then
MIRROR_SOURCE="official"
log_info "已回退到官方源"
fi
fi
# > Step 3: Install dependencies
log_info "步骤 3/8安装依赖..."
install_dependencies || return 1
# > Step 4: Handle existing installation
log_info "步骤 4/8检查已安装版本..."
remove_existing_nginx || return 1
# > Step 5: Import GPG key
log_info "步骤 5/8导入 NGINX GPG 密钥..."
import_nginx_gpg_key "${MIRROR_SOURCE}" || return 1
# > Step 6: Configure repository
log_info "步骤 6/8配置 NGINX 软件源..."
configure_nginx_repository "${MIRROR_SOURCE}" || return 1
configure_apt_pinning || return 1
# > Step 7: Install NGINX
log_info "步骤 7/8安装 NGINX..."
install_nginx_package "${NGINX_VERSION}" || return 1
verify_nginx_installation || return 1
# > Step 8: Enable service
log_info "步骤 8/8启用 NGINX 服务..."
enable_nginx_service || return 1
log_info "========================================="
log_info "✓ NGINX 安装完成!"
log_info "========================================="
if [[ "${DRY_RUN}" == false ]]; then
log_info "服务状态: $(systemctl is-active nginx)"
log_info "NGINX 版本: $(nginx -v 2>&1 | cut -d'/' -f2)"
log_info ""
log_info "常用命令:"
log_info " 启动: sudo systemctl start nginx"
log_info " 停止: sudo systemctl stop nginx"
log_info " 重启: sudo systemctl restart nginx"
log_info " 状态: sudo systemctl status nginx"
log_info " 校验配置: sudo nginx -t"
fi
return 0
}
###############################################################################
# SCRIPT ENTRY POINT
###############################################################################
# ASCII Flow Diagram - Function Call Hierarchy
# ┌─────────────────────────────────────────────────────────────┐
# │ MAIN() │
# └──────────────────┬──────────────────────────────────────────┘
# │
# ┌─────────────┼─────────────┬──────────────┬─────────────┐
# │ │ │ │ │
# ▼ ▼ ▼ ▼ ▼
# ┌─────────┐ ┌──────────┐ ┌─────────┐ ┌────────────┐ ┌─────────┐
# │Pre-flight│ │Install │ │Import │ │Configure │ │Install │
# │Checks │ │Deps │ │GPG Key │ │Repository │ │NGINX │
# └─────────┘ └──────────┘ └─────────┘ └────────────┘ └─────────┘
# │ │ │ │ │
# ├─check_root_privileges │ │ │
# ├─validate_ubuntu_version │ │ │
# └─validate_mirror_source │ │ │
# │ │ │ │
# └─install_dependencies │ │
# │ │ │
# └─import_nginx_gpg_key │
# │ │
# ├─configure_nginx_repository
# └─configure_apt_pinning
# │
# ├─install_nginx_package
# └─verify_nginx_installation
# Parse command line arguments
parse_arguments "$@"
# Execute main workflow
main
exit $?

View File

@@ -1,26 +0,0 @@
#!/bin/bash
sudo yum install -y yum-utils
cat >/etc/yum.repos.d/nginx.repo<<EOF
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/8/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/8/x86_64/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
EOF
yum-config-manager --enable nginx-mainline
yum install -y nginx

View File

@@ -1,19 +0,0 @@
#!/bin/bash
sudo apt install -y curl gnupg2 ca-certificates lsb-release ubuntu-keyring
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
| sudo tee /etc/apt/preferences.d/99nginx
sudo apt update
sudo apt install -y nginx

View File

@@ -1,32 +0,0 @@
server {
listen 8889;
server_name localhost;
#允许跨域请求的域,*代表所有
add_header 'Access-Control-Allow-Origin' *;
#允许带上cookie请求
add_header 'Access-Control-Allow-Credentials' 'true';
#允许请求的方法,比如 GET/POST/PUT/DELETE
add_header 'Access-Control-Allow-Methods' *;
#允许请求的header
add_header 'Access-Control-Allow-Headers' *;
location /electronic {]
root /root/offline_map/;
autoindex on;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET,POST';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
}
location /satellite {
root /root/offline_map/;
autoindex on;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET,POST';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
}
# http://192.168.6.6:8889/electronic/{z}/{x}/{y}.png
# http://192.168.6.6:8889/satellite/{z}/{x}/{y}.png
# /root/offline_map/satellite /root/offline_map/electronic
}

View File

@@ -1,50 +0,0 @@
upstream proxy_server {
ip_hash;
server 192.168.1.4:30500;
server 192.168.1.3:30500;
server 192.168.1.5:30500;
}
server {
listen 8088;
server_name localhost;
location / {
proxy_pass http://proxy_server;
client_max_body_size 5120m;
client_body_buffer_size 5120m;
client_body_timeout 6000s;
proxy_send_timeout 10000s;
proxy_read_timeout 10000s;
proxy_connect_timeout 600s;
proxy_max_temp_file_size 5120m;
proxy_request_buffering on;
proxy_buffering off;
proxy_buffer_size 4k;
proxy_buffers 4 12k;
proxy_set_header Host fake-domain.sc-my-uav-260202.io;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /_AMapService/v4/map/styles {
set $args "$args&jscode=cf66cea95bdcdfcf8048456b36f357a1";
proxy_pass https://webapi.amap.com/v4/ap/styles;
}
location /_AMapService/ {
set $args "$args&jscode=cf66cea95bdcdfcf8048456b36f357a1";
proxy_pass https://restapi.amap.com/;
}
location /rtc/v1/ {
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
proxy_pass http://127.0.0.1:30985/rtc/v1/;
}
location ~ ^/\w*/actuator/ {
return 403;
}
}

View File

@@ -1,44 +0,0 @@
user root;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
use epoll;
worker_connections 65535;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
server_tokens off;
sendfile on;
send_timeout 1200;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 600;
types_hash_max_size 2048;
client_max_body_size 2048m;
client_body_buffer_size 2048m;
underscores_in_headers on;
proxy_send_timeout 600;
proxy_read_timeout 600;
proxy_connect_timeout 600;
proxy_buffer_size 128k;
proxy_buffers 8 256k;
include /etc/nginx/conf.d/*.conf;
}
stream {
include /etc/nginx/conf.d/stream/*.conf;
}

View File

@@ -1,17 +0,0 @@
version: '3'
services:
cmii-nginx:
image: 172.16.100.55:8033/cmii/nginx:1.27.0
volumes:
- /etc/nginx/conf.d:/etc/nginx/conf.d
- /etc/nginx/nginx.conf:/etc/nginx/nginx.conf
- /root/offline_map:/root/offline_map
ports:
- "8088:8088"
- "8089:8089"
restart: always
# mkdir -p /etc/nginx/conf.d
# touch /etc/nginx/nginx.conf

View File

@@ -1,45 +0,0 @@
#!/bin/bash
modify_ingress_nginx_host_network(){
echo "start to modify hostnetwork to false !"
kubectl patch daemonset nginx-ingress-controller -n ingress-nginx --patch '{"spec":{"template":{"spec":{"hostNetwork": false}}}}'
echo ""
kubectl get daemonset -n ingress-nginx nginx-ingress-controller -o jsonpath='{.spec.template.spec.hostNetwork}'
}
build_for_ingress_nginx_node_port(){
echo "start to write ingress nginx node port service !"
mkdir -p /root/wdd/install/
cat >>/root/wdd/install/k8s-ingress-nginx.yaml<<EOF
kind: Service
apiVersion: v1
metadata:
name: ingress-nginx-service
namespace: ingress-nginx
spec:
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
nodePort: 30500
- name: https
protocol: TCP
port: 443
targetPort: 443
nodePort: 31500
selector:
app: ingress-nginx
type: NodePort
sessionAffinity: None
EOF
echo ""
kubectl apply -f /root/wdd/install/k8s-ingress-nginx.yaml
}
modify_ingress_nginx_host_network
build_for_ingress_nginx_node_port

View File

@@ -2,7 +2,7 @@ export tenant_name=outside
export inner_master_ip=Master节点的内网IP
export minio_host_ip=MINIO的内网IP
mc alias set ${tenant_name} http://${minio_host_ip}:9000 cmii B#923fC7mk
mc alias set ${tenant_name} http://${minio_host_ip}:39000 cmii B#923fC7mk
mc mb ${tenant_name}/jadenq ${tenant_name}/tus ${tenant_name}/thumbnail ${tenant_name}/pub-cms ${tenant_name}/live-srs-hls/ ${tenant_name}/mission/ ${tenant_name}/surveillance ${tenant_name}/playback ${tenant_name}/tower ${tenant_name}/modelprocess ${tenant_name}/srs-hls ${tenant_name}/live-cluster-hls ${tenant_name}/geodata ${tenant_name}/ilm-detect ${tenant_name}/ilm-geodata

View File

@@ -31,11 +31,12 @@ kubectl delete -f k8s-nfs-test.yaml
cd /var/lib/docker/nfs_data
kubectl create ns sc-my-uav-260202
kubectl create ns cq-ws-260319
kubectl apply -f k8s-pvc.yaml
kubectl delete -f k8s-pvc.yaml
#飞行服务不需要
kubectl apply -f k8s-mongo.yaml
kubectl delete -f k8s-mongo.yaml
@@ -49,6 +50,7 @@ kubectl delete -f k8s-rabbitmq.yaml
kubectl apply -f k8s-redis.yaml
kubectl delete -f k8s-redis.yaml
# 监管平台不需要
kubectl apply -f k8s-influxdb.yaml
kubectl delete -f k8s-influxdb.yaml
@@ -57,7 +59,7 @@ kubectl delete -f k8s-mysql.yaml
----
doris部署
doris部署-监管
---
kubectl apply -f doris-pvc.yaml
kubectl apply -f doris-fe-configmap.yaml
@@ -76,12 +78,15 @@ kubectl delete -f doris-be-statusfulset.yaml
---
数据库初始化
参照 999-数据库脚本/a_rmdc-db-operator.sh
---
--- 飞服务不需要
kubectl apply -f k8s-nacos.yaml
kubectl delete -f k8s-nacos.yaml
vim k8s-configmap.yaml
kubectl apply -f k8s-configmap.yaml
kubectl delete -f k8s-configmap.yaml
@@ -90,6 +95,10 @@ vi k8s-ingress.yaml
kubectl apply -f k8s-ingress.yaml
kubectl delete -f k8s-ingress.yaml
vi k8s-minio.yaml
kubectl apply -f k8s-minio.yaml
kubectl delete -f k8s-minio.yaml
vi k8s-frontend.yaml
kubectl apply -f k8s-frontend.yaml
kubectl delete -f k8s-frontend.yaml
@@ -98,7 +107,6 @@ vi k8s-backend.yaml
kubectl apply -f k8s-backend.yaml
kubectl delete -f k8s-backend.yaml
kubectl -n kube-system get pods -o jsonpath='{.items[*].metadata.name}'
vi k8s-srs.yaml

View File

@@ -1,6 +1,6 @@
export harbor_host=192.168.1.4:8033
export harbor_host=harbor.wdd.io:8033
curl -X POST -u "admin:V2ryStr@ngPss" -H "authorization: Basic YWRtaW46VjJyeVN0ckBuZ1Bzcw==" -H "Content-Type: application/json" -d '{"project_name":"cmii","registry_id":null,"metadata":{"public":"true"},"storage_limit":-1}' http://$harbor_host/api/v2.0/projects

View File

@@ -1,154 +0,0 @@
#!/usr/bin/env bash
### 需要修改以下的内容 ###
#### 需要修改以下的内容 ###
#### 需要修改以下的内容 ###
cmlc_app_image_list="szga-0711.txt" # 需要修改版本
rancher_image_list="kubernetes-images-2.5.7-1.20.4.txt" # 一般不需要修改
middleware_image_list="middleware-images.txt" # 一般不需要修改
#DockerRegisterDomain="20.47.129.116:8033" # 需要根据实际修改
DockerRegisterDomain="172.31.2.7:8033/admin" # 需要根据实际修改
HarborAdminPass=V2ryStr@ngPss # 需要跟第一脚本中的密码保持一致
#### 需要修改以上的内容 ###
#### 需要修改以上的内容 ###
#### 需要修改以上的内容 ###
downloadAllNeededImages() {
while [[ $# > 0 ]]; do
pulled=""
while IFS= read -r i; do
[ -z "${i}" ] && continue
echo "开始下载:${i}"
if docker pull --platform linux/arm64 "${i}" >/dev/null 2>&1; then
echo "Image pull success: ${i}"
# 增加检查,镜像 的架构
docker image inspect ${i} | grep Architecture
pulled="${pulled} ${i}"
else
if docker inspect "${i}" >/dev/null 2>&1; then
pulled="${pulled} ${i}"
else
echo "Image pull failed: ${i}"
fi
fi
echo "-------------------------------------------------"
done <"${1}"
shift
done
}
downloadAllNeededImagesAndCompress() {
while [[ $# > 0 ]]; do
pulled=""
while IFS= read -r i; do
[ -z "${i}" ] && continue
echo "开始下载:${i}"
if docker pull --platform linux/arm64 "${i}" >/dev/null 2>&1; then
echo "Image pull success: ${i}"
# 增加检查,镜像 的架构
docker image inspect ${i} | grep Architecture
pulled="${pulled} ${i}"
else
if docker inspect "${i}" >/dev/null 2>&1; then
pulled="${pulled} ${i}"
else
echo "Image pull failed: ${i}"
fi
fi
echo "-------------------------------------------------"
done <"${1}"
compressPacName="$(echo ${1} | cut -d"." -f1).tar.gz"
echo "Creating ${compressPacName} with $(echo ${pulled} | wc -w | tr -d '[:space:]') images"
docker save $(echo ${pulled}) | gzip --stdout > ${compressPacName}
shift
done
echo "已经完成打包工作!"
}
pushRKEImageToHarbor(){
linux_images=()
while IFS= read -r i; do
[ -z "${i}" ] && continue
linux_images+=("${i}");
done < "${rancher_image_list}"
docker login -u admin -p ${HarborAdminPass} ${DockerRegisterDomain}
for i in "${linux_images[@]}"; do
[ -z "${i}" ] && continue
case $i in
*/*)
image_name="${DockerRegisterDomain}/${i}"
;;
*)
image_name="${DockerRegisterDomain}/rancher/${i}"
;;
esac
echo "开始镜像至私有仓库推送:${image_name}"
docker tag "${i}" "${image_name}"
docker push "${image_name}"
echo "-------------------------------------------------"
done
}
pushCMLCAPPImageToHarbor(){
app_images=()
while IFS= read -r i; do
[ -z "${i}" ] && continue
app_images+=("${i}");
done < "${cmlc_app_image_list}"
docker login -u admin -p ${HarborAdminPass} ${DockerRegisterDomain}
for app in "${app_images[@]}"; do
[ -z "${app}" ] && continue
image_name="${DockerRegisterDomain}/$(echo ${app} | cut -d"/" -f2-8)"
echo "开始镜像至私有仓库推送:${image_name}"
docker tag "${app}" "${image_name}"
docker push "${image_name}"
echo "-------------------------------------------------"
done
}
pushMiddlewareImageToHarbor(){
middleware_image=()
while IFS= read -r i; do
[ -z "${i}" ] && continue
middleware_image+=("${i}");
done < "${middleware_image_list}"
docker login -u admin -p ${HarborAdminPass} ${DockerRegisterDomain}
for app in "${middleware_image[@]}"; do
[ -z "${app}" ] && continue
case ${app} in
*/*/*)
image_name="${DockerRegisterDomain}/cmii/$(echo "${app}" | cut -d"/" -f3-8)"
;;
*/*)
image_name="${DockerRegisterDomain}/cmii/$(echo "${app}" | cut -d"/" -f2-8)"
;;
esac
echo "开始镜像至私有仓库推送:${image_name}"
docker tag "${app}" "${image_name}"
docker push "${image_name}"
echo "-------------------------------------------------"
done
}
# downloadAllNeededImagesAndCompress "${middleware_image_list}"
#downloadAllNeededImages "${rancher_image_list}"
#pushRKEImageToHarbor
#pushCMLCAPPImageToHarbor
pushMiddlewareImageToHarbor

View File

@@ -1,154 +0,0 @@
#!/usr/bin/env bash
### 需要修改以下的内容 ###
#### 需要修改以下的内容 ###
#### 需要修改以下的内容 ###
cmlc_app_image_list="szga-0711.txt" # 需要修改版本
rancher_image_list="kubernetes-images-2.5.7-1.20.4.txt" # 一般不需要修改
middleware_image_list="middleware-images.txt" # 一般不需要修改
#DockerRegisterDomain="20.47.129.116:8033" # 需要根据实际修改
DockerRegisterDomain="172.10.125.92:8033" # 需要根据实际修改
HarborAdminPass=V2ryStr@ngPss # 需要跟第一脚本中的密码保持一致
#### 需要修改以上的内容 ###
#### 需要修改以上的内容 ###
#### 需要修改以上的内容 ###
downloadAllNeededImages() {
while [[ $# > 0 ]]; do
pulled=""
while IFS= read -r i; do
[ -z "${i}" ] && continue
echo "开始下载:${i}"
if docker pull "${i}" >/dev/null 2>&1; then
echo "Image pull success: ${i}"
# 增加检查,镜像 的架构
docker image inspect ${i} | grep Architecture
pulled="${pulled} ${i}"
else
if docker inspect "${i}" >/dev/null 2>&1; then
pulled="${pulled} ${i}"
else
echo "Image pull failed: ${i}"
fi
fi
echo "-------------------------------------------------"
done <"${1}"
shift
done
}
downloadAllNeededImagesAndCompress() {
while [[ $# > 0 ]]; do
pulled=""
while IFS= read -r i; do
[ -z "${i}" ] && continue
echo "开始下载:${i}"
if docker pull "${i}" >/dev/null 2>&1; then
echo "Image pull success: ${i}"
# 增加检查,镜像 的架构
docker image inspect ${i} | grep Architecture
pulled="${pulled} ${i}"
else
if docker inspect "${i}" >/dev/null 2>&1; then
pulled="${pulled} ${i}"
else
echo "Image pull failed: ${i}"
fi
fi
echo "-------------------------------------------------"
done <"${1}"
compressPacName="$(echo ${1} | cut -d"." -f1).tar.gz"
echo "Creating ${compressPacName} with $(echo ${pulled} | wc -w | tr -d '[:space:]') images"
docker save $(echo ${pulled}) | gzip --stdout > ${compressPacName}
shift
done
echo "已经完成打包工作!"
}
pushRKEImageToHarbor(){
linux_images=()
while IFS= read -r i; do
[ -z "${i}" ] && continue
linux_images+=("${i}");
done < "${rancher_image_list}"
docker login -u admin -p ${HarborAdminPass} ${DockerRegisterDomain}
for i in "${linux_images[@]}"; do
[ -z "${i}" ] && continue
case $i in
*/*)
image_name="${DockerRegisterDomain}/${i}"
;;
*)
image_name="${DockerRegisterDomain}/rancher/${i}"
;;
esac
echo "开始镜像至私有仓库推送:${image_name}"
docker tag "${i}" "${image_name}"
docker push "${image_name}"
echo "-------------------------------------------------"
done
}
pushCMLCAPPImageToHarbor(){
app_images=()
while IFS= read -r i; do
[ -z "${i}" ] && continue
app_images+=("${i}");
done < "${cmlc_app_image_list}"
docker login -u admin -p ${HarborAdminPass} ${DockerRegisterDomain}
for app in "${app_images[@]}"; do
[ -z "${app}" ] && continue
image_name="${DockerRegisterDomain}/$(echo ${app} | cut -d"/" -f2-8)"
echo "开始镜像至私有仓库推送:${image_name}"
docker tag "${app}" "${image_name}"
docker push "${image_name}"
echo "-------------------------------------------------"
done
}
pushMiddlewareImageToHarbor(){
middleware_image=()
while IFS= read -r i; do
[ -z "${i}" ] && continue
middleware_image+=("${i}");
done < "${middleware_image_list}"
docker login -u admin -p ${HarborAdminPass} ${DockerRegisterDomain}
for app in "${middleware_image[@]}"; do
[ -z "${app}" ] && continue
case ${app} in
*/*/*)
image_name="${DockerRegisterDomain}/cmii/$(echo "${app}" | cut -d"/" -f3-8)"
;;
*/*)
image_name="${DockerRegisterDomain}/cmii/$(echo "${app}" | cut -d"/" -f2-8)"
;;
esac
echo "开始镜像至私有仓库推送:${image_name}"
docker tag "${app}" "${image_name}"
docker push "${image_name}"
echo "-------------------------------------------------"
done
}
downloadAllNeededImagesAndCompress "${middleware_image_list}"
#downloadAllNeededImages "${rancher_image_list}"
#pushRKEImageToHarbor
#pushCMLCAPPImageToHarbor
#pushMiddlewareImageToHarbor

View File

@@ -1,168 +0,0 @@
#!/bin/bash
all_image_list_txt="all-cmii-image-list.txt" # 需要修改版本
gzip_image_list_txt="all-gzip-image-list.txt" # 一般不需要修改
oss_prefix_url="https://oss.demo.uavcmlc.com/cmlc-installation"
local_gzip_path="/root/octopus-image"
DockerRegisterDomain="192.168.0.2:8033" # 需要根据实际修改
HarborAdminPass=V2ryStr@ngPss # 需要跟第一脚本中的密码保持一致
print_green() {
echo -e "\033[32m${1}\033[0m"
echo ""
}
print_red() {
echo -e "\033[31m${1}\033[0m"
echo ""
}
Download_Load_Tag_Upload() {
print_green "[DLTU] - start !"
while [[ $# -gt 0 ]]; do
case "$1" in
rke)
# print_green "download rke "
local_gzip_path="$local_gzip_path/rke"
mkdir -p ${local_gzip_path}
oss_prefix_url="$oss_prefix_url/rke/"
dltu
shift # past argument
;;
middle)
local_gzip_path="$local_gzip_path/middle"
mkdir -p $local_gzip_path
oss_prefix_url="$oss_prefix_url/middle/"
dltu
shift # past argument
;;
cmii)
local_gzip_path="$local_gzip_path/uavms-2.0"
mkdir -p $local_gzip_path
oss_prefix_url="$oss_prefix_url/uavms-2.0/"
dltu
shift # past argument
;;
*)
# unknown option
print_red "bad arguments"
;;
esac
done
}
dltu() {
print_green "download all image name list and gzip file list!"
cd $local_gzip_path || exit
rm $all_image_list_txt
rm $gzip_image_list_txt
wget "$oss_prefix_url$all_image_list_txt"
wget "$oss_prefix_url$gzip_image_list_txt"
docker login -u admin -p ${HarborAdminPass} ${DockerRegisterDomain}
echo ""
while IFS= read -r i; do
[ -z "${i}" ] && continue
echo "download gzip file =>: $oss_prefix_url${i}"
if wget "$oss_prefix_url${i}" >/dev/null 2>&1; then
echo "Gzip file download success : ${i}"
image_full_name=$(docker load -i ${i} | head -n1 |awk -F': ' '{print $2}')
app_name=$(echo "$image_full_name" | sed 's|.*/||g')
echo "extract short name is $app_name"
if echo $image_full_name | grep -q "rancher"
then
print_green "tag image to => $DockerRegisterDomain/rancher/$app_name"
docker tag ${image_full_name} $DockerRegisterDomain/rancher/$app_name
docker push $DockerRegisterDomain/rancher/$app_name
else
print_green "tag image to => $DockerRegisterDomain/cmii/$app_name"
docker tag ${image_full_name} $DockerRegisterDomain/cmii/$app_name
docker push $DockerRegisterDomain/cmii/$app_name
fi
else
print_red "Gzip file download FAILED : ${i}"
fi
echo "-------------------------------------------------"
done <"${gzip_image_list_txt}"
shift
}
Load_Tag_Upload(){
print_green "[LTU] - start to load image from offline !"
while [[ $# -gt 0 ]]; do
case "$1" in
rke)
# print_green "download rke "
local_gzip_path="$local_gzip_path/rke"
mkdir -p ${local_gzip_path}
oss_prefix_url="$oss_prefix_url/rke/"
ltu
shift # past argument
;;
middle)
local_gzip_path="$local_gzip_path/middle"
mkdir -p $local_gzip_path
oss_prefix_url="$oss_prefix_url/middle/"
ltu
shift # past argument
;;
cmii)
local_gzip_path="$local_gzip_path/cmii"
mkdir -p $local_gzip_path
oss_prefix_url="$oss_prefix_url/cmii/"
ltu
shift # past argument
;;
*)
# unknown option
print_red "bad arguments"
;;
esac
done
}
ltu(){
all_file_list=$(find $local_gzip_path -type f -name "*.tar.gz")
for file in $all_file_list; do
echo "offline gzip file is => : $file"
image_full_name=$(docker load -i ${file} | head -n1 |awk -F': ' '{print $2}')
docker login -u admin -p ${HarborAdminPass} ${DockerRegisterDomain}
app_name=$(echo "$image_full_name" | sed 's|.*/||g')
echo "extract short name is $app_name"
if echo $image_full_name | grep -q "rancher"
then
print_green "tag image to => $DockerRegisterDomain/rancher/$app_name"
docker tag ${image_full_name} $DockerRegisterDomain/rancher/$app_name
docker push $DockerRegisterDomain/rancher/$app_name
else
print_green "tag image to => $DockerRegisterDomain/cmii/$app_name"
docker tag ${image_full_name} $DockerRegisterDomain/cmii/$app_name
docker push $DockerRegisterDomain/cmii/$app_name
fi
done
}
test(){
app_name=$(echo "nginx:latest" | sed 's|.*/||g')
echo "extract short name is $app_name"
}
# test
Download_Load_Tag_Upload "rke"
# Load_Tag_Upload "cmii"

View File

@@ -0,0 +1,22 @@
rancher/mirrored-coreos-etcd:v3.5.12
rancher/rke-tools:v0.1.114
rancher/mirrored-k8s-dns-kube-dns:1.23.0
rancher/mirrored-k8s-dns-dnsmasq-nanny:1.23.0
rancher/mirrored-k8s-dns-sidecar:1.23.0
rancher/mirrored-cluster-proportional-autoscaler:v1.9.0
rancher/mirrored-coredns-coredns:1.11.1
rancher/mirrored-cluster-proportional-autoscaler:v1.9.0
rancher/mirrored-k8s-dns-node-cache:1.23.0
rancher/hyperkube:v1.30.14-rancher1
rancher/mirrored-flannel-flannel:v0.25.1
rancher/flannel-cni:v1.4.1-rancher1
rancher/mirrored-calico-node:v3.28.1
rancher/calico-cni:v3.28.1-rancher1
rancher/mirrored-calico-kube-controllers:v3.28.1
rancher/mirrored-calico-ctl:v3.28.1
rancher/mirrored-calico-pod2daemon-flexvol:v3.28.1
rancher/mirrored-pause:3.7
rancher/nginx-ingress-controller:nginx-1.11.5-rancher1
rancher/mirrored-nginx-ingress-controller-defaultbackend:1.5-rancher2
rancher/mirrored-ingress-nginx-kube-webhook-certgen:v1.5.2
rancher/mirrored-metrics-server:v0.7.1

View File

@@ -0,0 +1,13 @@
bitnamilegacy/redis:6.2.14-debian-11-r19
bitnamilegacy/redis:7.4.3-debian-12-r0
bitnamilegacy/mysql:8.1.0-debian-11-r42
bitnamilegacy/os-shell:12-debian-12-r51
bitnamilegacy/rabbitmq:3.13.7-debian-12-r5
ossrs/srs:v5.0.195
emqx/emqx:5.8.8
bitnamilegacy/influxdb:2.7.11-debian-12-r19
minio/minio:RELEASE.2023-06-02T23-17-26Z
kubernetesui/dashboard:v2.7.0
kubernetesui/metrics-scraper:v1.0.9
dyrnq/nfs-subdir-external-provisioner:v4.0.2
nginx:1.28.2

View File

@@ -0,0 +1,29 @@
我现在需要有一个镜像下载的脚本,有如下的要求
1. 通过参数传递docker镜像的文件 txt
1. docker镜像名文件约定为每行代表一个镜像的全名称
2. 脚本需要依次读取txt文件中的镜像名
3. 脚本具备三大类的功能
1. 下载镜像
2. 压缩镜像
3. 重新打包镜像,上传镜像
4. 下载镜像
1. 可以指定下载的CPU架构下载成功之后 需要inpsect提示镜像的架构
2. 可以附加下载的镜像加速前缀,如果附带 下载成功之后需要重新Tag为txt中的镜像名
3. 需要总结提示,下载失败的镜像
5. 压缩镜像
1. 需要首先判定每个镜像是否全部存在
1. 如果全部存在,则继续执行下一步
2. 如果存在不全,则退出脚本给出提示,显示所有缺失的镜像
3. 同样需要检测镜像的CPU架构是否正确
4. 可以通过--force强行跳过检查
2. 可以指定将每个镜像单独压缩为tar.gz文件
3. 可以指定将所有镜像打包为一个tar.gz文件
4. 默认为统一压缩
5. 压缩镜像需要使用多线程压缩充分利用CPU的性能
6. 重新打包镜像,上传镜像
1. 指定目标Harbor的地址
2. Harbor地址为 IP:PORT
3. Harbor的用户名和密码
4. Harbor的用户名 密码 PORT都有默认值可以写入脚本中

View File

@@ -1,9 +0,0 @@
#!/bin/bash
rm -rf *.tar.gz
rm -rf 2023*.txt
for item in $(mc ls demo/cmlc-installation/tmp/ | awk '{print$6}')
do
mc rm demo/cmlc-installation/tmp/"${item}"
done

View File

@@ -1,438 +0,0 @@
#!/bin/bash
# 约定内容
NeedUploadFolder=99
IsUpload=99
UploadImageName=""
ImageListName=""
ImageTarName=""
ImageName=""
ImageTag=""
InnerIPv4CIDR=""
InnerIPv6CIDR=""
InnerIPv4=""
InnerIPv6=""
CmiiImagePrefix="harbor.cdcyy.com.cn/cmii/"
OSS_URL="https://oss.demo.uavcmlc.com/cmlc-installation/tmp/"
Custom_Client_Harbor="REPLACE:8033"
app_name=""
new_tag=""
harbor_host=""
namespace="xmyd"
#######################################
# description
# Globals:
# ImageName
# ImageTag
# ImageTarName
# RANDOM
# UploadImageName
# Arguments:
# None
#######################################
get_image_tar_name() {
# harbor.cdcyy.com.cn/cmii/cmii-uav-oauth:4.1.6
ImageName=$(echo $UploadImageName | cut -d ":" -f1 | cut -d"/" -f3)
ImageTag=$(echo $UploadImageName | cut -d ":" -f2)
local currentDate=$(date +'%Y-%m-%d')
local random_number=$((RANDOM % 900 + 100))
ImageTarName="$ImageName=$ImageTag=$currentDate=$random_number.tar.gz"
}
#######################################
# description
# Globals:
# ImageName
# ImageTag
# ImageTarName
# UploadImageName
# Arguments:
# None
#######################################
get_image_name_from_tar() {
if [[ $ImageTarName == cmlc* ]]; then
# 兼容octopus-agent的模式
# cmlc=cmii=cmii-uav-busybox=0326.tar.gz
# rancher=rancher=cmii-uav-busybox=0326.tar.gz
# 使用${variable%.pattern}进行后缀删除
ImageName=$(echo $image_name | cut -d "=" -f3)
local tagWithSuffix=$(echo $image_name | cut -d "=" -f4)
ImageTag="${tagWithSuffix%.tar.gz}"
UploadImageName="$ImageName:$ImageTag"
return
fi
# cmii-uav-oauth_4.1.6-0918_20230918_123.tar.gz
ImageName=$(echo $ImageTarName | cut -d "=" -f1)
ImageTag=$(echo $ImageTarName | cut -d"=" -f2)
UploadImageName="$ImageName:$ImageTag"
}
# 获取服务器的公网IP地址
get_Internal_IP_CIDR() {
local interface_prefix=("[[:space:]]eth[0-9]{1,2}" "[[:space:]]ens[0-9]{1,3}" "[[:space:]]eno[0-9]{1,3}" "[[:space:]]enp[0-9]{1,2}")
local real_interface="eth90"
for interface in "${interface_prefix[@]}"; do
echo $(ip link show) | grep -oE ${interface} | head -1
if [[ $? -eq 0 ]]; then
real_interface=$(echo $(ip link show) | grep -oE ${interface} | head -1 | cut -d" " -f2)
echo "当前主机的真实内网网卡为 => [$real_interface]"
break
fi
done
# 提取IPv4地址CIDR格式
local ipv4_regex="inet[[:space:]](25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/[0-9]{1,2}"
# 提取IPv6地址CIDR格式
local ipv6_regex="inet6[[:space:]]([0-9a-fA-F]{0,4}(:[0-9a-fA-F]{0,4}){1,7})\/[0-9]{1,3}"
# 查找IPv4地址
local inner_ipv4=$(echo $(ip addr show $real_interface) | grep -oE $ipv4_regex | cut -d" " -f2)
InnerIPv4CIDR=$inner_ipv4
echo "Interface: $real_interface, IPv4 Address: $inner_ipv4"
# 查找IPv6地址
local inner_ipv6=$(echo $(ip addr show $real_interface) | grep -oE $ipv6_regex | cut -d" " -f2)
InnerIPv6CIDR=$inner_ipv6
echo "Interface: $real_interface, IPv4 Address: $inner_ipv6"
}
#######################################
# description
# Globals:
# InnerIPv4
# InnerIPv4CIDR
# InnerIPv6
# InnerIPv6CIDR
# Arguments:
# None
#######################################
get_Internal_IP() {
get_Internal_IP_CIDR
InnerIPv4=$(echo $InnerIPv4CIDR | cut -d "/" -f1)
InnerIPv6=$(echo $InnerIPv6CIDR | cut -d "/" -f1)
echo "服务器的内网IPv4地址为 $InnerIPv4"
echo "服务器的内网IPv6地址为 $InnerIPv6"
}
parse_args(){
if [ "$1" == "" ]; then
echo "no zip file in error!"
exit 233
fi
local image_name="$1"
if [[ $image_name == cmlc* ]]; then
# 兼容octopus-agent的模式
# cmlc=cmii=cmii-uav-busybox=0326.tar.gz
# rancher=rancher=cmii-uav-busybox=0326.tar.gz
app_name=$(echo $image_name | cut -d "=" -f3)
local tagWithSuffix=$(echo $image_name | cut -d "=" -f4)
new_tag="${tagWithSuffix%.tar.gz}"
return
fi
# 本脚本的模式
# cmii-uav-surveillance=5.2.0-27031-cqga=2024-03-04=573.tar.gz
# cmii-uav-mqtthandler=5.4.0-031201=2024-03-12=138.tar.gz
app_name=$(echo $image_name | cut -d "=" -f1)
new_tag=$(echo $image_name | cut -d "=" -f2)
}
update_image_tag(){
if [ "$new_tag" == "" ]; then
echo "new tag error!"
exit 233
fi
echo ""
echo "[update_image_tag] - start to update => ${harbor_host}/cmii/$app_name:${new_tag}"
echo ""
local image_prefix=$(kubectl -n ${namespace} get deployment "${app_name}" -o=jsonpath='{.spec.template.spec.containers[*].image}' | cut -d":" -f1)
echo "image grep is => ${image_prefix}"
echo "start to update ${namespace} ${app_name} to ${new_tag} !"
echo ""
kubectl -n ${namespace} patch deployment "${app_name}" -p "{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\":\"${app_name}\",\"image\": \"${harbor_host}/cmii/$app_name:${new_tag}\"}]}}}}"
echo ""
echo "start to wait for 3 seconds!"
sleep 3
local image_new=$(kubectl -n ${namespace} get deployment "${app_name}" -o=jsonpath='{.spec.template.spec.containers[*].image}')
echo ""
echo "new image are => $image_new"
echo ""
}
#######################################
# description
# Globals:
# _m_opts
# Arguments:
# None
#######################################
_math() {
_m_opts="$@"
printf "%s" "$((_m_opts))"
}
# 前文内容
while [[ $# -gt 0 ]]; do
case "$1" in
-fu | --fileupload)
NeedUploadFolder=1
ImageListName=${2}
shift # past argument
;;
-fd | --filedownload)
NeedUploadFolder=2
ImageListName=${2}
shift # past argument
;;
-u | --upload)
IsUpload=1
UploadImageName="${2}"
shift # past argument
;;
-d | --download)
IsUpload=2
ImageTarName="${2}"
shift # past argument
;;
-h | --harbor)
Custom_Client_Harbor="${2}"
shift # past argument
;;
*)
# unknown option
;;
esac
shift # past argument or value
done
#######################################
# description
# Globals:
# ImageTarName
# UploadImageName
# Arguments:
# None
#######################################
Download_Compress_UploadOss() {
# upload
echo "【上传】 - 需要处理的镜像名称为 => $UploadImageName"
echo ""
echo "【上传】 - 开始下载镜像!"
echo ""
if docker pull "${UploadImageName}" >/dev/null 2>&1; then
echo "下载-镜像下载成功! => $UploadImageName"
else
if docker inspect "${UploadImageName}" >/dev/null 2>&1; then
echo "下载-镜像已经存在 => $UploadImageName"
else
echo ""
echo "下载-镜像下载 失败! => $UploadImageName"
echo "下载-镜像下载 失败! => $UploadImageName"
echo ""
return 233
fi
fi
echo ""
get_image_tar_name
echo "【上传】 - 将要把镜像压缩为 => $ImageTarName"
docker save $UploadImageName | gzip --stdout >${ImageTarName}
echo "【上传】 - 压缩成功 $(ls | grep ${ImageTarName})"
echo""
echo "【上传】 - 开始上传至OSS中!"
mc cp ./${ImageTarName} demo/cmlc-installation/tmp/
echo "【上传】 - 上传OSS成功 => $(mc ls demo/cmlc-installation/tmp/ | grep ${ImageTarName})"
echo""
}
#######################################
# description
# Globals:
# CmiiImagePrefix
# ImageTarName
# InnerIPv4
# OSS_URL
# UploadImageName
# custom_prefix
# Arguments:
# None
# Returns:
# <unknown> ...
#######################################
Download_Load_Tag_UploadHarbor_Update() {
# 更加方便
# Check if the variable starts with "harbor"
# if [[ $ImageTarName != harbor* ]]; then
# ImageTarName="$CmiiImagePrefix$ImageTarName"
# fi
echo "【下载】 - 需要处理的压缩包名称为 => $ImageTarName"
echo "【下载】 - 开始下载 ↓"
wget "$OSS_URL$ImageTarName"
if [[ $? -ne 0 ]]; then
echo "【下载】- 下载镜像失败!退出!"
return
fi
echo ""
echo "【下载】 - 开始解压压缩包 "
docker load <"${ImageTarName}"
echo ""
get_Internal_IP
echo "【下载】 - 开始上传镜像到本地的镜像仓库中 => $InnerIPv4:8033 "
custom_prefix="$InnerIPv4:8033/cmii/"
echo ""
get_image_name_from_tar
echo "【下载】 - 解析得到的 私有镜像地址为 => $custom_prefix$UploadImageName"
docker tag "$CmiiImagePrefix${UploadImageName}" "$custom_prefix$UploadImageName"
echo "【下载】 - 开始上传镜像到私有仓库 ↓"
docker login -u admin -p V2ryStr@ngPss "$InnerIPv4:8033"
echo ""
echo "【下载】 - 开始推送到私有仓库! "
docker push "$custom_prefix$UploadImageName"
echo ""
echo ""
echo ""
echo "【更新】-开始更新镜像名称!"
harbor_host="$InnerIPv4:8033"
parse_args $ImageTarName
update_image_tag
}
if [[ $NeedUploadFolder == 1 ]]; then
# 上传的是一个目录
echo "【上传】 - 上传的文件目录为 => ${ImageListName}"
currentDate=$(date +'%Y-%m-%d')
random_number=$((RANDOM % 900 + 100))
tar_image_txt_file="$currentDate-$random_number.txt"
echo "【上传】 - 复制文件目录为临时文件 => $tar_image_txt_file"
touch $tar_image_txt_file
echo ""
echo ""
while IFS= read -r i; do
[ -z "${i}" ] && continue
UploadImageName=${i}
Download_Compress_UploadOss || return ?
# 写入压缩文件名称
echo "$ImageTarName" >>"$tar_image_txt_file"
echo "-------------------------------------------------"
done <"${ImageListName}"
echo ""
echo "【上传】 - 上传压缩文件名称列表至OSS中 "
mc cp ./"$tar_image_txt_file" demo/cmlc-installation/tmp/
echo "【上传】 - 上传OSS成功 => $(mc ls demo/cmlc-installation/tmp/ | grep "${tar_image_txt_file}")"
echo ""
echo "【上传】 - 请在目标Master主机执行如下命令 ↓↓↓↓↓↓"
echo ""
echo ""
echo "source <(curl -sL https://b2.107421.xyz/image-sync.sh) -fd "$OSS_URL$tar_image_txt_file""
echo ""
echo ""
elif [[ $NeedUploadFolder == 2 ]]; then
# file download
echo "【下载】- 需要下载的压缩列表文件为 => $ImageListName"
wget ${ImageListName}
tar_image_txt_file=$(echo ${ImageListName} | cut -d"/" -f6)
image_count=0
while IFS= read -r i; do
[ -z "${i}" ] && continue
ImageTarName=${i}
Download_Load_Tag_UploadHarbor_Update
image_count="$(_math "$image_count" + 1)"
echo "-------------------------------------------------"
done <"${tar_image_txt_file}"
echo ""
echo "【下载】 - 请等待流程结束 ↓"
_sleep_c="500"
for (( i=1; i<$image_count; i++ )) ; do
_sleep_c="$(_math "$_sleep_c" + 500)"
done
echo "【下载】 - 共有 【 $image_count 】个镜像, 等待上传结束 => $_sleep_c"
while [ "$_sleep_c" -ge "0" ]; do
printf "\r \r"
printf -- "%b" "$_sleep_c"
_sleep_c="$(_math "$_sleep_c" - 1)"
sleep 1
done
printf "\r"
fi
if [[ $IsUpload == 1 ]]; then
# upload a image
Download_Compress_UploadOss || return ?
echo "【上传】 - 请在目标Master主机执行如下命令 ↓↓↓↓↓↓"
echo ""
echo ""
echo "source <(curl -sL https://b2.107421.xyz/image-sync.sh) -d $ImageTarName"
echo ""
echo ""
Client_Harbor_Address="$Custom_Client_Harbor/cmii/$ImageName:$ImageTag"
echo "【上传】 - 手动命令执行如下, 目标镜像全程地址为 => $Client_Harbor_Address"
echo ""
echo "wget $OSS_URL$ImageTarName && docker load < $ImageTarName && docker tag ${UploadImageName} $Client_Harbor_Address && docker push $Client_Harbor_Address"
echo ""
echo ""
elif [[ $IsUpload == 2 ]];then
# download a image
Download_Load_Tag_UploadHarbor_Update
echo "【下载】 - 请等待流程结束 ↓"
_sleep_c="500"
while [ "$_sleep_c" -ge "0" ]; do
printf "\r \r"
printf -- "%b" "$_sleep_c"
_sleep_c="$(_math "$_sleep_c" - 1)"
sleep 1
done
printf "\r"
fi

View File

@@ -1,15 +0,0 @@
# https://dl.min.io/client/mc/release/windows-amd64/mc.exe
& "C:\Users\makn\Downloads\mc.exe" alias set uav-demo https://oss.demo.uavcmlc.com cmii B#923fC7mk
& "C:\Users\makn\Downloads\mc.exe" ls uav-demo/cmlc-installation/6.2.0-szgz-arm/ | ForEach-Object {
$item=($_.Split()[-1])
Write-Host "start to download $item "
& "C:\Users\makn\Downloads\mc.exe" get uav-demo/cmlc-installation/6.2.0-szgz-arm/$item "D:\Desktop\cmii\cmii\"
Write-Host ""
}

View File

@@ -1,69 +0,0 @@
function DownloadFileInChunks {
param (
[string]$url,
[string]$destinationFile,
[int]$chunkSizeGB = 1
)
# 将 GB 转换为字节
$chunkSize = $chunkSizeGB * 1024 * 1024 * 1024
# 获取文件的总大小
$response = Invoke-WebRequest -Uri $url -Method Head
$totalSize = [long]$response.Headers["Content-Length"]
# 计算分段数量
$chunks = [math]::Ceiling($totalSize / $chunkSize)
# 下载每一段
for ($i = 0; $i -lt $chunks; $i++) {
$start = $i * $chunkSize
$end = [math]::Min($start + $chunkSize - 1, $totalSize - 1)
$headers = @{
"Range" = "bytes=$start-$end"
}
$chunkResponse = Invoke-WebRequest -Uri $url -Headers $headers -Method Get
$chunkData = $chunkResponse.Content
# 以追加模式写入文件
[System.IO.File]::WriteAllBytes($destinationFile, $chunkData)
}
Write-Host "dowonload ok"
}
# 指定文件路径
$filePath = "D:\CmiiDeployOffline\ZheJiangErJiPingTai\all-gzip-image-list.txt"
# 指定下载的目标目录
$destinationFolder = "D:\CmiiDeployOffline\ZheJiangErJiPingTai"
$oss_prefix_url="https://oss.demo.uavcmlc.com/cmlc-installation/6.1.1/"
# 创建目标目录(如果不存在)
#if (-not (Test-Path $destinationFolder)) {
# New-Item -ItemType Directory -Path $destinationFolder
#}
#Write-Host "[DLTU] - 开始下载镜像压缩文件"
Write-Host ""
# 读取文件并下载每一行的 URL
Get-Content $filePath | ForEach-Object {
$url = $_
Write-Host "start to download $oss_prefix_url$url"
$fileName = Join-Path $destinationFolder $url
Write-Host $fileName
DownloadFileInChunks -url $oss_prefix_url$url -destinationFile $fileName -chunkSizeGB 0.1
# Invoke-WebRequest -Uri $oss_prefix_url$url -OutFile $fileName
Write-Host ""
}

View File

@@ -1,63 +0,0 @@
busybox
rancher/backup-restore-operator:v1.0.3
rancher/calico-cni:v3.17.2
rancher/calico-ctl:v3.17.2
rancher/calico-kube-controllers:v3.17.2
rancher/calico-pod2daemon-flexvol:v3.17.2
rancher/cis-operator:v1.0.3
rancher/cluster-proportional-autoscaler:1.7.1
rancher/coredns-coredns:1.8.0
rancher/coreos-etcd:v3.4.14-rancher1
rancher/coreos-kube-state-metrics:v1.9.7
rancher/coreos-prometheus-config-reloader:v0.39.0
rancher/coreos-prometheus-operator:v0.39.0
rancher/externalip-webhook:v0.1.6
rancher/flannel-cni:v0.3.0-rancher6
rancher/coreos-flannel:v0.13.0-rancher1
rancher/fleet-agent:v0.3.4
rancher/fleet:v0.3.4
rancher/fluentd:v0.1.24
rancher/grafana-grafana:7.1.5
rancher/hyperkube:v1.20.4-rancher1
rancher/jimmidyson-configmap-reload:v0.3.0
rancher/k8s-dns-dnsmasq-nanny:1.15.2
rancher/k8s-dns-kube-dns:1.15.2
rancher/k8s-dns-node-cache:1.15.13
rancher/k8s-dns-sidecar:1.15.2
rancher/klipper-lb:v0.1.2
rancher/kube-api-auth:v0.1.4
rancher/kubectl:v1.20.4
rancher/kubernetes-external-dns:v0.7.3
rancher/cluster-proportional-autoscaler:1.8.1
rancher/library-busybox:1.31.1
rancher/library-busybox:1.32.1
rancher/library-nginx:1.19.2-alpine
rancher/library-traefik:1.7.19
rancher/local-path-provisioner:v0.0.11
rancher/local-path-provisioner:v0.0.14
rancher/local-path-provisioner:v0.0.19
rancher/log-aggregator:v0.1.7
rancher/istio-kubectl:1.5.10
rancher/metrics-server:v0.4.1
rancher/configmap-reload:v0.3.0-rancher4
rancher/nginx-ingress-controller-defaultbackend:1.5-rancher1
rancher/nginx-ingress-controller:nginx-0.43.0-rancher1
rancher/opa-gatekeeper:v3.1.0-beta.7
rancher/openzipkin-zipkin:2.14.2
rancher/pause:3.2
rancher/plugins-docker:18.09
rancher/prom-alertmanager:v0.21.0
rancher/prom-node-exporter:v1.0.1
rancher/prom-prometheus:v2.18.2
rancher/prometheus-auth:v0.2.1
rancher/rancher-agent:v2.5.7
rancher/rancher-webhook:v0.1.0-beta9
rancher/rancher:v2.5.7
rancher/rke-tools:v0.1.72
rancher/security-scan:v0.1.14
rancher/security-scan:v0.2.2
rancher/shell:v0.1.6
rancher/sonobuoy-sonobuoy:v0.16.3
rancher/system-upgrade-controller:v0.6.2

View File

@@ -1,19 +0,0 @@
bitnami/redis:6.2.14-debian-11-r1
bitnami/mysql:8.1.0-debian-11-r42
simonrupf/chronyd:0.4.3
bitnami/bitnami-shell:11-debian-11-r136
bitnami/rabbitmq:3.11.26-debian-11-r2
ossrs/srs:v5.0.195
emqx/emqx:4.4.19
emqx/emqx:5.5.1
nacos/nacos-server:v2.1.2-slim
mongo:5.0
bitnami/minio:2023.5.4
kubernetesui/dashboard:v2.0.1
kubernetesui/metrics-scraper:v1.0.4
nginx:1.24.0
redis:6.0.20-alpine
dyrnq/nfs-subdir-external-provisioner:v4.0.2
jerrychina2020/rke-tools:v0.175-linux
jerrychina2020/rke-tools:v0.175
busybox:latest

View File

@@ -0,0 +1 @@
mc alias set demo http://192.168.11.33:9000 cmii B#923fC7mk

View File

@@ -1,23 +0,0 @@
#!/bin/bash
gzip_image_list_txt="all-gzip-image-list.txt" # 一般不需要修改
oss_prefix_url="https://oss.demo.uavcmlc.com/cmlc-installation"
local_gzip_path="/root/octopus-image"
local_gzip_path="$local_gzip_path/6.1.1"
mkdir -p $local_gzip_path
oss_prefix_url="$oss_prefix_url/6.1.1/"
cd $local_gzip_path || exit
wget "$oss_prefix_url$gzip_image_list_txt"
echo ""
while IFS= read -r i; do
[ -z "${i}" ] && continue
echo "download gzip file =>: $oss_prefix_url${i}"
if wget "$oss_prefix_url${i}" >/dev/null 2>&1; then
echo "download ok !"
echo ""
fi
done <"${gzip_image_list_txt}"

View File

@@ -0,0 +1,63 @@
#!/usr/bin/env bash
set -euo pipefail
# ============================================================
# 配置区:修改以下变量
# ============================================================
REGISTRY="chongqingshcis-a189ec98.ecis.chongqing-1.cmecloud.cn" # 登录地址 / 目标仓库域名
NAMESPACE="cmii" # 目标命名空间
USERNAME="cqcmii" # 仓库登录用户名
PASSWORD='pL8$kq9@m' # 仓库登录密码
# ============================================================
# 参数校验
if [ $# -ne 1 ]; then
echo "Usage: $0 <image>"
echo "Example:"
echo " $0 nginx:latest"
echo " $0 harbor.cdcyy.com.cm/cmii/asdad:v1.2"
echo " $0 harbor.cdcyy.com.cm/cmii/cmii-live/asdad:v1.2"
exit 1
fi
SRC_IMAGE="$1"
# ---------- 解析 image name 和 tag ----------
# 先分离 tag冒号后面部分
if [[ "$SRC_IMAGE" =~ ^(.*):([^:/]+)$ ]]; then
repo="${BASH_REMATCH[1]}"
tag="${BASH_REMATCH[2]}"
else
repo="$SRC_IMAGE"
tag="latest"
fi
# 只取路径最后一段作为镜像名(去掉任意层级 namespace/domain
image_name="${repo##*/}"
DEST_IMAGE="${REGISTRY}/${NAMESPACE}/${image_name}:${tag}"
# --------------------------------------------
echo ">>> Source : $SRC_IMAGE"
echo ">>> Target : $DEST_IMAGE"
echo ""
# 登录
echo ">>> Logging in to $REGISTRY..."
echo "$PASSWORD" | docker login "$REGISTRY" -u "$USERNAME" --password-stdin
# Pull
echo ">>> [pull ] $SRC_IMAGE"
docker pull "$SRC_IMAGE"
# Tag
echo ">>> [tag ] $SRC_IMAGE$DEST_IMAGE"
docker tag "$SRC_IMAGE" "$DEST_IMAGE"
# Push
echo ">>> [push ] $DEST_IMAGE"
docker push "$DEST_IMAGE"
echo ""
echo ">>> Done: $DEST_IMAGE"

View File

@@ -1,25 +0,0 @@
#!/bin/bash
image_name_prefix_list=(harbor.cdcyy.com.cn)
for (( i=1; i<=100; i++ ))
do
echo $i
for image_name_prefix in "${image_name_prefix_list[@]}"
do
content=$(docker image ls | grep "${image_name_prefix}" | head -n1)
if [ ! "$content" == "" ]; then
echo "$content"
echo "$(echo $content | awk '{print$1}'):$(echo $content | awk '{print$2}')"
if [ "$(echo $content | awk '{print$2}')" == "<none*" ]; then
continue
fi
docker image rm "$(echo $content | awk '{print$1}'):$(echo $content | awk '{print$2}')"
fi
done
done
echo "y
" | docker image prune

View File

@@ -1,68 +0,0 @@
#!/bin/bash
harbor_host=172.31.2.7:8033/admin
namespace=szgz
app_name=""
new_tag=""
upload_image_to_harbor(){
if [ "$app_name" == "" ]; then
echo "app name null exit!"
exit 233
fi
if ! docker load < "$1"; then
echo "docker load error !"
fi
docker tag "harbor.cdcyy.com.cn/cmii/$app_name:$new_tag" "$harbor_host/cmii/$app_name:$new_tag"
echo ""
echo ""
echo "upload_image_to_harbor - start to push to => $harbor_host/cmii/$app_name:$new_tag"
docker login -u admin -p V2ryStr@ngPss $harbor_host
docker push "$harbor_host/cmii/$app_name:$new_tag"
echo ""
echo ""
}
parse_args(){
if [ "$1" == "" ]; then
echo "no zip file in error!"
exit 233
fi
local image_name="$1"
# cmii-uav-surveillance=5.2.0-27031-cqga=2024-03-04=573.tar.gz
app_name=$(echo $image_name | cut -d "=" -f1)
new_tag=$(echo $image_name | cut -d "=" -f2)
}
update_image_tag(){
if [ "$new_tag" == "" ]; then
echo "new tag error!"
exit 233
fi
local image_prefix=$(kubectl -n ${namespace} get deployment "${app_name}" -o=jsonpath='{.spec.template.spec.containers[*].image}' | cut -d":" -f1)
echo "image grep is => ${image_prefix}"
echo "start to update ${namespace} ${app_name} to ${new_tag} !"
echo ""
kubectl -n ${namespace} patch deployment "${app_name}" -p "{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\":\"${app_name}\",\"image\": \"${harbor_host}/cmii/$app_name:${new_tag}\"}]}}}}"
echo ""
echo "start to wait for 3 seconds!"
sleep 3
local image_new=$(kubectl -n ${namespace} get deployment "${app_name}" -o=jsonpath='{.spec.template.spec.containers[*].image}')
echo ""
echo "new image are => $image_new"
echo ""
}
main(){
parse_args "$1"
upload_image_to_harbor "$1"
update_image_tag
}
main "$@"

View File

@@ -0,0 +1,52 @@
#!/usr/bin/env bash
set -euo pipefail
# ============================================================
# 配置区:修改以下变量
# ============================================================
REGISTRY="chongqingshcis-a189ec98.ecis.chongqing-1.cmecloud.cn" # 登录地址 / 目标仓库域名
NAMESPACE="cmii" # 目标命名空间
USERNAME="cqcmii" # 仓库登录用户名
PASSWORD='pL8$kq9@m' # 仓库登录密码
INPUT_FILE="middleware-fly-amd64-260311.txt" # 镜像列表文件路径
# ============================================================
# 登录到私有仓库
echo ">>> Logging in to $REGISTRY..."
echo "$PASSWORD" | docker login "$REGISTRY" -u "$USERNAME" --password-stdin
# 逐行处理镜像
while IFS= read -r line || [ -n "$line" ]; do
# 跳过空行和注释行
[[ -z "$line" || "$line" == \#* ]] && continue
# 拆分 repo 和 tag
if [[ "$line" =~ (.*):(.*) ]]; then
repo="${BASH_REMATCH[1]}"
tag="${BASH_REMATCH[2]}"
else
repo="$line"
tag="latest"
fi
# 只保留镜像名最后一段(去掉原有 namespace/domain
image_name="${repo##*/}"
src_image="${repo}:${tag}"
dest_image="${REGISTRY}/${NAMESPACE}/${image_name}:${tag}"
echo ""
echo ">>> [pull ] $src_image"
docker pull "$src_image"
echo ">>> [tag ] $src_image$dest_image"
docker tag "$src_image" "$dest_image"
echo ">>> [push ] $dest_image"
docker push "$dest_image"
done < "$INPUT_FILE"
echo ""
echo ">>> All done."

View File

@@ -0,0 +1,10 @@
kubectl get svc -A -o json | jq -r '
.items[]
| select(.spec.type=="NodePort")
| .metadata.namespace as $ns
| .metadata.name as $name
| .spec.ports[]
| [$ns, $name, .port, .nodePort]
| @tsv' | column -t

View File

@@ -0,0 +1,85 @@
#!/bin/bash
# ============================================================
# 脚本功能:收集指定命名空间下副本数 > 0 的 Deployment 信息
# 包含Deployment 名称、镜像名称、GIT 相关环境变量
# ============================================================
set -euo pipefail
# ── 配置区 ──────────────────────────────────────────────────
NAMESPACE="scydqlh"
OUTPUT_FILE="deployment_info_$(date +%Y%m%d_%H%M%S).txt"
# ────────────────────────────────────────────────────────────
echo "=========================================="
echo " 命名空间 : $NAMESPACE"
echo " 输出文件 : $OUTPUT_FILE"
echo "=========================================="
# 创建(清空)输出文件
> "$OUTPUT_FILE"
# 获取所有 Deployment 名称(换行分隔)
DEPLOYMENTS=$(kubectl get deployments -n "$NAMESPACE" \
-o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' 2>/dev/null)
if [[ -z "$DEPLOYMENTS" ]]; then
echo "[ERROR] 命名空间 '$NAMESPACE' 下未发现任何 Deployment请检查命名空间是否正确。"
exit 1
fi
PROCESSED=0
SKIPPED=0
while IFS= read -r DEPLOY; do
[[ -z "$DEPLOY" ]] && continue
# ── 1. 获取期望副本数 ──────────────────────────────────────
REPLICAS=$(kubectl get deployment "$DEPLOY" -n "$NAMESPACE" \
-o jsonpath='{.spec.replicas}' 2>/dev/null)
REPLICAS="${REPLICAS:-0}"
if [[ "$REPLICAS" == 0 ]]; then
echo "[SKIP] $DEPLOY (副本数=${REPLICAS},≤ 1跳过)"
(( SKIPPED++ )) || true
continue
fi
echo "[INFO] 处理 Deployment: $DEPLOY (副本数=${REPLICAS})"
# ── 2. 获取第一个容器的镜像名称 ───────────────────────────
IMAGE=$(kubectl get deployment "$DEPLOY" -n "$NAMESPACE" \
-o jsonpath='{.spec.template.spec.containers[0].image}' 2>/dev/null)
IMAGE="${IMAGE:-<未获取到镜像>}"
# ── 3. 在第一个副本 Pod 中执行 env | grep GIT ─────────────
GIT_ENV=$(kubectl exec -n "$NAMESPACE" "deploy/$DEPLOY" \
-- sh -c "env | grep GIT" 2>/dev/null || echo "")
# ── 4. 写入输出文件 ───────────────────────────────────────
{
echo "deployment名称${DEPLOY}"
echo "镜像名称:${IMAGE}"
echo "环境变量:"
if [[ -n "$GIT_ENV" ]]; then
while IFS= read -r env_line; do
echo " ${env_line}"
done <<< "$GIT_ENV"
else
echo " (未发现 GIT 相关环境变量)"
fi
echo ""
echo "------------------------------------------"
echo ""
} >> "$OUTPUT_FILE"
(( PROCESSED++ )) || true
done <<< "$DEPLOYMENTS"
# ── 汇总输出 ──────────────────────────────────────────────
echo ""
echo "=========================================="
echo " 完成!已处理: ${PROCESSED} 个,已跳过: ${SKIPPED}"
echo " 结果文件: $OUTPUT_FILE"
echo "=========================================="

View File

@@ -1,6 +1,6 @@
#!/bin/bash
namespace=xafkapp
namespace=命名空间
install_yq() {
wget https://oss.demo.uavcmlc.com/cmlc-installation/downloadfile/amd/yq_linux_amd64 -O /usr/local/bin/yq

View File

@@ -0,0 +1,111 @@
#!/bin/bash
# 定义命名空间
namespace="命名空间"
# 创建一个带时间戳的备份目录,保持目录整洁
backup_dir="backup_${namespace}_$(date +%Y%m%d%H%M%S)"
mkdir -p "${backup_dir}"
# YQ 清理规则:去除指定的 metadata 字段以及整个 status 字段
# 注意:加入了 .metadata.generation这在 deployment/statefulset 中也很常见
yq_filter='del(.metadata.managedFields, .metadata.annotations, .metadata.creationTimestamp, .metadata.uid, .metadata.resourceVersion, .metadata.selfLink, .metadata.generation, .status)'
install_yq() {
echo "=> 检查并安装 yq 工具..."
if ! command -v yq &> /dev/null; then
wget https://oss.demo.uavcmlc.com/cmlc-installation/downloadfile/amd/yq_linux_amd64 -O /usr/local/bin/yq
# wget https://oss.demo.uavcmlc.com/cmlc-installation/downloadfile/aarch/yq_linux_arm64 -O /usr/local/bin/yq
chmod +x /usr/local/bin/yq
echo "yq 安装完成!"
else
echo "yq 已安装,跳过。"
fi
echo ""
}
# 备份单个应用的函数
backup_single_app() {
local app_name=$1
local target_file="${backup_dir}/${app_name}.yaml"
echo "=> 正在备份应用: ${app_name}"
# 创建空文件或清空已有文件
> "${target_file}"
# 1. 备份 Deployment
if kubectl get deployment "${app_name}" -n "${namespace}" &>/dev/null; then
echo "---" >> "${target_file}"
kubectl get deployment "${app_name}" -n "${namespace}" -o yaml | yq eval "${yq_filter}" - >> "${target_file}"
fi
# 2. 备份 StatefulSet
if kubectl get statefulset "${app_name}" -n "${namespace}" &>/dev/null; then
echo "---" >> "${target_file}"
kubectl get statefulset "${app_name}" -n "${namespace}" -o yaml | yq eval "${yq_filter}" - >> "${target_file}"
fi
# 3. 备份 Service (假设 Service 名称与应用名称一致)
if kubectl get service "${app_name}" -n "${namespace}" &>/dev/null; then
echo "---" >> "${target_file}"
kubectl get service "${app_name}" -n "${namespace}" -o yaml | yq eval "${yq_filter}" - >> "${target_file}"
fi
# 4. 备份 ConfigMap (假设主 ConfigMap 名称与应用名称一致)
if kubectl get configmap "${app_name}" -n "${namespace}" &>/dev/null; then
echo "---" >> "${target_file}"
kubectl get configmap "${app_name}" -n "${namespace}" -o yaml | yq eval "${yq_filter}" - >> "${target_file}"
fi
}
backup_ingress() {
echo "=> 正在单独备份所有 Ingress 资源..."
local ingress_file="${backup_dir}/all-ingress-${namespace}.yaml"
# 检查是否存在 ingress 资源
if [ "$(kubectl get ingress -n "${namespace}" --no-headers 2>/dev/null | wc -l)" -gt 0 ]; then
# 因为 get ingress 拿到的是一个 List所以需要加 .items[] 遍历处理
kubectl get ingress -n "${namespace}" -o yaml | yq eval '.items[] | '"${yq_filter}" - > "${ingress_file}"
# 在每个 apiVersion 前面加上 --- 分隔符
sed -i '/^apiVersion:/i ---' "${ingress_file}"
echo "Ingress 备份完成: ${ingress_file}"
else
echo "命名空间 ${namespace} 下未找到 Ingress 资源。"
fi
echo ""
}
main() {
install_yq
echo "================================================="
echo "开始执行命名空间 ${namespace} 的多应用切分备份"
echo "备份目录: ${backup_dir}"
echo "================================================="
# 获取该命名空间下所有的 Deployment 和 StatefulSet 的名称,作为应用的基准列表
# 使用 sort -u 去重,防止某些同名情况
app_list=$(kubectl get deployments,statefulsets -n "${namespace}" -o custom-columns=NAME:.metadata.name --no-headers | sort -u)
if [ -z "${app_list}" ]; then
echo "未在命名空间中找到任何 Deployment 或 StatefulSet。"
exit 0
fi
# 遍历每个应用名称,执行合并备份
for app in ${app_list}; do
backup_single_app "${app}"
done
echo ""
# 单独备份 Ingress
backup_ingress
echo "================================================="
echo "所有资源备份完毕!文件已存放在 ${backup_dir}/ 目录下。"
echo "================================================="
}
# 执行主流程
main

View File

@@ -0,0 +1,11 @@
请实现yq工具使用kubectl工具针对特定的命名空间进行完整的备份
1. 需要去除metadata中的managedFields、annotations、creationTimestamp、uid、resourceVersion、status、selfLink等字段
2. 去除status字段
需要按照应用名称按照deployment的名称作为应用名称进行切分备份即为一个命名空间下有多个应用每个应用包含deployment、service、configmap、statefulset等资源每个应用的备份文件需要独立出来
例如一个命名空间下的应用名称为app1、app2、app3那么备份文件需要为app1.yaml、app2.yaml、app3.yaml每个文件中包含对应的资源。
需要单独备份ingress部分的资源
请你参考现在的备份命名空间实现一个新的shell脚本实现上述的功能

View File

@@ -0,0 +1,85 @@
#!/bin/bash
# ============================================================
# 脚本功能:收集指定命名空间下副本数 > 0 的 Deployment 信息
# 包含Deployment 名称、镜像名称、GIT 相关环境变量
# ============================================================
set -euo pipefail
# ── 配置区 ──────────────────────────────────────────────────
NAMESPACE="sd-wf-ga-fly-260327"
OUTPUT_FILE="deployment_info_$(date +%Y%m%d_%H%M%S).txt"
# ────────────────────────────────────────────────────────────
echo "=========================================="
echo " 命名空间 : $NAMESPACE"
echo " 输出文件 : $OUTPUT_FILE"
echo "=========================================="
# 创建(清空)输出文件
> "$OUTPUT_FILE"
# 获取所有 Deployment 名称(换行分隔)
DEPLOYMENTS=$(kubectl get deployments -n "$NAMESPACE" \
-o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' 2>/dev/null)
if [[ -z "$DEPLOYMENTS" ]]; then
echo "[ERROR] 命名空间 '$NAMESPACE' 下未发现任何 Deployment请检查命名空间是否正确。"
exit 1
fi
PROCESSED=0
SKIPPED=0
while IFS= read -r DEPLOY; do
[[ -z "$DEPLOY" ]] && continue
# ── 1. 获取期望副本数 ──────────────────────────────────────
REPLICAS=$(kubectl get deployment "$DEPLOY" -n "$NAMESPACE" \
-o jsonpath='{.spec.replicas}' 2>/dev/null)
REPLICAS="${REPLICAS:-0}"
if [[ "$REPLICAS" == 0 ]]; then
echo "[SKIP] $DEPLOY (副本数=${REPLICAS},≤ 1跳过)"
(( SKIPPED++ )) || true
continue
fi
echo "[INFO] 处理 Deployment: $DEPLOY (副本数=${REPLICAS})"
# ── 2. 获取第一个容器的镜像名称 ───────────────────────────
IMAGE=$(kubectl get deployment "$DEPLOY" -n "$NAMESPACE" \
-o jsonpath='{.spec.template.spec.containers[0].image}' 2>/dev/null)
IMAGE="${IMAGE:-<未获取到镜像>}"
# ── 3. 在第一个副本 Pod 中执行 env | grep GIT ─────────────
GIT_ENV=$(kubectl exec -n "$NAMESPACE" "deploy/$DEPLOY" \
-- sh -c "env | grep GIT" 2>/dev/null || echo "")
# ── 4. 写入输出文件 ───────────────────────────────────────
{
echo "deployment名称${DEPLOY}"
echo "镜像名称:${IMAGE}"
echo "环境变量:"
if [[ -n "$GIT_ENV" ]]; then
while IFS= read -r env_line; do
echo " ${env_line}"
done <<< "$GIT_ENV"
else
echo " (未发现 GIT 相关环境变量)"
fi
echo ""
echo "------------------------------------------"
echo ""
} >> "$OUTPUT_FILE"
(( PROCESSED++ )) || true
done <<< "$DEPLOYMENTS"
# ── 汇总输出 ──────────────────────────────────────────────
echo ""
echo "=========================================="
echo " 完成!已处理: ${PROCESSED} 个,已跳过: ${SKIPPED}"
echo " 结果文件: $OUTPUT_FILE"
echo "=========================================="

View File

@@ -0,0 +1,11 @@
export namespace=cq-ws-260319
kubectl rollout restart deployment -n "${namespace}" -l cmii.type=frontend,octopus.control=frontend-app-wdd
kubectl rollout restart deployment -n "${namespace}" -l cmii.type=backend,octopus/control=backend-app-1.0.0
kubectl rollout restart daemonset/nginx-ingress-controller -n ingress-nginx
kubectl rollout status daemonset/nginx-ingress-controller -n ingress-nginx
# 等待输出: daemon set "nginx-ingress-controller" successfully rolled out

View File

@@ -2,4 +2,6 @@
https://github.com/wise2c-devops/build-harbor-aarch64
https://github.com/wise2c-devops/build-harbor-aarch64
https://github.com/octohelm/harbor

View File

@@ -1,17 +1,23 @@
#!/bin/bash
wget https://oss.demo.uavcmlc.com/cmlc-installation/downloadfile/amd/jq-linux-amd64 -O /usr/local/bin/jq
wget https://oss.demo.uavcmlc.com/cmlc-installation/tmp/jq-linux-amd64 -O /usr/local/bin/jq
#wget https://oss.demo.uavcmlc.com/cmlc-installation/downloadfile/aarch/jq-linux-arm64 -O /usr/local/bin/jq
chmod +x /usr/local/bin/jq
export name_space=xayd
kubectl delete pods -n $name_space --field-selector status.phase!=Running --force
kubectl get pods -n $name_space -o json | jq -r '.items[] | select(.status.containerStatuses[0].ready == false) | .metadata.name' | xargs -r kubectl delete pod -n $name_space --force
export name_space_list=(kube-system kubernetes-dashboard ingress-nginx bj-sh-uas-260511)
export name_space_list=(bj-sh-uas-260511)
for name_space in ${name_space_list[*]};do
kubectl delete pods -n $name_space --field-selector status.phase!=Running --force
kubectl get pods -n $name_space -o json | jq -r '.items[] | select(.status.containerStatuses[0].ready == false) | .metadata.name' | xargs -r kubectl delete pod -n $name_space --force
done
kubectl -n ${name_space} delete pod helm-nacos-0 --force

View File

@@ -1,30 +0,0 @@
#!/usr/bin/env bash
name_space=zjyd
delete_all_fronted_cmii_pod(){
all_pod_list=($(kubectl get pods -n "$name_space" -o=jsonpath='{.items[*].metadata.name}' | tr " " "\n"))
for pod in "${all_pod_list[@]}"; do
if echo "$pod" | grep -q "platform"; then
echo ""
echo "current pod is $pod"
kubectl -n "$name_space" delete pod "$pod" --force
fi
done
}
delete_all_backend_cmii_pod(){
all_pod_list=($(kubectl get pods -n "$name_space" -o=jsonpath='{.items[*].metadata.name}' | tr " " "\n"))
for pod in "${all_pod_list[@]}"; do
if echo "$pod" | grep -v "platform" | grep -q "cmii"; then
echo ""
echo "current pod is $pod"
kubectl -n "$name_space" delete pod "$pod" --force
fi
done
}
delete_all_backend_cmii_pod
delete_all_fronted_cmii_pod

View File

@@ -1,68 +0,0 @@
#!/bin/bash
harbor_host=192.168.0.10:8033
namespace=hbyd
app_name=""
new_tag=""
upload_image_to_harbor(){
if [ "$app_name" == "" ]; then
echo "app name null exit!"
exit 233
fi
if ! docker load < "$1"; then
echo "docker load error !"
fi
docker tag "harbor.cdcyy.com.cn/cmii/$app_name:$new_tag" "$harbor_host/cmii/$app_name:$new_tag"
echo ""
echo ""
echo "upload_image_to_harbor - start to push to => $harbor_host/cmii/$app_name:$new_tag"
docker login -u admin -p V2ryStr@ngPss $harbor_host
docker push "$harbor_host/cmii/$app_name:$new_tag"
echo ""
echo ""
}
parse_args(){
if [ "$1" == "" ]; then
echo "no zip file in error!"
exit 233
fi
local image_name="$1"
# cmii-uav-surveillance=5.2.0-27031-cqga=2024-03-04=573.tar.gz
app_name=$(echo $image_name | cut -d "=" -f1)
new_tag=$(echo $image_name | cut -d "=" -f2)
}
update_image_tag(){
if [ "$new_tag" == "" ]; then
echo "new tag error!"
exit 233
fi
local image_prefix=$(kubectl -n ${namespace} get deployment "${app_name}" -o=jsonpath='{.spec.template.spec.containers[*].image}' | cut -d":" -f1)
echo "image grep is => ${image_prefix}"
echo "start to update ${namespace} ${app_name} to ${new_tag} !"
echo ""
kubectl -n ${namespace} patch deployment "${app_name}" -p "{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\":\"${app_name}\",\"image\": \"${harbor_host}/cmii/$app_name:${new_tag}\"}]}}}}"
echo ""
echo "start to wait for 3 seconds!"
sleep 3
local image_new=$(kubectl -n ${namespace} get deployment "${app_name}" -o=jsonpath='{.spec.template.spec.containers[*].image}')
echo ""
echo "new image are => $image_new"
echo ""
}
main(){
parse_args "$1"
upload_image_to_harbor "$1"
update_image_tag
}
main "$@"

View File

@@ -0,0 +1,117 @@
### 1先看这个 Deployment 对应的 ReplicaSet 列表
```bash
kubectl -n cq-fly-260311 get rs -o wide | grep cmii-sky-converge
```
更稳一点的方式,用 label 过滤:
```bash
kubectl -n cq-fly-260311 get rs -l cmii.app=cmii-sky-converge
```
如果你不确定 label不妨先看 Deployment 的 selector
```bash
kubectl -n cq-fly-260311 get deploy cmii-sky-converge -o jsonpath='{.spec.selector.matchLabels}'
echo
```
### 2从 ReplicaSet 里看 revision 和镜像
Deployment 的 revision 一般记录在 ReplicaSet 注解 `deployment.kubernetes.io/revision` 里。可以这样查:
```bash
kubectl -n cq-fly-260311 get rs \
-o custom-columns=NAME:.metadata.name,REVISION:.metadata.annotations.deployment\.kubernetes\.io/revision,REPLICAS:.spec.replicas,IMAGE:.spec.template.spec.containers[*].image \
| grep cmii-sky-converge
```
你会看到类似:
```bash
cmii-sky-converge-6f7c8d9b4d 12 0 repo/app:v1.2.2
cmii-sky-converge-7a8b9c0d1e 13 2 repo/app:v1.2.3
```
这里通常:
* **最大的 revision** 是当前版本
* **倒数第二大的 revision** 就是上一个版本
这些历史配置是保存在 ReplicaSet 中的。([Kubernetes][1])
### 3如果只是回滚到“上一个版本”
直接执行:
```bash
kubectl -n cq-fly-260311 rollout undo deployment/cmii-sky-converge
```
这是官方支持的标准写法,会把 Deployment 回滚到上一次部署状态。([Kubernetes][2])
### 4如果你已经从 ReplicaSet 确认了上一个 revision按 revision 回滚
例如上一个版本是 `revision=12`
```bash
kubectl -n cq-fly-260311 rollout undo deployment/cmii-sky-converge --to-revision=12
```
`--to-revision` 就是官方提供的指定修订版本回滚参数。([Kubernetes][2])
### 5回滚前先预览一下
如果你想先试运行:
```bash
kubectl -n cq-fly-260311 rollout undo deployment/cmii-sky-converge --dry-run=server
```
### 6回滚后确认状态
```bash
kubectl -n cq-fly-260311 rollout status deployment/cmii-sky-converge
kubectl -n cq-fly-260311 get deploy cmii-sky-converge -o wide
kubectl -n cq-fly-260311 get rs \
-o custom-columns=NAME:.metadata.name,REVISION:.metadata.annotations.deployment\.kubernetes\.io/revision,REPLICAS:.spec.replicas,IMAGE:.spec.template.spec.containers[*].image \
| grep cmii-sky-converge
```
---
### 一套可直接执行的命令
如果你就是想“先看上一个版本,再回滚”:
```bash
# 1. 查看当前 deployment 的历史对应的 ReplicaSet 和镜像
kubectl -n cq-fly-260311 get rs \
-o custom-columns=NAME:.metadata.name,REVISION:.metadata.annotations.deployment\.kubernetes\.io/revision,REPLICAS:.spec.replicas,IMAGE:.spec.template.spec.containers[*].image \
| grep cmii-sky-converge | sort -k2 -n
# 2. 回滚到上一个版本
kubectl -n cq-fly-260311 rollout undo deployment/cmii-sky-converge
# 3. 查看回滚结果
kubectl -n cq-fly-260311 rollout status deployment/cmii-sky-converge
```
---
### 如果你想精确拿到“上一个 ReplicaSet 的镜像”
可以用这个:
```bash
kubectl -n cq-fly-260311 get rs \
-o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.annotations.deployment\.kubernetes\.io/revision}{"\t"}{.spec.template.spec.containers[*].image}{"\n"}{end}' \
| grep cmii-sky-converge | sort -k2 -n
```
然后选倒数第二行,就是上一个版本的 revision 和镜像。
你要的话,我可以再给你一版 **一行 shell 命令**,自动找出 `cmii-sky-converge` 的上一个 revision 并直接执行回滚。
[1]: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/?utm_source=chatgpt.com "Deployments - Kubernetes"
[2]: https://kubernetes.io/zh-cn/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_undo/?utm_source=chatgpt.com "kubectl rollout undo | Kubernetes"

View File

@@ -0,0 +1,48 @@
#!/bin/bash
# 1. 定义命名空间
NAMESPACE="bj-sh-uas-260511"
IMAGE_NAME_PREFIX="192.168.3.31:8088/cmii"
# 检查输入文件是否存在
if [ ! -f "$1" ]; then
echo "使用方法: $0 <镜像列表文件>"
exit 1
fi
echo "开始更新命名空间 ${NAMESPACE} 下的 Deployment..."
# 2. 逐行读取文件内容
while IFS= read -r line || [ -n "$line" ]; do
# 忽略空行
[ -z "$line" ] && continue
# 以 = 为分隔符提取:
# 第3项为 Deployment 名称
# 第4项为 镜像 Tag
DEPLOY_NAME=$(echo "$line" | cut -d'=' -f3)
IMAGE_TAG=$(echo "$line" | cut -d'=' -f4 | sed 's/.tar.gz//')
# 假设容器名称Container Name与 Deployment 名称一致
# 这是 Kubernetes 部署中的常见规范。如果不一致,请修改 --image 后面的第一个参数。
IMAGE_NAME="${IMAGE_NAME_PREFIX}/${DEPLOY_NAME}:${IMAGE_TAG}"
echo "------------------------------------------------"
echo "正在更新: ${DEPLOY_NAME}"
echo "目标版本: ${IMAGE_TAG}"
# 3. 使用 kubectl 执行更新
# 格式kubectl set image deployment/<name> <container_name>=<new_image> -n <ns>
kubectl set image deployment/"${DEPLOY_NAME}" "${DEPLOY_NAME}"="${IMAGE_NAME}" -n "${NAMESPACE}"
if [ $? -eq 0 ]; then
echo "✅ 提交成功"
else
echo "❌ 提交失败,请检查 Deployment 名称是否正确"
fi
done < "$1"
echo "------------------------------------------------"
echo "所有更新指令已发送完毕。"