Kubernetes 101

Oct 01, 2020 • 预计阅读时间 9 分钟

前提准备:K8s 学习前必须要先了解容器    Docker/容器 101(2020.9 更新)

功能概述

同样先来道开胃菜:

Kubernetes 定义为容器编排引擎(orchestration),Kubernetes 对于容器,就相当于 Linux 内核对于线程,考虑到容器作为云基础设施上的基本运行单位,Kubernetes 就类似云上的操作系统内核,其作用包含:

features

集群架构

architecture

Kubernetes 的组件分成两种,通常相应运行在两种机器上:Master/控制节点负责管理集群,包含 kube-apiserverkube-controller-managerkube-scheduleretcd 组件;Node 节点运行具体的容器应用,由 Container Runtimekubeletkube-proxy 组成。

Master 正式名称为控制面板(Control Panel):

  • etcd 保存了整个集群/资源的状态,是一个分布式 key-value 存储。

  • kube-apiserver 提供了资源操作的唯一入口,并提供认证、授权、访问控制、API 注册和发现等机制,只有 API Server 会与 etcd 进行通信,其它模块都必须通过 API Server 访问集群状态。API Server 封装了核心资源对象的增删改查操作,以 RESTFul 接口方式提供给外部客户端和内部组件调用,API Server 再对相关的资源数据(全量查询 + 变化监听)进行操作,以达到实时完成相关的业务功能。

  • kube-controller-manager 负责维护各种资源对象,从现在状态(status)到用户想要的状态(spec),比如故障检测、自动扩展、滚动更新等,具体由各种 controller 负责执行: controller

  • kube-scheduler 负责资源的调度,主要用于收集和分析当前 Kubernetes 集群中所有负载节点的资源 (包括内存、CPU 等) 负载情况,并按照预定的调度策略(例如:根据用户对资源要求,CPU、内存、来评估哪个 nodes 最合适运行)将 Pod 调度到相应的机器上。

Node (也称为 Worker 或负载节点)是 Kubernetes 集群里的单台服务器,执行并运行从 Master 传来的各种负载任务:

  • Container runtime 负责镜像管理以及 Pod 和容器的真正运行时(CRI),默认的容器运行时为 Docker。

  • kubelet 相当于 Master 的 agent,负责和 Master 的通信,维持 Pod/容器的生命周期,同时确定其符合 YAML 所定义的 PodSpec,其中包括关于 Volume(CVI)和网络(CNI)的管理。

  • kube-proxy 负责为 Service 提供内部的服务发现和负载均衡,把 request 转发到相关容器上;

此外还有非常重要的集群管理命令行客户端工具集 Kubectl,通过 Kubectl 命令对 API Server 进行操作,API Server 响应并返回对应的命令结果,从而达到对 Kubernetes 集群的管理。

Kubernetes 还有一些安装扩展以达到真正可使用,包括网络 Calico/Flannel,CoreDNS,Dashboard 等,参考安装扩展

核心资源对象

和 OS 类似,Kubernetes 对底层静态和运行时的资源都进行了抽象,Kubernetes 的编排和管理功能就是通过对这些对象进行编排和管理:

-   workload:Pod、ReplicaSet、Deployment、StatefulSet、DaemonSet、Job、CronJob
-   服务发现及均衡:Service、Ingress
-   配置与存储:
    -   Volume、CSI
    -   ConfigMap、Secret
    -   DownwardAPI
-   集群级资源:Namespace、None、Role、ClusterRole、RoleBinding、ClusterRoleBinding
-   元数据类型资源:HPA、PodTemplate、LimitRange

在 Kubernetes 中,所有资源对象的配置都在配置清单中定义(yaml 或 json),基本格式:

apiVersion:
    # 以 "group/version" 形式指明,这个对象属于哪个 API 组(版本)
kind:
    # 资源类别,标记创建什么类型的资源: Pod, Deployment, Job 等
metadata:
    # 元数据内部是嵌套的字段
    # 定义了资源对象的名称、命名空间(k8s级别的不是系统的)等、标签、注解、UID等
spec:
    # 规范定义资源应该拥有什么样的特性,依靠控制器确保特性能够被满足
    # 它是用户定义的所期望了资源状态
status:
    # 显示资源的当前状态,k8s 就是确保当前状态向目标状态无限靠近从而满足用户期望
    # 它是只读的,代表了资源当前状态

几个核心资源介绍:

核心资源

  • Pod

Pod 是一组紧密关联的容器集合,它们共享 PID、IPC、Network 和 UTS namespace,是 Kubernetes 调度的基本单位。Pod 的设计理念是支持多个容器在一个 Pod 中共享网络和文件系统,可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。我们知道容器本质上就是进程,那么 Pod 实际上就是进程组了,只是这一组进程是作为一个整体来进行调度的。

kind: Pod
metadata:
    name: pod-deme # pod 的名称
    namespace: default
    labels:
        app: myapp
        tier: frontend
spec:
    containers:
        - name: myapp # 运行的容器名称
          image: ikubernetes/myapp:v1 # 容器的镜像
          imagePullPolicy: IfNotPresent # 从仓库获取镜像的策略
          ports: # 定义容器暴漏的端口
        - name: busybox
          image: busybox:latest
          command:
              - "/bin/sh"
              - "-c"
              - "sleep 10"
  • Replica Set

声明 Pod 的横向水平扩展,selector 标签选择器,可以使用 matchLabels、matchExpressions 两种类型的选择器来选中目标 POD:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
    name: myrs
    namespace: default
spec:
    replicas: 2
    selector:
        matchLabels:
            app: myapp
            release: canary
    template:
        metadata:
            name: myapp-pod
            labels:
                app: myapp # 标签一定要符合 replicaset 标签选择器的规则
                release: canary
        spec:
            containers:
                - name: myapp-containers
                  image: ikubernetes/myapp:v1
                  ports:
                      - name: http
                        containerPort: 80
  • Deployment

一般不直接管理 Pod,而是通过 Deployment 来管理应用程序。Deployment 通过控制 ReplicaSet 来实现功能,除了支持 ReplicaSet 的扩缩容意外,还支持滚动更新和回滚等,还提供了声明式的配置,这个是我们日常使用最多的控制器。它是用来管理无状态的应用。

Deployment 在滚动更新时候,通过控制多个 ReplicaSet 来实现,ReplicaSet 又控制多个 POD,多个 ReplicaSet 相当于多个应用的版本。

apiVersion: apps/v1
kind: Deployment
metadata:
    name: myapp-deploy
    namespace: default
spec:
    replicas: 2
    selector:
        matchLabels:
            app: myapp
            release: canary
    template:
        metadata:
            labels:
                app: myapp
                release: canary
        spec:
            containers:
                - name: myapp
                  image: ikubernetes/myapp:v1
                  ports:
                      - name: http
                        containerPort: 80
  • Service

Service 为 POD 控制器控制的 POD 集群提供一个固定的访问端点 - 一个集群内部有效的虚拟 IP,集群内部通过虚拟 IP 访问一个服务,负载均衡由 Kube-proxy 实现。Service 的工作还依赖于一个安装扩展,就是 CoreDNS ,它将 Service 地址提供一个域名解析。

apiVersion: v1
kind: Service
metadata:
    name: redis
    namespace: default
spec:
    selector:
        app: redis
        role: logstor
    type: ClusterIP
    clusterIP: 10.96.0.100
    ports:
        - port: 6379 # service 端口
          targetPort: 6379 # pod 监听的端口
          protocol: TCP
  • StatefulSet

StatefulSet 是为了解决有状态服务的问题(对应 Deployments 和 ReplicaSets 是为无状态服务而设计),其应用场景包括

  1. 稳定的持久化存储,即 Pod 重新调度后还是能访问到相同的持久化数据;
  2. 稳定的网络标志,即 Pod 重新调度后其 PodName 和 HostName 不变;
  3. 有序部署,有序扩展,即 Pod 是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依序进行(即从 0 到 N-1,在下一个 Pod 运行之前所有之前的 Pod 必须都是 Running 和 Ready 状态);
  4. 有序收缩,有序删除(即从 N-1 到 0);
  • Namespace

Namespace 是对一组资源对象的抽象集合,比如可以用来将系统内部的对象划分为不同的项目组或用户组,用来包括鉴权、资源管理等。常见的 pods, services, replication controllers 和 deployments 等都是属于某一个 namespace 的(默认是 default),而 node, persistentVolumes 等则不属于任何 namespace。同一个 Namespace 中的资源命名必须唯一。

Namespace 常用来隔离不同的团队/用户/项目,比如 Kubernetes 自带的服务一般运行在 kube-system namespace 中。

  • Volume

用来声明在 Pod 中的容器可以访问文件目录的,一个卷可以被挂载在 Pod 中一个或者多个容器的指定路径下面。

Volume 可以去支持多种的后端的存储,可以支持本地的存储,网络存储,以及分布式的存储,比如说像 ceph,GlusterFS;它也可以支持云存储,比如说阿里云盘、AWS 云盘、Google 云盘等等。

apiVersion: v1
kind: Pod
metadata:
    name: myapp
    namespace: default
    labels:
        app: myapp
spec:
    containers:
        - name: myapp
          image: ikubernetes/myapp:v1
          volumeMounts: # 容器挂载哪些卷
              - name: webstore # 挂载哪个卷
                mountPath: /usr/share/nginx/html # 挂载到容器内哪个目录
                readOnly: false # 是否只读
    volumes: # 存储卷属于POD的(不属于容器)
        - name: webstore # 存储卷对象名字
          hostPath: # hostpath 类型的存储卷对象
              path: /data/myapp # 处于宿主机的目录
              type: DirectoryOrCreate # 不存在则创建
  • ConfigMap

ConfigMap 用于保存配置数据的键值对,可以用来保存单个属性,也可以用来保存配置文件。可以使用 kubectl create configmap 从文件、目录或者 key-value 字符串创建等创建 ConfigMap。也可以通过 kubectl create -f file 创建。

ConfigMap 可以通过三种方式在 Pod 中使用,三种分别方式为:设置环境变量、设置容器命令行参数以及在 Volume 中直接挂载文件或目录。

  • Secret

Secret 和 ConfigMap 作用一样,但用于密码、token 等敏感数据。

  • Label

Label(标签)以 key/value 的方式附加到对象上(key 最长不能超过 63 字节,value 可以为空,也可以是不超过 253 字节的字符串)。 Label 定义好后其他对象可以使用 Selector 来选择一组相同 label 的对象(比如 ReplicaSet 和 Service 用 label 来选择一组 Pod)。Label Selector 支持以下几种方式:

-   等式,如 app=nginx 和 env!=production
-   集合,如 env in (production, qa)
-   多个 label(它们之间是 AND 关系),如 app=nginx,env=test
  • Annotations

Annotations 是 key/value 形式附加于对象的注解。不同于 Labels 用于标志和选择对象,Annotations 则是用来记录一些附加信息,用来辅助应用部署、安全策略以及调度策略等。比如 deployment 使用 annotations 来记录 rolling update 的状态。

架构原理

Kubernetes 虽然庞大复杂,但是其架构和设计机理却是很清晰。

分层架构: 分层架构

-   核心层:Kubernetes 最核心的功能,对外提供 API 构建高层的应用,对内提供插件式应用执行环境
-   应用层:部署(无状态应用、有状态应用、批处理任务、集群应用等)和路由(服务发现、DNS 解析等)
-   管理层:系统度量(如基础设施、容器和网络的度量),自动化(如自动扩展、动态 Provision 等)以及策略管理(RBAC、Quota、PSP、NetworkPolicy 等)
-   接口层:kubectl 命令行工具、客户端 SDK 以及集群联邦
-   生态系统:在接口层之上的庞大容器集群管理调度的生态系统,可以划分为两个范畴
    -   Kubernetes 外部:日志、监控、配置管理、CI、CD、Workflow、FaaS、OTS 应用、ChatOps 等
    -   Kubernetes 内部:CRI、CNI、CVI、镜像仓库、Cloud Provider、集群自身的配置和管理等

核心组件: 核心组件

生态系统: 生态系统

Kubernetes 以及云原生

技术是生产力发展的核心,发生第二次工业革命是因为有了蒸汽动力等技术的出现,发生 Internet 是因为有了 HTML,CSS,Tcp/Ip 等技术,发生 digital transformation 是因为有了 Kubernetes 等云原生技术,其中的一些显著特点:

  • 轻量级的容器技术
  • 不依赖底层 infrastructure 或服务,包括 OS,VM,物理机器,以及各种云基础设施
  • 声明式资源管理
  • 按需自动弹性扩展
  • 拥有强壮性和自愈功能
  • 编程语言无关
  • API 驱动
  • Stateless/Stateful 应用分离
  • 微服务架构
  • 敏捷和自动化 DevOps
  • 自服务

云原生众说纷纭,我的看法就是容器和 Kubernetes,因为还未看到有第二种技术来实现支持上述特性。


   Kubernetes 相当一个云操作系统内核,内外沿涉及到的东西几乎是个无底洞,不是 3-5 个小时或 3-5 天就能搞定,慢慢来。

云 & 云原生kubernetes

Kubernetes 安装方式简介

Go 极速上手

comments powered by Disqus