Files
k3s_auto_deploy/MANUAL-DEPLOYMENT-GUIDE.md

969 lines
20 KiB
Markdown
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.
# 手动创建项目并实现GitOps自动化部署指南
本指南将带你从零开始手动创建一个项目并实现GitOps自动化部署。
## 目录
1. [准备工作](#准备工作)
2. [创建项目结构](#创建项目结构)
3. [编写Kubernetes Manifests](#编写kubernetes-manifests)
4. [本地测试验证](#本地测试验证)
5. [上传到Gitea](#上传到gitea)
6. [配置ArgoCD自动部署](#配置argocd自动部署)
7. [验证和监控](#验证和监控)
8. [更新应用](#更新应用)
---
## 准备工作
### 环境要求
- K3s集群已部署并运行
- kubectl已配置并可访问集群
- Gitea已部署Git仓库服务
- ArgoCD已部署GitOps工具
- 域名已配置DNS解析
### 获取集群信息
```bash
# 查看集群节点
kubectl get nodes -o wide
# 获取Gitea访问地址
GITEA_PORT=$(kubectl get svc gitea-http -n gitea -o jsonpath='{.spec.ports[0].nodePort}')
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="ExternalIP")].address}')
echo "Gitea地址: http://$NODE_IP:$GITEA_PORT"
# 查看可用的IngressClass
kubectl get ingressclass
```
### 准备项目信息
在开始之前,确定以下信息:
- **项目名称**: 例如 `my-app`
- **域名**: 例如 `myapp.jpc.net3w.com`
- **应用类型**: Web应用、API服务、数据库等
- **容器镜像**: 例如 `nginx:1.25-alpine`
---
## 创建项目结构
### 步骤1: 创建项目目录
```bash
# 创建项目根目录
mkdir -p ~/my-app
cd ~/my-app
# 创建manifests目录存放Kubernetes配置文件
mkdir -p manifests
# 创建项目结构
tree
# my-app/
# └── manifests/
```
### 步骤2: 创建README文件
```bash
cat > README.md <<'EOF'
# My Application
这是一个由ArgoCD管理的应用使用GitOps自动化部署。
## 应用信息
- **应用名称**: my-app
- **域名**: myapp.jpc.net3w.com
- **命名空间**: default
## 访问方式
```bash
# HTTP访问
curl http://myapp.jpc.net3w.com
# HTTPS访问
curl https://myapp.jpc.net3w.com
```
## 更新应用
修改 `manifests/` 目录下的文件并提交到GitArgoCD会自动同步部署。
## 监控部署
```bash
# 查看Pod状态
kubectl get pods -l app=my-app -n default
# 查看ArgoCD Application
kubectl get application my-app -n argocd
```
EOF
```
---
## 编写Kubernetes Manifests
### 步骤3: 创建Deployment配置
```bash
cat > manifests/deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: default
labels:
app: my-app
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: nginx:1.25-alpine # 替换为你的镜像
ports:
- containerPort: 80
name: http
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
EOF
```
**配置说明**:
- `replicas: 2` - 运行2个Pod副本
- `image` - 容器镜像,根据实际情况修改
- `resources` - 资源限制,防止资源耗尽
- `livenessProbe` - 存活探针Pod不健康时自动重启
- `readinessProbe` - 就绪探针Pod未就绪时不接收流量
### 步骤4: 创建Service配置
```bash
cat > manifests/service.yaml <<'EOF'
apiVersion: v1
kind: Service
metadata:
name: my-app
namespace: default
labels:
app: my-app
spec:
type: ClusterIP
selector:
app: my-app
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
EOF
```
**配置说明**:
- `type: ClusterIP` - 集群内部访问
- `selector` - 选择带有 `app=my-app` 标签的Pod
- `port: 80` - Service端口
### 步骤5: 创建Ingress配置
```bash
cat > manifests/ingress.yaml <<'EOF'
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
namespace: default
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
traefik.ingress.kubernetes.io/router.entrypoints: websecure
spec:
ingressClassName: traefik # 使用traefik根据集群实际情况修改
tls:
- hosts:
- myapp.jpc.net3w.com # 替换为你的域名
secretName: my-app-tls
rules:
- host: myapp.jpc.net3w.com # 替换为你的域名
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app
port:
number: 80
EOF
```
**配置说明**:
- `ingressClassName` - 使用的Ingress控制器traefik或nginx
- `cert-manager.io/cluster-issuer` - 自动签发HTTPS证书
- `tls` - HTTPS配置
- `rules` - 路由规则将域名流量转发到Service
### 步骤6: 创建ConfigMap可选
如果需要自定义配置文件或HTML内容
```bash
cat > manifests/configmap.yaml <<'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
name: my-app-config
namespace: default
data:
# 配置文件内容
app.conf: |
server {
listen 80;
server_name myapp.jpc.net3w.com;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
# HTML内容
index.html: |
<!DOCTYPE html>
<html>
<head>
<title>My Application</title>
</head>
<body>
<h1>Welcome to My Application</h1>
<p>Version: v1.0</p>
</body>
</html>
EOF
```
如果使用ConfigMap需要在Deployment中挂载
```yaml
# 在deployment.yaml的containers部分添加
volumeMounts:
- name: config
mountPath: /etc/nginx/conf.d/app.conf
subPath: app.conf
- name: html
mountPath: /usr/share/nginx/html
# 在spec部分添加
volumes:
- name: config
configMap:
name: my-app-config
- name: html
configMap:
name: my-app-config
```
---
## 本地测试验证
### 步骤7: 验证YAML语法
```bash
# 验证所有manifest文件的语法
kubectl apply --dry-run=client -f manifests/
# 应该看到类似输出:
# deployment.apps/my-app created (dry run)
# service/my-app created (dry run)
# ingress.networking.k8s.io/my-app created (dry run)
```
### 步骤8: 本地部署测试
```bash
# 部署到集群
kubectl apply -f manifests/
# 查看部署状态
kubectl get pods -l app=my-app -n default
kubectl get svc my-app -n default
kubectl get ingress my-app -n default
# 查看Pod日志
kubectl logs -l app=my-app -n default --tail=50
# 查看Pod详情如果有问题
kubectl describe pod -l app=my-app -n default
```
### 步骤9: 测试访问
```bash
# 方式1: 通过Service ClusterIP测试集群内部
kubectl run test-pod --rm -it --image=curlimages/curl -- sh
# 在Pod内执行: curl http://my-app.default.svc.cluster.local
# 方式2: 通过域名测试
curl http://myapp.jpc.net3w.com
curl https://myapp.jpc.net3w.com
# 方式3: 通过Host header测试
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[0].address}')
curl -H "Host: myapp.jpc.net3w.com" http://$NODE_IP
```
### 步骤10: 验证成功后清理
```bash
# 测试成功后,删除手动部署的资源
# 稍后会通过ArgoCD重新部署
kubectl delete -f manifests/
```
---
## 上传到Gitea
### 步骤11: 在Gitea中创建仓库
**方式1: 通过Web界面创建**
1. 访问Gitea: `http://<NODE_IP>:<GITEA_PORT>`
2. 使用管理员账户登录gitea_admin / GitAdmin@2026
3. 点击右上角 "+" → "新建仓库"
4. 填写信息:
- 所有者: `k3s-apps`(组织)
- 仓库名称: `my-app`
- 描述: `My application for GitOps demo`
- 可见性: 公开
- 不要勾选"使用README初始化"
5. 点击"创建仓库"
**方式2: 通过API创建**
```bash
# 获取Gitea信息
GITEA_PORT=$(kubectl get svc gitea-http -n gitea -o jsonpath='{.spec.ports[0].nodePort}')
NODE_IP=8.216.38.248 # 替换为你的节点IP
GITEA_URL="http://$NODE_IP:$GITEA_PORT"
# 创建仓库
curl -X POST \
-u "gitea_admin:GitAdmin@2026" \
-H "Content-Type: application/json" \
-d '{"name":"my-app","description":"My application for GitOps demo","private":false,"auto_init":false}' \
"$GITEA_URL/api/v1/org/k3s-apps/repos"
# 验证仓库已创建
curl -s -u "gitea_admin:GitAdmin@2026" "$GITEA_URL/api/v1/orgs/k3s-apps/repos" | jq -r '.[].name'
```
### 步骤12: 初始化Git仓库
```bash
cd ~/my-app
# 初始化Git仓库
git init -b main
# 配置Git用户信息
git config user.name "gitea_admin"
git config user.email "admin@jpc.net3w.com"
# 添加所有文件
git add .
# 查看将要提交的文件
git status
# 提交
git commit -m "Initial commit: Add my-app manifests
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"
```
### 步骤13: 推送到Gitea
```bash
# 添加远程仓库
GITEA_PORT=$(kubectl get svc gitea-http -n gitea -o jsonpath='{.spec.ports[0].nodePort}')
NODE_IP=8.216.38.248 # 替换为你的节点IP
REPO_URL="http://$NODE_IP:$GITEA_PORT/k3s-apps/my-app.git"
git remote add origin "$REPO_URL"
# 推送(使用管理员账户)
git remote set-url origin "http://gitea_admin:GitAdmin%402026@$NODE_IP:$GITEA_PORT/k3s-apps/my-app.git"
git push -u origin main
# 验证推送成功
echo "访问Gitea查看仓库: $REPO_URL"
```
**常见问题**:
- **503错误**: Gitea服务可能正在启动等待几秒后重试
- **403错误**: 检查用户名密码是否正确
- **认证失败**: 确保密码中的特殊字符已URL编码@编码为%40
---
## 配置ArgoCD自动部署
### 步骤14: 创建ArgoCD Application
```bash
# 创建Application配置文件
cat > /tmp/my-app-argocd.yaml <<EOF
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
labels:
app: my-app
spec:
project: default
source:
repoURL: http://gitea-http.gitea.svc.cluster.local:3000/k3s-apps/my-app.git
targetRevision: main
path: manifests
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true # 自动删除Git中不存在的资源
selfHeal: true # 自动修复手动修改的资源
syncOptions:
- CreateNamespace=true
EOF
# 应用配置
kubectl apply -f /tmp/my-app-argocd.yaml
# 查看Application状态
kubectl get application my-app -n argocd
```
**配置说明**:
- `repoURL` - Git仓库地址使用集群内部地址
- `targetRevision: main` - 监控main分支
- `path: manifests` - manifests目录
- `automated` - 启用自动同步
- `prune: true` - 自动删除不需要的资源
- `selfHeal: true` - 自动修复被手动修改的资源
### 步骤15: 配置Git仓库凭证如果是私有仓库
```bash
# 创建Git凭证Secret
kubectl create secret generic gitea-creds \
-n argocd \
--from-literal=username="argocd" \
--from-literal=password="ArgoCD@2026" \
--dry-run=client -o yaml | kubectl apply -f -
```
### 步骤16: 手动触发首次同步
```bash
# 触发同步
kubectl patch application my-app -n argocd \
--type merge \
-p '{"operation":{"initiatedBy":{"username":"admin"},"sync":{"revision":"HEAD"}}}'
# 或者使用ArgoCD CLI如果已安装
argocd app sync my-app
```
---
## 验证和监控
### 步骤17: 监控同步状态
```bash
# 实时监控Application状态
watch kubectl get application my-app -n argocd
# 查看详细状态
kubectl describe application my-app -n argocd
# 查看同步历史
kubectl get application my-app -n argocd -o jsonpath='{.status.operationState}'
```
**状态说明**:
- `Sync Status: Synced` - 已同步
- `Health Status: Healthy` - 健康
- `Sync Status: OutOfSync` - 未同步Git有更新
- `Sync Status: Unknown` - 未知(可能有错误)
### 步骤18: 查看部署的资源
```bash
# 查看所有资源
kubectl get all -l app=my-app -n default
# 查看Pod
kubectl get pods -l app=my-app -n default -o wide
# 查看Service
kubectl get svc my-app -n default
# 查看Ingress
kubectl get ingress my-app -n default
# 查看证书状态
kubectl get certificate -n default | grep my-app
```
### 步骤19: 测试应用访问
```bash
# HTTP访问
curl http://myapp.jpc.net3w.com
# HTTPS访问
curl https://myapp.jpc.net3w.com
# 查看响应头
curl -I https://myapp.jpc.net3w.com
# 浏览器访问
echo "在浏览器中访问: https://myapp.jpc.net3w.com"
```
### 步骤20: 查看ArgoCD UI
```bash
# 获取ArgoCD访问地址
echo "ArgoCD UI: https://argocd.jpc.net3w.com"
# 获取admin密码如果忘记
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d && echo
```
在ArgoCD UI中可以看到
- 应用的同步状态
- 资源拓扑图
- 同步历史
- 事件日志
---
## 更新应用
### 方式1: 修改Git仓库
```bash
cd ~/my-app
# 修改配置(例如:增加副本数)
sed -i 's/replicas: 2/replicas: 3/' manifests/deployment.yaml
# 查看修改
git diff
# 提交更改
git add manifests/deployment.yaml
git commit -m "Scale up to 3 replicas"
git push
# ArgoCD会在3分钟内自动检测并同步
```
### 方式2: 创建更新脚本
```bash
cat > update-app.sh <<'EOF'
#!/bin/bash
set -e
VERSION=${1:-v2.0}
echo "🔄 更新应用到版本 $VERSION"
# 修改版本号(根据实际情况修改)
sed -i "s/Version: v[0-9.]*/Version: $VERSION/" manifests/configmap.yaml
# 提交更改
git add .
git commit -m "Update to $VERSION
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"
git push
echo "✅ 更新完成!"
echo "⏳ 等待ArgoCD同步约3分钟..."
EOF
chmod +x update-app.sh
# 使用脚本更新
./update-app.sh v2.0
```
### 方式3: 通过ArgoCD UI手动同步
1. 访问ArgoCD UI
2. 找到你的应用
3. 点击"SYNC"按钮
4. 选择同步选项
5. 点击"SYNCHRONIZE"
### 监控更新进度
```bash
# 监控Pod更新
watch kubectl get pods -l app=my-app -n default
# 查看滚动更新状态
kubectl rollout status deployment/my-app -n default
# 查看更新历史
kubectl rollout history deployment/my-app -n default
```
---
## 故障排查
### 常见问题1: Pod无法启动
```bash
# 查看Pod状态
kubectl get pods -l app=my-app -n default
# 查看Pod详情
kubectl describe pod -l app=my-app -n default
# 查看Pod日志
kubectl logs -l app=my-app -n default --tail=100
# 查看事件
kubectl get events -n default --sort-by='.lastTimestamp' | grep my-app
```
**可能原因**:
- 镜像拉取失败
- 资源不足
- 配置错误
- 健康检查失败
### 常见问题2: Ingress无法访问
```bash
# 检查Ingress配置
kubectl describe ingress my-app -n default
# 检查IngressClass
kubectl get ingressclass
# 测试Service是否正常
kubectl run test-pod --rm -it --image=curlimages/curl -- \
curl http://my-app.default.svc.cluster.local
# 检查DNS解析
nslookup myapp.jpc.net3w.com
```
**可能原因**:
- IngressClass配置错误应该是traefik
- DNS未解析到正确IP
- 证书未签发
- Service配置错误
### 常见问题3: ArgoCD不同步
```bash
# 查看Application状态
kubectl describe application my-app -n argocd
# 查看ArgoCD repo-server日志
kubectl logs -n argocd -l app.kubernetes.io/name=argocd-repo-server --tail=50
# 清除ArgoCD缓存
kubectl exec -n argocd deployment/argocd-repo-server -- \
sh -c "rm -rf /tmp/_argocd-repo/*"
# 重启repo-server
kubectl delete pod -n argocd -l app.kubernetes.io/name=argocd-repo-server
# 手动触发同步
kubectl patch application my-app -n argocd \
--type merge \
-p '{"operation":{"initiatedBy":{"username":"admin"},"sync":{"revision":"HEAD"}}}'
```
**可能原因**:
- Git仓库访问失败
- YAML语法错误
- ArgoCD缓存问题
- 网络问题
### 常见问题4: 证书未签发
```bash
# 查看证书状态
kubectl get certificate -n default
# 查看证书详情
kubectl describe certificate my-app-tls -n default
# 查看cert-manager日志
kubectl logs -n cert-manager -l app=cert-manager --tail=50
# 查看证书请求
kubectl get certificaterequest -n default
```
**可能原因**:
- cert-manager未正确配置
- DNS验证失败
- Let's Encrypt速率限制
- Ingress注解错误
---
## 回滚操作
### 通过Git回滚
```bash
cd ~/my-app
# 查看提交历史
git log --oneline
# 回滚到指定commit
git revert <commit-hash>
git push
# ArgoCD会自动同步回滚
```
### 通过kubectl回滚
```bash
# 查看部署历史
kubectl rollout history deployment/my-app -n default
# 回滚到上一个版本
kubectl rollout undo deployment/my-app -n default
# 回滚到指定版本
kubectl rollout undo deployment/my-app -n default --to-revision=2
```
### 通过ArgoCD回滚
```bash
# 查看历史版本
argocd app history my-app
# 回滚到指定版本
argocd app rollback my-app <revision-id>
```
---
## 清理资源
### 删除应用
```bash
# 删除ArgoCD Application会自动删除K8s资源
kubectl delete application my-app -n argocd
# 或者手动删除资源
kubectl delete -f manifests/
```
### 删除Git仓库
```bash
# 通过API删除
GITEA_PORT=$(kubectl get svc gitea-http -n gitea -o jsonpath='{.spec.ports[0].nodePort}')
NODE_IP=8.216.38.248
curl -X DELETE \
-u "gitea_admin:GitAdmin@2026" \
"http://$NODE_IP:$GITEA_PORT/api/v1/repos/k3s-apps/my-app"
```
---
## 最佳实践
### 1. 项目结构
```
my-app/
├── README.md # 项目说明
├── manifests/ # Kubernetes配置
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ └── configmap.yaml
├── update-app.sh # 更新脚本
└── .gitignore # Git忽略文件
```
### 2. 命名规范
- **应用名称**: 使用小写字母和连字符,如 `my-app`
- **标签**: 统一使用 `app=my-app`
- **命名空间**: 根据环境划分,如 `default`, `staging`, `production`
### 3. 资源配置
- **副本数**: 至少2个保证高可用
- **资源限制**: 必须设置requests和limits
- **健康检查**: 配置liveness和readiness探针
- **镜像标签**: 使用具体版本号避免使用latest
### 4. Git提交规范
```bash
# 好的提交信息
git commit -m "Add health check endpoint"
git commit -m "Scale up to 3 replicas"
git commit -m "Update to version 2.0"
# 不好的提交信息
git commit -m "update"
git commit -m "fix"
```
### 5. 安全建议
- 使用私有仓库存储敏感配置
- 使用Kubernetes Secrets存储密码
- 定期更新镜像版本
- 启用HTTPS和证书自动续期
- 配置网络策略限制Pod通信
### 6. 监控和日志
```bash
# 配置日志收集
kubectl logs -l app=my-app -n default --tail=100 -f
# 配置监控告警
# 使用Prometheus + Grafana监控应用指标
# 配置资源监控
kubectl top pods -l app=my-app -n default
```
---
## 快速参考
### 常用命令
```bash
# 查看应用状态
kubectl get all -l app=my-app -n default
# 查看ArgoCD Application
kubectl get application my-app -n argocd
# 查看日志
kubectl logs -l app=my-app -n default --tail=50 -f
# 进入Pod调试
kubectl exec -it <pod-name> -n default -- sh
# 查看资源使用
kubectl top pods -l app=my-app -n default
# 手动触发同步
kubectl patch application my-app -n argocd \
--type merge \
-p '{"operation":{"initiatedBy":{"username":"admin"},"sync":{"revision":"HEAD"}}}'
```
### 配置文件模板
所有配置文件模板可以在 `templates/` 目录找到,或参考现有项目:
- nginx-app: http://8.216.38.248:32158/k3s-apps/nginx-app
- test-app: http://8.216.38.248:32158/k3s-apps/test-app
- demo-app: http://8.216.38.248:32158/k3s-apps/demo-app
---
## 总结
通过本指南,你已经学会了:
1. ✅ 创建项目结构和编写Kubernetes manifests
2. ✅ 本地测试和验证配置
3. ✅ 上传代码到Gitea Git仓库
4. ✅ 配置ArgoCD实现GitOps自动化部署
5. ✅ 监控和更新应用
6. ✅ 故障排查和回滚操作
**GitOps工作流**:
```
开发者修改代码 → 提交到Git → ArgoCD检测变化 → 自动同步部署 → 应用更新完成
```
**下一步**:
- 学习更多Kubernetes资源类型StatefulSet, DaemonSet等
- 配置多环境部署dev, staging, production
- 集成CI/CD流水线Jenkins, GitLab CI等
- 配置监控告警系统Prometheus, Grafana
---
## 相关文档
- [K3s官方文档](https://docs.k3s.io/)
- [ArgoCD官方文档](https://argo-cd.readthedocs.io/)
- [Kubernetes官方文档](https://kubernetes.io/docs/)
- [Gitea官方文档](https://docs.gitea.io/)
## 技术支持
如有问题,请查看:
- 项目README: `/home/fei/opk3s/k3s自动化部署/README.md`
- 故障排查指南: `/home/fei/opk3s/k3s自动化部署/TROUBLESHOOTING-ACCESS.md`
- 部署指南: `/home/fei/opk3s/k3s自动化部署/DEPLOYMENT-GUIDE.md`