给 K8s API “做减法”:阿里巴巴云原生应用管理的挑战和实践

点击这里,查看阿里巴巴具体解决办法及更多重要内容

简介: 本文为携程技术分享演讲内容整理而来。 早在 2011 年,阿里内部便开始了应用容器化,当时最开始是基于 LXC 技术构建容器,然后逐渐切换到 Docker,自研了大规模编排调度系统。到了 2018 年,我们团队依托 K8s 体系开始推进“轻量级容器化”,同时投入了工程力量跟开源社区一起解决了诸多规模与性能问题,从而逐步将过去“类虚拟机&rdqu

早在 2011 年,阿里内部便开始了应用容器化,当时最开始是基于 LXC 技术构建容器,然后逐渐切换到 Docker,自研了大规模编排调度系统。到了 2018 年,我们团队依托 K8s 体系开始推进“轻量级容器化”,同时投入了工程力量跟开源社区一起解决了诸多规模与性能问题,从而逐步将过去“类虚拟机”的运维链路和阿里巴巴整体应用基础设施架构升级到了云原生技术栈。

到了 2019 年,Kubernetes 基础设施底盘在阿里巴巴经济体中已经覆盖了阿里巴巴方方面面的业务,规模化的接入了包括核心电商、物流、金融、外卖、搜索、计算、AI 等诸多头部互联网场景。这套技术底盘,也逐步成为了阿里巴巴支撑 618、双 11 等互联网级大促的主力军之一。

目前,阿里巴巴与蚂蚁金服内部运行了数十个超大规模的 K8s 集群,其中最大的集群约 1 万个机器节点,而其实这还不是能力上限。每个集群都会服务上万个应用。在阿里云 Kubernetes 服务(ACK)上,我们还维护了上万个用户的 K8s 集群,这个规模和其中的技术挑战在全世界也是首屈一指的。

我们的 Kubernetes 面临的新挑战
在规模和性能等基础设施领域的问题逐步解决的同时,在规模化铺开 Kubernetes 的过程中,我们逐步发现这套体系里面其实还有很多意想不到的挑战。这也是今天分享的主题。

第一个是 K8s 的 API 里其实并没有“应用”的概念。而且,Kubernetes API 的设计把研发、运维还有基础设施关心的事情全都糅杂在一起了。这导致研发觉得 K8s 太复杂,运维觉得 K8s 的能力非常凌乱、零散,不好管理,只有基础设施团队(也就是我们团队)觉得 Kubernetes 比较好用。但是基础设施团队也很难跟研发和运维解释清楚 Kubernetes 的价值到底是什么。

我们来看个实际的例子。

kind: Deployment
apiVersion: apps/v1
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      deploy: example
  template:
    metadata:
      labels:
        deploy: example
    spec:
      containers:
        - name: nginx
          image: nginx:1.7.9
      shareProcessNamespace: false

就拿上图中的 replica 为 3 来说,开发人员怎么知道实例数应该配几个呢?如果运维想要改replica,敢不敢改?能不能改?如果 replica 还能理解的话,那像 shareProcessNamespace 这种字段真是灵魂拷问了。 开发人员仅从字面意思知道这个可能跟容器进程共享有关,那么配置了这个应用会有什么影响呢?会不会有安全问题?

在阿里巴巴内部,很多 Paas 平台只允许开发填 Deployment 的极个别字段。为什么允许填的字段这么少?是平台能力不够强吗?其实不是的,本质原因在于业务开发根本不想理解这众多的字段。

所以这个 PaaS 平台只允许用户填个别字段,其实反倒是帮助业务开发人员避免了这些灵魂拷问。但是反过来想,屏蔽掉大量字段真的就解决问题了吗?这种情况下,整个组织的基础设施能力还如何演进?应用开发和应用运维人员的诉求又该怎么传递给基础设施呢?

实际上,归根到底,Kubernetes 是一个 Platform for Platform 项目,它的设计是给基础设施工程师用来构建其他平台(比如 PaaS 或者 Serverless)用的,而不是直面研发和运维同学的。从这个角度来看,Kubernetes 的 API,其实可以类比于 Linux Kernel 的 System Call,这跟研发和运维真正要用的东西(Userspace 工具)完全不是一个层次上的。你总不能让本来写Java Web 的同学每天直接调用着 Linux Kernel System Call ,还给你点赞吧?

第二, K8s 实在是太灵活了,插件太多了,各种人员开发的 Controller 和 Operator 也非常多。这种灵活性,让我们团队开发各种能力很容易,但也使得对应用运维来说, K8s 的这些能力管理变得非常困难。比如,一个环境里的不同运维能力,实际上有可能是冲突的。

我们来看一个例子,基础设施团队最近开发上线了一个新的插件,叫做 CronHPA,一个具体的 Spec 如下所示。

apiVersion: "app.alibaba.com/v1"
kind: CronHPA
metadata:
  name: cron-scaler
spec:
  timezone: Asia/Shanghai
  schedule:
  - cron: '0 0 6 * * ?'
    minReplicas: 20
    maxReplicas: 25
  - cron: '0 0 19 * * ?'
    minReplicas: 1
    maxReplicas: 9
  template:
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        name: nginx-deployment
      metrics:
      - type: Resource
        resource:
          name: cpu
          target:
            type: Utilization
            averageUtilization: 50
 

作为基础设施团队,我们觉得这种 K8s 插件很简单, CRD 也很容易理解。就像这个的 CronHPA 的功能,从早上六点开始到下午七点钟这个实例最少有 20 个、最多有 25 个,到第二天早上六点钟最少 1 个、最多有 9 个,在每个阶段会根据 CPU 这个指标衡量调整实例数。

然而,就在我们美滋滋的上线这个插件不久,应用运维同学就开始跟我们抱怨了:

“这个能力到底该怎么使用呢?它的使用手册在哪里?是看 CRD 呢还是看文档呢?”
“我怎么知道这个插件在某个集群里有没有装好呢?”
“我们运维不小心把 CronHPA 和 HPA 绑定给同一个应用,结果发现这个应用是会抽风的。为什么你们 K8s 非要等到这种冲突发生的时候才报错呢?你们就不能设计个机制自动检查一下这些插件的使用过程有没有发生冲突吗?”这个我们后来确实做了,解决方法是给我们的 K8s 加了 20 多个 Admission Hook。
第三,也是阿里巴巴上云之后我们团队特别痛的一个点。我们需要处理的应用的交付场景,除了公有云以外,还会有专有云、混合云、IoT 等各种复杂的环境。各种各样的云服务在这种复杂场景下,连 API 都是不统一的,这个时候我们就需要专门的交付团队来进行弥补,一个一个的去对接、去交付应用。对他们来说这是一个非常痛苦的事情:“不是说好的 Docker 化了之后就能‘一次打包、随处运行’了吗?”说白了,K8s 现在并没有一个统一的、平台无关的应用描述能力。

阿里巴巴的解决办法

所以在 2019 年,我们团队开始思考如何通过技术手段解决上述应用管理与交付相关的问题,到现在已经取得了一定得成果。

不过,在讲解阿里巴巴如何解决上述问题的方案之前,有必要先介绍一下我们推进所有这些方案的理论基础。在这里,我们主要遵循的是 CNCF 倡导的“应用交付分层模型”,如下图所示:

关键字:运维 Kubernetes Cloud Native Java 应用服务中间件 Linux API nginx Docker 容器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值