1.云原生相关
1.1.什么是云原生
Cloud Native 最早是在 2013 年由 Pivotal 公司的 Matt Stine 提出的。2015 年 CNCF(Cloud Native Computing Foudation,云原生计算基金会)成立。
官方发布的云原生 v1.0 定义是:“云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。
云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式 API。
这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段,云原生技术使工程师能够轻松地对系统作出频繁和可预测的重大变更。” 在该定义中,容器、不可变基础设施、声明式 API 都与 kubernetes 直接相关。
1.2.什么是云原生应用
云原生应用是指在云上生长出来的应用,云上的“原住民”。然而这也没有解释它与传统应用的区别,也没有说明它为何更“高级”?2017 年,Red Hat 架构师、《Kubernetes Patterns》的作者 Bilgin Lbryam 给云原生应用下了一个比较准确而连贯的定义:
- 以微服务原则进行划分设计。
- 使用 devops 和 CI/CD 的方式进行开发和交付。
- 以容器技术进行打包发布。
- 在云基础设施上运行并被调度。
2.K8S 相关
如果说 istio 是一艘快艇的话,k8s 就是一艘巨轮,驰骋在更广阔的海域。 用最简短的语言描述 K8S,可以说,K8S 是一个容器编排系统(Container Ochestration)。那么,“编排”二字包含了哪些核心内容?
- 镜像管理(Image): 管理与分发。
- 容器管理(Container): 创建、调度、状态监控、自动伸缩。
- 服务管理(Service): 发布升级、服务发现与负载均衡。
- 配置管理(Config): ConfigMap 是普通配置,Secret 是敏感数据。配置也是非常重要的,有很多细节可以深入展开。
- 流量治理(Traffic): 日志、监控、鉴权等。
3.K8S 群集架构
K8S 的架构是非常经典的 Master-Worker 架构模式,我们可以借此机会复习下互联网大规模分布式系统的设计思路。
Master 相当于大脑和心脏,负责接收外部请求、管理与调度 worker 节点。
Worker 相当于四肢,每一台 worker 都干着相同的工作,随时可以被踢除或加入,以实现横向伸缩。
自 Google 在 2003 到 2006 年连续发布了著名的“三驾马车”论文之后,业界数不清的分布式系统均是采用这套架构。
3.1.Master 组件
- kube-apiserver: 对外暴露可以操作整个 kubernetes 集群的 REST API。
- kube-scheduler: 负责调度 worker 上的 pods。
- kube-controller-manager: 管理各种 kubernetes 定义的 controller。
- etcd: Key-Value 存储组件,采用 Raft 协议,存储集群的各种状态数据,包括配置、节点、Pod 等。
3.2.Worker/Node 组件
kubelet: 是一个 Agent,监控 node 上的 container 是否正常运行。
kube-proxy: 操纵机器上的 iptables 网络规则,执行转发。
container runtime: 容器运行的基础环境,负责下载镜像与运行容器。
4.常见问题
4.1.有了 kubernetes,为何还需要 istio?
答:kubernetes 并不提供精细化的流量调度能力,例如精细化路由、分布式限流等。
4.2.GKE (Google Kubernetes Engine) 与 K8S 的区别?
答:GKE 只是托管 K8S 集群的一个平台,面向企业与用户提供快速搭建与维护自己 K8S 集群的能力。业界还有阿里的 ACK,腾讯的 TKE,华为的 CCE 等竞品。有个说法很形象:K8S 只是一套毛坯样板,而像 GKE 这样的平台则相当于房地产商,开发并出售一套套精装修的商品房,让你可以拎包入住。
GKE 是开箱即用(Out-of-Box)的: 做好了控制台页面,客户只需要点击就能完成自己的 k8s 集群的创建。
GKE 是多租户的: 面向不同的企业和用户。
4.3.何为不可变基础设施(Immutable Infrastructure)?
答:不可变基础设施里的“不可变”非常类似于程序设计中的“不可变”概念。程序设计中不可变变量(Immutable Variable)就是在完成赋值后就不能发生更改,只能创建新的来整体替换旧的。由于具有这样的特性这种变量可以在并发环境下安全的使用。对于基础设施的不可变性,最基本的就是指运行服务的服务器在完成部署后,就不在进行更改。
在过去依赖传统的高可靠性基础设施的时代,服务的可靠性依赖于高可靠性的服务器。然而,这些基础设施具有很高的拥有成本,并且初始化,配置的成本也非常高(对于大中型机,甚至重启都是一种奢侈的)。所以,在当时不可变基础设施的设想是难以实现的,开发人员总是需要在服务器上对运行环境做一下持续的更改,如:系统升级,配置修改,补丁等。在许多手动修改之后,服务器的不同配置的重要性或必要性变得不清楚,因此更新或更改任何配置可能会产生意想不到的副作用
4.4.为何推荐一个容器只部署一个进程?
答:最主要应该还是设计思想的考虑,就是倡导一个容器只做一件事。其次是为了解耦,因为在同一个容器内,一个进程的挂掉会导致容器杀掉其他所有进程。
4.5.同一个 Pod 内的容器可否使用共享内存通信?
答:可以。同一个 Pod 内的容器共享同一个 IPC 命名空间,它们可以使用标准的进程间通信方式来互相通信,比如“SystemV 信号量”与“POSIX 共享内存”。
4.6.同一个 Pod 内的容器可否使用 Unix Domain Socket 通信
答:可以。同一个 Pod 内的容器是共享网络与存储的。因此,不仅可以使用 UDS 通信,也可以支持部署一个日志 Agent 采集同一个 Pod 内的业务服务的日志。
4.7.K8S 能否根据机器负载进行自动扩缩容,而不是人工调整 replica 数量?
答:可以。该特性称作 HPA (Horizontal Pod Autoscaling),还有一个与之对称的概念 VPA(Vertical Pod Autoscaling)。
4.8.K8S 为何选择 etcd 作为数据存储,而不是其他分布式 KV 存储?
答:k8s 使用 etcd 存储集群的 API objects、服务发现、配置与状态数据。etcd 拥有如下特点,可以说是一个比较全面的选手:
持久化能力: 有些 KV 缓存并不具备该能力,比如 memcache。
数据一致性
高可用
高性能
安全性: 支持基于 TLS 与 SSL 的鉴权。也可以看看 etcd 官网自己是怎么说的。最后可能还有一点,etcd 是使用 golang 开发的,是 Clouad Native 阵营里的“自己人”。