nginx/k8s/deploy.sh
huangzhiqiang de93ff12a9
All checks were successful
Build NGINX on Ubuntu / build-and-deploy (push) Successful in 58s
fix:统一使用k8s的namespace
2025-06-12 14:09:35 +08:00

302 lines
9.3 KiB
Bash
Raw Permalink 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.

#!/bin/bash
# Kubernetes 自动部署脚本
# 用于从私有 Harbor 仓库拉取 NGINX 镜像并部署到 K8s 集群
set -e
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 打印带颜色的信息
print_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查必要的环境变量
check_env_vars() {
print_info "检查环境变量..."
required_vars=("HARBOR_REGISTRY" "HARBOR_USERNAME" "HARBOR_PASSWORD" "NGINX_IMAGE_TAG")
missing_vars=()
for var in "${required_vars[@]}"; do
if [[ -z "${!var}" ]]; then
missing_vars+=("$var")
fi
done
if [[ ${#missing_vars[@]} -gt 0 ]]; then
print_error "缺少必要的环境变量:"
for var in "${missing_vars[@]}"; do
echo " - $var"
done
print_info "请设置以下环境变量:"
echo " export HARBOR_REGISTRY=<你的Harbor仓库地址>"
echo " export HARBOR_USERNAME=<Harbor用户名>"
echo " export HARBOR_PASSWORD=<Harbor密码>"
echo " export NGINX_IMAGE_TAG=<镜像标签,如: \${GITHUB_SHA} 或 latest>"
exit 1
fi
print_success "环境变量检查通过"
}
# 检查 kubectl 连接
check_kubectl() {
print_info "检查 kubectl 连接..."
if ! command -v kubectl &> /dev/null; then
print_error "kubectl 未安装或不在 PATH 中"
exit 1
fi
if ! kubectl cluster-info &> /dev/null; then
print_error "无法连接到 Kubernetes 集群"
print_info "请确保:"
echo " 1. kubectl 已正确配置"
echo " 2. 能够访问 Kubernetes 集群"
echo " 3. 当前用户有适当的权限"
exit 1
fi
print_success "kubectl 连接正常"
kubectl cluster-info
}
# 创建命名空间(如果不存在)
create_namespace() {
local namespace=${1:-default}
print_info "检查命名空间: $namespace"
if kubectl get namespace "$namespace" &> /dev/null; then
print_success "命名空间 '$namespace' 已存在"
else
print_info "创建命名空间: $namespace"
kubectl create namespace "$namespace"
print_success "命名空间 '$namespace' 创建成功"
fi
}
# 创建或更新 Harbor 仓库访问凭据
create_harbor_secret() {
local namespace=${1:-default}
print_info "创建/更新 Harbor 仓库访问凭据..."
# 删除已存在的 secret如果存在
kubectl delete secret harbor-registry-secret -n "$namespace" --ignore-not-found=true
# 创建新的 secret
kubectl create secret docker-registry harbor-registry-secret \
--docker-server="$HARBOR_REGISTRY" \
--docker-username="$HARBOR_USERNAME" \
--docker-password="$HARBOR_PASSWORD" \
--namespace="$namespace"
print_success "Harbor 仓库访问凭据创建成功"
}
# 更新部署文件中的镜像标签
update_deployment_image() {
local deployment_file="$1"
local image_tag="$2"
print_info "更新部署文件中的镜像标签: $image_tag"
# 使用镜像完整路径
local full_image="${HARBOR_REGISTRY}/test/nginx:${image_tag}"
print_info "使用镜像: $full_image"
# 备份原文件
cp "$deployment_file" "${deployment_file}.bak"
# 使用 sed 替换环境变量
sed -i.tmp "s|\$HARBOR_REGISTRY|${HARBOR_REGISTRY}|g" "$deployment_file"
sed -i.tmp "s|\$NGINX_IMAGE_TAG|${image_tag}|g" "$deployment_file"
sed -i.tmp "s|\$NAMESPACE|${DEPLOY_NAMESPACE}|g" "$deployment_file" # 添加命名空间替换
# 如果有其他环境变量需要替换,可以继续添加类似的 sed 命令
# 例如sed -i.tmp "s|\$NAMESPACE|${NAMESPACE}|g" "$deployment_file"
# 清理临时文件
rm -f "${deployment_file}.tmp"
print_success "镜像标签和环境变量替换完成,使用镜像: $full_image"
}
# 应用 Kubernetes 配置
apply_k8s_config() {
local deployment_file="$1"
print_info "应用 Kubernetes 配置..."
if [[ ! -f "$deployment_file" ]]; then
print_error "部署文件不存在: $deployment_file"
exit 1
fi
kubectl apply -f "$deployment_file"
print_success "Kubernetes 配置应用成功"
}
# 等待部署就绪
wait_for_deployment() {
local deployment_name="nginx-deployment"
local namespace=${1:-default}
local timeout=${2:-300}
print_info "等待部署就绪..."
# 添加初始检查和调试信息
if ! kubectl get deployment "$deployment_name" -n "$namespace" &> /dev/null; then
print_error "找不到部署 $deployment_name"
print_info "检查部署状态..."
kubectl get deployments -n "$namespace" -o wide
print_info "检查Pod状态..."
kubectl get pods -n "$namespace" -o wide
print_info "检查最近事件..."
kubectl get events -n "$namespace" --sort-by='.lastTimestamp'
exit 1
fi
if kubectl wait --for=condition=available deployment/"$deployment_name" \
--namespace="$namespace" --timeout="${timeout}s"; then
print_success "部署已就绪"
else
print_error "部署超时,请检查部署状态"
# 添加更详细的错误信息
print_info "Pod状态:"
kubectl get pods -n "$namespace" -l app=nginx -o wide
print_info "描述deployment:"
kubectl describe deployment "$deployment_name" -n "$namespace"
print_info "最近的事件:"
kubectl get events -n "$namespace" --sort-by='.lastTimestamp' | tail -n 20
print_info "Pod日志:"
kubectl logs -n "$namespace" -l app=nginx --tail=50
exit 1
fi
}
# 显示部署状态
show_deployment_status() {
local namespace=${1:-default}
print_info "部署状态:"
echo
echo "=== Pods ==="
kubectl get pods -l app=nginx -n "$namespace" -o wide
echo
echo "=== Services ==="
kubectl get services -l app=nginx -n "$namespace"
echo
echo "=== Deployments ==="
kubectl get deployments -l app=nginx -n "$namespace"
echo
echo "=== HPA ==="
kubectl get hpa -l app=nginx -n "$namespace" 2>/dev/null || echo "HPA 未启用"
echo
echo "=== Events ==="
kubectl get events --sort-by=.metadata.creationTimestamp -n "$namespace" | tail -10
}
# 获取访问信息
get_access_info() {
local namespace=${1:-default}
print_info "获取访问信息..."
local service_type=$(kubectl get service nginx-service -n "$namespace" -o jsonpath='{.spec.type}')
case "$service_type" in
"NodePort")
local node_port=$(kubectl get service nginx-service -n "$namespace" -o jsonpath='{.spec.ports[0].nodePort}')
local node_ip=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="ExternalIP")].address}')
if [[ -z "$node_ip" ]]; then
node_ip=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}')
fi
print_success "NodePort 访问地址: http://${node_ip}:${node_port}"
;;
"LoadBalancer")
print_info "等待 LoadBalancer 外部 IP..."
local external_ip=$(kubectl get service nginx-service -n "$namespace" -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
if [[ -n "$external_ip" ]]; then
print_success "LoadBalancer 访问地址: http://${external_ip}"
else
print_warning "LoadBalancer 外部 IP 仍在分配中"
fi
;;
"ClusterIP")
local cluster_ip=$(kubectl get service nginx-service -n "$namespace" -o jsonpath='{.spec.clusterIP}')
print_success "ClusterIP 访问地址: http://${cluster_ip}"
print_info "注意: ClusterIP 只能在集群内部访问"
;;
esac
}
# 主函数
main() {
print_info "开始 NGINX Kubernetes 自动部署..."
# 修改命名空间处理逻辑,优先使用 CI 变量
local namespace="app-nginx" # 默认值
if [[ -n "${K8S_NAMESPACE}" ]]; then
namespace="${K8S_NAMESPACE}" # 使用 GitHub Actions 变量
fi
print_info "使用命名空间: $namespace"
local deployment_file=${DEPLOYMENT_FILE:-./nginx-deployment.yaml}
local image_tag=${NGINX_IMAGE_TAG:-latest}
# 执行部署步骤
check_env_vars
check_kubectl
create_namespace "$namespace"
create_harbor_secret "$namespace"
# 添加命名空间环境变量替换
export DEPLOY_NAMESPACE="$namespace"
update_deployment_image "$deployment_file" "$image_tag"
apply_k8s_config "$deployment_file"
wait_for_deployment "$namespace"
show_deployment_status "$namespace"
get_access_info "$namespace"
print_success "🎉 NGINX 部署完成!"
}
# 清理函数
cleanup() {
print_info "执行清理操作..."
# 恢复备份文件
if [[ -f "./nginx-deployment.yaml.bak" ]]; then
mv "./nginx-deployment.yaml.bak" "./nginx-deployment.yaml"
fi
}
# 设置清理陷阱
trap cleanup EXIT
# 如果直接运行此脚本
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi