一文了解K8s-概念详解

一、基本概念

(一) Why Container?

在这篇文章中我们介绍了Docker的基本概念以及入门教程。在这里我们聊一下为什么我们需要使用容器。通过下面的图进行对比。
一文了解K8s-概念详解_第1张图片
在传统的项目部署时,使用物理机或者VM(虚拟机)来直接安装。如左图所示,在内核的上层是运行环境(需要一系列手动安装或使用脚本主动安装),上层运行着一个一个独立的APP。对于VM来说,它是可以整体迁移的,但是这个迁移还是比较重,主要体现在VM是整个操作系统的镜像实例,在做扩容和迁移时需要大费周章。
转到右图,容器是一个更轻量级的概念,他存在于VM之上,拥有自己的文件系统,也拥有一个独立的ip,等等。每一个应用均运行在一个容器中,有容器为其提供所需要的基础资源和运行时环境。它更适合扩展和迁移,并且迁移成本极低(镜像发布)。

(二)K8s是用来做什么的

简单来说,Docker不具备自动扩容、负载均衡以及分布式集群部署的能力。Kubernetes是容器集群管理系统,是一个开源的平台,可以实现容器集群的自动化部署、自动扩缩容、维护等功能。它是基于容器(通常是Docker)之上的。

二、K8s架构

我们从整体架构来入手。下面是一张K8s架构图。
一文了解K8s-概念详解_第2张图片

(一)kubectl/user-client

这一层是给K8s的运维人员使用的,kubectl是命令行交互工具,可以通过它来操作K8s集群。

(二)Master

首先K8s是基于主从(Master-Slaver)模型的,Master节点负责整个集群的调度管理工作,不负责应用的运行。在K8s中,Master节点可以简称为Master,SLave节点可以简称Node。在企业级K8s集群中,通常存在多个Master节点以实现HA(高可用)。

Master节点全部的持久化数据都存储在ETCD上,除此之外,Node、Pod的运行状态、用户的配置信息等也都存放在此。值得注意的是,只有Api-SERVCER组件有权限读写ETCD,因此只能通过API-SERVER来访问ETCD。
Master节点还包含Scheduler进行资源调度,将Pod调度到满足条件的Node上运行。
ControllerManager负责管理全部的Controller,这些Controller负责监控、调度集群的状态,比如故障检测、自动扩展、滚动更新等。
ApiServer负责接收K8S所有请求,是k8s资源操作的唯一入口,并提供认证、授权、访问控制、API 注册和发现等机制。API Server根据的具体请求,去通知其他组件干活。

(三)Node

在Node上通常有Kublet、Kybe-proxy以及Conatiner-Runtime。
Kubelet是Node的监视器。每个节点上都运行一个 kubelet 服务进程,默认监听 10250 端口,接收并执行 master 发来的指令,管理 Pod 及 Pod 中的容器。每个 kubelet 进程会在 API Server 上注册节点自身信息,定期向 master 节点汇报节点的资源使用情况,并监控节点和容器的资源,维护node节点上Pod的生命周期。
Kube-Proxy是K8S的网络代理。Kube-Proxy负责Node在K8S的网络通讯、以及对外部网络流量的负载均衡。
Container Runtime是Node的运行环境。容器运行时(Container Runtime)是 Kubernetes 最重要的组件之一,负责真正管理镜像和容器的生命周期。Kubelet 通过 Container Runtime Interface (CRI) 与容器运行时交互,以管理镜像和容器。Docker是比较常见的容器运行时。

三、相关术语解释

(一)Node

Node即一台物理机或者VM。
Node是Kubernetes中的工作节点,最开始被称为minion。每个Node(节点)具有运行pod的一些必要服务,并由Master组件进行管理,Node节点上的服务包括Docker、kubelet和kube-proxy。

(二)Pod(K8中最重要的概念)

1. Pod是什么

Pod是Kubernetes创建或部署的最小/最简单的基本单位,一个Pod代表集群上正在运行的一个进程。
一个Pod封装一个应用容器(也可以有多个容器),存储资源、一个独立的网络IP以及管理控制容器运行方式的策略选项。Pod代表部署的一个单位:Kubernetes中单个应用的实例,它可能由单个容器或多个容器共享组成的资源。

Docker是Kubernetes Pod中最常见的runtime ,Pods也支持其他容器runtimes。

2. Pod工作方式

Kubernetes中的Pod使用可分两种主要方式:

  • Pod中运行一个容器。“one-container-per-Pod”模式是Kubernetes最常见的用法; 在这种情况下,你可以将Pod视为单个封装的容器,但是Kubernetes是直接管理Pod而不是容器。
  • Pods中运行多个需要一起工作的容器。Pod可以封装紧密耦合的应用,它们需要由多个容器组成,它们之间能够共享资源,这些容器可以形成一个单一的内部service单位 - 一个容器共享文件,另一个“sidecar”容器来更新这些文件。Pod将这些容器的存储资源作为一个实体来管理。
    每个Pod都是运行应用的单个实例,如果需要水平扩展应用(例如,运行多个实例),则应该使用多个Pods,每个实例一个Pod。在Kubernetes中,这样通常称为Replication。Replication的Pod通常由Controller创建和管理(自动扩容)。

3. Pod网络

每个Pod被分配一个独立的IP地址,Pod中的每个容器共享网络命名空间,包括IP地址和网络端口。Pod内的容器可以使用localhost相互通信。

4. Pod存储

Pod可以指定一组共享存储volumes。Pod中的所有容器都可以访问共享volumes,允许这些容器共享数据。volumes 还用于Pod中的数据持久化,以防其中一个容器需要重新启动而丢失数据。

(三)Volume

Volume中文名叫,是Pod数据持久化存储的地方。
默认情况下容器中的磁盘文件是非持久化的,对于运行在容器中的应用来说面临两个问题:

  • 第一,当容器挂掉kubelet将重启启动它时,文件将会丢失。
  • 第二,当Pod中同时运行多个容器,容器之间需要共享文件。Volume就解决了这两个问题。

你可以简单地认为Volume就是Pod的磁盘,它同Pod的生命周期一致,当Pod被销毁时Volume即被销毁。
Kubernetes支持许多类型的Volume。这里就不详细介绍了。

(三)组件

K8s同传统的分布式模型一样,有Master-Node之分。

1. Master组件

Master组件提供集群的管理控制中心。Master相关的组件并不是只能运行在Master节点上,而是通常来讲将其运行在Master节点上。

(1)kube-apiserver

kube-apiserver用于暴露Kubernetes API。任何的资源请求/调用操作都是通过kube-apiserver提供的接口进行。

(2) ETCD

K8S的存储服务。ETCD保存了集群中Master Node和Worker Node中各个组件的状态,同时也存储了K8S的关键配置和用户配置,k8s架构所有需要持久化的数据都会存储在ETCD中。K8S中仅API Server才具备读写权限,其他组件必须通过API Server的接口才能读写数据;

(3)kube-controller-manager

控制器管理器,管理所有的控制器。K8s包含的控制器可以分为:

  • 节点(Node)控制器。
  • 副本(Replication)控制器:负责维护系统中每个副本中的pod。
  • 端点(Endpoints)控制器:填充Endpoints对象(即连接Services&Pods)。
  • Service Account和Token控制器:为新的Namespace创建默认帐户访问API Token。

(4)kube-scheduler

这个组件的作用是为未分配的Pod分配一个Node。

(5)DNS

不强制。但是每一个K8s集群都应该使用DNS组件。

(6) kube-ui

图形化管理界面。

(7) 容器资源监测

(8) Cluster-level Logging

日志

2. Node组件

节点组件运行在Node,提供Kubernetes运行时环境,以及维护Pod。

(1)kubelet

kubelet是主要的节点代理,它会监视已分配给节点的pod,具体功能为:

  • 安装Pod所需的volume。
  • 下载Pod的Secrets。
  • Pod中运行的 docker(或experimentally,rkt)容器。
  • 定期执行容器健康检查并报告。

(2) kube-proxy

kube-proxy通过在主机上维护网络规则并执行连接转发来实现Kubernetes服务抽象。
kube-proxy在每个Node上。服务集群 IP 和端口是通过 Docker-links-compatible 环境变量找到的,指定proxy打开的端口。DNS组件为这些集群 IP 提供集群 DNS。用户必须使用上问题到的 apiserver API 创建服务来配置代理。

(3)docker

每一个Node需要安装Docker

(4) supervisord

监控并保障kubelet和docker正常运行。

(5) fluentd

日志

(四) 对象

对象即指本节中提到的几乎全部的概念。K8s对象包括:

类别 名称
资源对象 Pod、ReplicaSet、ReplicationController、Deployment、StatefulSet、DaemonSet、Job CronJob、HorizontalPodAutoscaling
配置对象 Node、Namespace、Service、Secret、ConfigMap、Ingress、Label、ThirdPartyResource、 ServiceAccount
存储对象 Volume、Persistent Volume
策略对象 SecurityContext、ResourceQuota、LimitRange

这些对象使用kubectl命令,传入yml文件作为参数来配置部署方案。

一个例子

假设我们配置yml文件内容如下:

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

命令如下:

$ kubectl create -f docs/user-guide/nginx-deployment.yaml --record

(五)Names、NameSpace、Labels、Service、Deployment

  • Name是对象的Name,除此之外还有UID,每一个Name在同一个NameSpace下只能有一个。当K8s用户较多时,可以创建NameSpace,便于管理用户和权限。
  • 在一个Kubernetes集群中可以使用namespace创建多个“虚拟集群”,这些namespace之间可以完全隔离,资源名称在同一个命名空间内需保持唯一,但是两个不同的命名空间可以包含同名的资源。例如service访问pod时,如果service的命名空间不指定正确,那么就无法通过标签关联到pod。但是可以通过某种方式,让一个namespace中的service可以访问到其他的namespace中的pod。也就是说命名空间不会隔离不同空间下的Pod 之间的网络通讯,除非针对命名空间加了相应的安全策略。
  • 和Name类似,Labels也是对象的属性,它以key-value的形式存在,可以存在于命令或者yml中。
  • Service代理Pod的对外接口,外部通过Service来访问Pod。实际上算作一层代理。
  • Deployment的作用是管理和控制Pod和ReplicaSet,管控它们运行在用户期望的状态中,确保每时每刻有用户要求数量的Pod在工作。如果一旦发现某Pod不行了,就从其他的node上启动一个新的pod替换掉。

每个pod有独一的ip地址,当有多个pod提供相同的服务的时候,就需要有负载均衡的能力,从而这里就涉及到一个概念就是service,专门用来提供服务的。服务主要是用来提供外界访问的接口,service可以关联一组pod,这些pod的ip地址各不相同,而service相当于一个复杂均衡的vip,用来指向各个pod,当pod的ip地址发生改变之后,也能做到自动进行负载均衡,在关联的时候,service和pod之间主要通过label来关联,也就是标签,例如图中的A,B就是标签,每个deployment通过标签可以知道它所管理哪些pod
##(六)ReplicaSet
ReplicaSet 的目的是维护一组Pod在任何时候都处于稳定运行的状态。 因此,它通常用来保证给定数量的、完全相同的 Pod 的可用性。ReplicaSet受控制于Deployment
##(七)Ingress
Ingress是整个K8S集群的接入层,负责集群内外通讯,类似springcloud的zuul网关的作用。

四、一个例子

为了缩短篇幅本文不详细描述搭建K8s集群的过程,实际上,可以有多种方式搭建K8s集群,你可以选择简单地MiniKube搭建,也可以选择搭建一个完全自定义的K8s集群,都有相应的社区文档参考。

我们以在K8s上部署一个Nginx应用为例

  1. 新建NameSpace配置文件:nginx-namespace.yaml
apiVersion: v1 #类型为Namespace
kind: Namespace  #类型为Namespace
metadata:
  name: ns-test  #命名空间名称
  1. 创建NameSpace
#创建
kubectl create -f nginx-namespace.yaml
#查询
kubectl get namespace
  1. 在Namespace下创建资源,通过deployment-controller来创建pod。
# 新建配置文件
vim nginx-deployment.yaml

# 配置文件内容
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: ns-test
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        ports:
        - containerPort: 80

#创建
kubectl create -f nginx-deployment.yaml
#查询
kubectl get deployment
#或
kubectl get pods -n ns-test
  1. 创建service,使用随机生产ip
vim nginx-service.yaml

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

kubectl create -f nginx-service.yaml
//查看生成的ip
kubectl get svc nginx-service -o wide

五、参考文章

http://docs.kubernetes.org.cn/227.html
https://www.jianshu.com/p/20e8a74e3a73
https://www.jianshu.com/p/a73c33283de8
https://www.jianshu.com/p/8e077225e4f7

你可能感兴趣的:(docker,运维)