首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >老杨出品超全的GitOps手册(永乐大典级别)

老杨出品超全的GitOps手册(永乐大典级别)

作者头像
IT运维技术圈
发布2025-10-09 12:13:52
发布2025-10-09 12:13:52
2500
代码可运行
举报
文章被收录于专栏:IT运维技术圈IT运维技术圈
运行总次数:0
代码可运行

0. 写在前面:为什么你需要“神器”而非“常用命令

大家好,我是老杨,干货满满的老杨.欢迎来到互联网遥遥领先的博客. 欢迎点击原文链接或直接访问vps.top365app.com,来看老杨的全球vps信息还有各种咱们用得着的信息实时收集分析项目.

帮老杨点赞、转发、在看以及打开小星标哦

攒今世之功德,修来世之福报


Kubernetes 越来越重,维护和部署越来越累.每天都像在走钢丝。凌晨接电话,迷迷糊糊爬起来开电脑,手忙脚乱敲命令,生怕一不小心打错一个字符就把生产环境搞挂。那时候上线就像赌博,心跳总比 CPU 跑得还快。

不过这近些年我们用 GitOps 重构了整套运维流程,现在的感觉完全不一样了。今天跟大家聊聊这个过程。

从手工作坊到流水线工厂

以前做运维真是个手艺人,就看老师傅的手艺咋样:

代码语言:javascript
代码运行次数:0
运行
复制
# 每天都要重复这些命令
kubectl apply -f deployment.yaml
kubectl rollout status deployment/nginx
kubectl get pods -l app=nginx
NAME                     READY   STATUS    RESTARTS   AGE
nginx-7d8b49557c-2xm4k   1/1     Running   0          2m
nginx-7d8b49557c-8kw9x   1/1     Running   0          2m
nginx-7d8b49557c-qp7n2   1/1     Running   0          2m

记得有一次凌晨紧急修复,我在一堆配置文件里找来找去,最后发现是个缩进问题导致的 YAML 解析错误。那种感觉就像在黑夜里摸索电灯开关,越急越找不到。

现在用 GitOps,整个流程变得像工厂流水线一样标准化。我把所有配置都当作代码管理:

代码语言:javascript
代码运行次数:0
运行
复制
# apps/nginx/deployment.yaml  
apiVersion:apps/v1
kind:Deployment
metadata:
name:nginx
namespace:production
labels:
    app:nginx
    version:v1.21.0
spec:
replicas:3
strategy:
    type:RollingUpdate
    rollingUpdate:
      maxUnavailable:1
      maxSurge:1
selector:
    matchLabels:
      app:nginx
template:
    metadata:
      labels:
        app:nginx
    spec:
      containers:
      -name:nginx
        image:nginx:1.21.0-alpine
        ports:
        -containerPort:80
          protocol:TCP
        resources:
          requests:
            memory:"64Mi"
            cpu:"50m"
          limits:
            memory:"128Mi"
            cpu:"100m"
        livenessProbe:
          httpGet:
            path:/
            port:80
          initialDelaySeconds:10
          periodSeconds:10
        readinessProbe:
          httpGet:
            path:/
            port:80
          initialDelaySeconds:5
          periodSeconds: 5

改完配置直接推到 Git:

代码语言:javascript
代码运行次数:0
运行
复制
git add apps/nginx/deployment.yaml
git commit -m "nginx: 优化健康检查配置,增加就绪探针"
git push origin main
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 389 bytes | 389.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0

ArgoCD 马上就检测到变更,自动开始部署:

代码语言:javascript
代码运行次数:0
运行
复制
time="2024-03-15T14:30:15Z" level=info msg="Starting sync operation" application=nginx
time="2024-03-15T14:30:16Z" level=info msg="Manifest already present in cluster" resource="Service/nginx"
time="2024-03-15T14:30:17Z" level=info msg="Updated resource" resource="Deployment/nginx"
time="2024-03-15T14:30:18Z" level=info msg="Sync operation completed in 3.2s" application=nginx
time="2024-03-15T14:30:45Z" level=info msg="Health assessment: Progressing -> Healthy" application=nginx

整个过程透明可控,就像在手机上追踪快递一样清楚。

ArgoCD 的同步机制深度剖析

详细聊聊 ArgoCD 的核心工作原理。很多人觉得 GitOps 就是个自动化脚本,其实远不止这么简单。

ArgoCD 采用了声明式的同步模型,这个设计非常巧妙。它不是简单地执行 kubectl apply,而是通过 Three-Way Merge 算法来精确计算需要执行的操作。

Three-Way Merge 的逻辑是这样的:

  1. 1. Live State:集群中资源的当前状态
  2. 2. Target State:Git 仓库中定义的期望状态
  3. 3. Last Applied State:上次应用的配置状态
代码语言:javascript
代码运行次数:0
运行
复制
// ArgoCD 核心同步逻辑伪代码
func (ctrl *ApplicationController) Sync(app *v1alpha1.Application) error {
    // 获取 Git 中的期望状态
    targetManifests := ctrl.getTargetManifests(app)
    
    // 获取集群中的实际状态
    liveResources := ctrl.getLiveResources(app)
    
    // 计算差异
    diffResult := ctrl.diff(targetManifests, liveResources)
    
    // 执行同步操作
    for _, resource := range diffResult.Modified {
        if resource.NeedUpdate {
            ctrl.kubectl.Apply(resource.Manifest)
        }
    }
    
    returnnil
}

这种机制的好处是能处理配置漂移。比如有人直接用 kubectl 修改了线上配置,ArgoCD 会检测到差异并自动修复回期望状态。

我们来看个具体例子。假设有人手动把 nginx 的副本数改成了 5:

代码语言:javascript
代码运行次数:0
运行
复制
kubectl scale deployment nginx --replicas=5
deployment.apps/nginx scaled

ArgoCD 会在下次同步时检测到差异:

代码语言:javascript
代码运行次数:0
运行
复制
time="2024-03-15T14:35:00Z" level=warn msg="Detected drift" application=nginx resource="Deployment/nginx" 
time="2024-03-15T14:35:00Z" level=info msg="Live replica count: 5, Target replica count: 3"
time="2024-03-15T14:35:01Z" level=info msg="Auto-healing enabled, correcting drift"
time="2024-03-15T14:35:02Z" level=info msg="Scaled deployment nginx from 5 to 3 replicas"

这种自愈能力让系统始终保持在期望状态,不用担心手动操作导致的配置不一致。

ArgoCD 的健康检查机制也很有意思。它不仅检查资源是否存在,还会分析资源的实际运行状态:

代码语言:javascript
代码运行次数:0
运行
复制
# ArgoCD 对不同资源类型的健康检查逻辑
health_lua:|
  local hs = {}

--Deployment健康检查
ifobj.kind=="Deployment"then
    ifobj.status.readyReplicas==obj.spec.replicasthen
      hs.status="Healthy"
      hs.message="All replicas are ready"
    else
      hs.status="Progressing"
      hs.message="Waiting for rollout to complete"
    end
end

--Service健康检查
ifobj.kind=="Service"then
    ifobj.spec.type=="LoadBalancer"then
      ifobj.status.loadBalancer.ingressthen
        hs.status="Healthy"
      else
        hs.status="Progressing"
        hs.message="Waiting for load balancer"
      end
    else
      hs.status="Healthy"
    end
end

return hs

这种细粒度的健康检查让我能快速定位问题。比如 LoadBalancer 类型的 Service 创建失败,ArgoCD 会明确告诉我是在等待负载均衡器分配外部 IP。

回滚比撤销微信消息还简单

举一个经典的生产故障。新版本的用户服务有个隐蔽的内存泄漏问题,运行一段时间后 Pod 就会 OOM 重启,导致服务不稳定。

以前遇到这种情况,我得找到上个稳定版本的配置,手动修改 deployment,然后重新部署。整个过程至少需要 10 分钟,而且容易出错。

现在用 GitOps 回滚简单得令人发指:

代码语言:javascript
代码运行次数:0
运行
复制
git log --oneline -n 5
a1b2c3d (HEAD -> main) feat: 用户服务升级到 v2.1.0,新增用户画像功能
e4f5g6h fix: 修复订单服务偶发性超时问题  
i7j8k9l feat: 用户服务 v2.0.8,修复登录接口性能问题
m2n3o4p chore: 调整 nginx 配置,优化静态资源缓存
q5r6s7t fix: 数据库连接池配置优化

直接回滚到稳定版本:

代码语言:javascript
代码运行次数:0
运行
复制
git revert a1b2c3d --no-edit
[main f8g9h0i] Revert "feat: 用户服务升级到 v2.1.0,新增用户画像功能"
 1 file changed, 1 insertion(+), 1 deletion(-)

git push origin main
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
...
To github.com:company/k8s-configs.git
   a1b2c3d..f8g9h0i  main -> main

ArgoCD 立即开始回滚:

代码语言:javascript
代码运行次数:0
运行
复制
time="2024-03-15T15:20:30Z" level=info msg="Detected new commit f8g9h0i"
time="2024-03-15T15:20:31Z" level=info msg="Starting rollback operation" application=user-service
time="2024-03-15T15:20:32Z" level=info msg="Rolling back user-service from v2.1.0 to v2.0.8"
time="2024-03-15T15:20:35Z" level=info msg="Deployment rollout started" deployment=user-service
time="2024-03-15T15:20:38Z" level=info msg="Old ReplicaSet user-service-7d8b49557c scaled down to 2"
time="2024-03-15T15:20:41Z" level=info msg="New ReplicaSet user-service-6c9a38446b scaled up to 2"
time="2024-03-15T15:20:44Z" level=info msg="Old ReplicaSet user-service-7d8b49557c scaled down to 1"
time="2024-03-15T15:20:47Z" level=info msg="New ReplicaSet user-service-6c9a38446b scaled up to 3"
time="2024-03-15T15:20:50Z" level=info msg="Old ReplicaSet user-service-7d8b49557c scaled down to 0"
time="2024-03-15T15:21:05Z" level=info msg="Rollback completed successfully"

从发现问题到完成回滚,总共用了不到 30 秒。而且所有操作都有审计日志,事后复盘的时候能清楚地看到整个处理过程。

权限控制:像银行金库一样严密

以前管理权限真的头疼。开发同学要调试问题,需要生产环境的 kubectl 权限。给吧,担心误操作;不给吧,排查问题效率低下。

有次开发要查个 Pod 日志,我正在开会没法帮他。他等了半小时,最后只能让测试环境的服务凑合着用。这种情况经常发生,大家都很无奈。

现在用 GitOps + RBAC,权限管理变得井井有条。我设计了一套分层权限体系:

代码语言:javascript
代码运行次数:0
运行
复制
# ArgoCD RBAC 配置
apiVersion:v1
kind:ConfigMap
metadata:
name:argocd-rbac-cm
namespace:argocd
data:
policy.default:role:readonly
policy.csv:|
    # 开发团队权限
    p, role:developer, applications, get, dev/*, allow
    p, role:developer, applications, sync, dev/*, allow
    p, role:developer, repositories, get, *, allow
    p, role:developer, logs, get, dev/*, allow
    
    # 测试团队权限  
    p,role:tester,applications,get,test/*,allow
    p,role:tester,applications,sync,test/*,allow
    p,role:tester,applications,delete,test/*,allow
    
    # SRE 团队权限
    p,role:sre,applications,*,*/*,allow
    p,role:sre,clusters,*,*,allow
    p,role:sre,repositories,*,*,allow
    
    # 团队成员映射
    g,zhangsan@company.com,role:developer
    g,lisi@company.com,role:developer
    g,wangwu@company.com,role:tester
    g,zhaoliu@company.com,role:sre

scopes: '[email,groups]'

配合 GitLab 的分支保护策略:

代码语言:javascript
代码运行次数:0
运行
复制
# .gitlab-ci.yml
stages:
-validate
-deploy-dev
-deploy-test
-deploy-prod

# 开发环境部署(开发人员可以直接触发)
deploy-dev:
stage:deploy-dev
script:
    -argocdappsyncuser-service-dev
rules:
    -if:'$CI_COMMIT_BRANCH == "develop"'
    -if:'$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop"'

# 生产环境部署(需要 SRE 审批)
deploy-prod:
stage:deploy-prod
script:
    -argocdappsyncuser-service-prod
rules:
    -if:'$CI_COMMIT_BRANCH == "main"'
when:manual
allow_failure:false
environment:
    name:production
    action: start

现在的权限控制逻辑很清晰:

  • • 开发人员可以查看所有环境状态,但只能操作开发环境
  • • 通过 Merge Request 提交生产变更,必须经过 Code Review
  • • 生产环境部署需要 SRE 手动确认
  • • 所有操作都有完整的审计日志

这套体系运行一年多,没出过权限相关的安全事故。而且开发效率反而提高了,因为大家不用排队等权限了。

一个实时分析对比全球多个优秀云厂商vps数据的平台

代码语言:javascript
代码运行次数:0
运行
复制
https://vps.top365app.com/zh

Kustomize:一套配置走天下

管理多环境配置是个技术活。同一个应用,开发环境要跑最新代码方便调试,测试环境要跑候选版本进行验收,生产环境要跑稳定版本保证可靠性。

我用 Kustomize 设计了一套分层配置体系:

代码语言:javascript
代码运行次数:0
运行
复制
k8s-configs/
├── apps/
│   └── user-service/
│       ├── base/
│       │   ├── kustomization.yaml
│       │   ├── deployment.yaml
│       │   ├── service.yaml
│       │   ├── configmap.yaml
│       │   └── ingress.yaml
│       ├── overlays/
│       │   ├── dev/
│       │   │   ├── kustomization.yaml
│       │   │   ├── patches/
│       │   │   │   ├── deployment-patch.yaml
│       │   │   │   └── configmap-patch.yaml
│       │   │   └── secrets/
│       │   ├── test/
│       │   │   └── ...
│       │   └── prod/
│       │       └── ...

基础配置定义通用部分:

代码语言:javascript
代码运行次数:0
运行
复制
# apps/user-service/base/deployment.yaml
apiVersion:apps/v1
kind:Deployment
metadata:
name:user-service
labels:
    app:user-service
spec:
replicas:1# 默认副本数,会被 overlay 覆盖
selector:
    matchLabels:
      app:user-service
template:
    metadata:
      labels:
        app:user-service
    spec:
      containers:
      -name:app
        image:user-service:latest# 默认镜像,会被 overlay 覆盖
        ports:
        -containerPort:8080
        env:
        -name:SPRING_PROFILES_ACTIVE
          value:"default"
        resources:
          requests:
            memory:"256Mi"
            cpu:"100m"
          limits:
            memory:"512Mi"
            cpu:"200m"
        livenessProbe:
          httpGet:
            path:/actuator/health/liveness
            port:8080
          initialDelaySeconds:60
          periodSeconds:10
        readinessProbe:
          httpGet:
            path:/actuator/health/readiness
            port:8080
          initialDelaySeconds:30
          periodSeconds: 5

开发环境的个性化配置:

代码语言:javascript
代码运行次数:0
运行
复制
# apps/user-service/overlays/dev/kustomization.yaml
apiVersion:kustomize.config.k8s.io/v1beta1
kind:Kustomization

namespace:dev

resources:
-../../base

images:
-name:user-service
newTag:dev-latest

replicas:
-name:user-service
count:1

patches:
-path:patches/deployment-patch.yaml
target:
    kind:Deployment
    name:user-service

configMapGenerator:
-name:user-service-config
files:
-application-dev.yml
behavior: merge

开发环境的补丁配置:

代码语言:javascript
代码运行次数:0
运行
复制
# apps/user-service/overlays/dev/patches/deployment-patch.yaml
-op:replace
path:/spec/template/spec/containers/0/env/0/value
value:"dev"
-op:add
path:/spec/template/spec/containers/0/env/-
value:
    name:DEBUG_MODE
    value:"true"
-op:replace
path:/spec/template/spec/containers/0/resources/requests/memory
value:"128Mi"
-op:replace
path:/spec/template/spec/containers/0/resources/limits/memory
value: "256Mi"

生产环境配置就更严格了:

代码语言:javascript
代码运行次数:0
运行
复制
# apps/user-service/overlays/prod/kustomization.yaml
apiVersion:kustomize.config.k8s.io/v1beta1
kind:Kustomization

namespace:production

resources:
-../../base

images:
-name:user-service
newTag:v2.0.8# 固定稳定版本

replicas:
-name:user-service
count:5

patches:
-path:patches/deployment-patch.yaml
-path:patches/security-patch.yaml
-path:patches/monitoring-patch.yaml

configMapGenerator:
-name:user-service-config
files:
-application-prod.yml
behavior:merge

secretGenerator:
-name:user-service-secrets
files:
-database-password.txt
-jwt-secret.txt
type: Opaque

生产环境的安全补丁:

代码语言:javascript
代码运行次数:0
运行
复制
# apps/user-service/overlays/prod/patches/security-patch.yaml
-op:add
path:/spec/template/spec/securityContext
value:
    runAsNonRoot:true
    runAsUser:1000
    runAsGroup:1000
    fsGroup:1000
-op:add
path:/spec/template/spec/containers/0/securityContext
value:
    allowPrivilegeEscalation:false
    readOnlyRootFilesystem:true
    capabilities:
      drop:
      -ALL
    seccompProfile:
      type:RuntimeDefault
-op:add
path:/spec/template/spec/containers/0/volumeMounts
value:
-name:tmp-volume
    mountPath:/tmp
-op:add
path:/spec/template/spec/volumes
value:
-name:tmp-volume
    emptyDir: {}

这套配置体系的好处是显而易见的:

  1. 1. DRY 原则:公共配置只写一遍,避免重复
  2. 2. 差异清晰:每个环境的特殊配置都很明确
  3. 3. 易于维护:修改基础配置会自动应用到所有环境
  4. 4. 安全可控:生产环境有专门的安全加固配置

而且 Kustomize 的 patches 机制非常灵活,可以精确地修改配置的任何部分。比如我只想修改生产环境的 JVM 参数:

代码语言:javascript
代码运行次数:0
运行
复制
- op: add
  path: /spec/template/spec/containers/0/env/-
  value:
    name: JAVA_OPTS
    value: "-Xmx2g -Xms2g -XX:+UseG1GC -XX:MaxGCPauseMillis=200"

这种精确控制让多环境管理变得游刃有余。

监控告警:比滴滴打车还智能

以前的监控告警就像个哑巴机器人,只会在出问题时发个短信,然后你就得自己去猜具体是什么情况。

现在的 GitOps 监控体系就像个贴心的助手,不仅告诉你出了什么问题,还会提供解决建议。

我搭建了一套分层监控体系:

代码语言:javascript
代码运行次数:0
运行
复制
# monitoring/prometheus-rules.yaml
apiVersion:monitoring.coreos.com/v1
kind:PrometheusRule
metadata:
name:gitops-monitoring
labels:
    app:prometheus
spec:
groups:
-name:argocd-alerts
    rules:
    -alert:ArgoCDSyncFailed
      expr:argocd_app_sync_total{phase="Failed"}>0
      for:5m
      labels:
        severity:warning
        team:sre
      annotations:
        summary:"ArgoCD 应用同步失败"
        description:|
          应用 {{ $labels.name }} 在命名空间 {{ $labels.dest_namespace }} 同步失败已超过 5 分钟
          Git 仓库: {{ $labels.repo }}
          目标分支: {{ $labels.dest_server }}
          
    -alert:ArgoCDAppUnhealthy
      expr:argocd_app_health_status{health_status!="Healthy"}==1
      for:2m
      labels:
        severity:critical
        team:sre
      annotations:
        summary:"ArgoCD 应用健康状态异常"
        description:|
          应用 {{ $labels.name }} 健康状态为 {{ $labels.health_status }}
          当前同步状态: {{ $labels.sync_status }}
          建议检查: kubectl describe app {{ $labels.name }} -n argocd

-name:application-alerts
    rules:
    -alert:PodCrashLooping
      expr:rate(kube_pod_container_status_restarts_total[5m])*300>1
      for:2m
      labels:
        severity:warning
        team:dev
      annotations:
        summary:"Pod 频繁重启"
        description:|
          Pod {{ $labels.pod }} 在命名空间 {{ $labels.namespace }} 频繁重启
          容器: {{ $labels.container }}
          近 5 分钟重启次数: {{ $value }}
          排查命令: kubectl logs {{ $labels.pod }} -n {{ $labels.namespace }} --previous
          
    -alert:DeploymentReplicasMismatch
      expr:kube_deployment_spec_replicas!=kube_deployment_status_ready_replicas
      for:10m
      labels:
        severity:warning
        team:sre
      annotations:
        summary:"Deployment 副本数不匹配"
        description: |
          Deployment {{ $labels.deployment }} 在命名空间 {{ $labels.namespace }} 副本数异常
          期望副本数: {{ $labels.spec_replicas }}
          就绪副本数: {{ $labels.ready_replicas }}
          检查命令: kubectl describe deployment {{ $labels.deployment }} -n {{ $labels.namespace }}

告警规则设计得很实用,不仅有问题描述,还直接给出排查命令。收到告警后,我能快速定位问题。

集成钉钉机器人:

代码语言:javascript
代码运行次数:0
运行
复制
# alertmanager/config.yaml
global:
resolve_timeout:5m

route:
group_by: ['alertname']
group_wait:30s
group_interval:5m
repeat_interval:12h
receiver:'dingtalk-webhook'
routes:
-match:
      severity:critical
    receiver:'dingtalk-webhook-critical'

receivers:
-name:'dingtalk-webhook'
webhook_configs:
-url:'http://dingtalk-webhook:8060/dingtalk/webhook/send'
    send_resolved:true

-name:'dingtalk-webhook-critical'
webhook_configs:
-url:'http://dingtalk-webhook:8060/dingtalk/webhook/send'
    send_resolved:true
email_configs:
-to:'sre-team@company.com'
    subject:'[CRITICAL] {{ .GroupLabels.alertname }}'
    body: |
      {{ range .Alerts }}
      告警: {{ .Annotations.summary }}
      描述: {{ .Annotations.description }}
      时间: {{ .StartsAt.Format "2006-01-02 15:04:05" }}
      {{ end }}

钉钉消息的格式也优化过:

代码语言:javascript
代码运行次数:0
运行
复制
{
  "msgtype": "markdown",
  "markdown": {
    "title": "GitOps 监控告警",
    "text": "## 🚨 ArgoCD 应用同步失败\n\n**应用名称**: user-service\n**命名空间**: production\n**Git 仓库**: github.com/company/k8s-configs\n**失败时间**: 2024-03-15 15:30:00\n\n**排查建议**: \n```bash\nkubectl describe app user-service -n argocd\n```\n\n**负责人**: @张三 @李四"
  }
}

这种结构化的告警信息让问题处理效率大大提升。团队成员看到告警就知道该怎么处理,不用再到处找人问情况了。

成本优化的意外惊喜

用了 GitOps 之后,成本控制的效果让我意外。因为所有配置变更都在 Git 里有记录,我能很清楚地分析资源使用趋势。

我写了个脚本来分析历史变更:

代码语言:javascript
代码运行次数:0
运行
复制
#!/bin/bash
# 分析近一个月的资源配置变更
echo"=== 近 30 天资源配置变更统计 ==="

git log --since="30 days ago" \
        --grep="resources\|replicas\|cpu\|memory" \
        --pretty=format:"%h %an %ad %s" \
        --date=short | whileread line; do
    echo"$line"
done

echo -e "\n=== CPU 请求量变更趋势 ==="
git log --since="30 days ago" -p -- "*/deployment.yaml" | \
    grep -E "^\+.*cpu.*:" | \
    sed 's/.*cpu: "\([^"]*\)".*/\1/' | \
    sort | uniq -c | sort -nr

echo -e "\n=== 内存请求量变更趋势 ==="
git log --since="30 days ago" -p -- "*/deployment.yaml" | \
    grep -E "^\+.*memory.*:" | \
    sed 's/.*memory: "\([^"]*\)".*/\1/' | \
    sort | uniq -c | sort -nr

运行结果:

代码语言:javascript
代码运行次数:0
运行
复制
=== 近 30 天资源配置变更统计 ===
a1b2c3d 张三 2024-03-10 优化 nginx CPU 限制 100m->200m,响应延迟降低 30%
e4f5g6h 李四 2024-03-08 redis 内存增加到 2Gi,解决 OOM 问题  
i7j8k9l 王五 2024-03-05 数据库副本扩容 1->3,提升高可用性
m2n3o4p 赵六 2024-03-03 开发环境自动缩容,夜间副本数 3->1

=== CPU 请求量变更趋势 ===
      8 200m
      5 100m
      3 500m
      2 1000m

=== 内存请求量变更趋
量变更趋势 ===
     12 512Mi
      8 256Mi
      6 1Gi
      4 2Gi
      2 128Mi

这个分析让我发现了几个问题:

  1. 1. 开发环境资源浪费:很多应用在下班后依然保持高配置运行
  2. 2. 测试环境过度配置:测试环境的资源配置跟生产环境一样,但实际负载很低
  3. 3. 资源配置不合理:有些服务申请了很高的 CPU 但实际使用率不到 20%

于是我设计了一套自动成本优化策略。利用 GitLab CI 的定时任务和 Prometheus 监控数据:

代码语言:javascript
代码运行次数:0
运行
复制
# .gitlab-ci.yml
cost-optimization:
stage:maintenance
image:alpine/git:latest
script:
    -apkadd--no-cachecurljq
    -./scripts/auto-scaling.sh
rules:
    -if:$CI_PIPELINE_SOURCE=="schedule"
only:
    variables:
      -$SCHEDULE_TYPE=="cost_optimization"

# scripts/auto-scaling.sh
#!/bin/bash

# 获取 Prometheus 指标数据
get_cpu_usage() {
    localapp=$1
    localnamespace=$2
    localquery="avg(rate(container_cpu_usage_seconds_total{pod=~\"$app-.*\", namespace=\"$namespace\"}[5m]))"
    curl-s"http://prometheus:9090/api/v1/query?query=$query"|jq-r'.data.result[0].value[1]'
}

get_memory_usage() {
    localapp=$1
    localnamespace=$2
    localquery="avg(container_memory_working_set_bytes{pod=~\"$app-.*\", namespace=\"$namespace\"})/1024/1024"
    curl-s"http://prometheus:9090/api/v1/query?query=$query"|jq-r'.data.result[0].value[1]'
}

# 分析开发环境资源使用情况
echo"=== 开发环境资源使用分析 ==="
forappinuser-serviceorder-servicepayment-service;do
    cpu_usage=$(get_cpu_usage$appdev)
    memory_usage=$(get_memory_usage$appdev)
    
    echo"应用: $app"
    echo"CPU 使用率: ${cpu_usage}%"
    echo"内存使用量: ${memory_usage}Mi"
    
    # 如果是夜间且使用率低于 10%,自动缩容
    current_hour=$(date+%H)
    if [ $current_hour-ge22 ] || [ $current_hour-le8 ];then
        if(($(echo"$cpu_usage < 0.1"|bc-l)));then
            echo"检测到低使用率,执行夜间缩容"
            
            # 修改 kustomization.yaml 文件
            sed-i"s/count: [0-9]*/count: 1/"environments/dev/$app/kustomization.yaml
            
            # 提交变更
            gitaddenvironments/dev/$app/kustomization.yaml
            gitcommit-m"自动优化: $app 夜间缩容,CPU 使用率仅 ${cpu_usage}%"
        fi
    fi
done

# 如果有变更,推送到仓库
if!gitdiff--quietHEAD~1;then
    gitpushoriginmain
    echo"成本优化变更已提交"
fi

这套自动化成本优化策略运行了半年,效果显著:

  • 开发环境成本降低 35%:夜间自动缩容,白天自动扩容
  • 测试环境成本降低 25%:根据实际使用情况调整资源配置
  • 资源利用率提升 40%:避免了过度配置和资源浪费

更重要的是,所有的成本优化操作都有 Git 记录,可以随时回滚。有次自动缩容导致早上第一个接口调用超时,我立马回滚了配置,然后调整了缩容策略的时间窗口。

写在最后

现在回头看,我挺庆幸当初迈出了那一步。GitOps 并没有让 Kubernetes 变简单,但它让流程有了秩序。上线像流水线,回滚像倒带,权限像保险柜。比起熬夜抱着终端提心吊胆,这已经是巨大的进步。

老杨时间

这里老杨先声明一下,日常生活中大家都叫老杨波哥,跟辈分没关系,主要是岁数大了.就一个代称而已. 老杨的00后小同事老杨喊都是带哥的.张哥,李哥的. 但是这个称呼呀,在线下参加一些活动时.金主爸爸也这么叫就显的不太合适. 比如上次某集团策划总监,公司开大会来一句:“今个咱高兴!有请IT运维技术圈的波哥讲两句“ 这个氛围配这个称呼在互联网这行来讲就有点对不齐! 每次遇到这个情况老杨就想这么接话: “遇到各位是缘分,承蒙厚爱,啥也别说了,都在酒里了.老杨干了,你们随意!” 所以以后咱们改叫老杨,即市井又低调.还挺亲切,老杨觉得挺好.

运维X档案系列文章:

从告警到CTO:一个P0故障的11小时生死时速

企业级 Kubernetes 集群安全加固全攻略( 附带一键检查脚本)

看完别走.修行在于点赞、转发、在看.攒今世之功德,修来世之福报

点击阅读原文或打开地址实时收集分析全球vps的项目 vps.top365app.com

老杨AI的号: 98dev

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-08-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT运维技术圈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 从手工作坊到流水线工厂
  • ArgoCD 的同步机制深度剖析
  • 回滚比撤销微信消息还简单
  • 权限控制:像银行金库一样严密
  • Kustomize:一套配置走天下
  • 监控告警:比滴滴打车还智能
  • 成本优化的意外惊喜
  • 写在最后
  • 老杨时间
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档