01 kubernetes简介

2020-01-08  本文已影响0人  wangfs

在实践之前,必须先学习k8s的几个重要概念,它们是组成k8s集群的基石。

1. Cluster

Cluster是计算、存储和网络资源的组合,k8s利用这些资源运行各种基于容器的应用。

2. Master

Master是Cluster的大脑,它的主要职责是调度,即决定将应用放在哪里运行。Master运行Linux操作系统,可以是物理机或者虚拟机。为了实现高可用,可以运行多个Master。

3. Node

Node的职责是运行容器应用。Node由Master管理,Node负责监控并汇报容器的状态,同时根据Master的要求管理容器的生命周期。Node运行在Linux操作系统上,可以是物理机或者是虚拟机。

4. Pod

Pod时k8s的最小工作单元。每个Pod包含一个或多个容器。Pod中的容器会作为一个整体被Master调度到一个Node上运行。

kubernets引入Pod主要基于下面的两个目的:

可管理性
有些容器天生就是需要紧密联系到一起工作。Pod提供了比容器更高层次的抽象,将它们封装到一个部署单元中。k8s以Pod为最小单位进行调度、扩展、共享资源、管理声明周期。
通信和资源共享
Pod中的所有容器使用同一个网络NameSpace,即相同的IP地址和Port空间。它们之间直接可以使用localhost通信。同样的这些容器可以共享存储,当k8s挂载volume到Pod,本质上是将volume挂载到Pod中的每一个容器。

Pods有两种使用方式:
1. 运行单一容器

one-container-per-Pod 是 k8s最常见的模型,这种情况下,只是将单个容器简单封装成Pod。即便是只有一个容器,k8s管理的也是Pod而不是直接管理容器。

2. 运行多个容器

问题在于: 哪些容器应该被放到一个Pod中?
答案是:这些容器联系必须非常紧密,而且需要直接共享资源

5. Controller

k8s通常不会直接创建Pod,而是通过Controller来管理Pod的。Controller中定义了Pod的部署特性,比如有几个副本、在什么样的Node上运行等。为了满足不同业务场景,k8s提供了多种Controller,包括Deployment、ReplicaSet、DaemonSet、StatefuleSet、Job等。

6. Service

Deployment可以部署多个副本,每个Pod都有自己的IP,外界如何访问这些副本呢?
通过Pod的IP吗?
要知道Pod很可能被频繁的销毁和重启,它们的IP会发生变化,用IP来访问不太现实。
答案是Service。
kubernetes Service 定义了外界访问一组特定Pod的方式。Service有自己的IP和端口,Service为Pod提供了负载均衡。
k8s运行容器(Pod)与访问容器(Pod)这两项任务分别由Controller和Service执行。

7. Namespace

如果有多个用户或项目组使用同一个Kubernetes Cluster,如何将他们创建的Controller、Pod等资源分开呢?
使用Namespace可以将一个物理的Cluster逻辑上划分成多个虚拟Cluster,每个Cluster就是一个Namespace。不同Namespace里的资源是完全隔离的。

k8s架构图

1.png

从上面的图我们可以看出k8s由Master和Node两种节点组成,这两种角色分别对应着控制节点工作节点

1. Master节点由三个独立的组件组成。

整个集群的数据都是通过kube-apiserver保存到etcd数据库中的,而其他所有组件的通信也都是通过kube-apiserver作为媒介来和etcd数据库进行通信的,都不会直接和etcd进行通信。

2. Node节点上最核心的组件就是kubelet以及底层的容器运行时,比如Docker

组件

上面介绍了k8s集群的整体架构,下面我们再来更加详细的了解下这些组件的功能。

1. kube-apiserver

API Server提供了资源对象的唯一操作入口,其他所有组件都必须通过它提供的API来操作资源数据。只有API Server会与etcd进行通信,其他模块都必须通过API Server访问集群状态
API Server作为k8s系统的入口,封装了核心对象的增删改查操作。API Server以RESTFul接口方式提供给外部客户端和内部组件调用,API Server再对相关的资源数据(全量查询+变化监听)进行操作,以达到实时完成相关的业务功能。以API Server为k8s入口的设计主要有以下好处:

2.kube-controller-manager

1.png

Controller Manager用于实现k8s集群故障检测和恢复的自动化工作。主要负责执行各种控制器。

3. kube-scheduler

Scheduler是负责整个集群的资源调度的,主要的职责如下所示:

4. kubelet

kubelet是负责容器真正运行的核心组件,主要的职责如下所示:

5. kube-proxy

kube-proxy是为了解决外部网络能够访问集群中容器提供的应用服务而设计的,Proxy运行在每一个Node上。

每创建一个Service,kube-proxy就会从API Server获取Services和Endpoints的配置信息,然后根据其配置信息在Node上启动一个Proxy的进程并监听相应的服务端口。

当接收到外部请求时,kube-proxy会根据Load Balancer将请求分发到后端正确的容器处理。

kube-proxy不但解决了同一宿主机相同服务端口冲突的问题,还提供了Service转发服务端口对外提供服务的能力。

kube-proxy后端使用随机、轮训等负载均衡算法进行调度。

6. kubectl

Kubectl是k8s的集群管理命令行客户端工具集。通过Kubectl命令对API Server进行操作,API Server响应并返回对应的命令结果,从而达到对k8s集群的管理。

核心资源对象

上面我们都是在架构层面了解k8s,但是似乎没有关于容器的说明,k8s作为容器编排引擎,那么它是怎么去对容器进行编排的呢?在k8s集群中抽象了很多集群内部的资源对象,我们可以通过这些资源对象去操作容器的编排工作。

Pod

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

1.png

在k8s中,所有资源对象都是用资源清单(yaml或json)来定义,比如我们可以定义一个简单的nginx服务,它包含一个镜像为nginx的容器:( nignx-pod.yaml)

apiVersion: v1
kind: Pod
metadata:  
  name: nginx  
  labels:    
    app: nginx
spec:  
  containers:  
  - name: nginx    
    image: nginx    
    ports:    
    - containerPort: 80

定义了这样一个资源清单文件后,我们就可以利用上面我们提到的kubectl工具将这个Pod创建到k8s集群中:
kubectl apply -y nginx-pod.yaml

Pod在k8s集群中被创建的基本流程如下所示:
注意实线和虚线的流程。理解整个流程以及各个组件的功能和组件之间的关系非常重要

1.png

Label

Label标签在k8s资源对象中使用很多,也是非常重要的一个属性,Lable是识别k8s对象的标签,以key/value的方式附加到对象上(key最长不能超过63字节,value可以为空,但是不能超过253字节,且为字符串)。上面我们定义的Nginx的Pod就添加了一个app=nginx的Label标签。Label不提供唯一性,并且实际上经常是很多对象(如Pods)都使用相同的Label来标志具体的应用。Label定义好后其他对象可以使用Label Selector来选择一组相同Label的对象(比如Service用Label来选择一组Pod)。Label Selector支持以下几种方式:

Namespace

Namespace(命名空间)是一组资源和对象的抽象集合,比如可以用来讲系统内部的对象划分为不同的项目组或用户组。常见的Pods、Service、Deployments等都属于某一个Namespace的(默认是default),比如上面我们的Nginx Pod没有指定namespace,则默认就在default的命名空间下面,而Node,PersistentVolumes等资源则不属于任何Namespace,它们是全局的

注意:这里说的Namespace并不是Linux Namespace,二者之间没有任何关系。这里说的Namespace只是k8s划分不同工作区间的一个逻辑单位。

Deployment

我们说了Pod是k8s集群中的最基本的调度单元,但是如果想要创建同一个容器的多份拷贝,需要一个一个分别创建出来吗?那么能否将Pods划分到一个逻辑组里面呢?Deployment就是来管理Pod的资源对象

Deployment确保任意时间都有指定数量的Pod"副本"在运行。如果为某个Pod创建了Deployment并且指定3个副本,它会创建3个Pod,并且持续监控它们。如果某个Pod不响应,那么Deployment会替换它,始终保持总数为3.

如果之前不响应的 Pod 恢复了,现在就有4个 Pod 了,那么 Deployment 会将其中一个终止保持总数为3。如果在运行中将副本总数改为5,Deployment 会立刻启动2个新 Pod,保证总数为5。持回滚和滚动升级。

当创建Deployment时,需要指定两个东西:

现在已经创建了Pod的一些副本,那么这些副本上如何进行负载呢?如何把这些Pod暴露出去呢?这个时候我们就需要用到Service这种资源对象了。

Service

Service是应用服务的抽象,通过Labels为应用提供负载均衡和服务发现匹配Labels的Pod IP和端口列表组成Endpoints,由kube-proxy负责将服务IP负载均衡到这些Endpoints上

每个Service都会自动分配一个Cluster IP(仅在集群内部可访问的虚拟地址)和DNS 名,其他容器可以通过该地址或DNS来访问服务,而不需要了解后端容器的运行。


1.png
上一篇下一篇

猜你喜欢

热点阅读