Kubernetes 实现原理和架构,后端工程师必懂知识
随着 Kubernetes 的日趋成熟,其已经基本成为了容器编排调度框架的标准。各大厂基本都基于 Kubernetes 构建自己的容器编排平台。
Kubernetes 首当其冲成为一项必备技能,面试时用于吹牛提升自身竞争力,工作时能将开发与运维双剑合璧,减少开发与运维之间相互扯皮,避免被甩锅。当然了,Kubernetes 本身就是自带马甲的强 buff,后端工程师要想升级打怪,Kubernetes 简直就是助攻神器。
本文将整体概述 Kubernetes 的实现原理和架构,让大家对 Kubernetes 的原理和架构有一个具体的认识。
此文的最后为大家提供了一个 Kubernetes 在线体验地址,大家可以参考本文提供的技术教学步骤,体验一下 Kubernetes 具体实践。
Kubernetes 简介
Kubernetes,又称为 k8s(首字母为 k、首字母与尾字母之间有 8 个字符、尾字母为 s,所以简称 k8s)或者简称为 "kube" ,是一种可自动实施 Linux 容器操作的开源平台。
是一个生产级别的容器编排系统。
服务管理技术的发展
传统部署时代
在物理服务器上运行应用程序。
缺点:
- 无法限制在物理服务器中运行的应用程序资源使用,因此会导致资源分配问题。例如,如果在物理服务器上运行多个应用程序, 则可能会出现一个应用程序占用大部分资源的情况,而导致其他应用程序的性能下降
- 环境依赖问题
- 安全性
虚拟化部署时代:
- 虚拟化能使应用程序在不同 VM 之间被彼此隔离,且能提供一定程度的安全性, 因为一个应用程序的信息不能被另一应用程序随意访问。
- 更好地利用物理服务器的资源,具有更高的可伸缩性,降低硬件成本。
容器部署时代:
容器类似于 VM,但是容器之间可以共享操作系统(OS)。容器比 VM 更轻量级。
容器的一些优势:
- 镜像创建,启动速度都比 VM 快,提高了容器镜像创建的简便性和效率,可以快速简单的回滚,提供可靠且频繁的容器镜像构建和部署。
- 关注开发与运维的分离:在构建、发布时创建应用程序容器镜像,而不是在部署时, 从而将应用程序与基础架构分离。
- 跨开发、测试和生产的环境一致性:在笔记本计算机上也可以和在云中运行一样的应用程序。
- 跨云和操作系统发行版本的可移植性:可在 Ubuntu、RHEL、CoreOS、本地、 Google Kubernetes Engine 和其他任何地方运行。
- 以应用程序为中心的管理:提高抽象级别,从在虚拟硬件上运行 OS 到使用逻辑资源在 OS 上运行应用程序。
- 资源隔离:可预测的应用程序性能。
- 资源利用:高效率和高密度。
为什么需要 Kubernetes
容器是打包和运行应用程序的好方式。在生产环境中, 你需要管理运行着应用程序的容器,并确保服务不会下线。例如,如果一个容器发生故障,则你需要启动另一个容器。如果此行为交由给系统处理,是不是会更容易一些?
这就是 Kubernetes 要来做的事情!Kubernetes 为你提供了一个可弹性运行分布式系统的框架。Kubernetes 会满足你的扩展要求、故障转移、部署模式等。例如,Kubernetes 可以轻松管理系统的 Canary 部署。
Kubernetes 为你提供:
- 服务发现和负载均衡
Kubernetes 可以使用 DNS 名称或自己的 IP 地址来曝露容器。如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。
- 存储编排
Kubernetes 允许你自动挂载你选择的存储系统,例如本地存储、公共云提供商等。
- 自动部署和回滚
你可以使用 Kubernetes 描述已部署容器的所需状态, 它可以以受控的速率将实际状态更改为期望状态。例如,你可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。
- 自动完成装箱计算
Kubernetes 允许你指定每个容器所需 CPU 和内存(RAM)。当容器指定了资源请求时,Kubernetes 可以做出更好的决策来为容器分配资源。
- 自我修复
Kubernetes 将重新启动失败的容器、替换容器、杀死不响应用户定义的运行状况检查的容器, 并且在准备好服务之前不将其通告给客户端。
- 密钥与配置管理
Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。
使用 Kubernetes 可以:
- 自动化容器的部署和复制
- 随时扩展或收缩容器规模
- 将容器组织成组,并且提供容器间的负载均衡
- 很容易地升级应用程序容器的新版本
- 节省资源,优化硬件资源的使用
- 提供容器弹性,如果容器失效就替换它,等等...
架构图
各组件简介
kubectl
kubectl 是 Kubernetes 官方提供的命令行工具,用户可以 通过kubectl以命令行交互的方式对 Kubernetes 进行操作。
kube-apiserver
所有服务访问的唯一入口,提供认证、授权、访问控制、API 注册和发现等机制。
Kube-apiserver 负责将 Kubernetes 的资源以 RESTful 风格的形式对外暴露并提供服务。Kubernetes 集群中的所有组件都通过 kube-apiserver 组件操作资源对象。kube-apiserver组件也是集群中唯一与 Etcd 集群 进行交互的核心组件。拥有丰富的集群安全访问机制,以及认证、授权及准入控制器。
kube-controller-manager
负责确保 Kubernetes 系统的实际状态收敛到 所需状态。
kube-controller-manager 组 件 负责管理 Kubernetes 集群中的节点 (Node)、Pod副本、服务、端点(Endpoint)、命名空间 (Namespace)、服务账户(ServiceAccount)、资源定额 (ResourceQuota)等。例如,当某个节点意外宕机时,Controller Manager会及时发现并执行自动化修复流程,确保集群始终处于预期的工作状态。
kube-scheduler
负责资源的调度,按照预定的调度策略将 Pod 调度到相应的机器上。
kube-scheduler 组件监控整个集群的 Pod 资源对象和Node资源对 象,当监控到新的 Pod资源对象时,会通过调度算法为其选择最优节点。调度算法分为两种,分别为预选调度算法和优选调度算法。
kubelet
负责维护容器的生命周期,同时也负责 Volume 和网络的管理。
kubelet组件用来接收、处理、上报kube-apiserver组件下发的任务。kubelet进程启动时会向kube-apiserver注册节点自身信息。它主要负 责所在节点(Node)上的Pod资源对象的管理,例如Pod资源对象的创 建、修改、监控、删除、驱逐及Pod生命周期管理等。
kube-proxy
负责为 Service 提供 cluster 内部的服务发现和负载均衡。
是一个简单的网络访问代理,同时也是一个 Load Balancer。它负责将访问到某个服务的请求具体分配给工作节点上同一类标签的 Pod。kube-proxy 实质就是通过操作防火墙规则(iptables或者ipvs)来实现 Pod 的映射。
kube-proxy 组 件 是 参 与 管 理 Pod-to-Service 和 External-to- Service网络的最重要的节点组件之一。
Etcd
键值对数据库,保存了整个集群的状态。
是一种高一致的分布式键值存储,它提供了一种可靠的方式来存储需要由分布式系统或机器集群访问的数据。它在网络内优雅地处理领导者选举,并且可以容忍机器故障,就算是领导者故障也不会影响高一致性。
Pod
Pod 介绍
Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。
Pod : 豌豆荚
Pod: 是一组(一个或多个) 容器。这些容器共享存储、网络、以及怎样运行这些容器的声明。
Pod 创建
运行一个 nginx
apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80
要创建上面显示的 Pod,请运行以下命令:
kubectl apply -f https://k8s.io/examples/pods/simple-pod.yaml
使用 kubectl describe pod nginx 查看 Pod 详细信息
可以看到 Pod 的 ip 是 172.18.0.6, 访问这个地址, curl 172.18.0.6
Pod 创建流程
Kubectl 读取 yaml 文件,向 APIServer 发起请求。
- APIServer 接收到请求后,经过鉴权,校验等操作,将 Pod 定义写入 Etcd。
- Scheduler 通过 通过 list-watch 的监听机制,感知到有需要调度的 Pod,立即开始调度。调度过程中先使用预选算法对节点进行筛选,过滤掉不满足条件的主机。然后使用优选算法对 Node 进行打分,找到最适合的节点。
- kubelet 通过 list-watch 机制,感知到有节点被调度到当前 Node 了,然后就会通过 Kubernetes CRI(容器运行环境接口) 操作容器运行环境(如 Docker)创建容器。
- kube-proxy为新创建的 pod 注册动态 DNS 到CoreOS,然后给 pod 的 service 添加对应的 iptables 规则,用于服务发现和负载均衡。
Pod 副本控制
服务一般是多节点的,我们会通过负载来扩容缩容。
使用 ReplicaSet 来扩缩容示例:
apiVersion: apps/v1 kind: ReplicaSet metadata: name: frontend labels: app: guestbook tier: frontend spec: *# 按你的实际情况修改副本数 * replicas: 3 selector: matchLabels: tier: frontend template: metadata: labels: tier: frontend spec: containers: - name: php-redis image: gcr.io/google_samples/gb-frontend:v3
- 运行
kubectl apply -f https://kubernetes.io/examples/controllers/frontend.yaml
过一会运行
kubectl get pods
就可以看到部署了3个 以 frontend 开头的 pod。
- 接下来尝试删除一个 Pod
然后再查看 pod 情况
发现原先的 h476q 已经没了,又出来一个新的 hb8x8。
- 我们给其中一个 pod 修改一下 label
YAML kubectl label pod frontend-hb8x8 tier=backend --overwrite
然后查看 pod 情况
发现 Pod 数量从原来的 3 个变成了 4 个。
Pod 副本控制流程
所有 ReplicaSet 对象的增删改查都是由 ReplicaSetController 控制器完成的,该控制器会监听 ReplicaSet 的变更。
Replication Controller 的核心作用是确保在任何时候集群中一个RC所关联的Pod 副本数量
保持预设值。如果发现 Pod 副本数量超过预期值,则 Replication Controller 会销毁一些Pod 副本;
Controller Manager 里面的 Controller 原理类似, 它们通过API Server 提供的接口实时监控整个集群里的每个资源对象的当前状态,当发生各种故障导致系统状态发生变化时,会尝试着将系统状态从“现有状态”修正到“期望状态”。
第一个示例中,创建 ReplicaSet 之前,满足带有 tier: frontend label 条件的 pod 数量是 0 个,Controller Manager 发现期望状态是 3 个,就会按模板创建出 3 个Pod。
第二个示例中,我们删除了一个 Pod, Controller Manager 发现期望状态是 3 个,但是实际值是 2 个,就会再根据模板创建一个新的 Pod。
第三个示例中,我们修改了一个 Pod 的 label, 导致它不满足 ReplicaSet 的 selector 条件:tier: frontend。Controller Manager 根据 selector 规则来统计数量时发现只有 2 个(期望 3 个),就会根据模板再创建一个 Pod,总共就有 4 个 Pod 了。
体验地址
在线实践 Kubernetes
https://kubernetes.io/zh-cn/docs/tutorials/kubernetes-basics/deploy-app/deploy-interactive/
https://labs.play-with-k8s.com/
参考资料:
《Kubernetes权威指南:从Docker到Kubernetes实践全接触(第2版)》
《Kubernetes源码剖析》
https://kubernetes.io/zh-cn/docs/concepts/overview/what-is-kubernetes/
https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/
https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/replicaset/
https://www.cnblogs.com/yanjieli/p/11792737.html
https://juejin.cn/post/6952331691524358174
https://www.modb.pro/db/174089
- 本文链接: http://hjwblog.com/archives/k8sarchitecture
- 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!