文章 44
评论 0
浏览 14956
k8s资源对象

k8s资源对象

一、K8s资源管理的核心概念

1.1 分层架构

官方文档:http://docs.kubernetes.org.cn/251.html

image-20210427135454990

  • 核心层:Kubernetes最核心的功能,对外提供API构建高层的应用,对内提供插件式应用执行环境
  • 应用层:部署(无状态应用、有状态应用、批处理任务、集群应用等)和路由(服务发现、DNS解析等)
  • 管理层:系统度量(如基础设施、容器和网络的度量),自动化(如自动扩展、动态Provision等)以及策略管理(RBAC、Quota、PSP、NetworkPolicy等)
  • 接口层:kubectl命令行工具、客户端SDK以及集群联邦
  • 生态系统:在接口层之上的庞大容器集群管理调度的生态系统,可以划分为两个范畴
    • Kubernetes外部:日志、监控、配置管理、CI、CD、Workflow、FaaS、OTS应用、ChatOps等
    • Kubernetes内部:CRI、CNI、CVI、镜像仓库、Cloud Provider、集群自身的配置和管理等

1.2 API设计原理

官方文档:https://www.kubernetes.org.cn/kubernetes%e8%ae%be%e8%ae%a1%e7%90%86%e5%bf%b5

  1. 所有API应该是声明式的。正如前文所说,声明式的操作,相对于命令式操作,对于重复操作的效果是稳定的,这对于容易出现数据丢失或重复的分布式环境来说是很重要的。另外,声明式操作更容易被用户使用,可以使系统向用户隐藏实现的细节,隐藏实现的细节的同时,也就保留了系统未来持续优化的可能性。此外,声明式的API,同时隐含了所有的API对象都是名词性质的,例如Service、Volume这些API都是名词,这些名词描述了用户所期望得到的一个目标分布式对象。
  2. API对象是彼此互补而且可组合的。这里面实际是鼓励API对象尽量实现面向对象设计时的要求,即“高内聚,松耦合”,对业务相关的概念有一个合适的分解,提高分解出来的对象的可重用性。事实上,K8s这种分布式系统管理平台,也是一种业务系统,只不过它的业务就是调度和管理容器服务。
  3. 高层API以操作意图为基础设计。如何能够设计好API,跟如何能用面向对象的方法设计好应用系统有相通的地方,高层设计一定是从业务出发,而不是过早的从技术实现出发。因此,针对K8s的高层API设计,一定是以K8s的业务为基础出发,也就是以系统调度管理容器的操作意图为基础设计。
  4. 低层API根据高层API的控制需要设计。设计实现低层API的目的,是为了被高层API使用,考虑减少冗余、提高重用性的目的,低层API的设计也要以需求为基础,要尽量抵抗受技术实现影响的诱惑。
  5. 尽量避免简单封装,不要有在外部API无法显式知道的内部隐藏的机制。简单的封装,实际没有提供新的功能,反而增加了对所封装API的依赖性。内部隐藏的机制也是非常不利于系统维护的设计方式,例如PetSet和ReplicaSet,本来就是两种Pod集合,那么K8s就用不同API对象来定义它们,而不会说只用同一个ReplicaSet,内部通过特殊的算法再来区分这个ReplicaSet是有状态的还是无状态。
  6. API操作复杂度与对象数量成正比。这一条主要是从系统性能角度考虑,要保证整个系统随着系统规模的扩大,性能不会迅速变慢到无法使用,那么最低的限定就是API的操作复杂度不能超过O(N),N是对象的数量,否则系统就不具备水平伸缩性了。
  7. API对象状态不能依赖于网络连接状态。由于众所周知,在分布式环境下,网络连接断开是经常发生的事情,因此要保证API对象状态能应对网络的不稳定,API对象的状态就不能依赖于网络连接状态。
  8. 尽量避免让操作机制依赖于全局状态,因为在分布式系统中要保证全局状态的同步是非常困难的

1.3 API对象

API对象是k8s中的管理操作单元

image-20210427141644408

类别名称
资源对象Pod、ReplicaSet、ReplicationController、Deployment、StatefulSet、DaemonSet、Job、CronJob、HorizontalPodAutoscaling、Node、Namespace、Service、Lngress、Label、CustomResourceDefinition
存储对象Volume、PersistentVolume、Secret、ConfigMap
策略对象SecurityContext、ResourceQuota、LimitRange
身份对象ServiceAccount、Role、ClusterRole

二、K8s命令使用

命令集命令用途
基础命令create/delete/edit/get/describe/logs/exec/scale增删改查
explain资源类型说明
配置命令Label:给node标记label,实现亲pod与node亲和性标签管理
apply动态配置
集群管理命令cluster-info/top集群状态
cordon:警戒线,标记node不被调用uncordon:取消警戒标记为cordon的nodedrain:驱逐node上的pod,用于node下线场景taint:给node标记污点,实现反亲pod与node反亲和性node节点管理
api-resources/api-versions/versionapi资源
config客户端kube-config配置

示例

#资源类型说明
[14:46:56 root@k8s-master ~]#kubectl explain pod
[14:47:39 root@k8s-master ~]#kubectl explain service
[14:47:39 root@k8s-master ~]#kubectl explain node

#集群状态
[14:48:41 root@k8s-master ~]#kubectl cluster-info 
Kubernetes control plane is running at https://192.168.10.181:6443
KubeDNS is running at https://192.168.10.181:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
#top命令需要Metrics API才可以使用
[14:49:15 root@k8s-master ~]#kubectl top node 
error: Metrics API not available

#api查看
[14:49:23 root@k8s-master ~]#kubectl api-versions #查看所有api
[14:50:26 root@k8s-master ~]#kubectl api-resources  #查看api的详细信息
NAME                              SHORTNAMES   APIVERSION                             NAMESPACED   KIND
bindings                                       v1                                     true         Binding
componentstatuses                 cs           v1                                     false        ComponentStatus
#NAME名称
#SHORTNAMES别名,表示可以在命令行使用别名替换此api
#APIVERSION版本
#NAMESPACED,true表示需要指定Namespace,如不指定表示默认Namespace及default,false表示是全局api不需要指定namespace

Namespace:命名空间,对资源进行逻辑隔离,通常是公司的项目名称

#创建
[14:53:31 root@k8s-master ~]#kubectl create namespace zhang  #创建namespace
namespace/zhang created
#查看
[15:02:07 root@k8s-master ~]#kubectl get namespaces 
NAME                   STATUS   AGE
default                Active   28h
kube-node-lease        Active   28h
kube-public            Active   28h
kube-system            Active   28h
kubernetes-dashboard   Active   27h
zhang                  Active   30s
#删除
[15:02:37 root@k8s-master ~]#kubectl delete namespaces zhang 
namespace "zhang" deleted

#apply创建namespace
#帮助查看
[15:11:24 root@k8s-master namespace]#kubectl explain namespace
[15:11:41 root@k8s-master namespace]#kubectl explain namespace.metadata
[15:11:56 root@k8s-master namespace]#kubectl explain namespace.metadata.name
[15:12:27 root@k8s-master namespace]#cat namespace.yaml
apiVersion: v1
kind: Namespace
metadata: 
  name: zhangzhuo
[15:15:18 root@k8s-master namespace]#kubectl apply -f namespace.yaml 
namespace/zhangzhuo created
[15:15:54 root@k8s-master namespace]#kubectl get namespaces 
NAME                   STATUS   AGE
default                Active   28h
kube-node-lease        Active   28h
kube-public            Active   28h
kube-system            Active   28h
kubernetes-dashboard   Active   28h
zhangzhuo              Active   42s
#删除
[15:16:04 root@k8s-master namespace]#kubectl delete -f namespace.yaml 
namespace "zhangzhuo" deleted
[15:16:24 root@k8s-master namespace]#kubectl get namespaces 
NAME                   STATUS   AGE
default                Active   28h
kube-node-lease        Active   28h
kube-public            Active   28h
kube-system            Active   28h
kubernetes-dashboard   Active   28h

#动态编辑资源
[15:16:46 root@k8s-master namespace]#kubectl edit namespaces zhangzhuo

#查看资源
[15:29:04 root@k8s-master namespace]#kubectl  get namespaces

#详细查看
[15:30:25 root@k8s-master namespace]#kubectl describe namespaces zhangzhuo 
Name:         zhangzhuo
Labels:       <none>
Annotations:  <none>
Status:       Active

No resource quota.

No LimitRange resource.

#查看pod日志
[15:34:35 root@k8s-master namespace]#kubectl logs -f net-test1


#node节点下线前操作
[15:50:38 root@k8s-master namespace]#kubectl drain k8s-node1.zhangzhuo.org  --ignore-daemonsets --delete-emptydir-data

三、K8s的牛鼻子—API

3.1 K8s的几个重要概念

  • 对象 用k8s是和什么打交道? K8s 声明式API
  • yaml文件 怎么打交道? 调用声明式API
  • 必需字段 怎么声明
    • apiVersion - 创建该对象所使用的 Kubernetes API 的版本
    • kind - 想要创建的对象的类型
    • metadata - 帮助识别对象唯一性的数据,包括一个 name 名称 、 可选的 namespace
    • spec
    • status(Pod创建完成后k8s自动生成status状态)

yaml文件及必需字段

每个API对象都有3大类属性:元数据metadata、规范spec和状态status。

#示例
apiVersion: v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
      spec:
        containers:
        - name: nginx
          image: harbor.zhangzhuo.org/images/nginx:latest
          ports:
          - containerPort: 80
  • spec和status的区别:
    • spec是期望状态
    • status是实际状态

3.2 Pod

官方文档:https://kubernetes.io/zh/docs/concepts/workloads/pods/

概述

  1. pod是k8s中的最小单元
  2. 一个pod中可以运行一个容器,也可以运行多个容器
  3. 运行多个容器的话,这些容器是一起被调度的
  4. Pod的生命周期是短暂的,不会自愈,是用完就销毁的实体
  5. 一般我们是通过**Controller(控制器)**来创建和管理pod的

Pod生命周期

初始化容器、启动前操作、就绪探针、存活探针、删除pod操作

image-20210427161643707

3.3 livenessProbe和readinessProbe

官方文档:https://kubernetes.io/zh/docs/concepts/workloads/pods/pod-lifecycle/#container-probes

livenessProbe:存活探针

  • 检测应用发生故障时使用,不能提供服务、超时等
  • 检测失败重启pod

readinessProbe:就绪探针

  • 检测pod启动之后应用是否就绪,是否可以提供服务
  • 检测成功,pod才开始接收流量

3.4 Controller 控制器

3.4.1 Replication Controller第一代pod副本控制器

官方文档:https://kubernetes.io/zh/docs/concepts/workloads/controllers/replicationcontroller/

ReplicationController 如何工作

当 Pod 数量过多时,ReplicationController 会终止多余的 Pod。当Pod数量太少时,ReplicationController 将会启动新的 Pod。 与手动创建的 Pod 不同,由 ReplicationController 创建的 Pod 在失败、被删除或被终止时会被自动替换。 例如,在中断性维护(如内核升级)之后,你的 Pod 会在节点上重新创建。 因此,即使你的应用程序只需要一个 Pod,你也应该使用 ReplicationController 创建 Pod。 ReplicationController 类似于进程管理器,但是 ReplicationController 不是监控单个节点上的单个进程,而是监控跨多个节点的多个 Pod。

在讨论中,ReplicationController 通常缩写为 "rc",并作为 kubectl 命令的快捷方式。

示例:

[16:44:55 root@k8s-master controller]#cat nginx-rc.yaml 
apiVersion: v1     #版本需要写正确的版本使用kubectl api-resources命令可以查询
kind: ReplicationController
metadata:
  name: ng-rc     #控制器名称
spec:
  replicas: 2     #副本数量
  selector:       #识别那个pod,只能识别等于或不等于
    app: ng-rc-80
  template:       #下面是pod的定义
    metadata:
      labels:     #标签控制器会使用这个匹配到他
        app: ng-rc-80
    spec:
      containers:
      - name: ng-rc-80  #容器名称ng-rc-80-控制器名称-随机pod名称
        image: harbor.zhangzhuo.org/images/nginx:latest
        ports:
        - containerPort: 80
[16:52:32 root@k8s-master controller]#kubectl apply -f nginx-rc.yaml -n zhangzhuo
[16:52:43 root@k8s-master controller]#kubectl get pod -n zhangzhuo
NAME          READY   STATUS    RESTARTS   AGE
ng-rc-2745q   1/1     Running   0          12s
ng-rc-bp4zh   1/1     Running   0          12s

3.4.2 ReplicaSet 第二代pod副本控制器

官方文档:https://kubernetes.io/zh/docs/concepts/workloads/controllers/replicaset/

副本控制集,和副本控制器的区别是:对选择器的支持 (selector 还支持in notin)

ReplicaSet 的工作原理

RepicaSet 是通过一组字段来定义的,包括一个用来识别可获得的 Pod 的集合的选择算符、一个用来标明应该维护的副本个数的数值、一个用来指定应该创建新 Pod 以满足副本个数条件时要使用的 Pod 模板等等。 每个 ReplicaSet 都通过根据需要创建和删除 Pod 以使得副本个数达到期望值, 进而实现其存在价值。当 ReplicaSet 需要创建新的 Pod 时,会使用所提供的 Pod 模板。

示例:

[17:20:53 root@k8s-master controller]#cat nginx-rs.yaml 
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
spec:
  replicas: 2
  selector:
    matchLabels:   #等于ng-rs-80
      app: ng-rs-80
   # matchExpressions:
   #   - {key: app, operator: In, values: [ng-rs-80,ng-rs-81]}   #匹配其中的一个
  template:
    metadata:
      labels:
        app: ng-rs-80
    spec:
      containers:
      - name: ng-rs-80
        image: harbor.zhangzhuo.org/images/nginx:latest
        ports:
        - containerPort: 80
[17:20:52 root@k8s-master controller]#kubectl apply -f nginx-rs.yaml -n zhangzhuo 
replicaset.apps/frontend created

3.4.3 Deployment 第三代pod控制器

官方文档:https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/

比rs更高一级的控制器,除了有rs的功能之外,还有很多高级 功能,,比如说最重要的:滚动升级、回滚等

你负责描述 Deployment 中的 目标状态,而 Deployment 以受控速率更改实际状态, 使其变为期望状态。你可以定义 Deployment 以创建新的 ReplicaSet,或删除现有 Deployment, 并通过新的 Deployment 收养其资源。

说明: 不要管理 Deployment 所拥有的 ReplicaSet 。

示例:

[17:49:38 root@k8s-master controller]#cat nginx-deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    #app: ng-deploy-80
    matchLabels:
      app: ng-deploy-80
    #matchExpressions:
    #  - {key: app, operator: In, values: [ng-deploy-80,ng-rs-81]}
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-depoy-80
        image: harbor.zhangzhuo.org/images/nginx:latest
        ports:
        - containerPort: 80
[17:50:05 root@k8s-master controller]#kubectl apply -f nginx-deploy.yaml -n zhangzhuo 
deployment.apps/nginx-deployment unchanged
#查看
[17:51:09 root@k8s-master controller]#kubectl get deployments.apps -n zhangzhuo 
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   2/2     2            2           2m26s
[17:52:04 root@k8s-master controller]#kubectl get replicasets.apps -n zhangzhuo 
NAME                         DESIRED   CURRENT   READY   AGE
nginx-deployment-c596f7444   2         2         2       2m51s
[17:52:29 root@k8s-master controller]#kubectl get pod -n zhangzhuo 
NAME                               READY   STATUS    RESTARTS   AGE
nginx-deployment-c596f7444-2c44r   1/1     Running   0          3m4s
nginx-deployment-c596f7444-b6bgc   1/1     Running   0          3m4s

Deployment会调用ReplicaSet来维持副本数,Deployment主要实现更高级的功能

3.4.4 三种控制器区别

控制器名称selector方法使用情况
Replication Controller只能实现等于或不等于基本不在使用
ReplicaSet在等于和不等于下实现in和notin基本不单独使用,依靠Deployment来调用,用户一般不会手动维护它
Deployment在等于和不等于下实现in和notin,继承于ReplicaSet使用最多,它的副本数量维持依靠ReplicaSet来完成,本身实现更高级的功能

3.5 Service

官方文档:https://kubernetes.io/zh/docs/concepts/services-networking/service/

将运行在一组 Pods上的应用程序公开为网络服务的抽象方法。

使用 Kubernetes,你无需修改应用程序即可使用不熟悉的服务发现机制。 Kubernetes 为 Pods 提供自己的 IP 地址,并为一组 Pod 提供相同的 DNS 名, 并且可以在它们之间进行负载均衡。

作用:

创建和销毁 Kubernetes Pod以匹配集群状态。 Pod 是非永久性资源。 如果你使用 Deployment 来运行你的应用程序,则它可以动态创建和销毁 Pod。每个 Pod 都有自己的 IP 地址,但是在 Deployment 中,在同一时刻运行的 Pod 集合可能与稍后运行该应用程序的 Pod 集合不同。这导致了一个问题: 如果一组 Pod(称为“后端”)为集群内的其他 Pod(称为“前端”)提供功能, 那么前端如何找出并跟踪要连接的 IP 地址,以便前端可以使用提供工作负载的后端部分?

  • pod重建之后ip就变了,pod之间直接访问会有问题
  • 解耦了服务和应用。
  • 声明一个service对象

service一般常用的有两种

  • k8s集群内的service:selector指定pod,自动创建Endpoints
  • k8s集群外的service:手动创建Endpoints,指定外部服务的ip,端口和协议

kube-proxy和service的关系

kube-proxy监听着k8s-apiserver,一旦service资源发生变化(调k8s-api修改service信息),kube-proxy 就会生成对应的负载调度的调整,这样就保证service的最新状态。

kube-proxy有三种调度模型

  • userspace:k8s1.1之前,已经废弃
  • iptables:k8s1.10之前
  • ipvs:k8s 1.11之后,如果没有开启ipvs,则自动降级为iptables

示例1:ClusterIP

[20:06:14 root@k8s-master service]#cat nginx-svc.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: harbor.zhangzhuo.org/images/nginx:latest
        ports:
        - containerPort: 80
---                   #多个定义需要使用---隔离
apiVersion: v1        #Service版本为v1
kind: Service
metadata:
  name: ng-deploy-80
spec:
  ports:
  - name: http
    port: 80    #service监听端口
    targetPort: 80  #目的pod端口
    protocol: TCP
  type: ClusterIP   #类型,默认就是ClusterIP,意思为只能被k8s内部访问
  selector:
    app: ng-deploy-80  #管理那个pod,就是pod的labels
#执行创建
[20:15:32 root@k8s-master service]#kubectl apply -f nginx-svc.yaml -n zhangzhuo 
deployment.apps/nginx-deployment unchanged
service/ng-deploy-80 unchanged
#查看
[20:15:41 root@k8s-master service]#kubectl get service -n zhangzhuo 
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
ng-deploy-80   ClusterIP   10.200.94.250   <none>        80/TCP    9m30s
[20:20:24 root@k8s-master service]#kubectl get endpoints -n zhangzhuo 
NAME           ENDPOINTS                       AGE
ng-deploy-80   10.100.2.30:80,10.100.2.31:80   14m
#在pod中测试
root@nginx-deployment-959555b6b-c4xb8:/# curl ng-deploy-80 -I
HTTP/1.1 200 OK

示例2:NodePort

[20:32:42 root@k8s-master service]#cat nginx-svc-port.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: harbor.zhangzhuo.org/images/nginx:latest
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: ng-deploy-80
spec:
  ports:
  - name: http
    port: 80     #server监听端口
    targetPort: 80  #目标pod端口
    nodePort: 30015  #宿主机监听端口
    protocol: TCP
  type: NodePort
  selector:
    app: ng-deploy-80
[20:32:03 root@k8s-master service]#kubectl apply -f nginx-svc-port.yaml -n zhangzhuo 
deployment.apps/nginx-deployment created
service/ng-deploy-80 created
#查看
[20:33:57 root@k8s-master service]#kubectl get svc -n zhangzhuo 
NAME           TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
ng-deploy-80   NodePort   10.200.50.72   <none>        80:30015/TCP   115s
[20:34:43 root@k8s-master service]#kubectl get ep -n zhangzhuo 
NAME           ENDPOINTS                       AGE
ng-deploy-80   10.100.2.34:80,10.100.2.35:80   2m6s
[20:43:54 root@k8s-master service]#ss -ntl | grep 30015
LISTEN   0         20480                0.0.0.0:30015            0.0.0.0:*    
#宿主机测试访问
[20:33:53 root@k8s-master service]#curl 127.0.0.1:30015 -I
HTTP/1.1 200 OK

service的type

#type的类型有四种
[19:57:14 root@k8s-master ~]#kubectl explain service.spec.type  查看命令
#使用最多的俩个
ClusterIP    #用于k8s内部使用,不对外开放
NodePort     #用于提共外部访问,会在每台k8s集群的主机打开一个端口

#portocol的类型有三种TCP,UDP,SCTP默认为TCP
[20:10:03 root@k8s-master ~]#kubectl explain service.spec.ports.protocol

不同的命名空间的service通信

#正常情况下不通的命名空间是相互隔离的,但是可以通过域名全称进行访问
#在default命名空间再次创建一个service
[20:34:48 root@k8s-master service]#kubectl apply -f nginx-svc-clu.yaml -n default 
deployment.apps/nginx-deployment created
service/ng-deploy-80 created
#进入pod测试
[20:39:08 root@k8s-master service]#kubectl exec -it nginx-deployment-959555b6b-2wsnn -n default bash
root@nginx-deployment-959555b6b-2wsnn:/# curl ng-deploy-80.zhangzhuo.svc.zhangzhuo.org -I
HTTP/1.1 200 OK

#说明
ng-deploy-80.zhangzhuo.svc.zhangzhuo.org
service名称.命名空间名称.svc.安装k8s集群时指定的域名--service-dns-domain

3.6 Volume

官方文档:https://kubernetes.io/zh/docs/concepts/storage/volumes/

Container 中的文件在磁盘上是临时存放的,这给 Container 中运行的较重要的应用程序带来一些问题。问题之一是当容器崩溃时文件丢失。kubelet 会重新启动容器, 但容器会以干净的状态重启。 第二个问题会在同一 Pod 中运行多个容器并共享文件时出现。 Kubernetes 卷(Volume )这一抽象概念能够解决这两个问题。

常用的几种卷

  • emptyDir:本地临时卷
  • hostPath:本地卷
  • nfs等:共享卷
  • configmap: 配置文件

3.6.1 emptyDir

当 Pod 分派到某个 Node 上时,emptyDir卷会被创建,并且在 Pod 在该节点上运行期间,卷一直存在。 就像其名称表示的那样,卷最初是空的。 尽管 Pod 中的容器挂载 emptyDir卷的路径可能相同也可能不同,这些容器都可以读写 emptyDir卷中相同的文件。 当 Pod 因为某些原因被从节点上删除时,emptyDir 卷中的数据也会被永久删除。

示例:

[19:01:59 root@k8s-master volume]#cat nginx-emptyDir.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: harbor.zhangzhuo.org/images/nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:              #声明挂载点
        - mountPath: /data/cache   #pod中容器挂载点
          name: cache-volume
      volumes:                #声明volumes
        - name: cache-volume  #名称
          emptyDir: {}        #类型,emptydir类型删除容器数据也会删除
---
apiVersion: v1
kind: Service
metadata:
  name: ng-deploy-80
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30011
    protocol: TCP
  type: NodePort
  selector:
    app: ng-deploy-80
#创建
[19:01:53 root@k8s-master volume]#kubectl apply -f nginx-emptyDir.yaml -n zhangzhuo
deployment.apps/nginx-deployment created
service/ng-deploy-80 configured
#测试
#进去容器创建文件
[19:04:33 root@k8s-master volume]#kubectl exec -it -n zhangzhuo nginx-deployment-7bfb9bb456-l825v  bash
root@nginx-deployment-7bfb9bb456-l825v:/# echo "zhangzhuo" >/data/cache/zhangzhuo
#在宿主机查看创建的文件
[19:06:20 root@k8s-master volume]#kubectl describe -n zhangzhuo pod nginx-deployment-7bfb9bb456-l825v 
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  4m53s  default-scheduler  Successfully assigned zhangzhuo/nginx-deployment-7bfb9bb456-l825v to k8s-node2.zhangzhuo.org
#找到调度到的主机
[19:08:07 root@k8s-node2 ~]#cd /var/lib/kubelet/pods/
[19:09:11 root@k8s-node2 pods]#tree 
├── 895e8725-b011-4cd9-8260-8e815455a39d
│   ├── containers
│   │   └── ng-deploy-80
│   │       └── b066012a
│   ├── etc-hosts
│   ├── plugins
│   │   └── kubernetes.io~empty-dir
│   │       ├── cache-volume
│   │       │   └── ready
│   │       └── wrapped_default-token-rmdpl
│   │           └── ready
│   └── volumes
│       ├── kubernetes.io~empty-dir
│       │   └── cache-volume
│       │       └── zhangzhuo
│       └── kubernetes.io~secret
│           └── default-token-rmdpl
│               ├── ca.crt -> ..data/ca.crt
│               ├── namespace -> ..data/namespace
│               └── token -> ..data/token
[19:11:27 root@k8s-node2 pods]#cd 895e8725-b011-4cd9-8260-8e815455a39d/volumes/kubernetes.io~empty-dir/cache-volume/
[19:11:31 root@k8s-node2 cache-volume]#cat zhangzhuo 
zhangzhuo

3.6.2 hostPath

hostPath 卷将主机节点的文件系统中的文件或目录挂载到集群中, pod删除的时候,卷不会被删除

示例:

[19:14:57 root@k8s-master volume]#cat nginx-hostPath.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: harbor.zhangzhuo.org/images/nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:             #pod的容器引用
        - mountPath: /data/cache
          name: cache-volume
      volumes:
        - name: cache-volume
          hostPath:                #类型,hostpath类型删除容器并不会删除数据,但是数据是放在pod宿主机中
            path: /tmp/zhangzhuo   #定义宿主机挂载目录
---
apiVersion: v1
kind: Service
metadata:
  name: ng-deploy-80
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30011
    protocol: TCP
  type: NodePort
  selector:
    app: ng-deploy-80
[19:14:08 root@k8s-master volume]#kubectl apply -f nginx-hostPath.yaml -n zhangzhuo deployment.apps/nginx-deployment created
service/ng-deploy-80 created
#测试
[19:15:49 root@k8s-master volume]#kubectl describe -n zhangzhuo pod nginx-deployment-7468d57f9c-967ns 
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  74s   default-scheduler  Successfully assigned zhangzhuo/nginx-deployment-7468d57f9c-967ns to k8s-node2.zhangzhuo.org
#在宿主机写入文件到容器查看
[19:16:53 root@k8s-node2 ~]#cd /tmp/zhangzhuo/
[19:17:04 root@k8s-node2 zhangzhuo]#echo "zhangzhuo" > zhangzhuo
root@nginx-deployment-7468d57f9c-967ns:/# cat /data/cache/zhangzhuo 
zhangzhuo

3.6.3 nfs等

nfs卷能将 NFS (网络文件系统) 挂载到你的 Pod 中。 不像 emptyDir 那样会在删除 Pod 的同时也会被删除,nfs卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 nfs卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。

单个目录示例:

#创建nfs
[19:25:53 root@harbor ~]#mkdir /tmp/zhangzhuo -p 
[19:27:33 root@harbor ~]#vim /etc/exports 
/tmp/zhangzhuo *(rw,no_root_squash)
[19:27:07 root@harbor ~]#systemctl restart nfs-server.service
#测试挂载
[19:28:26 root@harbor ~]#mount -t nfs 192.168.10.185:/tmp/zhangzhuo /mnt/
#写yaml文件
[19:32:31 root@k8s-master volume]#cat nginx-nfs.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: harbor.zhangzhuo.org/images/nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:                #pod的容器引用
        - mountPath: /data/zhangzhuo
          name: nfs-volumes
      volumes:
        - name: nfs-volumes
          nfs:                 #类型
            server: 192.168.10.185  #服务器地址
            path: /tmp/zhangzhuo    #共享目录
---
apiVersion: v1
kind: Service
metadata:
  name: ng-deploy-80
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30011
    protocol: TCP
  type: NodePort
  selector:
    app: ng-deploy-80
[19:32:29 root@k8s-master volume]#kubectl apply -f nginx-nfs.yaml -n zhangzhuo 
deployment.apps/nginx-deployment created
service/ng-deploy-80 unchanged
#测试
[19:29:36 root@harbor ~]#cd /tmp/zhangzhuo/
[19:33:47 root@harbor zhangzhuo]#echo "<h1>zhangzhuo</h1>" >index.html
#容器中查看
root@nginx-deployment-554ffdcd55-6tqjb:/# cat /data/zhangzhuo/index.html 
<h1>zhangzhuo</h1>

多个目录示例

#准备多个nfs共享目录
[19:40:42 root@harbor zhangzhuo]#mkdir /tmp/cy
[19:40:52 root@harbor zhangzhuo]#vim /etc/exports
/tmp/zhangzhuo *(rw,no_root_squash)
/tmp/cy *(rw,no_root_squash)
[19:41:49 root@harbor zhangzhuo]#systemctl restart nfs-server.service
[19:42:35 root@harbor ~]#echo "cy" >/tmp/cy/index.html
#准备yaml文件
[19:47:00 root@k8s-master volume]#cat nginx-nfs-2.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: harbor.zhangzhuo.org/images/nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /data/zhangzhuo
          name: nfs-volumes-1
        - mountPath: /data/cy    #第二个引用
          name: nfs-volumes-2
      volumes:
        - name: nfs-volumes-1
          nfs:
            server: 192.168.10.185
            path: /tmp/zhangzhuo
        - name: nfs-volumes-2      #第二个nfs写法
          nfs:
            server: 192.168.10.185
            path: /tmp/cy
---
apiVersion: v1
kind: Service
metadata:
  name: ng-deploy-80
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30011
    protocol: TCP
  type: NodePort
  selector:
    app: ng-deploy-80
[19:46:57 root@k8s-master volume]#kubectl apply -f nginx-nfs-2.yaml -n zhangzhuo
deployment.apps/nginx-deployment configured
service/ng-deploy-80 unchanged
#容器测试
root@nginx-deployment-7bc8974998-mh8x6:/# cat /data/zhangzhuo/index.html 
<h1>zhangzhuo</h1>
root@nginx-deployment-7bc8974998-mh8x6:/# cat /data/cy/index.html 
cy

3.6.4 configmap

configMap卷 提供了向 Pod 注入配置数据的方法。 ConfigMap 对象中存储的数据可以被 configMap 类型的卷引用,然后被 Pod 中运行的容器化应用使用。

示例:

#准备yaml文件
[20:31:07 root@k8s-master volume]#cat nginx-configmap.yaml 
apiVersion: v1        #创建configMap
kind: ConfigMap
metadata:
  name: nginx-config
data:            #定义nginx配置文件
  default: |
    server {
       listen  80;
       server_name www.zhangzhuo.org;
       index index.html;
       location / {
          root /data;
       }
    }
  username: user1       #定义变量
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: harbor.zhangzhuo.org/images/nginx:latest
        env:                  #pod容器中引用变量
        - name: MY_USERNAME   #容器中那个变量引用
          valueFrom:
            configMapKeyRef:
              name: nginx-config  #configmap名称
              key: username       #变量key名
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /data/zhangzhuo
          name: nfs-volumes-1
        - mountPath: /data/cy
          name: nfs-volumes-2
        - mountPath: /etc/nginx/conf.d
          name: nginx-config
      volumes:
        - name: nfs-volumes-1
          nfs:
            server: 192.168.10.185
            path: /tmp/zhangzhuo
        - name: nfs-volumes-2
          nfs:
            server: 192.168.10.185
            path: /tmp/cy
        - name: nginx-config
          configMap:
            name: nginx-config
            items:
              - key: default
                path: zhangzhuo.conf
---
apiVersion: v1
kind: Service
metadata:
  name: ng-deploy-80
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30011
    protocol: TCP
  type: NodePort
  selector:
    app: ng-deploy-80
[20:09:19 root@k8s-master volume]#kubectl apply -f nginx-configmap.yaml -n zhangzhuo 
configmap/nginx-config unchanged
deployment.apps/nginx-deployment unchanged
service/ng-deploy-80 unchanged
#测试nginx配置文件
[20:11:22 root@k8s-master volume]#echo "127.0.0.1 www.zhangzhuo.org" >>/etc/hosts
[20:11:43 root@k8s-master volume]#curl www.zhangzhuo.org:30011/zhangzhuo/
<h1>zhangzhuo</h1>
[20:12:12 root@k8s-master volume]#curl www.zhangzhuo.org:30011/cy/
<h1>cy</h1>
#容器中测试变量
root@nginx-deployment-697958847b-ps65b:/# env | grep MY  
MY_USERNAME=user1

3.7 DaemonSet

官方文档:https://kubernetes.io/zh/docs/concepts/workloads/controllers/daemonset/

DaemonSet 在当前集群中每个节点运行同一个pod,当有新的节点加入集群时也会为新的节点配置相同的pod,当节点从集群中移除时其pod也会被 kubernetes回收,但是删除DaemonSet 将删除其创建的所有的pod。

示例:

[20:56:09 root@k8s-master DaemonSet]#cat DaemonSet.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: harbor.zhangzhuo.org/fluentd_elasticsearch/fluentd:v2.5.2 
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers
[20:55:55 root@k8s-master DaemonSet]#kubectl apply -f DaemonSet.yaml 
daemonset.apps/fluentd-elasticsearch created
#查看
[20:57:04 root@k8s-master DaemonSet]#kubectl get pod -n kube-system 
NAME                                               READY   STATUS    RESTARTS   AGE
fluentd-elasticsearch-4wbhn                        1/1     Running   0          56s
fluentd-elasticsearch-tdb9b                        1/1     Running   0          56s
fluentd-elasticsearch-tggtc                        1/1     Running   0          56s

四、YAML文件及语法基础

4.1 创建业务namespace yaml文件

#创建namespace的YAML文件
[14:07:53 root@k8s-master namespace]#cat namespace-zhangzhuo.yaml 
apiVersion: v1     #API版本
kind: Namespace    #类型为namespace
metadata:          #源数据定义
  name: zhangzhuo  #namespace名称
#创建namespace并且验证
[14:09:59 root@k8s-master namespace]#kubectl apply -f namespace-zhangzhuo.yaml 
namespace/zhangzhuo created
#查看已经有的namespace
[14:10:10 root@k8s-master namespace]#kubectl get namespaces 
NAME                   STATUS   AGE
default                Active   3d3h
kube-node-lease        Active   3d3h
kube-public            Active   3d3h
kube-system            Active   3d3h
kubernetes-dashboard   Active   3d2h
zhangzhuo              Active   36s

4.2 YAML与JSON文件格式

yaml和json对比,在线yaml与json编辑器:https://www.bejson.com/validators/yaml_editor/

4.2.1 json格式

{ "人员名单":
	{ "张三": { "年龄": 18, "职业": "Linux运维工程师", "爱好": [ "看书","学习","加班"]},
	"李四": {"年龄": 20,"职业":"java开发工程师","爱好":["开源技术","微服务","分布式存储"]}}
}
#json特点
json 不能注释
json 可读性较差
json 语法很严谨
比较适用于API返回值,也可用于配置文件

4.2.2 yaml格式

人员名单:
  张三:
    年龄: 18
    职业: Linux运维工程师
    爱好:
      - 看书
      - 学习
      - 加班
  李四:
    年龄: 20
    职业: java开发工程师
    爱好:
      - 开源技术
      - 微服务
      - 分布式存储
#yaml特点
大小写敏感
使用缩进表示层级关系
缩进时不允许有Tab键,只允许使用空格
缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
使用"#"表示注释,从这个字符一直到行尾,都会被解析器忽略
比json更适用于配置文件

4.2.3 yaml文件主要特性

k8s中的yaml文件及其他场景的yaml文件,大部分都是以下类型

上下级关系
列表
键值对(也称为maps,及key:value格式的键值对数据)

4.3 Nginx业务yaml文件详解

apiVersion: apps/v1    #API版本,#查看命令kubectl explain Deployment.apiVersion
kind: Deployment  #类型,是deployment控制器,#查看命令kubectl explain Deployment
metadata:         #控制器的的元数据信息#查看命令kubectl explain  Deployment.metadata
  labels:         #自定义deployment的标签,# kubectl explain  Deployment.metadata.labels
    app: linux36-nginx-deployment-label #标签名称为app值为linux36-nginx-deployment-label,后面会用到此标签 
  name: linux36-nginx-deployment        #控制器的名称
  namespace: linux36  #控制器的namespace,不写默认是defaule
spec:          #定义deployment中容器的详细信息,kubectl explain  Deployment.spec
  replicas: 1  #创建出的pod的副本数,即多少个pod,默认值为1
  selector: #定义标签选择器
    matchLabels: #定义匹配的标签,必须要设置
      app: linux36-nginx-selector #匹配的目标标签,即pod的标签
  template: #定义模板,必须定义,模板是起到描述要创建的pod的作用
    metadata: #定义模板元数据
      labels: #定义模板label,Deployment.spec.template.metadata.labels
        app: linux36-nginx-selector #定义标签,等于Deployment.spec.selector.matchLabels
    spec: #定义pod信息
      containers:   #定义pod中容器列表,可以多个至少一个,pod不能动态增减容器
      - name: linux36-nginx-container   #容器名称
        image: harbor.magedu.net/linux36/nginx-web1:v1 #容器镜像地址
        #command: ["/apps/tomcat/bin/run_tomcat.sh"]   #容器启动执行的命令或脚本,一般不用指定
        #imagePullPolicy: IfNotPresent #本机如果存在此镜像,即直接使用本机镜像启动而不拉取镜像,默认为这个
        imagePullPolicy: Always  #拉取镜像策略,这个表示一直去拉取镜像即使本机存在
        ports:  #定义容器端口列表
        - containerPort: 80 #定义一个端口,并不起实际作用,只用来声明
          protocol: TCP #端口协议
          name: http #端口名称,并不起实际作用,只用来声明
        - containerPort: 443 #定义一个端口
          protocol: TCP #端口协议
          name: https #端口名称
        env: #配置环境变量
        - name: "password" #变量名称。必须要用引号引起来
          value: "123456" #当前变量的值
        - name: "age" #另一个变量名称
          value: "18" #另一个变量的值
        resources: #对资源的请求设置和限制设置
          limits: #资源限制设置,上限
            cpu: 2  #cpu的限制,单位为core数,可以写0.5或者500m等CPU压缩值
            memory: 2Gi #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
          requests: #资源请求的设置
            cpu: 1 #cpu请求数,容器启动的初始可用数量,可以写0.5或者500m等CPU压缩值
            memory: 512Mi #内存请求大小,容器启动的初始可用数量,用于调度pod时候使用     
---                         #不同的资源类型创建需要使用---隔离开
kind: Service #类型为service
apiVersion: v1 #service API版本, service.apiVersion
metadata: #定义service元数据,service.metadata
  labels: #自定义标签,service.metadata.labels
    app: linux36-nginx #定义service标签的内容
  name: linux36-nginx-spec #定义service的名称,此名称会被DNS解析
  namespace: linux36  #该service隶属于的namespaces名称,即把service创建到哪个namespace里面
spec: #定义service的详细信息,service.spec
  type: NodePort #service的类型,定义服务的访问方式,默认为ClusterIP, service.spec.type
  ports: #定义访问端口, service.spec.ports
  - name: http #定义一个端口名称
    port: 80 #service 80端口
    protocol: TCP #协议类型
    targetPort: 80 #目标pod的端口
    nodePort: 30001 #node节点暴露的端口
  - name: https #SSL 端口
    port: 443 #service 443端口
    protocol: TCP #端口协议
    targetPort: 443 #目标pod端口
    nodePort: 30043 #node节点暴露的SSL端口
  selector: #service的标签选择器,定义要访问的目标pod
    app: linux36-nginx #将流量路到选择的pod上,须等于Deployment.spec.selector.matchLabels

五、k8s的资源限制

当多个用户或团队共享具有固定节点数目的集群时,人们会担心有人使用超过其基于公平原则所分配到的资源量,资源配额是帮助管理员解决这一问题的工具。

资源配额,通过 ResourceQuota 对象来定义,对每个命名空间的资源消耗总量提供限制。 它可以限制命名空间中某种类型的对象的总数目上限,也可以限制命令空间中的 Pod 可以使用的计算资源的总上限。

资源配额的工作方式如下:

  • 不同的团队可以在不同的命名空间下工作,目前这是非约束性的,在未来的版本中可能会通过 ACL (Access Control List 访问控制列表) 来实现强制性约束。
  • 集群管理员可以为每个命名空间创建一个或多个 ResourceQuota 对象。
  • 当用户在命名空间下创建资源(如 Pod、Service 等)时,Kubernetes 的配额系统会跟踪集群的资源使用情况,以确保使用的资源用量不超过 ResourceQuota 中定义的硬性资源限额。
  • 如果资源创建或者更新请求违反了配额约束,那么该请求会报错(HTTP 403 FORBIDDEN), 并在消息中给出有可能违反的约束。
  • 如果命名空间下的计算资源 (如 cpumemory)的配额被启用,则用户必须为 这些资源设定请求值(request)和约束值(limit),否则配额系统将拒绝 Pod 的创建。 提示: 可使用 LimitRanger 准入控制器来为没有设置计算资源需求的 Pod 设置默认值。

5.1 ResourceQuota资源配额

官方文档:https://kubernetes.io/zh/docs/concepts/policy/resource-quotas/

ResourceQuota是对namespace中总体的资源使用进行限制

当命名空间中存在一个 ResourceQuota 对象时,对于该命名空间而言,资源配额就是开启的。

5.1.1 计算资源配额

用户可以对给定命名空间下的可被请求的计算资源总量进行限制。

配额机制所支持的资源类型:

资源名称描述
limits.cpu在同一个namespace中,处于运行状态的所有pod的CPU分配总和不能超过CPU的限制最大值
limits.memory在同一个namespace中,处于运行状态的所有pod的内存分配总和不能超过内存的限制最大值
requests.cpu在同一个namespace中,处于运行状态的单个pod的CPU最大不能超过此值
requests.mempry在同一个namespace中,处于运行状态的单个pod的内存最大不能超过此值
hugepages-size在同一个namespace中,处于运行状态的单个pod的CPU最大不能超过此值
cpu与 requests.cpu相同
memory与 requests.memory相同

示例:

[15:37:50 root@k8s-master namespace]#cat namespace.yaml 
apiVersion: v1
kind: Namespace
metadata:
  name: zhangzhuo
---
apiVersion: v1   #api版本                                                           
kind: ResourceQuota #类型
metadata:           #元数据
  name: quota-zhangzhuo       #名称
  namespace: zhangzhuo #创建在那个namespace
spec:
  hard:
    requests.cpu: "2"      #单个pod的cpu最大值
    requests.memory: 4Gi   #单个pod的内存最大值
    limits.cpu: "2"        #namespace的cpu最大值
    limits.cpu: 4Gi        #namespace的内存最大值
    requests.nvidia.com/gpu: 4  #namespace使用nvidia的gpu最大核心数
    pods: "2"             #namespace最多能创建几个pod
    services: "6"         #namespace最多能创建几个service
[15:37:29 root@k8s-master namespace]#kubectl apply -f namespace.yaml 
namespace/zhangzhuo unchanged
resourcequota/quota-zhangzhuo created
#验证查看
[15:39:42 root@k8s-master namespace]#kubectl get resourcequotas -n zhangzhuo 
NAME              AGE     REQUEST                                                                                             LIMIT
quota-zhangzhuo   2m49s   pods: 0/2, requests.cpu: 0/2, requests.memory: 0/4Gi, requests.nvidia.com/gpu: 0/4, services: 0/6   limits.cpu: 0/4Gi

5.2 Limit Range限制范围

官方文档:https://kubernetes.io/zh/docs/concepts/policy/limit-range/

默认情况下, Kubernetes 集群上的容器运行使用的计算资源没有限制。 使用资源配额,集群管理员可以以命名空间为单位,限制其资源的使用与创建。 在命名空间中,一个 Pod 或 Container 最多能够使用命名空间的资源配额所定义的 CPU 和内存用量。 有人担心,一个 Pod 或 Container 会垄断所有可用的资源。 LimitRange 是在命名空间内限制资源分配(给多个 Pod 或 Container)的策略对象。

一个 LimitRange(限制范围)对象提供的限制能够做到:

  • 在一个命名空间中实施对每个 Pod 或 Container 最小和最大的资源使用量的限制。
  • 在一个命名空间中实施对每个 PersistentVolumeClaim 能申请的最小和最大的存储空间大小的限制。
  • 在一个命名空间中实施对一种资源的申请值和限制值的比值的控制。
  • 设置一个命名空间中对计算资源的默认申请/限制值,并且自动的在运行时注入到多个 Container 中。

示例:

apiVersion: v1
kind: Namespace
metadata:
  name: zhangzhuo
---
apiVersion: v1    #api版本 
kind: LimitRange  #类型
metadata:           #元数据
  name: limitrange-zhangzhuo       #名称
  namespace: zhangzhuo #创建在那个namespace
spec:
  limits:
  - type: Container #限制资源类型
    max:
      cpu: "1"        #限制单个容器的最大CPU
      memory: "500Mi" #限制单个容器的最大内存
    min:
      cpu: "200m"     #限制单个容器的最小CPU
      memory: "128Mi" #限制单个容器的最小内存
    default:
      cpu: "400m"     #默认单个容器的CPU限制
      memory: "256Mi" #默认单个容器的内存限制
    defaultRequest: 
      cpu: "256m"     #默认单个容器的CPU创建请求
      memory: "256Mi" #默认单个容器的内存创建请求
    maxLimitRequestRatio:
      cpu: 2          #限制CPU limit/request比值最大为2
      memory: 1.5     #限制内存limit/request比值最大为1.5
  - type: Pod
    max:
      cpu: "1"        #限制单个Pod的最大CPU
      memory: "1Gi"   #限制单个POd的最大内存
  - type: PersistentVolumeClaim
    max:
      storage: 50Gi    #限制PVC最大的requests.storage
    min:
      storage: 30Gi    #限制PVC最小的requests.storage

5.3 容器中定义资源限制

[16:41:46 root@k8s-master namespace]#cat namespace-zhangzhuo.yaml 
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-deply
  name: nginx
  namespace: zhangzhuo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-deply
  template:
    metadata:
      labels:
        app: nginx-deply
    spec:
      containers:
      - name: nginx
        image: harbor.zhangzhuo.org/images/nginx:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 80
          protocol: TCP
          name: http
        - containerPort: 443
          protocol: TCP
          name: https
        env:
        - name: "password"
          value: "123456"
        - name: "age"
          value: "18"
        resources:         #资源限制
          limits:          #容器最大可使用资源
            cpu: 600m 
            memory: 500Mi
          requests:        #容器初始申请资源
            cpu: 500m
            memory: 128Mi
#注意如果设置了资源限制后容器不进行定义,会导致容器不会被创建

5.4 示例

5.4.1 ResourceQuota演示

创建资源限制验证

#创建namespace资源
[16:45:59 root@k8s-master namespace]#cat namespace-quotas.yaml 
apiVersion: v1
kind: Namespace
metadata:
  name: zhangzhuo
---
apiVersion: v1   #api版本                                                           
kind: ResourceQuota #类型
metadata:           #元数据
  name: quota-zhangzhuo       #名称
  namespace: zhangzhuo #创建在那个namespace
spec:
  hard:
    requests.cpu: "2" #单个pod的cpu最大值
    requests.memory: 4Gi #单个pod的内存最大值
    limits.cpu: "2"      #namespace的cpu最大值
    limits.memory: 4Gi      #namespace的内存最大值
    requests.nvidia.com/gpu: 4 #namespace使用nvidia的gpu最大核心数
    pods: "2"            #namespace最多能创建几个pod
    services: "6"         #namespace最多能创建几个service
[16:46:20 root@k8s-master namespace]#kubectl apply -f namespace-quotas.yaml 
namespace/zhangzhuo created
resourcequota/quota-zhangzhuo created
#验证
[16:46:40 root@k8s-master namespace]#kubectl get resourcequotas -n zhangzhuo 
NAME              AGE   REQUEST                                                                                             LIMIT
quota-zhangzhuo   43s   pods: 0/2, requests.cpu: 0/2, requests.memory: 0/4Gi, requests.nvidia.com/gpu: 0/4, services: 0/6   limits.cpu: 0/2, limits.memory: 0/4Gi

创建pod

[16:49:27 root@k8s-master namespace]#cat namespace-zhangzhuo.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-deply
  name: nginx
  namespace: zhangzhuo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-deply
  template:
    metadata:
      labels:
        app: nginx-deply
    spec:
      containers:
      - name: nginx
        image: harbor.zhangzhuo.org/images/nginx:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 80
          protocol: TCP
          name: http
        - containerPort: 443
          protocol: TCP
          name: https
        env:
        - name: "password"
          value: "123456"
        - name: "age"
          value: "18"
        resources:
          limits:
            cpu: 1 
            memory: 500Mi
          requests:
            cpu: 1
            memory: 500Mi
[16:49:42 root@k8s-master namespace]#kubectl apply -f namespace-zhangzhuo.yaml 
deployment.apps/nginx created
service/nginx-svc created
#验证
[16:49:52 root@k8s-master namespace]#kubectl get pod -n zhangzhuo 
NAME                     READY   STATUS    RESTARTS   AGE
nginx-676fb55b77-m5ld2   1/1     Running   0          16s
nginx-676fb55b77-mt7zk   1/1     Running   0          16s
[16:51:32 root@k8s-master namespace]#kubectl get resourcequotas -n zhangzhuo 
NAME              AGE   REQUEST                                                                                                  LIMIT
quota-zhangzhuo   5m    pods: 2/2, requests.cpu: 2/2, requests.memory: 1000Mi/4Gi, requests.nvidia.com/gpu: 0/4, services: 1/6   limits.cpu: 2/2, limits.memory: 1000Mi/4Gi

演示容器资源大于限制的情况

[16:52:36 root@k8s-master namespace]#cat namespace-zhangzhuo.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-deply
  name: nginx
  namespace: zhangzhuo
spec:
  replicas: 2   #这里是俩个pod副本
  selector:
    matchLabels:
      app: nginx-deply
  template:
    metadata:
      labels:
        app: nginx-deply
    spec:
      containers:
      - name: nginx
        image: harbor.zhangzhuo.org/images/nginx:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 80
          protocol: TCP
          name: http
        - containerPort: 443
          protocol: TCP
          name: https
        env:
        - name: "password"
          value: "123456"
        - name: "age"
          value: "18"
        resources:
          limits:
            cpu: 2
            memory: 500Mi
          requests:
            cpu: 1.5       #申请1.5个cpu,1.5*2=3大于上面资源限制中namespace最大CPU资源2
            memory: 500Mi
#创建,显示创建成功
[16:52:38 root@k8s-master namespace]#kubectl apply -f namespace-zhangzhuo.yaml 
deployment.apps/nginx created
service/nginx-svc created
#验证,但是只创建成功一个,另一个由于资源限制并未创建
[16:54:20 root@k8s-master namespace]#kubectl get pod -n zhangzhuo 
NAME                     READY   STATUS    RESTARTS   AGE
nginx-5bbc847b67-zjwh9   1/1     Running   0          32s
#查看信息资源限制信息
[16:54:52 root@k8s-master namespace]#kubectl get resourcequotas -n zhangzhuo 
NAME              AGE     REQUEST                                                                                                     LIMIT
quota-zhangzhuo   9m48s   pods: 1/2, requests.cpu: 1500m/2, requests.memory: 500Mi/4Gi, requests.nvidia.com/gpu: 0/4, services: 1/6   limits.cpu: 2/2, limits.memory: 500Mi/4Gi
#查看调度器信息,只创建成功一个
[16:57:03 root@k8s-master namespace]#kubectl get deployments.apps -n zhangzhuo 
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   1/2     1            1           2m45s
#查看调度器json信息,找报错信息
"message": "pods \"nginx-5bbc847b67-cr7g2\" is forbidden: exceeded quota: quota-zhangzhuo, requested: limits.cpu=2,requests.cpu=1500m, used: limits.cpu=2,requests.cpu=1500m, limited: limits.cpu=2,requests.cpu=2"

5.4.2 LimitRange演示

创建LimitRange资源限制

[17:04:05 root@k8s-master namespace]#cat namespace-limit.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: zhangzhuo
---
apiVersion: v1    #api版本 
kind: LimitRange  #类型
metadata:           #元数据
  name: limitrange-zhangzhuo       #名称
  namespace: zhangzhuo #创建在那个namespace
spec:
  limits:
  - type: Container #限制资源类型
    max:
      cpu: "1"        #限制单个容器的最大CPU
      memory: "500Mi" #限制单个容器的最大内存
    min:
      cpu: "200m"     #限制单个容器的最小CPU
      memory: "128Mi" #限制单个容器的最小内存
    default:
      cpu: "400m"     #默认单个容器的CPU限制
      memory: "256Mi" #默认单个容器的内存限制
    defaultRequest: 
      cpu: "256m"     #默认单个容器的CPU创建请求
      memory: "256Mi" #默认单个容器的内存创建请求
  - type: Pod
    max:
      cpu: "2"        #限制单个Pod的最大CPU
      memory: "4Gi"   #限制单个POd的最大内存
  - type: PersistentVolumeClaim
    max:
      storage: 50Gi    #限制PVC最大的requests.storage
    min:
      storage: 30Gi    #限制PVC最小的requests.storage
#创建
[17:04:09 root@k8s-master namespace]#kubectl apply -f namespace-limit.yaml 
namespace/zhangzhuo unchanged
limitrange/limitrange-zhangzhuo created
#验证
[17:04:31 root@k8s-master namespace]#kubectl get limitranges -n zhangzhuo 
NAME                   CREATED AT
limitrange-zhangzhuo   2021-04-29T09:04:31Z
[17:05:03 root@k8s-master namespace]#kubectl describe limitranges -n zhangzhuo 
Name:                  limitrange-zhangzhuo
Namespace:             zhangzhuo
Type                   Resource  Min    Max    Default Request  Default Limit  Max Limit/Request Ratio
----                   --------  ---    ---    ---------------  -------------  -----------------------
Container              memory    128Mi  500Mi  256Mi            256Mi          -
Container              cpu       200m   1      256m             400m           -
Pod                    cpu       -      2      -                -              -
Pod                    memory    -      4Gi    -                -              -
PersistentVolumeClaim  storage   30Gi   50Gi   -                -              -

创建pod

[17:06:39 root@k8s-master namespace]#cat namespace-zhangzhuo.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-deply
  name: nginx
  namespace: zhangzhuo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-deply
  template:
    metadata:
      labels:
        app: nginx-deply
    spec:
      containers:
      - name: nginx
        image: harbor.zhangzhuo.org/images/nginx:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 80
          protocol: TCP
          name: http
        - containerPort: 443
          protocol: TCP
          name: https
        env:
        - name: "password"
          value: "123456"
        - name: "age"
          value: "18"
        resources:
          limits:
            cpu: 1
            memory: 256Mi
          requests:
            cpu: 500m
            memory: 128Mi
#创建
[17:07:12 root@k8s-master namespace]#kubectl get pod -n zhangzhuo 
NAME                    READY   STATUS    RESTARTS   AGE
nginx-c6b4c5f95-fv9k2   1/1     Running   0          6s
nginx-c6b4c5f95-msx45   1/1     Running   0          6s

演示容器资源大于限制的情况

[17:08:33 root@k8s-master namespace]#cat namespace-zhangzhuo.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-deply
  name: nginx
  namespace: zhangzhuo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-deply
  template:
    metadata:
      labels:
        app: nginx-deply
    spec:
      containers:
      - name: nginx
        image: harbor.zhangzhuo.org/images/nginx:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 80
          protocol: TCP
          name: http
        - containerPort: 443
          protocol: TCP
          name: https
        env:
        - name: "password"
          value: "123456"
        - name: "age"
          value: "18"
        resources:
          limits:
            cpu: 3        #最大资源大于限制
            memory: 256Mi
          requests:
            cpu: 500m
            memory: 128Mi
#创建
[17:08:40 root@k8s-master namespace]#kubectl apply -f namespace-zhangzhuo.yaml 
deployment.apps/nginx created
service/nginx-svc created
#验证,一个也不会创建
[17:09:24 root@k8s-master namespace]#kubectl get pod -n zhangzhuo 
No resources found in zhangzhuo namespace.
#查看控制器json信息,寻找报错信息
[17:09:38 root@k8s-master namespace]#kubectl get deployments.apps -n zhangzhuo nginx  -o json
message": "pods \"nginx-78f7c64d79-j4q9l\" is forbidden: [maximum cpu usage per Container is 1, but limit is 3, maximum cpu usage per Pod is 2, but limit is 3]

六、RBAC多账户实现

官方文档:https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/ #使用RBAC鉴权

官方文档:https://kubernetes.io/zh/docs/reference/access-authn-authz/authorization/ #鉴权概述

RBAC是基于角色(Role)的访问控制(Role-Based Access Control),在RBAC中先权限与角色进行关联,然后把用户设置为角色的成员从而继承角色中的权限,即把权限授权给角色,而把角色管理至用户,后期新增加用户和角色进行关联即可,删除用户的权限只要从角色移除对用户的关联即可,而修改权限只要修改角色的权限即可对角色内的所有用户同时生效。

Kubernetes 使用 API 服务器对 API 请求进行鉴权。 它根据所有策略评估所有请求属性来决定允许或拒绝请求。 一个 API 请求的所有部分都必须被某些策略允许才能继续。 这意味着默认情况下拒绝权限。

Kubernetes 仅审查以下 API 请求属性:

  • 用户 - 身份验证期间提供的 user 字符串。
  • - 经过身份验证的用户所属的组名列表。
  • 额外信息 - 由身份验证层提供的任意字符串键到字符串值的映射。
  • API - 指示请求是否针对 API 资源。
  • 请求路径 - 各种非资源端点的路径,如 /api/healthz
  • API 请求动词 - API 动词 getlistcreateupdatepatchwatchproxyredirectdeletedeletecollection 用于资源请求。 要确定资源 API 端点的请求动词。
  • HTTP 请求动词 - HTTP 动词 getpostputdelete 用于非资源请求。
  • Resource - 正在访问的资源的 ID 或名称(仅限资源请求)- 对于使用 getupdatepatchdelete 动词的资源请求,你必须提供资源名称。
  • 子资源 - 正在访问的子资源(仅限资源请求)。
  • 名字空间 - 正在访问的对象的名称空间(仅适用于名字空间资源请求)。
  • API 组 - 正在访问的 API 组(仅限资源请求)。空字符串表示核心 API 组。

RBAC - 基于角色的访问控制(RBAC)是一种基于企业内个人用户的角色来管理对 计算机或网络资源的访问的方法。在此上下文中,权限是单个用户执行特定任务的能力, 例如查看、创建或修改文件。

  • 被启用之后,RBAC(基于角色的访问控制)使用 rbac.authorization.k8s.io API 组来驱动鉴权决策,从而允许管理员通过 Kubernetes API 动态配置权限策略。
  • 要启用 RBAC,请使用 --authorization-mode = RBAC 启动 API 服务器。

6.1 使用 RBAC 鉴权

API 对象

RBAC API 声明了四种 Kubernetes 对象:Role、ClusterRole、RoleBinding 和 ClusterRoleBinding。

Role 和 ClusterRole

RBAC 的 Role或 ClusterRole 中包含一组代表相关权限的规则。 这些权限是纯粹累加的(不存在拒绝某操作的规则)。

Role 总是用来在某个命名空间内设置访问权限;在你创建 Role 时,你必须指定该 Role 所属的名字空间。

与之相对,ClusterRole 则是一个集群作用域的资源。这两种资源的名字不同(Role 和 ClusterRole)是因为 Kubernetes 对象要么是名字空间作用域的,要么是集群作用域的, 不可两者兼具。

ClusterRole 有若干用法。你可以用它来:

  1. 定义对某名字空间域对象的访问权限,并将在各个名字空间内完成授权;
  2. 为名字空间作用域的对象设置访问权限,并跨所有名字空间执行授权;
  3. 为集群作用域的资源定义访问权限。

如果你希望在名字空间内定义角色,应该使用 Role; 如果你希望定义集群范围的角色,应该使用 ClusterRole。

6.1.1 Role演示

创建role角色

[20:18:26 root@k8s-master role]#cat role.yaml 
apiVersion: rbac.authorization.k8s.io/v1  #api版本
kind: Role     #类别
metadata:
  namespace: zhangzhuo  #需要指定namespace,指定那个就是对那个命名空间授权
  name: zhangzhuo-role  #名称后面角色绑定时需要使用
rules:                  #权限
- apiGroups: ["*"]    #api组
  resources: ["*"]    #授权那些资源对象,*表示namespace下所有资源对象
  verbs: ["*"]        #动作,也就是可以执行的操作
[20:25:25 root@k8s-master role]#kubectl apply -f role.yaml 
role.rbac.authorization.k8s.io/zhangzhuo-role created
[20:26:09 root@k8s-master role]#kubectl describe role -n zhangzhuo zhangzhuo-role 
Name:         zhangzhuo-role
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  *.*        []                 []              [*]

创建用户

[20:22:13 root@k8s-master role]#cat zhangzhuo.yaml
apiVersion: v1       #api版本
kind: ServiceAccount #类别
metadata:              
  name: zhangzhuo    #账户名称
  namespace: zhangzhuo  #创建在那个命名空间需
[20:25:34 root@k8s-master role]#kubectl apply -f zhangzhuo.yaml 
serviceaccount/zhangzhuo created
[20:26:23 root@k8s-master role]#kubectl describe serviceaccounts -n zhangzhuo zhangzhuo 
Name:                zhangzhuo
Namespace:           zhangzhuo
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none>
Mountable secrets:   zhangzhuo-token-9fqkq
Tokens:              zhangzhuo-token-9fqkq
Events:              <none>

绑定角色

[20:22:14 root@k8s-master role]#cat zhangzhuo-role.yaml 
apiVersion: rbac.authorization.k8s.io/v1  #api版本
kind: RoleBinding            #类型
metadata:
  name: role-bind-zhangzhuo   #名称
  namespace: zhangzhuo        #命名空间
subjects:
- kind: ServiceAccount        #绑定的账户类型
  name: zhangzhuo             #账户名称
  namespace: zhangzhuo        #命名空间
roleRef:
  kind: Role                  #绑定的权限类型为role
  name: zhangzhuo-role        #role名称
  apiGroup: rbac.authorization.k8s.io  #api组
[20:25:38 root@k8s-master role]#kubectl apply -f zhangzhuo-role.yaml 
rolebinding.rbac.authorization.k8s.io/role-bind-zhangzhuo created
[20:26:55 root@k8s-master role]#kubectl describe rolebinding -n zhangzhuo role-bind-zhangzhuo 
Name:         role-bind-zhangzhuo
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  Role
  Name:  zhangzhuo-role
Subjects:
  Kind            Name       Namespace
  ----            ----       ---------
  ServiceAccount  zhangzhuo  zhangzhuo

获取token

[20:27:40 root@k8s-master role]#kubectl get secrets -n zhangzhuo 
NAME                    TYPE                                  DATA   AGE
default-token-f6mn4     kubernetes.io/service-account-token   3      63m
zhangzhuo-token-9fqkq   kubernetes.io/service-account-token   3      2m44s
[20:28:22 root@k8s-master role]#kubectl describe secrets -n zhangzhuo zhangzhuo-token-9fqkq 
Name:         zhangzhuo-token-9fqkq
Namespace:    zhangzhuo
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: zhangzhuo
              kubernetes.io/service-account.uid: 6e1fec0b-6f91-4478-8b68-72255412d6a7

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1066 bytes
namespace:  9 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6ImQ2UEpfcmlSclZLQXJDOGl0YnRPX3ItR0lkTzFSUTc4NkI0MnEzcW9fcEUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJ6aGFuZ3podW8iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlY3JldC5uYW1lIjoiemhhbmd6aHVvLXRva2VuLTlmcWtxIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6InpoYW5nemh1byIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjZlMWZlYzBiLTZmOTEtNDQ3OC04YjY4LTcyMjU1NDEyZDZhNyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDp6aGFuZ3podW86emhhbmd6aHVvIn0.o1CqnlxhDHx-BMeRL27CpD5_4JNiuqJFqupAStraRw9Ms5KMahiYC71R8vXum9UFLT6sZc2LtCOXVU7wbtSjAsEHoT7IBhzkKCUY0yydEyK5RwkxhRJB1ycqQXIK6Vc_J0rCxe-ciQbAVlHtco3ysdcx2qbEaWQaS-_ZjGC3b6pLsjImcGSVMvi_coZJqMGaBilajPW6ZBqyXX6G8HM-f27S4GtaCX7rmi3lDpFaJs0TeKffdEEJcknsPjkZifJxFAQM2fnv9UQ203kmiEPPx_vDMBHZ0IDygep0mWTbNgsodFx6X_swyOs4WNHYoHwHrr3FoAkJODlSc1vDZk45IA

七、Pod生命周期和探针

7.1 Pod的状态和探针

官方文档:https://kubernetes.io/zh/docs/concepts/workloads/pods/pod-lifecycle/ #Pod的生命周期

7.1.1 Pod状态

image-20210430104544120

第一阶段:
	Pending:
	#正在创建Pod但是Pod中的容器还没有全部被创建完成,处于此状态的Pod应该检查Pod依赖的存储是否有权限挂载、镜像是否可以下载、调度是否正常等。
	Failed
	#Pod中有容器启动失败而导致pod工作异常。
	Unknown
	#由于某种原因无法获得pod的当前状态,通常是由于与pod所在的node节点通信错误。
	Succeeded
	#Pod中的所有容器都被成功终止即pod里所有的containers均已terminated。
第二阶段:
	Unschedulable:
	#Pod不能被调度,kube-scheduler没有匹配到合适的node节点
	PodScheduled
	#pod正处于调度中,在kube-scheduler刚开始调度的时候,还没有将pod分配到指定的pid,在筛选出合适的节点后就会更新etcd数据,将pod分配到指定的pod
	Initialized
	#所有pod中的初始化容器已经完成了
	ImagePullBackOff:
	#Pod所在的node节点下载镜像失败
	Running
	#Pod内部的容器已经被创建并且启动。
	Ready
	#表示pod中的容器已经可以提供访问服务

image-20210430104738483

7.1.2 探针

官方文档:https://kubernetes.io/zh/docs/concepts/workloads/pods/pod-lifecycle/#%E5%AE%B9%E5%99%A8%E6%8E%A2%E9%92%88

探针简介

探针是由 kubelet 对容器执行的定期诊断,以保证Pod的状态始终处于运行状态,要执行诊断,kubelet 调用由容器实现的Handler,有三种类型的处理程序:

ExecAction
	#在容器内执行指定命令,如果命令退出时返回码为0则认为诊断成功。
TCPSocketAction
	#对指定端口上的容器的IP地址进行TCP检查,如果端口打开,则诊断被认为是成功的。
HTTPGetAction
	#对指定的端口和路径上的容器的IP地址执行HTTPGet请求,如果响应的状态码大于等于200且小于 400,则诊断被认为是成功的。

每次探测都将获得以下三种结果之一

成功:容器通过了诊断。
失败:容器未通过诊断。
未知:诊断失败,因此不会采取任何行动。

探针类型

livenessProbe
	#存活探针,检测容器容器是否正在运行,如果存活探测失败,则kubelet会杀死容器,并且容器将受到其重启策略的影响,如果容器不提供存活探针,则默认状态为 Success,livenessProbe用户控制是否重启pod。
readinessProbe
	#就绪探针,如果就绪探测失败,端点控制器将从与Pod匹配的所有Service的端点中删除该Pod的IP地址,初始延迟之前的就绪状态默认为Failure,如果容器不提供就绪探针,则默认状态为 Success,readinessProbe用于控制pod是否添加至service。

livenessProbe和readinessProbe的对比

配置参数一样
	livenessProbe #连续探测失败会重启、重建pod,readinessProbe不会执行重启或者重建Pod操作
	livenessProbe #连续检测指定次数失败后会将容器置于(Crash Loop BackOff)不可用,readinessProbe不会
	readinessProbe #连续探测失败会从service的endpointd中删除该Pod,livenessProbe不具备此功能,但是会将容器挂起livenessProbe

livenessProbe用户控制是否重启pod,readinessProbe用于控制pod是否添加至service

建议:
两个探针都配置

7.2 探针配置

官方文档:https://kubernetes.io/zh/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/

探针有很多配置字段,可以使用这些字段精确的控制存活和就绪检测的行为

initialDelaySeconds: 120
	#初始化延迟时间,告诉kubelet在执行第一次探测前应该等待多少秒,默认是0秒,最小值是0
periodSeconds: 60
	#探测周期间隔时间,指定了kubelet应该每多少秒秒执行一次存活探测,默认是 10 秒。最小值是 1
timeoutSeconds: 5
	#单次探测超时时间,探测的超时后等待多少秒,默认值是1秒,最小值是1。
successThreshold: 1
	#从失败转为成功的重试次数,探测器在失败后,被视为成功的最小连续成功数,默认值是1,存活探测的这个值必须是1,最小值是 1。
failureThreshold: 3
	#从成功转为失败的重试次数,当Pod启动了并且探测到失败,Kubernetes的重试次数,存活探测情况下的放弃就意味着重新启动容器,就绪探测情况下的放弃Pod 会被打上未就绪的标签,默认值是3,最小值是1。

HTTP 探测器可以在 httpGet 上配置额外的字段

host:
	#连接使用的主机名,默认是Pod的 IP,也可以在HTTP头中设置 “Host” 来代替。
scheme: http
	#用于设置连接主机的方式(HTTP 还是 HTTPS),默认是 HTTP。
path: /monitor/index.html
	#访问 HTTP 服务的路径。
httpHeaders:
	#请求中自定义的 HTTP 头,HTTP 头字段允许重复。
port: 80
	#访问容器的端口号或者端口名,如果数字必须在 1 ~ 65535 之间。

7.2.1 HTTP探针示例

存活探针

[11:11:01 root@k8s-master k8s]#cat apps.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: harbor.zhangzhuo.org/images/nginx:latest
        ports:
        - containerPort: 80
        livenessProbe:    #探针类型存活探针
          httpGet:        #检测方式httpGet请求
            scheme: http     #http协议,默认就是http,如果是https需要写https
            path: /index.html   #访问http路径
            port: 80            #访问端口
          initialDelaySeconds: 5  #第一次探测等待5秒
          periodSeconds: 3        #多少秒进行一次探测
          timeoutSeconds: 5       #探测超时等待多少秒
          successThreshold: 1     #从失败转为成功的次数
          failureThreshold: 3     #从成功转为失败的重试次数
---
apiVersion: v1
kind: Service
metadata:
  name: ng-deploy-80
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30012
    protocol: TCP
  type: NodePort
  selector:
    app: ng-deploy-80
#验证
[11:11:11 root@k8s-master k8s]#kubectl apply -f apps.yaml 
deployment.apps/nginx-deployment unchanged
service/ng-deploy-80 unchanged
[11:16:35 root@k8s-master k8s]#kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-77747fc7d4-dntgc   1/1     Running   0          8m18s
nginx-deployment-77747fc7d4-w6cnw   1/1     Running   0          8m18s
[11:17:07 root@k8s-master k8s]#curl 127.0.0.1:30012 -I
HTTP/1.1 200 OK
#进入其中一个容器删除index.html文件
root@nginx-deployment-77747fc7d4-dntgc:/# cd /usr/share/nginx/html
root@nginx-deployment-77747fc7d4-dntgc:/usr/share/nginx/html# ls
50x.html  index.html
root@nginx-deployment-77747fc7d4-dntgc:/usr/share/nginx/html# rm index.html 
#再次验证,会显示重建了一次pod,现在运行正常
[11:18:36 root@k8s-master k8s]#kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-77747fc7d4-dntgc   1/1     Running   1          10m
nginx-deployment-77747fc7d4-w6cnw   1/1     Running   0          10m
#修改yaml的path: /index.html为path: /zhangzhuo.html
[11:20:21 root@k8s-master k8s]#kubectl apply -f apps.yaml
#验证,俩个pod会随着时间增加一直重建,但是容器是可以一直访问的
[11:20:58 root@k8s-master k8s]#kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-768d9766b4-gb9hb   1/1     Running   2          34s
nginx-deployment-768d9766b4-gkmns   1/1     Running   2          32s

就绪探针

#就绪探针只需要把yaml文件的livenessProbe:探针类型换成readinessProbe
#修改完成yaml文件后执行
[11:30:10 root@k8s-master k8s]#kubectl apply -f apps-httpGet.yaml 
deployment.apps/nginx-deployment unchanged
service/ng-deploy-80 unchanged
#验证
[11:30:38 root@k8s-master k8s]#kubectl get pod
NAME                               READY   STATUS    RESTARTS   AGE
nginx-deployment-f96865974-6z96q   1/1     Running   0          29s
nginx-deployment-f96865974-sf6d9   1/1     Running   0          22s
[11:32:29 root@k8s-master k8s]#kubectl get endpoints 
NAME           ENDPOINTS                       AGE
kubernetes     192.168.10.181:6443             4d
ng-deploy-80   10.100.2.90:80,10.100.2.91:80   21m
#进入容器删除index.html文件
root@nginx-deployment-f96865974-sf6d9:/# cd /usr/share/nginx/html/
root@nginx-deployment-f96865974-sf6d9:/usr/share/nginx/html# rm index.html 
#再次验证,不会重建pod
[11:33:49 root@k8s-master k8s]#kubectl get pod
NAME                               READY   STATUS    RESTARTS   AGE
nginx-deployment-f96865974-6z96q   1/1     Running   0          3m40s
nginx-deployment-f96865974-sf6d9   0/1     Running   0          3m33s
[11:33:50 root@k8s-master k8s]#kubectl get endpoints 
NAME           ENDPOINTS             AGE
kubernetes     192.168.10.181:6443   4d
ng-deploy-80   10.100.2.90:80        23m
#会从service资源对象中的endpoints移除那个检测失败的pod
#其余三种探测方式配置方法也一样,就绪探针主要负责是否加入到service的endpoints当中,如果没有加入外界的访问就不会转到这个pod中,但是它不会重建容器无法自己解决问题,所以一般情况下一起使用俩种类型的探针

7.2.2 TCP探针示例

存活探针

[11:24:17 root@k8s-master k8s]#cat apps-tcp.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: harbor.zhangzhuo.org/images/nginx:latest
        ports:
        - containerPort: 80
        livenessProbe: #探针类型,存活探针
          tcpSocket:   #探测类型tcp
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 3
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
  name: ng-deploy-80
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30012
    protocol: TCP
  type: NodePort
  selector:
    app: ng-deploy-80
[11:25:51 root@k8s-master k8s]#kubectl apply -f apps-tcp.yaml 
deployment.apps/nginx-deployment unchanged
service/ng-deploy-80 unchanged
#验证
[11:25:54 root@k8s-master k8s]#kubectl apply -f apps-tcp.yaml 
deployment.apps/nginx-deployment unchanged
service/ng-deploy-80 unchanged

就绪探针

与之前配置一样只需要替换探针类型

7.2.3 ExecAction探针

可以基于指定的命令对Pod进行特定的状态检查

[11:53:45 root@k8s-master k8s]#cat apps-exec.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: redis-deploy-6379
  template:
    metadata:
      labels:
        app: redis-deploy-6379
    spec:
      containers:
      - name: redis-deploy-6379
        image: harbor.zhangzhuo.org/images/redis:6.0
        ports:
        - containerPort: 6379
        #readinessprobe:
        livenessProbe:
          exec:        #探测类型
            command:   #测试命令
            - /usr/local/bin/redis-cli #具体命令
            - quit 
          initialDelaySeconds: 5
          periodSeconds: 3
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
  name: redis-deploy-6379
spec:
  ports:
  - name: redis
    port: 6379
    targetPort: 6379
    nodePort: 30012
    protocol: TCP
  type: NodePort
  selector:
    app: redis-deploy-6379
#启动
[11:53:48 root@k8s-master k8s]#kubectl get pod
NAME                               READY   STATUS    RESTARTS   AGE
nginx-deployment-7697cdfc5-99sw8   1/1     Running   0          81s
nginx-deployment-7697cdfc5-k99l5   1/1     Running   0          81s

就绪探针跟之前一样更改探针类型

7.3 Pod重启策略

k8s在Pod出现异常的时候会自动将Pod重启以恢复Pod中的服务。

restartPolicy:
	Always:当容器异常时,k8s自动重启该容器,		ReplicationController/Replicaset/Deployment。
	OnFailure:当容器失败时(容器停止运行且退出码不为0),k8s自动重启该容器。
	Never:不论容器运行状态如何都不会重启该容器,Job或CronJob。

示例:

containers:
	- name: magedu-tomcat-app1-container
	  image: harbor.magedu.local/magedu/tomcat-app1:v1
	  #command: ["/apps/tomcat/bin/run_tomcat.sh"]
      #imagePullPolicy: IfNotPresent
      imagePullPolicy: Always
      ports:
      - containerPort: 8080
		protocol: TCP
		name: http
	  env:
      - name: "password"
		value: "123456"
      - name: "age"
		value: "18"
	  resources:
		limits:
		  cpu: 1
		  memory: "512Mi"
		requests:
		  cpu: 500m
          memory: "512Mi"
	restartPolicy: Alway

标题:k8s资源对象
作者:Carey
地址:HTTPS://zhangzhuo.ltd/articles/2021/05/17/1621241489391.html

生而为人

取消