artifacts/scripts/ingress-installer.sh
2025-09-13 15:11:40 +08:00

189 lines
5.9 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# gitops/scripts/ingress-installer.sh
# 目标:最小化参数/分支,专注“一键离线安装”
set -euo pipefail
# ======================
# Config & Defaults仅支持环境变量覆盖
# ======================
: "${NGINX_IC_IMAGE:=nginx/nginx-ingress:2.4.0}"
: "${CERT_IMG:=registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230407}"
# 打包阶段写入的 OCI layout 内部引用名(如果你改了打包 ref.name这里相应改
: "${OCI_NGINX_REF:=nginx-ingress-2.4.0}"
: "${OCI_CERT_REF:=kube-webhook-certgen}"
# 目录布局固定charts、images、脚本位于离线包根目录
: "${CHART_DIR:=./charts/nginx-ingress}"
: "${NAMESPACE:=ingress}"
: "${OCI_ARCHIVE:=images/oci-archive.tar}" # 优先使用
: "${DOCKER_IMG_TAR:=images/nginx-ingress.tar}" # 回退docker save
: "${DOCKER_CERT_TAR:=images/kube-webhook-certgen.tar}"
: "${NERDCTL_TAR:=nerdctl.tar.gz}"
# Ingress 暴露 IP默认取本机第一块网卡 IP节点选择器可选key=value
INGRESS_IP="${INGRESS_IP:-$(hostname -I 2>/dev/null | awk '{print $1}')}"
NODE_LABEL="${NODE_LABEL:-}"
SUDO=""; [ "$(id -u)" -ne 0 ] && SUDO="sudo"
log() { echo -e "$@"; }
die() { echo "$*" >&2; exit 1; }
ok() { echo "$*"; }
warn() { echo "⚠️ $*"; }
have() { command -v "$1" &>/dev/null; }
# ======================
# Nerdctl Install (wrapper)
# ======================
install_nerdctl() {
if [ -f "${NERDCTL_TAR}" ]; then
log "📦 安装 nerdctlwrapper..."
$SUDO tar xzf "${NERDCTL_TAR}" -C /usr/local/bin/
$SUDO chmod +x /usr/local/bin/nerdctl || true
fi
}
# ======================
# Import images优先 OCI其次 docker save tar
# ======================
import_images_from_oci() {
# 首选OCI 归档
if [ -f "${OCI_ARCHIVE}" ]; then
log "📦 从 OCI 归档导入镜像:${OCI_ARCHIVE}"
# A) Docker 环境(需要 skopeo
if have docker && docker info &>/dev/null; then
if have skopeo; then
skopeo --insecure-policy copy --all "oci-archive:${OCI_ARCHIVE}:${OCI_NGINX_REF}" "docker-daemon:${NGINX_IC_IMAGE}"
skopeo --insecure-policy copy --all "oci-archive:${OCI_ARCHIVE}:${OCI_CERT_REF}" "docker-daemon:${CERT_IMG}"
ok "OCI → docker-daemon 导入完成"
return
else
warn "docker 环境未安装 skopeo改用 docker-archive 回退(需 images/*.tar"
fi
fi
# B) containerd 环境K3s 或系统 containerd
if [ -S /run/k3s/containerd/containerd.sock ] || [ -S /run/containerd/containerd.sock ]; then
local ns="k8s.io"
$SUDO ctr -n "${ns}" images import --all-platforms "${OCI_ARCHIVE}"
$SUDO ctr -n "${ns}" images tag "${OCI_NGINX_REF}" "${NGINX_IC_IMAGE}" || true
$SUDO ctr -n "${ns}" images tag "${OCI_CERT_REF}" "${CERT_IMG}" || true
ok "OCI → containerd 导入完成"
return
fi
warn "未检测到 docker/skopo 或 containerd 可直接用 OCI 导入,尝试 docker-archive 回退。"
fi
# 回退docker save 的 tar 包
if [ -f "${DOCKER_IMG_TAR}" ] && [ -f "${DOCKER_CERT_TAR}" ]; then
log "📦 从 docker-archive tar 回退导入 images/*.tar"
if have docker && docker info &>/dev/null; then
docker load -i "${DOCKER_IMG_TAR}"
docker load -i "${DOCKER_CERT_TAR}"
ok "docker load 完成"
return
fi
if have nerdctl; then
nerdctl load -i "${DOCKER_IMG_TAR}"
nerdctl load -i "${DOCKER_CERT_TAR}"
ok "nerdctl load 完成"
return
fi
if [ -S /run/k3s/containerd/containerd.sock ] || [ -S /run/containerd/containerd.sock ]; then
$SUDO ctr -n k8s.io images import --all-platforms "${DOCKER_IMG_TAR}"
$SUDO ctr -n k8s.io images import --all-platforms "${DOCKER_CERT_TAR}"
ok "ctr import 完成"
return
fi
die "找不到可用容器运行时导入 images/*.tar"
fi
die "未发现可用的镜像来源(缺少 ${OCI_ARCHIVE}${DOCKER_IMG_TAR}/${DOCKER_CERT_TAR)})"
}
# ======================
# Kubernetes & Helm
# ======================
ensure_namespace() {
log "📁 创建命名空间 ${NAMESPACE}(如已存在忽略)"
kubectl create namespace "${NAMESPACE}" --dry-run=client -o yaml | kubectl apply -f -
}
generate_values() {
log "🧾 生成 Helm values.yaml"
local repo tag
repo="${NGINX_IC_IMAGE%:*}"
tag="${NGINX_IC_IMAGE##*:}"
cat > values.yaml <<EOF
controller:
ingressClass:
name: nginx
create: true
setAsDefaultIngress: false
replicaCount: 2
image:
repository: ${repo}
tag: "${tag}"
service:
enabled: true
type: NodePort
externalIPs:
- ${INGRESS_IP}
nodePorts:
http: 80
https: 443
EOF
if [[ -n "${NODE_LABEL}" ]]; then
cat >> values.yaml <<EOF
nodeSelector:
${NODE_LABEL%%=*}: "${NODE_LABEL#*=}"
EOF
fi
}
install_chart() {
[ -d "${CHART_DIR}" ] || die "未找到 Chart 目录:${CHART_DIR}"
log "🧭 使用本地 Chart 安装/升级:${CHART_DIR}"
helm upgrade --install nginx "${CHART_DIR}" \
--namespace "${NAMESPACE}" -f values.yaml \
--wait --timeout 10m
}
apply_configmap_tuning() {
log "🛠️ 应用 ConfigMap 调优参数"
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-nginx-ingress
namespace: ${NAMESPACE}
data:
proxy-connect-timeout: "10"
proxy-read-timeout: "10"
client-header-buffer-size: 64k
client-body-buffer-size: 64k
client-max-body-size: 1000m
proxy-buffers: "8 32k"
proxy-buffer-size: 32k
EOF
}
# ======================
# Main
# ======================
log "🚀 Ingress 离线部署开始"
log " Ingress IP: ${INGRESS_IP:-<auto>}"
log " Namespace: ${NAMESPACE}"
log " Chart Dir: ${CHART_DIR}"
log " Images: ${NGINX_IC_IMAGE} , ${CERT_IMG}"
install_nerdctl
import_images_from_oci
ensure_namespace
generate_values
install_chart
apply_configmap_tuning
ok "离线安装完成Ingress IP: ${INGRESS_IP}"