K8S概述
Kubernetes是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单高效,Kubernetes提供了应用部署、规划、更新、维护的一种机制。在Kubenetes中,所有的容器均在Pod中运行,一个Pod可以承载一个或者多个相关的容器。同一个Pod中的容器会部署在同一个物理机器上并且能够共享资源。一个Pod也可以包含0个或者多个磁盘卷组(volumes),这些卷组将会以目录的形式提供给一个容器,或者被所有Pod中的容器共享。
主要介绍一些什么知识
K8S的架构概览
k8s功能架构
DockerEngine由许多专用的工具协同工作,从而可以创建和运行容器,例如API、执行驱动、运行时、shim进程等。主要由两个核心组件构成:LXC和Dockerdaemon。Dockerdaemon是单一的二进制文件,包含诸如Docker客户端、DockerAPI、容器运行时、镜像构建等。LXC提供了对诸如命名空间(Namespace)和控制组(CGroup)等基础工具的操作能力,它们是基于Linux内核的容器虚拟化技术。LinuxNamespace是Linux内核用来隔离资源的方式。每个Namespace下的资源对于其他Namespace都是不透明,不可见的。容器就是进程,容器是与系统其他部分隔离开的进程。这个时候我们再看上图就更容易理解,容器是跑在宿主机OS(虚机容器的宿主机OS就是GuestOS)上的进程,容器间以及容器和宿主机间存在隔离性。
k8s架构拆解
k8s相关组件介绍:
apiservice:所有服务访问统一入口。对外暴露K8S的api接口,是外界进行资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制;
crontrollermanager:负责维护集群的状态,比如故障检测、自动扩展、滚动更新等,它们是处理集群中常规任务的后台线程。
scheduler:负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上;就是监视新创建的Pod,如果没有分配节点,就选择一个节点供他们运行,这就是pod的调度。
etcd:一个可信赖的分布式键值存储服务,能够为整个分布式集群存储一些关键数据,协助分布式集群运转。储存K8S集群所有重要信息(持久化)。v2版本时基于内存的存储,v3开始才是序列化到介质。新版本K8S(v1.11以上)已经改用v3版本etcd。
kubelet:直接跟容器引擎交互实现容器的生命周期管理。
kube-proxy:负责写入规则至IPTABLES、IPVS实现服务映射访问的。
其中scheduler和controller-manager两个组件是有leader选举的,这个选举机制是k8s对于这两个组件的高可用保障。apiserver是可以水平扩展的。
其他重要插件:
coredns:可以为集群中的SVC创建一个域名IP的对应关系解析
dashboard:给K8S集群提供一个B/S结构访问体系
ingresscontroller:官方只能实现四层代理,INGRESS可以实现七层代理
federation:提供一个可以跨集群中心多K8S统一管理功能
prometheus:提供K8S集群的监控能力
elk:提供K8S集群日志统一分析介入平台
K8S安装
学习还是需要跟实践结合的,这样理解更透彻。安装个单机版本K8S方便后面的学习整理K8S安装分3种方式:
单机版本,mac安装可以参考文档
伪多机(通过vm),网上资源非常多。
真实多台机器,可以几台低配置的买阿里云安装。文档描述非常清晰
K8S中的资源
K8S中所有的内容都抽象为资源,资源实例化之后叫做对象。在K8S中,一般适用yaml格式的文件来创建符合我们预期的Pod,这样的yaml文件一般称为资源清单。K8S中的资源可以分为:名称空间级资源、集群级资源、元数据型资源。名称空间级资源(通过kubectlapi-resources--namespaced=true查看全部)K8S是有空间概念的,以下资源是归属于某个空间的(没有指定就是默认空间)。名称空间级资源又可以根据功能分为以下几种:
工作负载型资源:Pod、ReplicaSet(ReplicationController在v1.11版本废弃)、Deployment、StatefulSet、DaemonSet、Job、CronJob
服务发现及负载均衡型资源:Service、Ingress等
配置与存储型资源:Volume、CSI(容器存储接口,可以扩展各种各样的第三方存储卷)
特殊类型的存储卷:ConfigMap(当配置中心来使用的资源类型)、Secret(保存敏感数据)、DownwardAPI(把外部环境中的信息输出给容器)
集群级资源(通过kubectlapi-resources--namespaced=false查看全部)Namespace、Node、Role、ClusterRole、RoleBinding、ClusterRoleBinding
元数据型资源HPA、PodTemplate、LimitRange
资源清单中常用字段
yaml文件是K8S资源声明式表达的格式。各种资源通用的常用字段如下:
工作负载
Node
Kubernetes中节点(node)指的是一个工作机器,曾经叫做minion。不同的集群中,节点可能是虚拟机也可能是物理机。每个节点都由master组件管理,并包含了运行Pod(容器组)所需的服务。这些服务包括:容器引擎、kubelet、kube-proxy。执行kubectlgetnodes-owide命令可查看所有节点的列表。执行kubectldescribenodeyour-node-name命令可查看节点状态以及节点的其他详细信息。输出的节点状态包含如下信息:
Addresses(包括内外部IP、hostname等信息)
Conditions(描述了节点的硬盘、内存、进程数等压力状态)
CapacityandAllocatable(描述节点上的可用资源如CPU、内存、该节点可调度的最大pod数等情况)
Info(描述了节点的基本信息,如Linux内核版本、Kubernetes版本、Docker版本、操作系统名称等)
节点管理
与Pod和Service不一样,节点并不是由Kubernetes创建的,节点由云供应商创建。向Kubernetes中创建节点时,仅仅是创建了一个描述该节点的API对象。节点API对象创建成功后,Kubernetes将检查该节点是否有效。例如,假设创建如下节点信息:
kind:NodeapiVersion:v1metadata:name:"10..79."labels:name:"my-first-k8s-node"
Kubernetes在APIServer上创建一个节点API对象(节点的描述),并且基于metadata.name字段对节点进行健康检查。如果节点有效,则可以向该节点调度Pod;否则,该节点API对象将被忽略,直到节点变为有效状态。节点控制器(NodeController)节点控制器是一个负责管理节点的Kubernetesmaster组件。在节点的生命周期中,节点控制器起到了许多作用。
首先,节点控制器在注册节点时为节点分配CIDR地址块
第二,节点控制器通过云供应商(cloud-controller-manager)接口检查节点列表中每一个节点对象对应的虚拟机是否可用。在云环境中,只要节点状态异常,节点控制器检查其虚拟机在云供应商的状态,如果虚拟机不可用,自动将节点对象从APIServer中删除。
第三,节点控制器监控节点的健康状况。当节点变得不可触达时(例如,由于节点已停机,节点控制器不再收到来自节点的心跳信号),节点控制器将节点API对象的NodeStatusCondition取值从NodeReady更新为Unknown;然后在等待pod-eviction-timeout时间后,将节点上的所有Pod从节点驱逐。
节点自注册(Self-Registration)
如果kubelet的启动参数--register-node为true(默认为true),kubelet会尝试将自己注册到APIServer。kubelet自行注册时,将使用如下选项:
--kubeconfig:向apiserver进行认证时所用身份信息的路径
--cloud-provider:向云供应商读取节点自身元数据
:自动向APIServer注册节点
--register-with-taints:注册节点时,为节点添加污点(逗号分隔,格式为key=value:effect
--node-ip:节点的IP地址
--node-labels:注册节点时,为节点添加标签
--node-status-update-frequency:向master节点发送心跳信息的时间间隔
如果Nodeauthorizationmode(opensnewwindow)和NodeRestrictionadmissionplugin(opensnewwindow)被启用,kubelet只拥有创建/修改其自身所对应的节点API对象的权限。
Pod
Pod(容器组)是Kubernetes中最小的可部署单元。一个Pod(容器组)包含了一个应用程序容器(某些情况下是多个容器)、存储资源、一个唯一的网络IP地址、以及一些确定容器该如何运行的选项。Pod容器组代表了Kubernetes中一个独立的应用程序运行实例,该实例可能由单个容器或者几个紧耦合在一起的容器组成。一个Pod是容器环境下的“逻辑主机”,它可能包含一个或者多个紧密相连的应用,这些应用可能是在同一个物理主机或虚拟机上。Pod的context可以理解成多个linux命名空间的联合:
PID命名空间(同一个Pod中应用可以看到其它进程)
网络命名空间(同一个Pod的中的应用对相同的IP地址和端口有权限)
IPC命名空间(同一个Pod中的应用可以通过VPC或者POSIX进行通信)
UTS命名空间(同一个Pod中的应用共享一个主机名称)
同一个Pod中的应用可以共享磁盘,磁盘是Pod级的,应用可以通过文件系统调用。
Pod创建流程
创建Pod的整个流程,时序图如下:
pod创建流程
用户提交创建Pod的请求,可以通过APIServer的RESTAPI,也可用Kubectl命令行工具,支持Json和Yaml两种格式;
APIServer处理用户请求,存储Pod数据到Etcd;
Schedule通过和APIServer的watch机制,查看到新的pod,尝试为Pod绑定Node。调度器用一组规则过滤掉不符合要求的主机,比如Pod指定了所需要的资源,那么就要过滤掉资源不够的主机,对上一步筛选出的符合要求的主机进行打分,在主机打分阶段,调度器会考虑一些整体优化策略进行调度;选择打分最高的主机,进行binding操作,结果存储到Etcd中;
kubelet根据调度结果执行Pod创建操作。绑定成功后,会启动container。scheduler会调用APIServer的API在etcd中创建一个boundpod对象,描述在一个工作节点上绑定运行的所有pod信息。运行在每个工作节点上的kubelet也会定期与etcd同步boundpod信息。
Pod的定义
可以通过kubectlexplainpod查看podyaml定义的顶级属性,然后通过类似kubectlexplainpod.{顶级属性}查看二级属性的细节定义。下面给出一个pod资源定义的样例,对pod的描述有一个初步了解。
apiVersion:v1#与k8s集群版本有关,使用kubectlapi-versions即可查看当前集群支持的版本kind:Pod#该配置的类型,我们使用的是Podmetadata:#译名为元数据,即Pod的一些基本属性和信息name:nginx-pod#Pod的名称labels:#标签,可以灵活定位一个或多个资源,其中key和value均可自定义,可以定义多组,目前不需要理解app:nginx#为该Deployment设置key为app,value为nginx的标签spec:#期望Pod实现的功能(即在pod中部署)containers:#生成container,与docker中的container是同一种-name:nginx#container的名称image:nginx:1.7.9#使用镜像nginx:1.7.9创建container,该container默认80端口可访问
保存为nginx-pod.yaml文件,通过kubectlapply-fnginx-pod.yaml启动pod。通过kubectlgetpods-owide查看pod的启动情况。
PodTemplate用户应该始终使用控制器来创建Pod,而不是直接创建Pod,控制器可以提供如下特性:
水平扩展(运行Pod的多个副本)
rollout(版本更新)
self-healing(故障恢复)
当一个节点出现故障,控制器可以自动地在另一个节点调度一个配置完全一样的Pod,以替换故障节点上的Pod。在Kubernetes中,广泛使用的控制器有:
Deployment
StatefulSet
DaemonSet
控制器通过其中配置的PodTemplate信息来创建Pod。PodTemplate是关于Pod的定义,但是被包含在其他的Kubernetes对象中(例如Deployment、StatefulSet、DaemonSet等控制器)。控制器通过PodTemplate信息来创建Pod上面部署pod的yaml文件如果改为通过deployment来部署,对应的文件如下:
apiVersion:apps/v1kind:Deployment#该配置的类型,我们使用的是Deploymentmetadata:#译名为元数据,即Deployment的一些基本属性和信息name:nginx-deployment#Deployment的名称labels:app:nginxspec:#这是关于该Deployment的描述,可以理解为你期待该Deployment在k8s中如何使用replicas:1#使用该Deployment创建一个应用程序实例selector:#标签选择器,与上面的标签共同作用,目前不需要理解matchLabels:#选择包含标签app:nginx的资源app:nginxtemplate:#这是选择或创建的Pod的模板metadata:#Pod的元数据labels:#Pod的标签,上面的selector即选择包含标签app:nginx的Podapp:nginxspec:containers:-name:nginximage:nginx:1.7.9
Pod的生命周期
pod生命周期
Pod能够具有多个容器,应用运行在容器里面,但是它也可能有一个或多个先于应用容器启动的Init容器。Init容器与普通容器非常像,除了以下两点:
Init容器总是运行到成功完成为止。也就是Init容器会退出结束。
每个Init容器都必须在下一个Init容器启动之前成功完成。
Init容器可以通过kubectlexplainpod.spec.initContainers查看init容器的属性配置。init容器属于pod的初始化容器列表。初始化容器是在容器启动之前按顺序执行。如果Pod的Init容器失败,Kubernetes会不断重启该Pod,直到Init容器成功为止(除非Pod对应的restartPolicy为Never)。因为Init容器具有与应用程序容器分离的单独镜像,所以它们的启动相关代码具有如下优势:
应用程序镜像可以分离出创建和部署的角色,而没必要联合它们构建一个单独的镜像。
Init容器使用LinuxNamespace,所以相比应用程序容器来说具有不同的文件系统视图。因此,它们能够具有访问Secret的权限,而应用程序则不能。
它们必须在应用容器启动之前运行完成,而应用程序容器是并行运行的,所以Init容器能够提供一种简单的阻塞或延迟应用容器的启动方法,直到满足一组先决条件。
如果Pod重启,所有Init容器必须重新执行
Init容器具有应用容器的所有字段,除了readinessProbe。因为Init容器无法定义不同于完成(