我对 Kubernetes 的片面理解 —— 基础篇(持续更新中)

Kubernetes 的高矮胖瘦(介绍)

Kubernetes 是一个 可移植可扩展 的开源平台。使用 声明式的配置 依据配置信息自动化执行容器化应用程序的管理。
在这里插入图片描述

Traditonal Deployment(传统部署时代):早期,企业直接将应用程序部署在物理机上,由于物理机不能为应用程序定义资源使用边界,很难合理地分配计算资源;
Virtualized Deployment(虚拟化部署时代):用户可以在单台物理机的 CPU 上运行多个虚拟机;

  • 虚拟化技术使得应用程序被虚拟机相互分隔开,限制了应用程序之间的非法访问,进而提供了一定程度的安全性;
  • 虚拟化技术提高了物理机的资源利用率,可以更容易地安装或更新应用程序,降低了硬件成本,更好地规模化实施;
  • 每一个虚拟机都可以被当作虚拟化的物理机上的一台完整机器,上面运行了一台机器的所有组件,包括虚拟机自身的操作系统。

Container Deployment(容器化部署时代):容器与虚拟机类似,但降低了隔离层级,共享了操作系统。因此,容器可以被当作轻量级的

  • 与虚拟机类似,每个容器都拥有自己的文件系统、CPU、内存、进程空间等;
  • 运行应用程序所需要的资源都被容器包装,并和底层基础架构解耦;
  • 容器化应用程序可以跨云服务商、跨 Linux 操作系统发行版进行部署

容器化的优势:

  • 敏捷创建和部署应用程序:和创建虚拟机镜像相比,创建容器镜像更容易且快速;
  • 持续构建集成:可快速构建容器镜像、部署容器化的应用程序、并轻松无痛回滚应用程序;
  • 降低开发和运维的耦合度:开发阶段关注如何构建容器镜像的过程、部署阶段关注如何提供基础设施以及如何使用容器镜像;
  • 可监控性:不仅可以查看操作系统级别的资源监控信息,还可以查看应用程序健康状态以及其他信号的监控信息;
  • 开发、测试、生产不同阶段的环境一致性
  • 跨云服务商、跨操作系统发行版的可移植性:容器可运行在 Ubuntu、RHEL、CoreOS、CentOS等不同的操作系统发行版上,可以运行在私有化部署、Google Kubernetes Engine、AWS、阿里云等不同的云供应商的环境中;
  • 以应用程序为中心的管理:虚拟机时代考虑在虚拟硬件上运行一个操作系统,而容器化时代则是在操作系统的逻辑资源上运行一个应用程序;
  • 松耦合、分布式、弹性、无约束的微服务:应用程序被切分成更小的、独立的微服务,并可以动态部署和管理,而不是一个部署在专属机器上的庞大的单片应用程序;
  • 资源隔离:确保应用程序性能不受干扰;
  • 资源利用:资源高效、高密度利用。

Kubernetes 功能

  • 服务发现和负载均衡:Kubernetes 可以通过 DNS 名称或 IP 地址暴露容器的访问方式。并且可以在同组容器内分发负载来实现负载均衡;
  • 存储编排:kubernetes 可以自动挂载指定的存储系统
  • 自动发布和回滚:可以在 kubernetes 中声明期望应用程序容器达到的状态,kubernetes 将以合适的合适的速率调整容器的实际状态,并逐步达到最终期望的结果
  • 自愈:
    • 重启已经停机的机器;
    • 替换、kill 掉不满足自定义健康检查条件的容器;
    • 容器就绪之前,避免调用者发现该容器。
  • 密钥及配置管理:
    • 重新构建容器的镜像
    • 在不合适的地方暴露密码信息

Kubernetes 边界

Kubernetes不是一个传统意义的、保罗万象的 PaaS(Platform as a Service)系统。Kubernetes在容器层面工作,而不是硬件层面,它提供了与 PaaS 平台相似的通用特性,例如:部署、伸缩、负载均衡、日志、监控等。然而,Kubernetes并不是一个单一整体,这些特性都是可选、可插拔的。Kubernetes提供用于搭建开发平台的基础模块,同时为用户提供了不同模块的选择性和多样性。

  • 不限制应用程序的类型。Kubernetes的目标是广泛支持不同类型的工作负载,包括:有状态、无状态、数据处理等类型的应用。只要应用可以在容器中运行,就能够非常好地在 Kubernetes 上运行;
  • 不部署源码、不编译或构建应用程序。持续集成、分发、部署(CI/CD)的工作流极大程度上取决于组织的文化、偏好以及技术要求。Kubernetes可以作为部署平台参与到 CI/CD 流程,但是不涉及镜像构建和分发的过程;

可选的有 Jenkins / Gitlab Runner / docker registry / harbour 等

  • 不提供应用程序级别的服务,包括:中间件(例如,消息总线)、数据处理框架(例如,Spark)、数据库(例如,mysql)、缓存(例如,Redis),或者分布式存储(例如,Ceph)。此类组件可以在 Kubernetes 上运行,或者可以被运行在 Kubernetes 上的应用程序访问;
  • 不限定日志、监控、报警的解决方案。Kubernetes 提供一些样例展示如何与日志、监控、报警等组件集成,同时提供收集、导出监控度量(metrics)的一套机制。您可以根据自己的需要选择日志、监控、报警组件;

可选的有 ELK / Prometheus / Graphana / Pinpoint / Skywalking / Metrics Server 等

  • 不提供或者限定配置语言(例如,jsonnet)。Kubernetes提供一组声明式的 API,您可以按照自己的方式定义部署信息;

可选的有 helm/kustomize/kubectl/kubernetes dashboard/kuboard/octant/k9s 等

  • 不提供或限定任何机器的配置、维护、管理或自愈的系统

可选的组件有 puppet、ansible、open stack 等

Kubernetes不是一个纯粹意义上的容器编排系统。事实上,Kubernetes 消除了容器编排的需求。容器编排的技术定义是预定义流程的执行(先做A、再做B、然后做C)。与此相对应,Kubernetes构建了一系列相互独立、可预排的控制过程,以持续不断地将系统从当前状态调整到声明的目标状态

声明式的配置

声明的方式是相对于非声明方式而言。

以滚动更新为例,假设当下有 3 个容器组,现在需要将它们的容器镜像更新为新的版本

  • 非声明方式:
    • 使用 kubectl 创建一个新版本镜像的容器组;
    • 使用 kubectl 观察新建容器组的状态;
    • 新建容器组的状态就绪之后,使用 kubectl 删除一个旧的容器组;
    • 重复执行,直到所有容器组都已经替换为新版本镜像的容器组。
  • 声明方式:
    • 使用 kubectl 更新 Deployment 定义中 spec.template.spec.containers[].image 字段。

声明 的方式管理 Pod 和 ReplicaSet,其本质上是将一些特定场景的一系列运维步骤固化下来,以便快速无误的执行。

  • 创建 Deployment:创建 Deployment 后,Deployment 控制器将立刻创建一个 ReplicaSet 副本集,并由 ReplicaSet 创建所需要的 Pod;
  • 更新 Deployment:更新 Deployment 中 Pod ,此时 Deployment 控制器将为该 Deployment 创建一个新的 ReplicaSet 副本集,并且逐步在新的副本集中创建 Pod,在旧的副本集中删除 Pod,以达到滚动更新的效果;
  • 回滚 Deployment:回滚到一个早期 Deployment 版本;
  • 伸缩 Deployment:水平扩展 Deployment,来支持更大的负载。或者水平收缩 Deployment,来节省服务器资源;
  • 暂停和继续 Deployment
  • 查看 Deployment 状态
  • 清理策略
  • 金丝雀发布

创建 Deployment

两种创建方式:

  • 使用 kubectl 创建 deployment
  • 使用 kuboard 创建 deployment

这里我们采用 kubectl 创建方式来完成~
(1)编辑 yaml 文件

## 该 yaml 文件定义了一个 Deployment,该 Deployment 将创建一个有 3 个 nginx Pod 副本的 ReplicaSet(副本集)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment       # .metadata.name 字段指定了名称
  labels:
    app: nginx
spec:
  replicas: 3
  selector:                    # .spec.selector 字段指定了 Deployment 如何找到由他管理的 Pod
    matchLabels:
      app: nginx
  template:                    
  # 使用了 Pod template 定义的一个标签(app:nginx),可根据需求添加更复杂的规则
    metadata:
      labels:                  # .template.metadata.labels 字段指定了 Pod 的标签
        app: nginx
    spec:
      containers:
      - name: nginx            # .template.spec.containers[].name 字段表明容器名字为 nginx
        image: nginx:1.7.9     # .template.spec.containers[].image 字段表明该 Pod 运行容器 nginx:1.7.9
        ports:
        - containerPort: 80

(2)执行命令来创建 Deployment

kubectl apply -f nginx-deployment.yaml
## 为该命令增加 --record 选项,kubectl 会将 kubectl apply -f nginx-deployment.yaml --record 写入 Deployment annotation(注解) kubernetes.io/change-cause 中,以便后期回顾某一个 Deployment 版本变化原因

(3)执行 kubectl get deployments 检查 deployment 创建情况,若还在创建过程中,则如下所示:

NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         0         0            0           1s
字段名称说明
NAMEDeployment name
DESIREDDeployment 期望的 Pod 副本数,即 Deployment 中 .spec.replicas 字段指定的数值,为“期望”值
CURRENT当前有多少个 Pod 副本数在运行
UP-TO-DATEDeployment 中,符合当前 Pod Template 定义的 Pod 数量
AVAILABLE当前对用户可用的 Pod 副本数
AGEDeployment 部署以来到现在的时长

(4)查看 Deployment 的发布状态(rollout status),执行命令 kubectl rollout status deployment.v1.apps/nginx-deployment
(5) 查看 Deployment 创建的 ReplicaSet(rs),执行命令 kubectl get rs
(6) 查看 Pod 的标签,执行命令 kubectl get pods --show-labels

警告:不要修改 Pod-template-hash 标签

更新 Deployment

当且仅当 Deployment 的 Pod template(.spec.template)字段中的内容发生变更时(例如标签、容器的镜像被改变),Deployment 的发布更新(rollout)将被触发。Deployment 中其他字段的变化(例如修改 .spec.replicas 字段)不会触发 Deployment 的发布更新(rollout)

两种途径对 Deployment 执行发布更新(rollout):

  • 使用 kubectl 更新 Deployment
  • 使用 Kuboard 更新 Deployment

这里我们采用 kubectl 更新方式来完成~
(1)将镜像从 nginx:1.7.9 更新到 nginx:1.9.1

kubectl --record deployment.apps/nginx-deployment set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1

(2)查看发布更新(rollout)的状态

kubectl rollout status deployment.v1.apps/nginx-deployment

查看 更新后 deployment 的情况

(1)更新(rollout)成功后,您可以执行命令 kubectl get deployments 以查看更新结果
(2)执行命令 kubectl get rs Deployment 的更新是通过创建一个新的 3 个副本数的 ReplicaSet 并同时将旧的 Replicaset 的副本数缩容到 0 个副本 来达成的
(3)执行命令 kubectl get pods,此时将只显示新的 Pod

  • 想要修改这些新的 Pod,只需要再次修改 Deployment 的 Pod template
  • Deployment 将确保更新过程中,任意时刻只有一定数量的 Pod 被关闭。默认情况下,Deployment 确保至少 .spec.replicas 的 75% 的 Pod 保持可用(25% max unavailable)
  • Deployment 将确保更新过程中,任意时刻只有一定数量的 Pod 被创建。默认情况下,Deployment 确保最多 .spec.replicas 的 25% 的 Pod 被创建(25% max surge)
    (4)执行命令 kubectl describe deployments 查看 Deployment 详情

创建 Deployment 时,Deployment Controller 创建了一个 ReplicaSet,并直接将其 scale up 到 3 个副本。当更新 Deployment 时,Deployment Controller 先创建一个新的 ReplicaSet 并将其 scale up 到 1 个副本,然后 scale down 旧的 ReplicaSet 到 2。
Deployment Controller 继续 scale up 新的 ReplicaSet 并 scale down 旧的 ReplicaSet,直到最后,新旧两个 ReplicaSet,一个副本数为 3,另一个副本数为 0。

回滚 Deployment

(1)检查 Deployment 更新历史

kubectl rollout history deployment.v1.apps/nginx-deployment 
# 检查当前 Deployment 的历史版本
deployments "nginx-deployment"
REVISION    CHANGE-CAUSE
1           kubectl apply --filename=https://k8s.io/examples/controllers/nginx-deployment.yaml --record=true

其中,CHANGE-CAUSE 是该 revision(版本)创建时从 Deployment 的 annotation kubernetes.io/change-cause 拷贝来
若需自定义,可通过如下操作完成:

  • kubectl annotate deployment.v1.apps/nginx-deployment kubernetes.io/change-cause="image updated to 1.9.1" 给 Deployment 添加注解
  • 执行 kubectl apply 命令,增加 --record 选项
  • 手动编辑 Deployment 的 .metadata.annotation 信息

(2)查看 revision(版本)详细信息

kubectl rollout history deployment.v1.apps/nginx-deployment --revision=2

(3)回滚前一个版本

kubectl rollout undo deployment.v1.apps/nginx-deployment

(4)回滚到前面某一个指定版本

kubectl rollout undo deployment.v1.apps/nginx-deployment --to-revision=2
## 通过 --to-revision=2 指定版本

(5)检查回滚是否成功

kubectl get deployment nginx-deployment

Kubernetes 大小粗细(组件)

Master 组件

Master 组件是集群的控制平台

  • master 组件负责集群中的全局决策(例如,调度);
  • master 组件探测并响应集群事件(例如, Deployment 的实际 Pod 副本数未达到 replicas 字段的规定时,启动一个新的 Pod)

kube-apiserver

该组件提供 Kubernetes API。这是Kubernetes控制平台的前端(front-end),可以水平扩展(通过部署更多的实例以达到性能要求)。kubectl / kubernetes dashboard / kuboard 等Kubernetes管理工具就是通过 kubernetes API 实现对 Kubernetes 集群的管理。

etcd

支持一致性和高可用的名值对存储组件,Kubernetes集群的所有配置信息都存储在 etcd 中。

kube-scheduler

master 组件监控所有新创建尚未分配到节点的 Pod,并自动选择为 Pod 选择一个合适的节点去运行。

影响调度的因素有

  • 单个或多个 Pod 的资源需求;
  • 硬件、软件、策略的限制;
  • 亲和和反亲和(affinity and anti-affinity)的约定;
  • 数据本地化要求;
  • 工作负载间的相互作用。

kube-controller-manager

此 master 组件运行了所有的控制器

逻辑上说,每一个控制器是一个独立的进程,但为了降低复杂度,可以将这些控制器都合并在一个进程里。

其中包含的控制器有:

  • 节点控制器:负责监听节点停机的事件并作出对应响应;
  • 副本控制器:负责为集群中的每一个副本控制器对象(Replication Controller Object)维护期望的 Pod 副本数;
  • 端点(Endpoints)控制器:负责为端点对象(Endpoint Object,连接 Service 和 Pod)赋值;
  • Service Account & Token 控制器:负责为新的名称空间创建 default Service Account 以及 API Access Token;

cloud-controller-manager

cloud-controller-manager 中运行了与具体云基础设施供应商互动的控制器。在 k8s 1.6 版本中引入的特性,它使得云供应商的代码和 Kubernetes 的代码可以各自独立的演化。在后续的版本中,特定于云供应商的代码将有云供应商自行维护,并在运行 kubernetes 时链接到
cloud-controller-manager。

下面这些控制器包含与云供应商相关的依赖:

  • 节点控制器:当某一个节点停止响应时,调用云供应商接口,以检查该节点的虚拟机是否已经被云供应商删除
  • 路由控制器:在云供应商的基础设施中设定网络路由
  • 服务控制器:创建、更新、删除云供应商提供的负载均衡器
  • 数据卷控制器:创建、绑定、挂载数据卷,并协调云供应商编排数据卷

Node 组件

Node 组件运行在每一个节点上(包括 master 节点和 worker 节点),负责维护运行中的 Pod 并提供 Kubernetes 运行时环境

kubelet

运行在每一个集群节点上的代理程序。确保 Pod 中的容器处于运行状态,Kubelet 通过多种途径获得 PodSpec 定义,并确保 PodSpec 定义中所描述的容器处于运行和健康的状态。它只管理通过 Kubernetes 创建的容器。

kube-proxy

kube-proxy 是一个网络代理程序,运行在集群中的每一个节点上,是实现 Kubernetes Service 的重要组成部分。

kube-proxy 在节点上维护网络规则。这些网络规则使得可以在集群内、外正确地与 Pod 进行网络通信。如果操作系统中存在
packet filtering layer,kube-proxy 将使用(iptables 代理模式)这一特性,否则的话,kube-proxy 将自行转发网络请求(User space 代理模式)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值