- 快召唤伙伴们来围观吧
- 微博 QQ QQ空间 贴吧
- 文档嵌入链接
- <iframe src="https://www.slidestalk.com/u39071/226Golanggocnvip58839?embed" frame border="0" width="640" height="360" scrolling="no" allowfullscreen="true">复制
- 微信扫一扫分享
Golang大规模云原生应用管理实践
云原生是以容器技术为基础围绕着Kubernetes进行的一场技术标准化演进。通过标准可扩展的调度,网络,存储,容器运行时接口来提供基础设施;通过标准可扩展的声明式资源和控制器来提供运维能力。两层标准化推进了细化的社会分工,各领域进一步提升规模化和专业化,全面达到成本,效率,稳定性的优化。
展开查看详情
1 .Golang⼤规模云原⽣应⽤管理实践 刘洋(炎寻)
2 .关于我 • 毕业于中国科学技术大学,定居杭州 • 就职于阿里云-云原生应用平台团队 • Problem Solver,聚焦中间件,容器,Kubernetes,PaaS平台… • OAM社区成员
3 .开局一张图 规模化应用交付效率对比去年 提升1倍 每万笔峰值交易的IT成本对比4年前 下降80% 稳定 云原生 技术 效率 成本
4 . 云原生-程序员视角 云原生应用 1 Kubectl plugins 非业务逻辑剥离, 2 Apiserver extension 提升交付效率 云原生生态(CNCF) 3 Custom resources 自动化运维, 1 2 3 5 提升稳定性 4 Scheduler extension K8s 5 Custom controller 统筹规划, 4 6 7 6 Network plugins 降低成本 基础设施 7 Storage plugins 云原生是以容器技术为基础围绕着Kubernetes进行的一场技术标准化演进。通过标准可扩展的调度,网络, 存储,容器运行时接口来提供基础设施;通过标准可扩展的声明式资源和控制器来提供运维能力。两层标 准化推进了细化的社会分工,各领域进一步提升规模化和专业化,全面达到成本,效率,稳定性的优化。
5 . Golang与云原生生态(CNCF) 项目数占比: 214/1512(14.2%) Github star数占比:1265737 / 2458072(51.5%)市值占比: $8.08T/$19.46T(41.5%) https://landscape.cncf.io/format=card-mode& 截止 fullscreen=yes&grouping=no&language=Go 2020.11.15
6 .插入:策略(Policy)与机制(Mechanism) • 员工进入公司需要验证是一个策略,人脸识别是机制; 策略是做事的一组概念和计 • 从杭州到上海是策略,坐火车是机制; 划,关注要做什么事 “what” • 接口是策略,实现是机制; • 声明是策略,过程是机制; 机制是获取结果的过程, • 策略面向外部交互,机制面向内部实现; 方法和系统,关注如何做事 • 策略追求开放标准,机制追求稳定可复用; “how” • 策略与机制要分离; • 策略与机制随着层次的变化而变化;
7 . 应用管理的策略与机制 部署策略 版本 策略 灰度 组件 发布 服务 工作负载 Tekton 持久卷 … 分批发布 应用 负载均衡 权限 依赖 实例 链路 Argo 重启 路由规则 报警 诊断 … 指标 日志 标签 流量 回滚 Jaeger KEDA 事件 容量 负载均衡 回退历史 存储挂载 Kube ES 定时弹性 … 调度策略 指标监控 eventer 服务绑定 指标弹性 健康检查 事件中心 InfluxDB 服务治理 Rook 手动弹性 Envoy 日志管理 组件管理 Ingress Istio Knative K8s Promethues 机制 K8s及云原生生态给 开发者提供的是机制
8 .开发者直接使用K8s的失败故事 • 认知成本高:K8s功能强大却没有统一的使用方式,不得不学习复杂的声明字段和各种奇怪的Annotation; • 稳定性不足:没有设置Pod的QoS等级,导致频繁被驱逐,没有设置反亲和性策略,导致节点流量不均; • 扩展效率低:需要负责安装,升级丰富的云原生插件,无法解决插件的依赖,冲突和资源浪费问题; • 运维成本高:Apiserver, etcd, Controller-Manager, Kubelet,等组件都具有一定复杂度,无法做到定期升 级以维持安全,高可用,高性能的状态; • … 稳定 安全 基础设施 能力复用 自动化 可观测 开发者真正想要的是策略:大象无形的基础设施,坚如磐石的中间件,丰富高效的应用PaaS平台
9 . 云原生PaaS平台提供应用管理策略 云原生应用 9 1 Kubectl plugins 云原生应用 云原生PaaS平台 2 Apiserver extension 8 3 Custom resources 云原生生态(CNCF) 云原生生态(CNCF) 4 Scheduler extension 1 2 3 5 1 2 3 5 5 Custom controller K8s K8s 6 Network plugins 4 6 7 4 6 7 7 Storage plugins 基础设施 基础设施 8 向下设计平台策略与机制融入云原生生态 9 向上提供应用管理策略与机制使用平台
10 . 插入:K8s核心机制-声明式资源与控制器 func (dc *DeploymentController) syncDeployment(key string) error { ... deployment, err := dc.dLister.Deployments(namespace).Get(name) d := deployment.DeepCopy() // rs rsList, err := dc.getReplicaSetsForDeployment(d) if err != nil { return err } // Deployment Pod 期望状态 控制器 podMap, err := dc.getPodMapForDeployment(d, rsList) • 使用声明式K8s资源 if err != nil { return err } 作为期望终态 apiVersion: apps/v1 // rolloutRolling Deployment template rs kind: Deployment metadata: switch d.Spec.Strategy.Type { name: nginx-deployment case apps.RecreateDeploymentStrategyType: • 循环控制器 return dc.rolloutRecreate(d, rsList, podMap) labels: 管控动作 case apps.RollingUpdateDeploymentStrategyType: app: nginx return dc.rolloutRolling(d, rsList) } spec: ... replicas: 3 • Label是一等公民 } selector: matchLabels: app: nginx func (dc *DeploymentController) processNextWorkItem() bool { template: 被控制系统 • 事件触发闭环反馈 key, quit := dc.queue.Get() metadata: labels: if quit { app: nginx return false • 多控制器组合 spec: } containers: defer dc.queue.Done(key) 监控状态 - name: nginx image: nginx:1.14.2 ports: err := dc.syncHandler(key.(string)) - containerPort: 80 dc.handleErr(err, key) return true } 基于控制论原理
11 . EDAS-阿里云云原生PaaS平台 EDAS 用户应用模型 1、应用管理策略 平台特定业务 2、应用管理机制 平台应用模型 3、平台构建策略 部署 弹性 流量 存储 应用模型 负载均衡 限流降级 监控 控制器 控制器 控制器 控制器 控制器 控制器 控制器 控制器 … 4、平台构建机制 用户界面(1) ApiServer PaaS 业务(2) Kube Cloud KEDA Flagger Prom- Istio- … Controller manager controller manager controller controller controller controller PaaS 内核(3,4) 云原生生态
12 . EDAS的平台构建策略-OAM应用模型 • 应用 • 组件1(工作负载) • 运维特征1 • 运维特征2 • … • 组件2 (工作负载) • 运维特征1 • 运维特征2 • … 作用域 • … 能力定义 依赖编排 组件版本 服务绑定 https://github.com/oam-dev/spec
13 . OAM应用模型 apiVersion: core.oam.dev/v1alpha2 apiVersion: core.oam.dev/v1alpha2 apiVersion: core.oam.dev/v1alpha2 kind: ApplicationConfiguration kind: TraitDefinition metadata: metadata: kind: Component name: helloworld 可组合 name: routes.extended.oam.dev metadata: spec: components: annotations: name: web-service - componentName: web-service instanceName: frontend version: v0.3.0 version: v0.3.0 dependencies: spec: description: Knative workload - backend traits: appliesTo: - serving.knative.dev/v1.Service spec: - trait: apiVersion: keda.k8s.io/v1alpha1 definitionRef: workload: kind: ScaledObject spec: 可发现 name: routes.extended.oam.dev apiVersion: serving.knative.dev/v1 maxReplicaCount: 4 triggers: kind: Service - type: redis spec: - trait: ... apiVersion: core.oam.dev/v1alpha2 template: apiVersion: extended.oam.dev/v1 kind: Route kind: TraitDefinition metatdata: spec: metadata: name: scaledobjects.keda.k8s.io name: web-service-v1 traffic: ... 标准可扩展 spec: scopes: - scope: annotations: version: v0.3.0 containerConcurrency: 0 apiVersion: core.oam.dev/v1alpha2 kind: Network spec: containers: name: my-vpc-network-X - instanceName: backend appliesTo: - env: componentName: redis - serving.knative.dev/v1.Service - name: TARGET scopes: - scope: definitionRef: value: Knative apiVersion: core.oam.dev/v1alpha2 简单开放 name: scaledobjects.keda.k8s.io kind: Network image: helloworld-go:latest name: my-vpc-network-X 能力定义 组件 应用配置 = 组件+运维特征+作用域 • 工作负载 • 运维特征 https://github.com/oam-dev/spec • 作用域
14 . EDAS的平台构建机制-KubeVela • OAM应用模型运行时 • 内置Workloads & Traits & Scopes • Capability Management https://github.com/oam-dev/kubevela
15 . KubeVela的核心机制-运行时 func Setup(mgr ctrl.Manager, args controller.Args, l logging.Logger) error { func (r *components) Render(ctx context.Context, ac *v1alpha2.ApplicationConfiguration) { func (r *OAMApplicationReconciler) Reconcile(req reconcile.Request) (result reconcile.Result, returnErr error) { workloads := make([]*Workload, 0, len(ac.Spec.Components)) return ctrl.NewControllerManagedBy(mgr). … dag := newDAG() Named(name). ac := &v1alpha2.ApplicationConfiguration{} for _, acc := range ac.Spec.Components { w, err := r.renderComponent(ctx, acc, ac, dag) For(&v1alpha2.ApplicationConfiguration{}). if err := r.client.Get(ctx, req.NamespacedName, ac); err != nil { 1 获取应用期望状态 Watches(&source.Kind{Type: &v1alpha2.Component{}}, return reconcile.Result{}, errors.Wrap(resource.IgnoreNotFound(err), errGetAppConfig) workloads = append(workloads, w) 2.1 渲染workload及其 &ComponentHandler{ } } Traits,scopes Client: mgr.GetClient(), acPatch := ac.DeepCopy() Logger: l, 控制器初始化 ds := &v1alpha2.DependencyStatus{} res := make([]Workload, 0, len(ac.Spec.Components)) RevisionLimit: args.RevisionLimit, workloads, depStatus, err := r.components.Render(ctx, ac) 2 解析期望的WTS状态 for i, acc := range ac.Spec.Components { }). if err := r.workloads.Apply(ctx, ac.Status.Workloads, workloads, resource.MustBeControllableBy(ac.GetUID())); err != nil { unsatisfied, err := r.handleDependency(ctx, workloads[i], acc, dag, ac) Complete(NewReconciler(mgr, dm, … WithLogger(l.WithValues("controller", name)), 3… 调谐动作-更新与新增 res = append(res, *workloads[i]) 2.2 检查依赖 } } WithRecorder(event.NewAPIRecorder(mgr.GetEventRecorderFor(name))))) } … return res, ds, nil for _, e := range r.gc.Eligible(ac.GetNamespace(), ac.Status.Workloads, workloads) { } e := e … func (a *workloads) Apply(ctx context.Context, status []v1alpha2.WorkloadStatus, w func (r *components) renderComponent(ctx context.Context, …) { []Workload, ao ...resource.ApplyOption) error { if err := r.client.Delete(ctx, &e); resource.IgnoreNotFound(err) != nil { 4 调谐动作-删除 if acc.RevisionName != "" { // they are all in the same namespace … acc.ComponentName = ExtractComponentName(acc.RevisionName) } var namespace = w[0].Workload.GetNamespace() } for _, wl := range w { 3.1 依赖满足,新增或更新workload … c, componentRevisionName, err := util.GetComponent(…) … if !wl.HasDep { p, err := r.params.Resolve(c.Spec.Parameters, acc.ParameterValues) err := a.patchingClient.Apply(ctx, wl.Workload, ao...) } w, err := r.workload.Render(c.Spec.Workload.Raw, p...) 2.1.1 渲染workload } // patch the final status on the client side, k8s sever can't merge them for _, trait := range wl.Traits { r.updateStatus(ctx, ac, acPatch, workloads) 5 调谐动作-状态同步 for _, ct := range acc.Traits { t, traitDef, err := r.renderTrait(ctx, ct, ac, acc.ComponentName, ref, dag) if trait.HasDep { … continue 3.2 依赖满足,新增或更新trait ac.Status.Dependency = v1alpha2.DependencyStatus{} } 2.1.2 渲染trait } if err := SetWorkloadInstanceName(traitDefs, w, c); err != nil { t := trait.Object waitTime := longWait return nil, err if err := a.updatingClient.Apply(ctx, &trait.Object, ao...); err != nil { if len(depStatus.Unsatisfied) != 0 { } return errors.Wrapf(err, errFmtApplyTrait, t.GetAPIVersion(), waitTime = dependCheckWait … t.GetKind(), t.GetName()) for i := range acc.Traits { ac.Status.Dependency = *depStatus } traitDef := traitDefs[i]2.1.3 建立workload与trait的关系 } } trait := traits[i] workloadRefPath := traitDef.Spec.WorkloadRefPath workloadRef := runtimev1alpha1.TypedReference{ if len(workloadRefPath) != 0 { APIVersion: wl.Workload.GetAPIVersion(), // the posthook function will do the final status update Kind: wl.Workload.GetKind(), return reconcile.Result{RequeueAfter: waitTime}, nil 6 异步轮询 } …SetValue(workloadRefPath, workloadRef)… Name: wl.Workload.GetName(), } } } scopes := make([]unstructured.Unstructured, 0, len(acc.Scopes)) for _, s := range wl.Scopes { for _, cs := range acc.Scopes { if err := a.applyScope(ctx, wl, s, workloadRef); err != nil { scopeObject, err := r.renderScope(ctx, cs, ac.GetNamespace()) return err … 2.1.4 建立workload与scope的关系 scopes = append(scopes, *scopeObject) } 3.3 新增或更新workload的scope } } } addDataOutputsToDAG(dag, acc.DataOutputs, w) 2.1.5 初始化依赖 return a.dereferenceScope(ctx, namespace, status, w) return &Workload{…Workload: w, Traits: traits, RevisionEnabled: } isRevisionEnabled(traitDefs), Scopes: scopes}, nil 3.4 删除workload的scope }
16 . EDAS的应用策略与机制 用户应用模型-OAM表单 平台业务 平台应用模型-OAM资源 apiVersion: core.oam.dev/v1alpha2 kind: ApplicationConfiguration metadata: name: helloworld spec: components: - componentName: web-service instanceName: frontend dependencies: - backend traits: - trait: apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject spec: maxReplicaCount: 4 triggers: - type: redis ... EDAS - trait: apiVersion: extended.oam.dev/v1 kind: Route spec: traffic: ... scopes: - scope: apiVersion: core.oam.dev/v1alpha2 kind: Network name: my-vpc-network-X - instanceName: backend componentName: redis scopes: - scope: apiVersion: core.oam.dev/v1alpha2 kind: Network name: my-vpc-network-X
17 . EDAS Review 云原生应用 1 Kubectl plugins 9 9 OAM表单 2 Apiserver extension EDAS 3 Custom resources 8 8 OAM & KubeVela 4 Scheduler extension 云原生生态(CNCF) 5 Custom controller 1 2 3 5 6 Network plugins K8s 标准 轻量化 简单开放 7 Storage plugins 4 6 7 可扩展 基础设施
18 .新的复杂度-开发模式 for { actualState := GetResourceActualState(rsvc) • 声明式资源设计不合理; expectState := GetResourceExpectState(rsvc) if actualState == expectState { // do nothing • Expect state变化导致大范围Pod重启; } else { Reconcile(rsvc) • Reconcile逻辑混乱不堪,不可测试; } } • 外部交互模式不匹配; • 声明式资源设计(要什么) • 控制器设计(做什么) • e2e测试 • Static • 基于“可重构”状态机,开放的世界 • Ginkgo BDD • Measurable • 不要修改资源声明 • Kind本地K8s集群 • Relevant • 事件驱动+主动轮询 • Attainable • 重试 + 幂等 • Timebound • 自愈
19 . 新的复杂度-最终一致性 status: • 过期的状态 … phase: succeed • 版本冲突 … • 业务及时性 status: ownerReferences: currentBatch: 1 metadata: - apiVersion: core.oam.dev/v1alpha2 blockOwnerDeletion: true lastPhaseTransitionTime: "2020-10-29T13:43:48Z" observedVersion: "5" … controller: true phase: succeed resourceVersion:"3442346549" kind: ApplicationConfiguration reason: "" name: oamhsf revision: 5 …. uid: 73eec338-c3c1-4936-bc5b-3c47f2eb63bc 使用version和observedVersion做收敛同步 使用resourceVersion做乐观并发 使用ownerRef做事件触发
20 .新的复杂度-可观测 • 关联资源太多 应用为什么没有到终态? • 关联控制器太多 • 异步响应式 status: workloads: - componentName: oamhsf-group-1 componentRevisionName: oamhsf-group-1-v5 status: Ready status: traits: conditions: - status: success - lastTransitionTime: "2020-11-17T18:33:02Z" traitRef: reason: Successfully reconciled resource apiVersion: edas.aliyun.oam.com/v1 status: "True" kind: Rollout type: Synced name: oamhsf-group-1-trait-5c4fdd8f6c - status: success traitRef: apiVersion: edas.aliyun.oam.com/v1 所有资源的status设计condition描述状态 kind: ImageBuilder name: oamhsf-group-1-trait-5bc99b979f workloadRef: apiVersion: apps/v1 LAST SEEN TYPE REASON OBJECT MESSAGE kind: Deployment 8m56s Normal RenderedComponents applicationconfiguration/oamacree Successfully rendered components name: oamhsf-group-1-v5 8m56s Normal AppliedComponents applicationconfiguration/oamacree Successfully applied components 应用的status里面关联所有资源 应用关联的事件与日志
21 .新的复杂度-控制器运维 我们要管控大规模的集群,每个集群也会部署大量的控制器,控制器本身的运维成为问题 • 控制器管控平台 • 观测性 • 能力管控 • 升级 • Prometheus • 版本管理 • 回滚 • 统一日志收集 • 依赖满足 • 灰度 • 事件中心 • 健康检查 • 重启 • 告警
22 . 云原生PaaS平台的发展趋势 • 开发者体验 • Serverless = FaaS + BaaS 云原生应用 • GitOps-自动化 9 9 标准化用户应用模型 • ServiceMesh-下一代分布式应用编程模式 云原生PaaS平台 • 应用运维可编程 8 8 标准化平台应用模型与机制 • 多元化(云,工作负载,服务) 云原生生态(CNCF) • 平台 K8s • 可观测是重中之重 • 智能化-AIOps 基础设施 • 一体化-扩展屏蔽基础设施 • 轻量化-下沉 • 自动化-端到端
23 .Thanks