找回密码
 立即注册
首页 业界区 安全 从 ”以应用为中心“ 的交付看DevOps平台的演进趋势 ...

从 ”以应用为中心“ 的交付看DevOps平台的演进趋势

凳舒 2025-7-3 22:07:45
引子-从传统的安装包到云原生时代的应用

过去,在传统的通过shell命令行部署的时代,开发者们习惯于按照面向过程的方式一步步通过代码编译构建打包,然后把安装包远程部署到环境上,安装包就是安装包,环境就是环境,部署脚本就是部署脚本。
随着k8s云原生和DevOps的普及,一种新的实践形式“应用” 脱颖而出,它的具体表现是通过一组声明式资源配置(Deployment、Service、ConfigMap 等)定义的容器化服务,可伸缩,可观测,通过GitOps直接从“代码”到“可运行的服务”。
在持续交付中,“应用”是最终要交付给用户的功能性实体,可以是单体应用(Monolithic Application)、云原生应用(Cloud-Native Application)、移动应用,这些仅仅是技术架构层面的解释,那么对于研发生命周期而言,应用又会带来什么不同的价值呢?
本篇文章将带大家从“研发生命周期”和“DevOps平台建设”的角度,诠释“应用新的含义”。
以“应用为中心”-建立“管理过程”和“研发过程”的纽带

如下图,这是一个很典型的产品版本需求迭代,到部署发布的简单示意图。
1.png

接着下面的图,当代码提交入库,触发Pipeline,最终形成一个可部署运行的应用服务。
2.png

这里我们思考几个问题

  • 1. 从“产品(需求)” 到“服务应用”之间是什么关系?前者是业务,后者是技术,从业务到技术实现如何表达?
  • 2. 将”一个市场需求“,快速的实现并且上线,需要多少个步骤?需要几个代码库的变更?涉及哪几个安装包/镜像?又有几个流水线需要编排?
  • 3. 在复杂且冗长的工具链编排中,如何精准的定位追溯每一次变更,快速的试错和回滚?
看到这里,可能你会习以为常,我们平时就是这样做的,有什么问题?
从“面向过程”到“面向对象”,用“声明方式”描述“产品骨架”

如下图,和上面的图进行对比,是不是有点“面向对象”的感觉?
3.png

对照上面的图,再看看下面的术语解释,仔细琢磨下

  • 1. 产品:提供用户价值(即组织发布活动)的独立单元,是由独立的产、研、测共同维护的功能和服务的集合。
  • 2. 应用:对应一个可独立运行、发布的线上服务叫做应用,是软件交付和运维的最小单元。应用对应某一个代码库,对应部署发布的应用。
  • 3. 版本:版本是产品的基础属性,产品每一次发布(可能涉及多个开发团队多个应用),产生该产品(系列需求)的一个新版本(结果)。新版本制作过程包含产研全生命周期。
云原生应用

基于上面的图,AI帮忙编写了对应的配置声明,帮助大家理解(片段有点长, 可以快速跳过)
  1. # ================================================
  2. # 应用部署模板 - Kubernetes 云原生服务编排示例
  3. # 对应架构图左侧「代码库」「制品/镜像」「配置信息」与右侧「部署环境」
  4. # ================================================
  5. ---
  6. # 部署环境定义(对应架构图右侧「dev/uat/prod」)
  7. # 使用命名空间隔离不同环境(此处以prod为例)
  8. apiVersion: v1
  9. kind: Namespace
  10. metadata:
  11.   name: prod
  12.   labels:
  13.     env: production
  14. ---
  15. # ------------------------------------------------
  16. # 核心部署配置(对应架构图左侧「制品/镜像」+「配置信息」)
  17. # ------------------------------------------------
  18. # 配置信息(ConfigMap对应架构图左侧「配置信息」模块)
  19. apiVersion: v1
  20. kind: ConfigMap
  21. metadata:
  22.   name: app-config
  23.   namespace: prod  # 绑定prod环境命名空间
  24. data:
  25.   app.properties: |
  26.     # 应用运行时配置
  27.     db.host=mysql.prod.svc.cluster.local
  28.     cache.enabled=true
  29.     log.level=INFO
  30. ---
  31. # 敏感信息配置(Secret属于特殊类型的配置信息)
  32. apiVersion: v1
  33. kind: Secret
  34. metadata:
  35.   name: db-credentials
  36.   namespace: prod
  37. type: Opaque
  38. data:
  39.   username: YWRtaW4=  # admin base64编码
  40.   password: cGFzc3dvcmQxMjM=  # password123 base64编码
  41. ---
  42. # ------------------------------------------------
  43. # 服务编排核心定义(对应架构图下方「服务编排(云原生)」模块)
  44. # ------------------------------------------------
  45. # 部署控制器(Deployment实现滚动更新策略)
  46. apiVersion: apps/v1
  47. kind: Deployment
  48. metadata:
  49.   name: myapp-deployment  # 部署版本标识
  50.   namespace: prod
  51.   labels:
  52.     app: myapp
  53.     track: stable  # 部署策略标识
  54. spec:
  55.   replicas: 3  # 初始副本数
  56.   strategy:
  57.     type: RollingUpdate  # 部署策略-滚动更新
  58.     rollingUpdate:
  59.       maxSurge: 1
  60.       maxUnavailable: 0
  61.   selector:
  62.     matchLabels:
  63.       app: myapp
  64.   template:
  65.     metadata:
  66.       labels:
  67.         app: myapp
  68.         env: prod
  69.     spec:
  70.       containers:
  71.       - name: app-container
  72.         image: registry.example.com/myapp:v1.2.3  # 制品/镜像(来自CI/CD流水线构建)
  73.         imagePullPolicy: Always
  74.         ports:
  75.         - containerPort: 8080
  76.         env:
  77.         - name: DB_HOST
  78.           valueFrom:
  79.             configMapKeyRef:
  80.               name: app-config
  81.               key: db.host
  82.         - name: DB_USERNAME
  83.           valueFrom:
  84.             secretKeyRef:
  85.               name: db-credentials
  86.               key: username
  87.         resources:
  88.           requests:
  89.             cpu: "100m"
  90.             memory: "256Mi"
  91.           limits:
  92.             cpu: "500m"
  93.             memory: "512Mi"
  94.         livenessProbe:  # 健康检查(可观测性)
  95.           httpGet:
  96.             path: /health
  97.             port: 8080
  98.           initialDelaySeconds: 30
  99.           periodSeconds: 10
  100. ---
  101. # 服务暴露(Service实现服务发现)
  102. apiVersion: v1
  103. kind: Service
  104. metadata:
  105.   name: myapp-service
  106.   namespace: prod
  107. spec:
  108.   type: ClusterIP  # 生产环境建议使用LoadBalancer
  109.   selector:
  110.     app: myapp
  111.   ports:
  112.   - name: http
  113.     port: 80
  114.     targetPort: 8080
  115.     protocol: TCP
  116. ---
  117. # ------------------------------------------------
  118. # 弹性伸缩策略(对应架构图「部署策略」模块)
  119. # ------------------------------------------------
  120. apiVersion: autoscaling/v2
  121. kind: HorizontalPodAutoscaler
  122. metadata:
  123.   name: myapp-hpa
  124.   namespace: prod
  125. spec:
  126.   scaleTargetRef:
  127.     apiVersion: apps/v1
  128.     kind: Deployment
  129.     name: myapp-deployment
  130.   minReplicas: 2
  131.   maxReplicas: 10
  132.   metrics:
  133.   - type: Resource
  134.     resource:
  135.       name: cpu
  136.       target:
  137.         type: Utilization
  138.         averageUtilization: 80
  139. # ================================================
  140. # 部署执行说明:
  141. # 1. 代码库变更触发CI/CD流水线构建镜像(更新image版本)
  142. # 2. 通过kubectl apply -f 应用部署模板文件.yaml
  143. # 3. 监控部署状态:kubectl -n prod get pods,svc,hpa
  144. # ================================================
复制代码
传统主机部署应用

上面说的是k8s应用,那么传统安装包主机部署呢?怎么通过应用表达?
通过 YAML 定义主机环境、应用包版本和全局配置(对应图中「制品/镜像」「配置信息」模块)
  1. # File: infrastructure.yaml
  2. # 定义主机环境、应用包版本等基础设施信息
  3. environments:
  4.   - name: dev
  5.     hosts:
  6.       - ip: 192.168.1.101
  7.         user: dev-user
  8.         deploy_dir: /opt/apps/dev
  9.     app_version: 1.0.0-SNAPSHOT
  10.   - name: prod
  11.     hosts:
  12.       - ip: 192.168.1.200
  13.         user: prod-admin
  14.         deploy_dir: /opt/apps/prod
  15.     app_version: 1.0.0-RELEASE
  16. # 全局配置模板(与环境解耦)
  17. global_config:
  18.   app_name: "my-spring-boot-app"
  19.   java_opts: "-Xmx512m -Xms256m"
  20.   health_check_url: "/actuator/health"
复制代码
每个环境(dev/prod)独立维护敏感配置(对应图中「配置信息」与「部署环境」分离)
  1. # File: config/prod.env
  2. # 生产环境数据库配置(敏感信息单独管理)
  3. DB_HOST=mysql.prod.internal
  4. DB_PORT=3306
  5. DB_USER=admin
  6. DB_PASSWORD=encrypted_password_here  # 建议使用加密工具(如Ansible Vault)
  7. # File: config/dev.env
  8. # 开发环境数据库配置
  9. DB_HOST=localhost
  10. DB_PORT=3306
  11. DB_USER=dev
  12. DB_PASSWORD=dev123
复制代码
通过 Shell 脚本实现自动化部署(对应图中「部署脚本」模块)
[code]#!/bin/bash# File: deploy.sh# 参数化部署:指定环境(dev/prod)和应用包路径ENV=$1APP_PACKAGE=$2# 加载基础设施定义INFRA_FILE="infrastructure.yaml"APP_NAME=$(yq eval '.global_config.app_name' $INFRA_FILE)DEPLOY_DIR=$(yq eval ".environments[] | select(.name == \"$ENV\").hosts[0].deploy_dir" $INFRA_FILE)REMOTE_USER=$(yq eval ".environments[] | select(.name == \"$ENV\").hosts[0].user" $INFRA_FILE)REMOTE_IP=$(yq eval ".environments[] | select(.name == \"$ENV\").hosts[0].ip" $INFRA_FILE)# 加载环境配置CONFIG_FILE="config/$ENV.env"source $CONFIG_FILE# 生成动态应用配置(模板化)cat > application.properties

相关推荐

您需要登录后才可以回帖 登录 | 立即注册