232 lines
8.2 KiB
YAML
232 lines
8.2 KiB
YAML
name: CI-CD-AKS-Agent
|
|
|
|
on:
|
|
push:
|
|
branches: ["main"]
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
build_and_deploy:
|
|
runs-on: self-hosted
|
|
|
|
env:
|
|
ACR_LOGIN_SERVER: ${{ secrets.ACR_LOGIN_SERVER }}
|
|
ACR_USERNAME: ${{ secrets.ACR_USERNAME }}
|
|
ACR_PASSWORD: ${{ secrets.ACR_PASSWORD }}
|
|
AZ_CLIENT_ID: ${{ secrets.AZ_CLIENT_ID }}
|
|
AZ_CLIENT_SECRET: ${{ secrets.AZ_CLIENT_SECRET }}
|
|
AZ_TENANT_ID: ${{ secrets.AZ_TENANT_ID }}
|
|
AZ_SUBSCRIPTION_ID: ${{ secrets.AZ_SUBSCRIPTION_ID }}
|
|
AZ_RG: ${{ secrets.AZ_RG }}
|
|
AZ_AKS: ${{ secrets.AZ_AKS }}
|
|
AZURE_DNS_ZONE: ${{ secrets.AZURE_DNS_ZONE }}
|
|
AZURE_DNS_RG: ${{ secrets.AZURE_DNS_RG }}
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Install Azure CLI
|
|
run: |
|
|
if ! command -v az &> /dev/null; then
|
|
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
|
|
fi
|
|
|
|
- name: Install kubectl
|
|
run: |
|
|
if ! command -v kubectl &> /dev/null; then
|
|
ARCH=$(uname -m)
|
|
case $ARCH in
|
|
x86_64) ARCH="amd64" ;;
|
|
aarch64|arm64) ARCH="arm64" ;;
|
|
esac
|
|
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/${ARCH}/kubectl"
|
|
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
|
|
rm kubectl
|
|
fi
|
|
|
|
- name: Build Docker image (ARM64)
|
|
run: |
|
|
docker build -t $ACR_LOGIN_SERVER/ai-agents/chat-v4-c5be6e:${{ github.sha }} .
|
|
docker tag $ACR_LOGIN_SERVER/ai-agents/chat-v4-c5be6e:${{ github.sha }} $ACR_LOGIN_SERVER/ai-agents/chat-v4-c5be6e:latest
|
|
|
|
- name: Debug Secrets
|
|
run: |
|
|
echo "ACR_LOGIN_SERVER=$ACR_LOGIN_SERVER"
|
|
echo "ACR_USERNAME=$ACR_USERNAME"
|
|
echo "ACR_PASSWORD length=$(echo -n "$ACR_PASSWORD" | wc -c)"
|
|
if [ -z "$ACR_PASSWORD" ]; then echo "ERROR: ACR_PASSWORD is empty!"; fi
|
|
|
|
- name: Login to ACR
|
|
run: |
|
|
echo "$ACR_PASSWORD" | docker login "$ACR_LOGIN_SERVER" -u "$ACR_USERNAME" --password-stdin
|
|
|
|
- name: Push Docker image
|
|
run: |
|
|
docker push $ACR_LOGIN_SERVER/ai-agents/chat-v4-c5be6e:${{ github.sha }}
|
|
docker push $ACR_LOGIN_SERVER/ai-agents/chat-v4-c5be6e:latest
|
|
|
|
echo "✅ 镜像已推送: $ACR_LOGIN_SERVER/ai-agents/chat-v4-c5be6e:latest"
|
|
|
|
- name: Login Azure
|
|
run: |
|
|
az login --service-principal \
|
|
-u "$AZ_CLIENT_ID" \
|
|
-p "$AZ_CLIENT_SECRET" \
|
|
--tenant "$AZ_TENANT_ID"
|
|
az account set --subscription "$AZ_SUBSCRIPTION_ID"
|
|
|
|
- name: Get AKS Credentials
|
|
run: |
|
|
az aks get-credentials \
|
|
--resource-group "$AZ_RG" \
|
|
--name "$AZ_AKS" \
|
|
--overwrite-existing
|
|
|
|
- name: Setup ACR Pull Secret
|
|
run: |
|
|
# 创建 Agent 专用命名空间
|
|
kubectl create namespace agent-chat-v4-c5be6e --dry-run=client -o yaml | kubectl apply -f -
|
|
|
|
# 创建或更新 ACR 拉取 Secret
|
|
kubectl create secret docker-registry acr-secret \
|
|
--docker-server=$ACR_LOGIN_SERVER \
|
|
--docker-username=$ACR_USERNAME \
|
|
--docker-password=$ACR_PASSWORD \
|
|
-n agent-chat-v4-c5be6e --dry-run=client -o yaml | kubectl apply -f -
|
|
|
|
- name: Deploy to AKS
|
|
run: |
|
|
# 删除旧的 deployment(如果存在)
|
|
kubectl delete deployment chat-v4-c5be6e -n agent-chat-v4-c5be6e --ignore-not-found=true
|
|
|
|
# 创建 deployment YAML
|
|
cat <<EOF | kubectl apply -f -
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: chat-v4-c5be6e
|
|
namespace: agent-chat-v4-c5be6e
|
|
labels:
|
|
app: chat-v4-c5be6e
|
|
managed-by: gitea-cicd
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: chat-v4-c5be6e
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: chat-v4-c5be6e
|
|
spec:
|
|
imagePullSecrets:
|
|
- name: acr-secret
|
|
nodeSelector:
|
|
kubernetes.io/arch: arm64
|
|
tolerations:
|
|
- key: "kubernetes.io/arch"
|
|
operator: "Equal"
|
|
value: "arm64"
|
|
effect: "NoSchedule"
|
|
containers:
|
|
- name: chat-v4-c5be6e
|
|
image: $ACR_LOGIN_SERVER/ai-agents/chat-v4-c5be6e:${{ github.sha }}
|
|
ports:
|
|
- containerPort: 8000
|
|
env:
|
|
- name: OPENAI_BASE_URL
|
|
value: "https://litellm.graystone-fb459c5d.southeastasia.azurecontainerapps.io/v1"
|
|
- name: MODEL_NAME
|
|
value: "taiji/gpt-4o-mini"
|
|
resources:
|
|
requests:
|
|
cpu: "100m"
|
|
memory: "128Mi"
|
|
limits:
|
|
cpu: "500m"
|
|
memory: "512Mi"
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 8000
|
|
initialDelaySeconds: 30
|
|
periodSeconds: 30
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 8000
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 10
|
|
EOF
|
|
|
|
# 创建 Service
|
|
cat <<EOF | kubectl apply -f -
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: chat-v4-c5be6e-service
|
|
namespace: agent-chat-v4-c5be6e
|
|
spec:
|
|
type: LoadBalancer
|
|
ports:
|
|
- port: 80
|
|
targetPort: 8000
|
|
selector:
|
|
app: chat-v4-c5be6e
|
|
EOF
|
|
|
|
- name: Wait for Deployment
|
|
run: |
|
|
kubectl rollout status deployment/chat-v4-c5be6e -n agent-chat-v4-c5be6e --timeout=180s || {
|
|
echo "=== Deployment 状态 ==="
|
|
kubectl get deployment chat-v4-c5be6e -n agent-chat-v4-c5be6e -o wide
|
|
echo "=== Pod 状态 ==="
|
|
kubectl get pods -l app=chat-v4-c5be6e -n agent-chat-v4-c5be6e -o wide
|
|
echo "=== Pod 事件 ==="
|
|
kubectl describe pods -l app=chat-v4-c5be6e -n agent-chat-v4-c5be6e | tail -30
|
|
exit 1
|
|
}
|
|
|
|
echo "=== 部署成功 ==="
|
|
kubectl get svc chat-v4-c5be6e-service -n agent-chat-v4-c5be6e
|
|
|
|
# 等待 LoadBalancer IP
|
|
echo "等待 LoadBalancer IP..."
|
|
for i in {1..30}; do
|
|
EXTERNAL_IP=$(kubectl get svc chat-v4-c5be6e-service -n agent-chat-v4-c5be6e -o jsonpath='{.status.loadBalancer.ingress[0].ip}' 2>/dev/null)
|
|
if [ -n "$EXTERNAL_IP" ]; then
|
|
echo "✅ Agent LoadBalancer IP: $EXTERNAL_IP"
|
|
echo "EXTERNAL_IP=$EXTERNAL_IP" >> $GITHUB_ENV
|
|
break
|
|
fi
|
|
sleep 10
|
|
done
|
|
|
|
- name: Create DNS Record
|
|
if: env.EXTERNAL_IP != ''
|
|
run: |
|
|
echo "创建 DNS 记录: chat-v4-c5be6e.$AZURE_DNS_ZONE -> $EXTERNAL_IP"
|
|
|
|
# 获取 Azure 访问令牌
|
|
ACCESS_TOKEN=$(az account get-access-token --query accessToken -o tsv)
|
|
|
|
# 创建 DNS A 记录 (DNS Zone 在单独的资源组中)
|
|
DNS_RG="${AZURE_DNS_RG:-taiji-Ai-v0}"
|
|
DNS_URL="https://management.azure.com/subscriptions/$AZ_SUBSCRIPTION_ID/resourceGroups/$DNS_RG/providers/Microsoft.Network/dnsZones/$AZURE_DNS_ZONE/A/chat-v4-c5be6e?api-version=2018-05-01"
|
|
|
|
curl -X PUT "$DNS_URL" \
|
|
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"properties": {
|
|
"TTL": 300,
|
|
"ARecords": [{"ipv4Address": "'"$EXTERNAL_IP"'"}]
|
|
}
|
|
}'
|
|
|
|
echo ""
|
|
echo "✅ DNS 记录创建成功!"
|
|
echo "🌐 Agent 访问地址: http://chat-v4-c5be6e.$AZURE_DNS_ZONE"
|
|
echo "🌐 Agent IP 地址: http://$EXTERNAL_IP"
|
|
|