

kubernetes集群组成
kubernetes集群主要是由控制节点(master)、工作节点(node)构成,每个节点上都会安装不同的组件。

master:集群的控制平面,负责集群的决策(管理)
ApiServer:资源操作的唯一入口,接收用户输入的命令,提供认证、授权、API注册和发现等机制
Scheduler:负责集群资源调度,按照预定的调度策略将Pod调度到相应的node节点上(算决策到哪个工作节点上)
ControllerManager:负责维护集群的状态,比如程序部署安排、故障检测、自动扩展、滚动更新等(安排)
Etcd :负责存储集群中各种资源对象的信息
node:集群的数据平面,负责为容器提供运行环境(干活的)
Kubelet:负责维护容器的生命周期,即通过控制docker,来创建、更新、销毁容器(等着接活)
KubeProxy:负责提供集群内部的服务发现和负载均衡
Docker:负责节点上容器的各种操作
概念
Master:集群控制节点,每个集群需要至少一个master节点负责集群的管控
Node:工作负载节点,由master分配容器到这些node工作节点上,然后node节点上的docker负责容器的运行
Pod:kubernetes的最小控制单元,容器都是运行在pod中的,一个pod中可以有1个或者多个容器
Controller:控制器,通过它来实现对pod的管理,比如启动pod、停止pod、伸缩pod的数量等等
Service:pod对外服务的统一入口,下面可以维护者同一类的多个pod
Label:标签,用于对pod进行分类,同一类pod会拥有相同的标签
NameSpace:命名空间,用来隔离pod的运行环境
namespace(注意删除命名空间后,该空间下的所有pod都会被删除)
Namespace是kubernetes系统中的一种非常重要资源,它的主要作用是用来实现多套环境的资源隔离或者多租户的资源隔离。
默认情况下,kubernetes集群中的所有的Pod都是可以相互访问的。但是在实际中,可能不想让两个Pod之间进行互相的访问,那此时就可以将两个Pod划分到不同的namespace下。kubernetes通过将集群内部的资源分配到不同的Namespace中,可以形成逻辑上的"组",以方便不同的组的资源进行隔离使用和管理。
可以通过kubernetes的授权机制,将不同的namespace交给不同租户进行管理,这样就实现了多租户的资源隔离。此时还能结合kubernetes的资源配额机制,限定不同租户能占用的资源,例如CPU使用量、内存使用量等等,来实现租户可用资源的管理。


kubectl get ns 获取所有命名空间
kubectl get pods -n xxx 获取该命名空间下的所有pod
kubectl get ns xxx 获取该命名空间的状态
kubectl create ns xxx 创建命名空间
kubectl delete ns xxx 删除命名空间
pod
Pod是kubernetes集群进行管理的最小单元,程序要运行必须部署在容器中,而容器必须存在于Pod中Pod可以认为是容器的封装,一个Pod中可以存在一个或者多个容器。**集群中各个组件也是以Pod方式运行的。**pause:根容器

# 命令格式:kubectl run pod控制器名称[参数]
#--image指定Pod的镜像
# --port指定端口
#--namespacd 指inamespace
[rootemaster ~]# kubectl run nginx --image=nginx:1.17.1 --port=88 --namespace dev
[rootemaster ~]# kubectl pod -n dev -o wide 查看该pod详细信息
[rootemaster ~]# kubectl describe pod xxx -n dev 查看该pod详细信息
[rootemaster ~]# kubectl delete deployment xxx -n dev 通过删除pod控制器删除pod
label
Label是kubernetes系统中的一个重要概念。它的作用就是在资源上添加标识,用来对它们进行区分和选择。
一个Label会以key/value键值对的形式附加到各种对象上,如Node、Pod、Service等等。
一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上去在资源对象走义时确定,当然也可以在对象创建后动态添加或者删除
Label通常实现资源的多维度分组,以便灵活、方便地进行资源分配、调度、配置、部等管理工作。
#为pod资源打标签
[root@master ~]# kubectl label pod nginx-pod version=1.8 -n dev
# 为pod资源更新标签
[root@master ~l# kubectl label pod nginx-pod version=2.0 -n dev --overwrite
# 查看标签
[root@master ~]# kubectl get pod nginx-pod -n dev --show-labels
Deployment
在kubernetes中,Pod是最小的控制单元,但是kubernetes很少直接控制Pod,一般都是通过Pod控制器来完成的。Pod控制器用于pod的管理,确保pod资源符合预期的状态,当pod的资源出现故障时,会尝试进行重启或重建pod。(比如直接删除pod是不可以的 因为pod控制器发现不符合预期状态 就直接新建 所以要通过删除控制器删除pod)

#命令格式:kubectl run deployment名称 [参数]
指定pod的镜像#--image
#--port指定端口
#--replicas 指定创建pod数量
#-namespace 指inamespace
[root@master ~]# kubectl run nginx --image=nginx:1.17.1 --port=80--replicas=3 -n dev
#查看创建的Pod
[rootemaster ~]# kubectl get pods -n dev
效果

service
虽然每个Pod都会分配一个单独的PodIP,然而却存在如下两问题:
Pod IP 会随着Pod的重建产生变化
Pod IP 仅仅是集群内可见的虚拟IP,外部无法访问这样对于访问这个服务带来了难度。因此,kubernetes设计了Service来解决这个问题,Service可以看作是一组同类Pod对外的访问接口 。借助Service,应用可以方便地实现服务发现和负载均衡。

服务打到Service上
#暴露Service
root@master \~\]# kubectl expose deploy nginx --name=svc-nginx1 --type=ClusterIp --port=88target-port=80 -n dev #上面创建的Service的type类型为ClusterIP,这个ip地址只用集群内部可访问#如果需要创建外部也可以访问的Service,需要修改type为NodePort #查看service \[root@master \~\]# kubectl get svc svc-nginx -n dev -o wide  ## pod详解(主要yaml文件配置) ### pod结构  每个Pod中都可以包含一个或者多个容器,这些容器可以分为两类: 1)用户程序所在的容器,数量可多可少 2)Pause容器,这是每个Pod都会有的一个根容器,它的作用有两个: 1、可以以它为依据,评估整个Pod的健康状态 2、可以在根容器上设置lp地址,其它容器都此Ip(PodIP),以实现Pod内部的网路通信 ### 资源清单举例  \[root@master \~\]kubectl explain pod 解释pod yaml文件的一级资源配置方式    \[root@master \~\]kubectl explain pod.metadata 查看一级资源metadata下面有哪些 ### pod配置(pod结构中spec下的containers)  #### 镜像拉取 参数 imagePullPolicy Never,Always,ifnotpresent 举例: apiVersion: v1 kind: Pod metadata: name: pod-imagepullpolicynamespace:dev spec : containers: -name:nginx image: nginx:1.17.1 imagePu1lPolicy:Always #用于设置镜像拉职策略 -name: busybox image: busybox:1.30 #### 启动命令(利用command) 例如busybox并不是一个程序,而是类似于一个工具类的集合,kubernetes集群启动管理后,它会自动关闭,解决方法就是让其一直在运行,这就用到了command配置。 apiVersion: v1 kind: Pod metadata: name: pod-command namespace: dev spec : containers: -name: nginx image: nginx:1.17.1 -name: busybox image: busybox:1.38 command:["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T)>>/tmp/hello.txt;sleep 3; done;"] #### 环境变量(env) apiVersion: v1 kind: Pod metadata : name: pod-env namespace:dev spec : containers: -name: busybox image: busybox:1.38 command:["/bin/sh","-c","while true;do /bin/echo $(date 4%T);sleep 68; done;"] env:#设照环境变量列表 - name:"username" value :"admin" - name: "password" value :123456 #### 端口设置(ports)  apiVersion:v1 kind: Pod metadata : name: pod-ports namespace: dev spec : containers: -name: nginx image: nginx:1.17.1 ports:#设置容器暴露的端口列表 -name: nginx-port containerPort:88 protocol:TCP 访问容器中的程序需要使用podip:containerPort #### 资源配额resources 容器中的程序要运行,肯定是要占用一定资源的,比如cpu和内存等,如果不对某个容器的资源做限制,那么它就可能吃掉大是资源,导致其它容器无法运行。针对这种情况,kubernetes提供了对内存和cpu的资源进行配额的机制,这种机制主要通过resources选项实现,他有两个子选项: limitg:用于限制运行时容器的最大占用资源,当容器占用资源超过limits时会被终止,并进行重启 requests:用于设置容器需要的最小资源,如果环境资源不够,容器将无法启动 apiVersion: v1 kind: Pod metadata: name: pod-resources namespace: dev spec: containers: -name: nginx image: nginx:1.17.1 resources:# 资源配额 limits: #限制资源(上限) cpu:"2"# CPU限制,单位是core数 memory:"18Gi"# 内存限制 requests:#请求资源(下限) cpu:"1" #CPU限制,单位是core数 memory:"18M1"#内存限制 ### pod生命周期 我们一般将pod对象从创建至终的这段时间范围称为pod的生命周期,它主要包含下面的过程: 1、pod创建过程 2、运行初始化容器(init container)过程 3、运行主容器(main container)过程 容器启动后钩子(post start)、容器终止前钩子(pre stop) 容器的存活性探测(liveness probe)、就绪性探测(readiness probe) 4、pod终止过程  在整个生命周期中,Pod会出现5种**状态(相位)** ,分别如下: 1、挂起(Pending): apiserver已经创建了pod资源对象,但它尚未被调度完成或者仍处于下载镜像的过程中 2、运行中(Running):pod已经被调度至某节点,并且所有容器都已经被kubelet创建完成 3、成功(Succeeded):pod中的所有容器都已经成功终止并且不会被重启 4、失败(Failed):所有容器都已经终止,但至少有一个容器终止失败,即容器返回了非0值的退出状态 5、未知(Unknown):apiserver无法正常获取到pod对象的状态信息,通常由网络通信失败所导致 #### 创建和终止 **创建过程:** 1.用户通过kubectl或其他api客户端提交需要创建的pod信息给apiServer 2.apiServer开始生成pod对象的信息,并将信息存入etcd,然后返回确认信息至客户端 3.apiServer开始反映etcd中的pod对象的变化,其它组件使用**watch机制**来跟踪检查apiserver上的变动 4.scheduler发现有新的pod对象要创建,开始为Pod分配主机并将结果信息更新至apiServer 5.node节点上的kubelet发现有pod调度过来,尝试调用docker启动容器,并将结果回送至apiServer6.apiServer将接收到的pod状态信息存入etcd中  **终止过程:** 1.用户向apiServer发送删除pod对象的命令 2.apiServcer中的pod对象信息会随着时间的推移而更新,在宽限期内(默认30s),pod被视为dead 3.将pod标记为terminating状态 4.kubelet在监控到pod对象转为terminating状态的同时启动pod关闭过程 5.端点控制器监控到pod对象的关闭行为时将其从所有匹配到此端点的service资源的端点列表中移除 6.如果当前pod对象定义了preStop钩子处理器,则在其标记为terminating后即会以同步的方式启动执行 7.pod对象中的容器进程收到停止信号 8.宽限期结束后,若pod中还存在仍在运行的进程,那么pod对象会收到立即终止的信号 9.kubelet请求apiserver将此pod资源的宽限期设置为0从而完成删除操作,此时pod对于用户已不可见 #### **运行初始化容器** 初始化容器是在pod的主容器启动之前要运行的容器,主要是做一些主容器的前置工作,它具有两大特征: 1.初始化容器必须运行完成直至结束,若某初始化容器运行失败,那么kubernetes需要重启它直到成功完成 2.初始化容器必须按照定义的顺序执行,当且仅当前一个成功之后,后面的一个才能运行 初始化容器有很多的应用场景,下面列出的是最常见的几个: 提供主容器镜像中不具备的工具程序或自定义代码 初始化容器要先于应用容器串行启动并运行完成,因此可用于延后应用容器的启动直至其依赖的条件得到满足 #### 主容器--钩子函数  **post start:** 容器创建之后执行,如果失败了会重启容器 **pre stop:** 容器终止之前执行,执行完成之后容器将成功终止,在其完成之前会阻塞删除容器的操作钩子处理器 三种方式定义动作: Exec命令:在容器内执行一次命令(这种比较多) lifecycle: postStart: exec: command : -cat -/tmp/healthy TCPSocket:在当前容器尝试访问指定的socket lifecycle : postStart: tcpSocket : port: 8080 HTTPGet:在当前容器中向某url发起http请求 lifecycle : postStart: httpGet: path:/#URI地址 port:88#端口号 host:192.168.189.108#主机地址 scheme:HTTP#支持的协议,http或者https 例子:  #### 容器探测 容器探测用于检测容器中的应用实例是否正常工作,是保障业务可用性的一种传统机制。如果经过探测,实例的状态不符合预期,那么kubernetes就会把该问题实例"摘除",不承担业务流量。kubernetes提供了两种探针来实现容器探测,分别是: 1、liveness probes:存活性探针,用于检测应用实例当前是否处于正常运行状态,如果不是,k8s会重启容器。 2、readiness probes:就绪性探针,用于检测应用实例当前是否可以接收请求,如果不能,k8s不会转发流量 **liveness Probe 决定是否重启容器,readiness Probe 决定是否将请求转发给容器。** **三种探测方式:** Exec命令:在容器内执行一次命令,如果命令执行的退出码为0,程序正常,否则不正常 livenessProbe: exec: command : -cat -/tmp/healthy TCPSocket:在当前容器尝试访问容器端口,如果能够建立连接,则程序组成,否则不正常 livenessProbe: tcpSocket : port: 8080 HTTPGet:调用容器内web的url,如果返回状态码在200和399之间,则程序正常,否则不正常 livenessProbe: httpGet: path:/#URI地址 port:88#端口号 host:192.168.189.108#主机地址 scheme:HTTP#支持的协议,http或者https 例子:  有一些额外的参数  #### 重启策略 在上一节中,一旦容器探测出现了问题,kubernetes就会对容器所在的Pod进行重启,其实这是由pod的重启策略决定的,pod的重启策略有3种,分别如下: Always :容器失效时,自动重启该容器,这也是默认值。 OnFailure :容器终止运行且退出码不为0时重启 Never:不论状态为何,都不重启该容器 重启策略适用于pod对象中的所有容器,首次需要重启的容器,将在其需要时立即进行重启,随后再次需要重启的操作将由kubelet延迟一段时间后进行,且反复的重启操作的延迟时长以此为105、20s、40s、80s、160s和300s,300s是最大延迟时长。 ### pod的调度(待更新完整) 在默认情况下,一个Pod在哪个Node节点上运行,是由Scheduler组件采用相应的算法计算出来的,这个过程是不受人工控制的。但是在实际使用中,这并不满足的需求,因为很多情况下,我们想控制某些Pod到达某些节点上,那么应该怎么做呢?这就要求了解kubernetes对Pod的调度规则,kubernetes提供了四大类调度方式: 1、**自动调度** :运行在哪个节点上完全由Scheduler经过一系列的算法计算得出 2、**定向调度** :NodeName、NodeSelector 3、**亲和性调度** :NodeAffinity、PodAffinity、PodAntiAffinity 4、**污点(容忍)调度**:Taints、Toleration  #### **定向调度** 强制将pod运行到指定节点 通过**kubectl get nodes**获取node名字 apiVersion: v1 Kind: pod metadata : name: pod-nodename namespace:dev spec : containers: -name: nginx image: nginx:1.17.1 nodeName:node1#指定调度到node1节点上 NodeSelector根据节点标签 1 首先分别为node节点添加标签 [ rootemaster ~]# kubectl label nodes nodel nodeenv-pronode/node2 labeled [ rootemaster ~]# kubectl label nodes node2 nodeenv=testnode/node2 labeled 2 创建一个pod-nodeselector.yaml文件,并使用它创建Pod apiVersion:v kind: Pod metadata: name:pod-nodeselector namespace: dev spec : containers: -name: nginx image: nginx:1.17.1nodeSelector : nodeenv:pro#指定调度到具有nodeenv=pro标签的节点上 #### **亲和性调度** ...