#!/bin/bash # 207 单点 K3s + Docker GitLab + Argo CD 演示(可重复执行,尽量幂等) set -euo pipefail DEMO_ROOT=/opt/argocd-demo GITLAB_NAME=gitlab-argocd-demo GITLAB_URL=http://192.168.110.207:8929 GITLAB_ROOT_PASSWORD="${GITLAB_ROOT_PASSWORD:-ArgoDemo207!}" MANIFESTS_REPO=argocd-manifests KUBECONFIG=/etc/rancher/k3s/k3s.yaml export KUBECONFIG KC="k3s kubectl" log() { echo "[$(date '+%H:%M:%S')] $*"; } install_k3s() { if command -v k3s >/dev/null 2>&1 && [ -f "$KUBECONFIG" ]; then log "k3s 已存在,跳过安装" $KC get nodes || true return fi log "安装 k3s(国内镜像;禁用 traefik,避免占用 80 与 Dify 冲突)" curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \ INSTALL_K3S_MIRROR=cn \ INSTALL_K3S_EXEC="server --disable traefik --write-kubeconfig-mode 644" sh - sleep 10 $KC wait --for=condition=Ready node --all --timeout=180s $KC get nodes } start_gitlab() { mkdir -p "$DEMO_ROOT/gitlab/config" "$DEMO_ROOT/gitlab/logs" "$DEMO_ROOT/gitlab/data" if docker ps -a --format '{{.Names}}' | grep -qx "$GITLAB_NAME"; then if ! docker ps --format '{{.Names}}' | grep -qx "$GITLAB_NAME"; then log "启动已有 GitLab 容器" docker start "$GITLAB_NAME" else log "GitLab 容器已在运行" fi else log "拉取并启动 GitLab CE(优先国内镜像代理)" local IMG="gitlab/gitlab-ce:16.11.10-ce.0" local MIRROR_IMG="docker.m.daocloud.io/gitlab/gitlab-ce:16.11.10-ce.0" if ! docker image inspect "$IMG" >/dev/null 2>&1; then if docker pull "$MIRROR_IMG"; then docker tag "$MIRROR_IMG" "$IMG" else log "国内镜像失败,再试 Docker Hub…" docker pull "$IMG" fi fi docker run -d --name "$GITLAB_NAME" \ --hostname 192.168.110.207 \ --restart unless-stopped \ -p 8929:8929 -p 2224:22 \ -v "$DEMO_ROOT/gitlab/config:/etc/gitlab" \ -v "$DEMO_ROOT/gitlab/logs:/var/log/gitlab" \ -v "$DEMO_ROOT/gitlab/data:/var/opt/gitlab" \ --shm-size 256m \ -e GITLAB_ROOT_PASSWORD="$GITLAB_ROOT_PASSWORD" \ -e GITLAB_OMNIBUS_CONFIG="external_url '${GITLAB_URL}'; nginx['listen_port'] = 8929; gitlab_rails['gitlab_shell_ssh_port'] = 2224;" \ "$IMG" fi } wait_gitlab() { log "等待 GitLab HTTP 就绪(最长 25 分钟)" for i in $(seq 1 150); do if curl -sf -o /dev/null "$GITLAB_URL/users/sign_in" 2>/dev/null; then log "GitLab Web 已响应 (${i}*10s)" # 再等 rails 完全可用 sleep 30 return 0 fi if (( i % 6 == 0 )); then log "仍在等待 GitLab… ${i}*10s docker: $(docker inspect -f '{{.State.Health.Status}}' "$GITLAB_NAME" 2>/dev/null || docker inspect -f '{{.State.Status}}' "$GITLAB_NAME")" fi sleep 10 done log "ERROR: GitLab 超时未就绪"; docker logs "$GITLAB_NAME" --tail 40; exit 1 } ensure_gitlab_project() { log "创建 GitLab 公开项目 root/${MANIFESTS_REPO}" docker exec "$GITLAB_NAME" bash -lc "gitlab-rails runner \" u = User.find_by_username('root') || User.find_by(username: 'root') raise 'no root user' unless u p = Project.find_by_full_path('root/${MANIFESTS_REPO}') unless p p = Projects::CreateService.new(u, { name: '${MANIFESTS_REPO}', path: '${MANIFESTS_REPO}', namespace_id: u.namespace.id, visibility_level: Gitlab::VisibilityLevel::PUBLIC }).execute raise (p.respond_to?(:errors) ? p.errors.full_messages.join(', ') : p.inspect) unless p.is_a?(Project) && p.persisted? end puts 'project_ok id=' + p.id.to_s \"" || log "WARN: rails runner 创建项目失败,若仓库已存在可忽略" } push_manifests() { command -v git >/dev/null || apt-get install -y git local src="$DEMO_ROOT/manifests-src" local work="$DEMO_ROOT/manifests-git" rm -rf "$work" mkdir -p "$work" # 只把 demo-nginx 清单放进 Git(Application YAML 由 kubectl 单独 apply) cp -a "$src/demo-nginx" "$work/" cd "$work" git init -b main git config user.email "argocd-demo@207.local" git config user.name "argocd-demo" git add -A git commit -m "argocd demo manifests $(date '+%Y%m%d_%H%M%S')" || true git remote add origin "http://root:${GITLAB_ROOT_PASSWORD}@192.168.110.207:8929/root/${MANIFESTS_REPO}.git" # 首次 push 可能遇到空仓延迟,重试几次 for i in 1 2 3 4 5; do if git push -u origin main --force; then log "manifests 已 push 到 GitLab" return 0 fi log "push 失败,重试 $i …" sleep 10 done exit 1 } install_argocd() { log "安装 Argo CD" $KC create namespace argocd --dry-run=client -o yaml | $KC apply -f - local ARGO_YAML="$DEMO_ROOT/argocd-install.yaml" if [ ! -s "$ARGO_YAML" ]; then log "下载 Argo CD install.yaml(优先 ghproxy)" curl -sfL -o "$ARGO_YAML" \ https://ghproxy.net/https://raw.githubusercontent.com/argoproj/argo-cd/v2.12.3/manifests/install.yaml \ || curl -sfL -o "$ARGO_YAML" \ https://cdn.jsdelivr.net/gh/argoproj/argo-cd@v2.12.3/manifests/install.yaml \ || curl -sfL -o "$ARGO_YAML" \ https://raw.githubusercontent.com/argoproj/argo-cd/v2.12.3/manifests/install.yaml fi $KC apply -n argocd -f "$ARGO_YAML" $KC wait --for=condition=available deployment/argocd-server -n argocd --timeout=900s $KC wait --for=condition=available deployment/argocd-repo-server -n argocd --timeout=900s $KC wait --for=condition=available statefulset/argocd-application-controller -n argocd --timeout=900s 2>/dev/null \ || $KC wait --for=condition=available deployment/argocd-application-controller -n argocd --timeout=900s 2>/dev/null \ || true $KC patch configmap argocd-cmd-params-cm -n argocd --type merge -p '{"data":{"server.insecure":"true"}}' 2>/dev/null || \ $KC create configmap argocd-cmd-params-cm -n argocd --from-literal=server.insecure=true --dry-run=client -o yaml | $KC apply -f - $KC patch svc argocd-server -n argocd -p '{"spec":{"type":"NodePort","ports":[{"name":"http","port":80,"protocol":"TCP","targetPort":8080,"nodePort":30080},{"name":"https","port":443,"protocol":"TCP","targetPort":8080,"nodePort":30443}]}}' $KC rollout restart deployment/argocd-server -n argocd $KC wait --for=condition=available deployment/argocd-server -n argocd --timeout=300s } configure_argocd_repo_and_app() { log "注册 GitLab 仓库并创建 Application" $KC -n argocd delete secret gitlab-argocd-manifests --ignore-not-found $KC apply -f - </dev/null || true } print_summary() { local admin_pw admin_pw=$($KC -n argocd get secret argocd-initial-admin-secret -o jsonpath='{.data.password}' 2>/dev/null | base64 -d || echo "(已改过密码)") cat > "$DEMO_ROOT/访问说明.txt" < Commit 2) Argo UI 看 OutOfSync -> Sync(或等 automated selfHeal) 3) k3s kubectl -n argocd-demo get po 4) 人肉改副本: k3s kubectl -n argocd-demo scale deploy/demo-nginx --replicas=5 稍等看 Self-Heal 拉回 Git 中的副本数 EOF cat "$DEMO_ROOT/访问说明.txt" } main() { install_k3s start_gitlab wait_gitlab ensure_gitlab_project push_manifests install_argocd configure_argocd_repo_and_app print_summary log "DONE" } main "$@"