K8S理论


引言: 今天不上班,摆烂

一、概念

Kubernetes 是用于自动部署,扩展和管理容器化应用程序的开源系统。它将组成应用程序的容器组合成逻辑单元,以便于管理和服务发现。Kubernetes 源自Google 15 年生产环境的运维经验,同时凝聚了社区的最佳创意和实践。

1.1 知识图谱

1.2 Kubernetes 解决的核心问题

服务发现和负载均衡

Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器,如果到容器的流量很大,Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。

存储编排

Kubernetes 允许您自动挂载您选择的存储系统,例如本地存储、公共云提供商等。

自动部署和回滚

您可以使用 Kubernetes 描述已部署容器的所需状态,它可以以受控的速率将实际状态更改为所需状态。例如,您可以自动化 Kubernetes 来为您的部署创建新容器,删除现有容器并将它们的所有资源用于新容器。

自动二进制打包

Kubernetes 允许您指定每个容器所需 CPU 和内存(RAM)。当容器指定了资源请求时,Kubernetes 可以做出更好的决策来管理容器的资源。

自我修复

Kubernetes 重新启动失败的容器、替换容器、杀死不响应用户定义的运行状况检查的容器,并且在准备好服务之前不将其通告给客户端。

密钥与配置管理

Kubernetes 允许您存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。您可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。

Kubernetes 的出现不仅主宰了容器编排的市场,更改变了过去的运维方式,不仅将开发与运维之间边界变得更加模糊,而且让 DevOps 这一角色变得更加清晰,每一个软件工程师都可以通过 Kubernetes 来定义服务之间的拓扑关系、线上的节点个数、资源使用量并且能够快速实现水平扩容、蓝绿部署等在过去复杂的运维操作。

二、K8S组件

2.1 控制平面组件

1、kube-apiserver/api接口 对外暴露K8S的api接口,是外界进行资源操作的唯一入口 提供认证、授权、访问控制、api注册和发现等机制 需部署在 master 节点上;是 Kubernetes 控制面的前端。kube-apiserver 在设计上考虑了水平扩展的需要,如果我们需要搭建集群,可以安装基数节点的kube-apiserver,然后可通过负载均衡器做集群

2、etcd/k8s后台数据库 etcd 是兼具一致性和高可用性的键值数据库,官方建议作为 Kubernetes 所有集群数据的后台数据库 Kubernetes集群的etcd数据通常需要有个备份计划

==3、kube-scheduler/k8s pod调度器 == 需部署在 master 节点上,该组件监视那些新创建的未指定运行节点的 Pod,并选择节点让 Pod 在上面运行。 调度决策考虑的因素包括单个 Pod 和 Pod 集合的资源需求、硬件/软件/策略约束、亲和性和反亲和性规范、数据位置、工作负载间的干扰和最后时限。 所有对K8S的集群操作,都必须经过主节点进行调度。

4、kube-controller-manager/k8s管理器 需部署在 master 节点上。 从逻辑上讲,每个控制器都是一个单独的进程,但是为了降低复杂性,它们都被编译到同一个可执行文件,并在一个进程中运行。

这些控制器包括:

1、节点控制器(Node Controller): 负责在节点出现故障时进行通知和响应

2、副本控制器(Replication Controller): 负责为系统中的每个副本控制器对象维护正确数量的 Pod

3、端点控制器(Endpoints Controller): 填充端点(Endpoints)对象(即加入 Service 与 Pod)

4、服务帐户和令牌控制器(Service Account & Token Controllers): 为新的命名空间创建默认帐户和 API 访问令牌

5、cloud-controller-manager/云控制器管理器 运行与基础云提供商交互的控制器,从k8s1.6之后出现的新功能

也包括了多个控制器:节点控制器、路由控制器、服务控制器、数据卷控制器

6、Node节点组件

kubelet/节点管理工具 一个在集群中每个节点运行的代理。它保证容器都运行在Pod中。 负责维护容器的生命周期、同时也负责Volume(CSI)和网络(CNI)的管理。 kubelet负责管理节点的pod,可以理解为当在master上执行创建、删除对象时,kubelet负责执行从kube-apiserver下达的指令

kube-proxy/网络管理器 kube-proxy运行在每个node节点上,管理维护node上的网络规则 (+负责为Service提供cluster内部的服务发现和负载均衡。)

Container Runtime/容器运行环境 简而言之,就是容器。我们需要在node节点安装runtime作为k8s部署容器的运行环境,目前主流当然是docker Kubernetes支持多个容器运行环境Dockers、Container、cri-o、rktlet以及任何实现Kubernetes CRI(容器运行环境接口)。

fluentd 是一个守护进程,它有助于提供集群层面日志。

集群插件

域名解析服务:如CoreDNS、Cluster DNS

资源监控服务:Prometheus、Metrics-Server

用户的ui管理界面:Dashboard、Kubesphere

集群日志:ELK

镜像仓库:Harbor

2.2 pod

pod是K8S的最小管理单元,一个pod中可运行一个或者一组容器。pod内的容器共享使用pod的唯一ip地址和一组存储卷。同一pod内的容器使用localhost进行通信;而与pod外的容器通信时,需要pod内的容器协调使用pod的端口进行通信

pod有生命周期,当一个pod生命周期结束后,该pod将不复存在,k8s会重新部署一个新的pod提供和该pod一样的服务。这样就用到service概念用于标记k8s集群提供一组服务的pod。

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
  - args:
    - /server
    image: k8s.gcr.io/liveness
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
        httpHeaders:
        - name: X-Custom-Header
          value: Awesome
      initialDelaySeconds: 15
      timeoutSeconds: 1
    name: liveness

即:

k8s使用Pod来组织一组容器 一个Pod中的所有容器共享同一个网络 Pod是k8s中最小部署单元

2.3 service

假定有一组 Pod,它们对外暴露了 9376 端口,同时还被打上 app=MyApp 标签,我们就可以部署一个service,将TCP:9376的请求代理到这组pod上,上述就是service的作用。所以可以大致理解为service是pod的代理层,根据用户请求的端口和服务,service找到对应标签的pod,将请求代理到这些pod去处理。如果您想要在应用程序中使用 Kubernetes 接口进行服务发现,则可以查询 API Server 的 endpoint 资源,只要服务中的Pod集合发生更改,endpoint 就会更新。

官方说:逻辑上的一组 Pod,一种可以访问它们的策略 —— 通常称为微服务。 这一组 Pod 能够被 Service 访问到,通常是通过selector实现的

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

即:

定义一组Pod的访问策略 Pod的负载均衡,提供一个或多个Pod的稳定访问地址 支持多种方式(ClusterIP、NodePort、LoadBalance)

2.4 volume

Kubernetes 卷具有明确的生命周期——与包裹它的 Pod 相同,但是卷比 Pod 中运行的任何容器的存活期都长,在容器重新启动时数据也会得到保留。Kubernetes支持多种类型的卷,如nfs、iscsi、cinder、azureDisk等

以下是cinder volume示例配置:

apiVersion: v1
kind: Pod
metadata:
  name: test-cinder
spec:
  containers:
  - image: k8s.gcr.io/test-webserver
    name: test-cinder-container
    volumeMounts:
    - mountPath: /test-cinder
      name: test-volume
  volumes:
  - name: test-volume
    # This OpenStack volume must already exist.
    cinder:
      volumeID: <volume-id>
      fsType: ext4

即:

声明在Pod容器中可以访问的文件目录 可以被挂载在Pod中一个或多个容器指定路径下 支持多种后端存储对象(本地存储、分布式存储、云存储…)

2.5 deployment

顾名思义,Deployment是一个部署,作用主要是创建、更新、回滚ReplicaSet以控制pod 如下是k8s官方的Deployment示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

2.6 namespace(命名空间)

命名空间为名称提供了一个范围。资源的名称需要在命名空间内是唯一的,但不能跨命名空间。命名空间不能相互嵌套,每个 Kubernetes 资源只能在一个命名空间中。

kubernetes存在三个初始的命名空间:

default/没有指定命名空间的容器默认的

kube-system/kubernetes系统创建的

kube-public/公共的,对于所有用户都可读
kubectl get namespace NAME STATUS AGE default Active 1d kube-public Active 1d kube-system Active 1d

即:

一个集群内部的逻辑隔离机制(鉴权、资源) 每个资源都属于一个namespace 同一个namespace所有的资源名不能重复 不同的namespace资源名可以同名

2.7 Job(一次性任务)

可创建一个或者多个pod,job在指定次数、指定个数的pod创建后job的工作就完成了

删除一个job,会将其创建的pod一并清除

2.8 endpoint

endpoint是kubernetes的一个资源对象,存储于etcd数据库中,用以记录service的所有pod的访问地址

2.9 object(对象)

object是持久化的实体,用以表示整个集群的状态:

哪些容器化应用在运行

可以被应用使用的资源

应用运行时重启策略、升级策略,以及容错策略

一个object一旦创建,kubernetes会持续工作以保证对象存在;也就是通过对象棵设置kubernetes集群的期望状态

object的操作依赖于Kubernetes API,如果使用kubectl也是通过调用Kubernetes API完成的操作(使用yaml文件操作会将文件的内容从yaml转换为json格式)

2.10 Object Name 和 UID(对象名和UID)

集群中的每一个对象都一个名称 来标识在同类资源中的唯一性。

每个 Kubernetes 对象也有一个UID 来标识在整个集群中的唯一性。

2.11 label(标签)

label是附加到对象的键/值对;label可以在创建时附加到对象,然后可以随时添加和修改。每个对象可以定义一组键/值标签。每个键对于给定的对象必须是唯一的。label不是唯一的,也就是说多个对象可以拥有同一个label,如我们可以创建多个label为nginx的pod用于统一管理。

2.12 label selector(标签选择器)

与名称和UID不同,标签不提供唯一性。通常,我们希望许多对象携带相同的标签。通过标签选择器,客户端/用户就可以识别一组同标签的对象。

2.13 ReplicaSet (确保预期的Pod副本数量)

ReplicaSet 是Replication Controller(RC)的下一代,区别在于支持基于集合的选择器。

官方说:ReplicaSet 确保任何时间都有指定数量的Pod副本在运行。 然而,Deployment 是一个更高级的概念,它管理 ReplicaSet,并向 Pod 提供声明式的更新以及许多其他有用的功能, 因此,我们建议使用 Deployment 而不是直接使用 ReplicaSet。

2.14 ReplicationController(RC)

是kubernetes的pod数量控制器,RC同时跨多个节点(node)控制多个pod的数量而不是仅限于单机。工作的内容主要是当pod数量跟预期不一样了,RC会将该数量维持为预期的数量

以下是配置运行 nginx web 服务器的三个副本的RC的示例(会控制pod数量始终为3个):

apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    app: nginx
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

2.15 StatefulSets(有状态应用部署)

StatefulSets用来管理 Deployment 和扩展一组 Pod

StatefulSet 和 Deployment 相同的是管理了基于相同容器定义的一组 Pod;但是StatefulSet 为它的每个 Pod 维护了一个固定的 ID,并且该ID是基于声明创建的,无论pod如何调度,ID永久不变

StatefulSet多用于满足以下一个或多个条件的应用程序:

稳定的、唯一的网络标识符。

稳定的、持久的存储。

有序的、优雅的部署和缩放。

有序的、自动的滚动更新。

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx # has to match .spec.template.metadata.labels
  serviceName: "nginx"
  replicas: 3 # by default is 1
  template:
    metadata:
      labels:
        app: nginx # has to match .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: k8s.gcr.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "my-storage-class"
      resources:
        requests:
          storage: 1Gi

2.16 DaemonSet(确保所有Node都运行一个指定Pod)

DaemonSet管理节点上的各个守护的pod,例如集存储群、日志收集器、监控客户端,通俗来讲就是K8S集群状态的控制器

总结:

今日歇业

经验分享 程序员 微信小程序 职场和发展