入门Kubernetes目前两周时间,对k8s有了一个基础模糊的认识,了解它之后就会觉得这是一门真正高端的技术。
什么是Kubernetes(K8S)? 它是一个基于容器技术的分布式架构领域解决方案,K8s提供了强大的分布式服务的自动管理机制,它是一个适用于任何语言的完备的分布式系统开发和支撑平台,具有完备的集群管理能力,包括多层次的安全防护和准入机制、多租户支撑能力(暂时未理解),透明的服务注册和发现能力,可拓展的资源自动调度能力和在线扩容能力。涵盖从开发到服务部署运维的全过程工具。
为什么使用K8S? 这么多功能,能够让开发测试运维都简化工作,用起来不香么。
二、kubernetes基础概念
K8S入门基础概念包括这些:Node,Pod,Label,RC,Deployment,HPA,Service、Volume、NameSpace、Annotation 接下来详细说明每一个概念。
k8s集群中用于执行工作任务的机器,可以是物理机器,当然也可以是虚拟机。Node中有一种特殊的Node称之为Master,Master指的是集群中的控制节点,每个K8s集群中都至少需要一台Master来负责整个集群的管理和控制,基本上上有的K8s控制命令都会发给它,它相当于是整个集群的“首脑”,一旦宕机则集群不可用。 除了Master之外其他Node都是由Master控制并分配工作。当某个Node宕机事时,其上的工作负载由Master转移至其他Node。
每个Node上运行着一组关键进程
1. kubelet:负责Pod对应的容器的创建、启停等任务,与Master节点密切协作,实现集群管理的基本功能; 2. kube-proxy:实现Kubernetes Service的通信与负载均衡机制; 3. Docker Engine:Docker引擎,负责本机的容器创建和管理工作。Node上安装并启动这些核心进程后,可在集群运行中动态的添加入集群。主要实现是kebulet会主动向集群master注册自己。
Pod是K8s中最重要最基础的概念,它由一个根容器“Pause容器”+ 一组容器组成的容器组。Pause容器作为Pod的根容器,它与业务无关并且不易死亡,所以用它来代表整个容器组的生命状态。Pod里的多个业务容器共享Pause容器的IP,共享容器Pause挂在的Volume以此来解决多个Pod之间的网络通信问题和文件共享问题。k8s支持集群内任何两个节点上的Pod的进行通信。
Pod中也有一类特殊的,称之为静态Pod。我们先说普通Pod的加载过程(Node,Pod关系图见下),普通Pod创建后会存储到etcd中,随后会被Master调度绑定到具体的Node上,由Node上的kubelet和docker engine实例化创建对应的容器并启动执行。而静态Pod创建后会存放到某个Node上的文件中去并在该Node上执行。 k8s会为每个Pod分配唯一IP就是前面我们所说的Pause容器上绑定的IP,该IP与Pod中容器的端口的组成称为“EndPoint”代表着一个服务进程的对外通信地址。每个Pod可以自定义的设置其占用服务器上的资源(CPU和内存)限额,CPU通常以千分之一为最小单元单位(m)比如设置100~300m,意味着Pod占用服务器CPU资源最小0.1,最大0.3个cpu,该值是一个绝对值不是相对值。内存限额也分request和limit,request表示执行Pod需要的最小内存值,limit表示内存最大使用,如果超过该值会被kill掉然后重启。
Label概念很好理解,由键值对key=value组成的标签,可以附加到各种资源对象上,一个资源可以有很多个label,一个label也可以附加到多个资源上。通过给资源对象捆绑一个或多个不同的Label来实现资源的分组管理功能。在为资源绑定标签后,可以通过Label Selector(标签选择器)进行查询和筛选资源。如下是Label Selector 的用法示例:
labels:
app: app-name
key: value
selector:
matchLabels:
tier: frontend
matchExpressions:
- {key:tier,operator: In,values:[frontend]}
Replication Controller用于声明某种Pod的副本数量在任意时刻符合指定的预期值。RC的组成包括:
1. Pod期待的副本数量
2. 用于筛选目标Pod的Label Selector
3. 当Pod的副本少于预期数量时,用于创建新的Pod的Pod template
当我们定义了一个RC并提交到k8s集群中以后,Master节点上的Controller Manager组件得到通知,定期巡检系统中当前存活的目标Pod,并确保目标Pod的存活数量当好等于RC期望值。多了则kill,少了则create。需要注意的是直接删除RC并不能删除RC创建的Pod可以通过设置replicas=0来删除Pod之后删除RC。
为了便于理解这里贴上创建RC的yaml代码:
apiVersion: v1
kind: ReplicationController
metadata:
name: frontend
spec:
replicas:1
selector:
tier:frontend
template:
metadata:
labels:
app: app-demo
tier:frontend
spec:
containers:
- name:tomcat-demo
image:tomcat
imagePullPolicy:IfNotPresent
env:
- name: GET_HOST_FROM
value:dns
ports:
-containerPort: 80
可以说Deployment是RC的一个升级版,Deployment通过使用Replica Set来实现与RC相同的Pod副本数量自动管理功能。Replica Set相比于RC在使用Label Selector更高级一点,RC仅支持基于等式的Label Selector而Replica Set支持集合式的LS,可用如下代码和上面RC进行对比体验。
apiVersion: v1
kind: ReplicaSet
metadata:
name: frontend
spec:
selector:
matchLabels:
tier: frontend
matchExpressions:
- {key:tier,operator: In,values:[frontend]}
template:
.....
Deployment 相对与RC而言最大的特点在于,它能够随时知道当前Pod的部署进度,假设Deployment中设置Replicas=N,系统在启动N个副本的是一个长的过程,Deployment支持开发者查询当前部署的状态。如下代码是创建Deployment的示例
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: frontend
spec:
replicas:1
selector:
matchLabels:
tier: frontend
matchExpressions:
- {key:tier,operator: In,values:[frontend]}
template:
metadata:
labels:
app: app-demo
tier:frontend
spec:
containers:
- name:tomcat-demo
image:tomcat
imagePullPolicy:IfNotPresent
ports:
-containerPort: 8080
Horizontal Pod Autoscaler,Pod横向自动扩容。我们先来看看前面的RC和Deployment实现自动控制Replicas时需要指定副本数量,在Pod使用前这是一个预估值,准不准并不知道,假如Pod执行过程中发现CPU占用特别高,意味着副本数量预估少了,每个Pod的负载过高,此时我们需要手动执行kubectl命令去添加Replicas,加多少呢,只能不断加不断看系统CPU情况。这种方式完全不是我们想要的自动化。HPA便因此诞生。
HPA支持配置minReplicas和maxReplicas,具体Pod的副本数量应该是多少,取决于HPA的Pod负载度量指标:
CPUUtilizationPercentage是目标Pod所有副本CPU利用率的平均值,HPA便根据这个值来在minReplicas~maxReplicas之间进行副本数的自动扩容和缩减。当然创建和删除Pod也是由指定的RC或者Deployment来实现的。
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
maxReplicas: 10
minReplicas: 1
scaleTargetRef:
kind: Deployment
name: php-apache
targetCPUUtilizationPercentage: 90
Kubernetes里的每个service就是经常提起的微服务架构中的一个服务,Kubernetes的service定义了一个服务的访问入口,外部请求通过这个入口地址访问其背后的一组由Pod副本组成的集群实例。Service与其后端的Pod副本集群之间则是通过Label Selector来实现无缝对接。kubernetes通过分析、识别并建模系统中的所有服务为微服务,通过集群中的一系列微服务相互配合实现我们需要的业务。微服务Service之间是彼此独立的单元,服务之间通过TCP/IP通信。通常一个Service后端是由多副本的Pod实现,一个Service的请求去访问哪一个Pod的endpoint呢? 一般的做法是部署负载均衡器来进行Pod选择和请求转发。篇幅有限,就不在详细描述Kubernetes中的负载均衡器的实现,后面会有文章详细说Service。
在Kubernetes系统中,Pod的管理对象RC、Deployment都是面向无状态的(这里的状态暂时没有理解)。但现实中有很多服务是有状态的,特别是复杂的中间件集群,例如:Mysql,MongoDB、ZooKeeper集群等,他们有如下特点:
每个节点都是有固定身份ID,通过这个ID,集群中的成员可以互相发现并且通信;
集群规模比较固定,集群规模不能随意变动;
集群里的每个节点都是有状态的,需要持久化数据到永久存储中;
如果磁盘损坏,则集群里的某个节点无法正常运行,集群功能受损。
我们发现使用RC/Deployment管理的Pod无法满足这些场景,RC/Deployment控制的Pod的名字是随机的,IP是变动的,并且这中有状态的集群需要多个Pod使用共享存储用于数据持久化。因此Stateful Set为解决这种问题而诞生。Stateful Set可以看作RC/Deployment的变种,它具有如下特征:
StatefulSet里的每个Pod都有稳定,唯一的网络标识,可以用于发现集群内的其他成员;
StatefulSet控制的Pod副本的启停是受控的,操作第n个Pod时,前n-1个Pod已经运行好的状态;
StatefulSet里的Pod采用稳定的持久化存储卷(Volume),通过PV/PVC(Volume的持久化实现类型)来实现,删除Pod时默认不会删除与StatefulSet相关的Volume
Volume是Pod中能够被多个容器访问的共享目录,Kubernetes中的Volume定义在Pod上,被一个Pod里的多个容器挂在到具体的文件目录下,与Pod具有相同的生命周期,但与容器的生命周期无关,当容器终止或者重启时,Volume中的数据不会丢失。Volume的使用也包括两部分,声明Volume,引用Volume并Mount到容器的目录上。
template:
metadata:
labels:
app: app-demo
tier:frontend
spec:
volumes:
- name: datavol
emptyDir: { }
containers:
- name:tomcat-demo
image:tomcat
volumeMounts:
- mountPath: /mydata-data
name: datavol
imagePullPolicy:IfNotPresent
ports:
-containerPort: 8080
Annotation与label类似,也适用key/value键值对的形式进行定义。不同的是Label具有严格的命名规则,他定义的是Kubernetes对象的元数据(Metadata),并且用于Label Selector。而Annotation则是用户任意定义的“附加信息”以便于外部工具进行查找,很多时候,kubernetes的模块自身会通过Annotation的方式标记资源对象的一些特殊信息。通常来说,用Annotation来记录的信息如下:
Namespace(命名空间)是Kubernetes系统中用于实现多租户的资源隔离。Namespace通过将集群内部的资源对象分配到不同的Namepace中,形成逻辑上的分组的不同项目、小组或用户组,便于不同的项目分组使用同一集群的资源的同时能够分组管理。Kubernetes在启动后,会创建一个名叫“default”的默认Namespace,创建Service、Pod、RC等资源时如果不指定Namespace就会被分配到默认空间去。创建Namespace的yaml定义如下:
apiVersion: v1
kind: Namespace
metadata:
name:dev
创建好Namespace之后创建Pod时就可以指定Namespace
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace:dev
......
当我们给每个租户创建一个Namespace来实现多租户隔离市,还能结合Kubernetes的资源配额管理,限定不同租户能占用的资源,例如CPU使用量、内存使用量等。
说明:本文内容文字及图片大部分来源于《Kubernetes权威指南》,我只是知识的搬运工。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。