Master
在Kubernetes中,Master指集群控制节点,负载集群的管理和控制,基本上Kubernetes所有的控制命令都是发给它,它来负责集体的执行过程。Master节点通常至少会占据一个独立的服务器或者虚拟机,它是整个集群的“首脑”,如果它宕机或者不可用,那所有的控制指令都将失效。
Master节点上运行的关键进程:
- Kubernetes API Server(kube-apiserver),提供HTTP Rest接口的关键服务进程,是Kubernetes里所有资源的增、删、改、查等操作的唯一入口,也是集群控制的入口进程。
- Kubernetes Controller Manager(Kube-controller-manager),Kubernetes中所有资源对象的自动化控制中心。
- Kubernetes Scheduler(Kube-scheduler),负责资源调度(Pod调度)的进程。
Master节点上往往还启动一个etcd Server进程,用于保存Kubernetes里的所有资源对象的数据。
Node
在Kubernetes集群中,除了Master节点外的机器节点,都被称为Node节点。Node节点是真正的工作负载节点,当某个Node宕机时,其上的工作负载(容器)会被Master自动转移到其它节点上去。
每个Node节点上运行的关键进程:
- kubelet:负责pod对应的容器的创建、启停等任务,同时与Master节点密切协作,实现集群管理的基本功能。
- kube-proxy:实现Kubernetes Service的通信与负载均衡机制的重要组建。
- Docker Engine(docker):负责本机容器创建和管理
Node节点可以动态增加到Kubernetes集群中,前提是已经正确安装、配置和启动上述关键进程。Node向Master注册自己,一旦Node被纳入集群管理范围,kubelet进程就会定时向Master节点汇报自身的情况,如操作系统、Docker版本、机器的CPU和内存情况,以及有哪些pod在运行等。这样Master可以获知每个Node的资源使用情况,并实现高效均匀的资源调度策略。如果某个Node超过这顶时间不上报信息,会被Master判定为“失联”,这个Node节点被标记为不可用(Not Ready),Master节点将触发“工作负载大转移”的自动流程。
kubectl get nodes #查看集群中有多少个Node
kubectl describe node <node_name> #查看某个Node的详细信息
Pod
Pod是Kubernetes最重要也是最基本的概念,每个Pod都有一个特殊的被称为“根容器”的Pause容器,Pause容器对应的镜像属于Kubernetes平台的一部分,另外,每个Pod还包含一个或者多个紧密相关的用户业务容器。多个业务容器共享Pause容器的IP(Pod IP)和Pause任凭器挂接的Volume。Kubernetes底层网络支持集群内任意两个Pod之间的TCP/IP直接通信,通过虚拟二层网络技术来实现。因此,一个Pod里的容器与另外主机上的Pod容器能够直接通信。
Pod包含两种类型:普通Pod和静态Pod(static Pod)。静态Pod不存储在Kubernetes的etcd中,而是存放在某个具体Node的一个具体文件中,并且只在次Node上启动运行。而普通Pod一旦被创建,会被放在etcd中存储,随后被Kubernetes Master调度到某个具体的Node上并进行绑定(Binding),该Pod被对Node上的Kubelet进程实例化成一组相关的Docker容器并启动起来。
Kubernetes中所有的资源对象都可以采用yaml或者JSON格式的文件来定义和描述。
Label
Label是Kubernetes中另外一个核心概念。一个Label是一个key=value的键值对。Label可以附加到各种资源对象上,一个资源对象可以定义任意数量的Label,用一个Label也可以添加到任意数量的资源对象上去。通过给指定的资源对象捆绑一个或者多个Label来实现多维度的资源分组管理,随后可以通过Label Selector(标签选择器)查询和筛选拥有某些Label的资源对象。
Label Selector有两种表达式,基于等式(Equality-based)和基于集合的(Set-based),下面的例子:
等式类
name = redis-salve
env != production
集合类
name in (redis-master,redis-slave)
name not in(php-frontend)
可以通过多个表达式的组合实现复杂的条件选择,多个表达式之间用“,”分割,几个条件之间是“AND”的关系。
Label Selector通常在一下场景中使用:
- Kube-controller进程通过资源对象RC上定义的Label Selector来筛选要监控的Pod副本的数量,从而实现Pod副本数量始终符合预期设定的数量。
- Kube-proxy进程通过Service的Label Selector来选择对应的Pod,自定建立Service到对应Pod的请求转发路由表,从而实现Service的负载均衡机制。
- 通过对Node定义特定的Label,并且在Pod定义文件使用Label Selector这种标签调度策略,Kube-scheduler进程可以实现Pod“定向调度”的特性。
总结,使用Label可以给对象创建多组标签,Label和Label Selector共同构成了Kubernetes系统中最核心的应用模型,实现对管理对象进行精细地分组管理,并实现了整个集群的高可用。
Replication Controller(RC)
RC是Kubernetes的核心概念之一,用于定义Pod的副本数量在任意时刻都符合某个预期值,RC定义包含一下几个部分:
- Pod期待的副本数(replicas)。
- 用于筛选目标Pod的Label Selector。
- 当Pod副本数量小于预期数量的时候,用于创建新Pod的Pod模版(template)
在运行时,可以通过修改RC的副本数量实现Pod的动态缩放(Scaling),命令如下:
kubectl scale rc redis-slave --replicas=3 #原来设置的replicas是2
为了删除Pod,可以将replicas的值设置为0,然后更新该RC。kubectl delete用来一次性删除RC和RC控制的全部Pod。
- 基于Pod.yaml定义的名称删除Pod
kubectl delete -f pod.yaml
- 删除所有包含某个label的Pod和service
kubectl delete pods,services -l name=<label-name>
- 删除所有Pod
kubectl delete pods --all
之前版本中,RC只支持基于等式的Label Selector,从Kubernetes 1.2开始,Replication Controller升级为Relica Set,支持基于集合的Label Selector。kubectl命令行工具适用于RC的绝大部分命令都同样适用于Replica Set。
RC(Replica Set)的特性和作用:
- 可用通过定义一个RC实现Pod的常见过程及副本数量的自动控制。
- RC里包含完成的Pod定义模版。
- RC通过Label Selector机制实现Pod副本的自动控制。
- 通过改变RC里的Pod副本数量,可以实现Pod的扩容或者缩容。
- 通过改变RC里的Pod模版中的镜像版本,可以实现Pod的滚动升级。
Deployment
为了更好的解决Pod编排问题,从Kubernetes 1.2开始,引入了Deployment的概念。Deployment内部使用 Replica Set。
Deployment典型使用场景:
- 创建一个Deployment对象来生成对应的Replica Set,并完成Pod副本创建。
- 检查Deployment的状态来查看部署动作是否完成(Pod副本数量是否达到预期值)。
- 更新Deployment来创建新的Pod(如镜像升级)。
- 如果当前版本不稳定,回滚到一个早先的Deployment版本。
- 挂起或者恢复一个Deployment。
Deployment的定义与Replica Set定义很类似,只有API声明与Kind类型等有所区别:
apiVersion: extensions/v1beta1 apiVersion: V1
kind: Deployment kind: ReplicaSet
metadata: metadata:
name: nginx-deployment name: nginx-deployment
kubectl create -f tomcat-deployment.yaml #创建Deployment(假设yaml文件名为tomcat-deployment.yaml)
kubectl get deployments #查看Deployment的信息
kubectl get rs #查看对应的Replica Set
kubectl get pods #查看创建的Pod
kubectl describe deployments #查看Deployment控制的Pod的水平扩展过程
Horizontal Pod Autoscaler(HPA)
Horizontal Pod Autoscaler 是指Pod横向自动扩容,与RC、Deployment一样,属于Kubernetes资源对象。通过追踪分析RC控制的所有目标Pod的负载变化情况,来确定是否针对性地调整目标Pod的副本数,这是HPA的实现原理。
HPA支持两种方式作为Pod负载的度量指标。
- CPU使用百分比(CPUUtilizationPercentage)
- 应用程序自定义的度量指标,如服务每秒内响应的请求数TPS或QPS)
CPUUtilizationPercentage是一个算术平均值,即目标Pod所有副本自身的CPU利用率的平均值。
一个Pod自身CPU利用率 = 当前CPU的使用量/Pod Request值
CPU使用量通常是1分钟内的平均值, Pod Request是我们定义的一个值,如0.4。
根据这个公式,可以计算出一个RC控制的所有Pod副本的CPU利用率的算术平均值,如果这个值超过80%,则意味着当前的Pod副本数不足以支持接下来更多的请求,需要进行动态扩容。当请求高峰时段过去,Pod的CPU利用率会降下来,此时,对应的副本数将会减少到一个合理水平。
HPA资源可以通过两种方式来定义。
- 定义yaml文件,并且通过kubectl create命令调用
- 直接执行命令创建HPA:kubectl autoscale deployment php-apache --cpu-percent=90 --min=1 --max=10
服务(Service)
1、概述
Service也是Kubernetes中最核心的资源对象之一。Service定义了一个服务的访问入口地址,其它应用Pod通过这个入口地址访问其背后的一组由Pod副本组成的集群实例,Service与后端Pod副本集群通过Label Selector来实现“无缝对接”。
客户端访问Pod集群提供的服务时,一般部署一个负载均衡器(软件或者硬件),开启一个对外服务的访问端口,然后将Pod的Endpoint(Pod IP+ContainerPort)列表加入端口的转发列表中,客户端通过负载均衡器地址+访问端口来访问Pod集群提供的服务,客户端的请求经过负载均衡器的算法来决定转发到哪个Pod上。
Service上分配的全局唯一虚拟IP地址被称为Cluster IP,Server Name与Service的Cluster IP地址进行DNS域名映射。
很多服务存在多个端口,Kubernetes Service支持多个Endpoint,在多个Endpoint的情况下,要求每个Endpoint定义一个名字来区分,这与Kubernetes的服务发现机制相关。
2、Kubernetes的服务发现机制
Kubernetes中,每个Service都有一个唯一的Cluster IP,名字由用户定义,并且在部署过程中没有必要更改,所以可以固定在配置中。而Service与Cluster IP间的解析由Kubernetes Add-On引入的DNS系统来完成,把服务名作为DNS域名,这样,程序就可以直接使用服务名来建立通信连接了。
3、外部系统访问Service
Kubernetes中的“三种IP”:
- Node IP:Node节点的IP地址
每个节点物理网卡的IP地址,属于真是存在的物理网络
- Pod IP:Pod的IP地址
Docker Engine根据docker0网桥的IP地址段给Pod分配的IP地址,通常是一个虚拟的二层网络。不同Node上的Pod容器通信,就是通过Pod IP所在的虚拟二层网络进行通信的。
- Cluster IP:Service的IP地址
一个虚拟的IP,具有一下特点:
1)Cluster IP由Kubernetes 管理和分配IP地址(来源于Cluster IP地址池),只在Kubernetes集群内部有效。
2)Cluster IP无法被Ping,因为没有“实体网络对象”来响应。
3)Cluster IP需要结合Service Port组成一个具体的通信端口,单独的Cluster IP不具备TCP/IP通信的基础,并且他们只属于Kubernetes集群内部,如果外部想要访问这个通信端口,需要做一些额外的工作。
4)Node IP网、Pod IP网与Cluster IP网之间的通信采用的是Kubernetes自己设计的一种编程方式的特殊路由规则,与IP路由有很大的不同。
综上所述,Service的Cluster IP无法在集群外直接访问到,实际上业务系统中很多都是需要用户来使用的,这里采用的NodePort来解决这个问题。具体做法如下:
apiVersion: v1
kind: Service
metadata:
name: tomcat-service
spec:
type: NodePort
ports:
- port: 8080
nodePort: 31002
selector:
tier:frontend
其中,nodePort: 31002这个属性标明我们手动指定tomcat-service的NodePort为31002,否则Kubernetes会自动分配一个可用的端口。NodePort的实现方式是在Kubernetes集群里的每个Node上为需要外部访问的Service开启一个对应的TCP监听端口。
但是NodePort无法解决用户访问是的负载均衡问题,所以需要一个负载均衡器,外部请求访问负载均衡器的IP,由负载均衡器负载转发流量到后端某个node的NodePort上去。Load balancer组建独立于Kubernetes集群之外。
Volume(存储卷)
Volume是Pod中能够被多个容器访问的共享目录。它可以实现多个Pod中的多个容器共享文件,让容器的数据写到宿主机磁盘或者写文件到网络存储中,Kubernetes Volume还扩展出一个非常有价值的功能,即容器配置文件集中化定义与管理,通过资源对象ConfigMap来实现。
下面是Kubernetes提供的Volume类型
1、emptyDir
一个emptyDir Volume在Pod分配到Node时创建,提的初始内容为空,无需指定宿主机上对应的目录文件 ,以为它是Kubernetes自动分配的一个目录。当Pod从Node中移除是,该目录中的数据也会被永久删除。主要用途如下:
- 临时空间。
- 长时间任务的中间过程CheckPoint的临时保存目录。
- 一个容器需要从另一个容器中获取数据的目录(多容器共享目录) 。
2、hostPath
hostPath为在Pod上挂载宿主机上的文件或目录,主要用途:
- 容器应用程序生成的日志文件需要永久保存时。
- 容器需要访问宿主机上Docker引擎内部数据结构,可定义hostPath为宿主机/var/lib/docker目录,是容器内部应用可以直接访问Docker的文件系统
使用hostPath Volume的注意事项
- 在不同Node上具有相同配置的Pod,可能由于宿主机上目录或者文件不同,导致访问异常。
- 资源配额管理无法管理hostPath Volume使用的资源。
3、NFS
使用NFS共享目录存储数据,需要在系统中部署一台NFS Server,实例如下:
volumes:
- name: nfs
nfs:
#改为自己的NFS服务器地址
server: nfs-server.localhost
path: " / "
4、其它类型的Volume:公有云提供的云盘等,iscsi、flocker、glusterfs、rbd、gitRepo、secret等
Persistent Volume(持久卷)
Persistent Volume简称PV,Kubernetes集群中某个网络存储中对应的一块存储,与Volume的区别:
- PV只是网络存储,不属于任何Node,但可以在Node上访问。
- PV不是定义在Pod上,独立于Pod之外。
- PV类型:GCE Persistent Disks、NFS、RBD、iSCSCI、AWS ElasticBlockStore、GlusterFS等。
PV的accessModes属性支持以下类型:
- ReadWriteOnce:读写权限、并且只能被单个Node挂载。
- ReadOnlyMany:只读权限、允许被多个Node挂载。
- ReadWriteMany:读写权限、允许被多个Node挂载。
如果 Pod想申请PV,首先需要定义一个PersistentVolumeClaim(PVC),然后在Pod的Volume定义中引用PVC。
PV是有状态的对象,有以下集中状态。
- Available:空闲状态。
- Bound:已绑定到某个PVC上。
- Released:对应的PVC已经删除,但资源没有被集群收回。
- Failed:PV自动回收失败。
Namespace(命名空间)
Namespace用于实现多租户的资源隔离,通过将集群内部的资源对象“分配”到不同的Namespace中,形成逻辑上分组的不同项目、小组或者用户组,不同分组在共享使用整个集群资源的同时,还能被分别管理。
Namespace的定义:
apiVersion: v1
kind: pod
metadata:
name: busybox
namespace: development
spec:
containers:
- images: busybox
command:
- sleep
- "3600"
name: busybox
查看某名称空间中的对象:kubectl get pods --namespace=development
如果不加--namespace参数,默认显示default名称空间中的对象。
Namespace与Kubernetes的资源配额管理,可以限定不同租户能占用的资源。
Annotation(注解)
Annotation使用key/value键值对的形式进行定义,是用户定义的“附加”信息,便于外部工具进行查找。
用Annotation记录的信息如下:
- build、release、Docker镜像等信息,例如时间戳、release id号、镜像hash值、docker register地址等
- 日志库、监控库、分析库等资源库的地址信息。
- 程序调试工具信息,例如工具名称、版本号等。
- 团队的联系信息,例如电话号码、负责人名称等。
小结
上述是Kubernetes系统的核心组建,通过对它们进行灵活组合,用户就可以快速、方便地对容器集群进行配置、创建和管理。