集群资源分布:

主要分为三种

  • 名称级别分布
    只在此名称级别下生效。例如k8s本身的系统组件是放在它本身的kube-system下的,因此我们在执行kubectl get pod -n default指令时就看不见系统本身的组件。
  • 集群级别
    不管在什么名称空间下,我在全局查询的过程中都可以看到,也就是说我们在定义的时候不指定集群,给他赋予一个全局访问的权限。
  • 元数据型
    给我们提供一个指标,通过指标进行操作

k8s中所有的内容都被抽象为资源,资源实例化以后,叫做对象

k8s中有哪些资源

名称空间级别:

  • 工作负载型资源(workload):Pod(特点共享网络栈和数据卷)、ReplicaSet(RS是调度器,通过标签的选择,控制pod运行的副本数)、Deployment(通过对rs的创建对运行副本数进行控制)、StatefulSet(主要是为了有状态服务建立的控制器)、DaemonSet(在每个节点都运行一个pod组件)、Job、CronJob(ReplicationController在v1.11版本被废弃)
  • 服务发现及负载均衡型资源(ServiceDiscoveryLoadBalance):Service、Ingress、…
  • 配置与存储型资源:Volume(存储卷)、CSI(容器存储接口,可以扩展各种各样的第三方存储卷)
  • 特殊类型的存储卷:ConfigMap(当配置中心来使用的资源类型)、Secret(保存敏感数据)、DownwardAPI(把外部环境中的信息输出给容器)

集群级资源:

  • Namespace、Node、Role、ClusterRole、RoleBinding、ClusterRoleBinding

元数据型资源:

  • HPA、PodTemplate、LimitRange

资源清单

当我们在创建一个符合我们预期期望的pod文件时,一般使用yaml格式的晚间来创建,这样的yaml文件被称为资源清单。

简单说明:

是一个可读性高,用来表达数据序列的格式。YAML 的意思其实是:仍是一种标记语言,但为了强调这种语言以数据做为中心,而不是以标记语言为重点。

基本语法:
  • 缩进时不允许使用Tab键,只允许使用空格
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • # 标识注释,从这个字符一直到行尾,都会被解释器忽略
YAML 支持的数据结构对象:
  • 键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)对象的一组键值对,使用冒号结构表示。
  • 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)一度连限次开头的行。
  • 纯量(scalars):单个的、不可再分的值对象类型:对象的一组键值对,使用冒号结构表示

当我们使用yaml文件构建pod需要使用的属性如下:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

使用资源清单构建一个pod

首先,vim pod.yaml建立一个yaml文件

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  labels:
    app: mytest
    version: v1
spec:
  containers:
  - name: test01
    image: nginx:latest
  - name: test02
    image: nginx:latest

我们创建一个pod这里面包含两个基于nginx镜像的容器,运行一下试试:kubectl apply -f pod.yaml创建成功
在这里插入图片描述
但是我们发现status出现了错误CrashLoopBackOff,那么遇见错误应该怎么解决呢

错误解决思路

当我们遇到错误的时候,我们当然可以通过百度等搜索错误原因,但是就拿我来说,我经常会出现一些错误,网上当然可以搜到结果,但是有很多解决方法都不适用于我的错误,那么怎么去培养独立查找错误原因的能力呢?

在这里我们出现了一个错误,我们要首先看pod的详细信息

kubectl describe pod test-pod(pod的名字)

我们可以看出来第二个容器卡住了
在这里插入图片描述
test01的状态良好,test02出现了错误

在这里插入图片描述
我们再来查询容器二的日志

kubectl log test-pod -c test02

在这里插入图片描述
问题根源出现了,80端口被占用,那么我们去修改一下yaml文件删除掉容器二看看可以不可以。
在这里插入图片描述
成功!

容器的生命周期

为了更好的使用和检测k8s我们需要对容器的生命周期有更深的理解
在这里插入图片描述
首先我们的kubectl向我们的api接口发送指令之后,kubeapi会通过etcd调度kubelet,再由kubelet去操作cri,CRI去完成容器的环境初始化,在初始化的过程中会先启动一个pause容器这个容器给我们提供了网络和存储卷共享的。然后去初始化多个容器,初始化完成后会启动一个或多个Main C容器,该容器启动的时候会使用一个start命令来启动,在结束的时候也能通过stop命令来结束结束,在过程中会有readness和liveness的参与,readness是用来探测就绪检测的,只有检测成功的时候,才会显示running状态,这时候就开始运行了,liveness是一个伴随running全过程的,在这个过程中,如果出现和之前的readness检测不相符的结果时,结束或重启容器,并返回error的值,(0是正常退出,非零是错误)

那么我们知道,pod主要分为两种,自主式pod和控制器管理的pod,他们的主要区别在哪里呢,体现在生命周期的区别上,自主式pod当他退出的时候,他的生命就已经结束,控制器管理的pod则不同,管理器的作用就是控制pod的具体行为和状态,他会控制pod的运行副本数量,当一个进程死掉以后会有一个新的pod补上。

刚刚我们所部属的pod实际上是一个自主式的pod,那么我们应该怎样去给他加上控制器呢?

控制器

控制器类型:
  1. ReplicationController和ReplicasSet
    ReplicationController(RC)用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的
    Pod 来替代;而如果异常多出来的容器也会自动回收;在新版本的 Kubernetes 中建议使用 ReplicaSet 来取代
    ReplicationController 。ReplicaSet 跟ReplicationController
    没有本质的不同,只是名字不一样,并且 ReplicaSet 支持集合式的 selector(通过标签进行选择)
  2. Deployment
    Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义 (declarative) 方法,用来替代以前的ReplicationController 来方便的管理应用。那么什么叫做声明式定义,与他相对的是命令式,命令式编程主要侧重于如何实现程序,就像我们刚接触编程的时候那样,我们需要把程序的实现过程按照逻辑结果一步步写下来;与之相对应的是声明式编程:他侧重于定义想要什么,然后告诉计算机/引擎,并让其自动去实现。Deployment是通过管理rs实现管理pod。
  3. DaemonSet
    DaemonSet确保全部或者一些Node 上运行一个 Pod 的副本,调度的选择可以通过标签的方式进行决定,比如在一定的node上运行一些node。当有 Node 加入集群时,也会为他们新增一个Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。
  4. StateFulSet
    为了解决有状态服务问题拥有稳定的持久化存储和稳定的网络标识,pod重新调度后还是能访问到相同的持久化的数据中,并且podname和hostname不变。另外一个特点是有序,有序进行部署,删除,扩展,收缩。
  5. Job/CronJob
    Job:适用于处理批处理任务,如果在使用job的过程中如果没有以0 的方式,就会被重新执行该程序。CornJob是在特定的时间循环创建Job。创建周期性处理任务。
  6. Horizontal Pod Autoscalling(HPA)
    应用的资源使用率通常都有高峰和低谷的时候,如何削峰填谷,提高集群的整体资源利用率,让service中的Pod个数自动调整呢?这就有赖于Horizontal Pod Autoscaling了,顾名思义,使Pod水平自动缩放。
使用ReplicaSet

我们首先来尝试使用一下ReplicaSet

vim Pod.yaml
#在文件中写入

apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
  name: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: test03
        image: doggymo/javaweb:v1
        env:
        - name: GET_HOSTS_FROM
          value: dns
        ports:
        - containerPort: 8080

#保存退出后执行:
kubectl apply -f Pod.yaml

在这里插入图片描述
我们删除多余的容器再来查看一下,我们可以发现这些pod下面是存在标签的:
在这里插入图片描述
我们发现这正符合我们之前学过的,RS可以支持集合式的sector,通过标签的方式进行处理操作。
在这里插入图片描述
当我们手动修改其中一个标签的时候,我们发现又重新生成一个标签为原标签的pod,也就更加证明RS是通过标签来监控pod副本数量的。也就是之前我们的yaml文件中matchLabels属性,就是用来监视那些是自己管辖之下的pod

使用Deployment
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

下图中哪个容器创建中的pod最后也正常生成了。
在这里插入图片描述
由此可见,其实我们的deployment是通过管理rs实现对pod的控制。
在这里插入图片描述
我们之前说过deployment控制器更方便进行扩容,如何来实现扩容呢

在这里插入图片描述
我们可以看到nginx-deployment下的pod增多了,但是rs还是之前的rs只不过容量大了而已。真的是非常方便。

我们之前发现在k8s中,每次删除一个pod时,虽然有资源管理器帮助我们构建新的pod但是IP和name却总是会改变,这在我们的访问过程中是非常不友好的,为了解决这个问题,我们需要开始学习SVC

service(SVC)

什么是SVC?

SVC定义了这样一种抽象:一个pod的逻辑分组,一种可以访问它们的策略 —— 通常称为微服务。这一组pod被service访问通常是通过sector标签来实现

Service能够提供负载均衡的能力,但是在使用上有以下限制:

  • 只提供 4 层负载均衡能力,而没有 7 层功能,但有时我们可能需要更多的匹配规则来转发请求,这点上 4 层负载均衡是不支持的
service的类型:

Service 在 K8s 中有以下四种类型

  • ClusterIP:默认类型,自动分配一个仅 Cluster 内部可以访问的虚拟 IP
  • NodePort:在 ClusterIP 基础上为 Service 在每台机器上绑定一个端口,这样就可以通过: NodePort 来访问该服务
  • LoadBalancer:在 NodePort 的基础上,借助 cloud provider 创建一个外部负载均衡器,并将请求转发到: NodePort
  • ExternalName:把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,这只有 kubernetes 1.7 或更高版本的 kube-dns 才支持

这是ClusterIP模式的图像,自动分配一个进内部访问的虚拟ip 但是只能被内部所访问,被外部是无法访问的。
在这里插入图片描述
NodePort模式一种常用的暴露svc服务的一种方式:
是把每一个node分配一个端口然后对每一个<nodeip:port>进行访问然后通过匹配svc的标签对相应的该node下的pod进行访问。
在这里插入图片描述
在nodeport的基础上,这里的前端的负载均衡器不需要自己去设置,只需要引入云供应商提供的接口即可完成。
在这里插入图片描述

客户端访问流程

这张图也就是一个我们客户端访问的流程图,首先监听我们的服务和断点是通过我们的apiserver来实现的,通过kube-proxy来监控,他通过匹配pod的信息,把它写入到iptables 的规则里面去,当客户端想访问我们的svc的时候其实访问的就是我们的iptables规则和导向后端的节点信息
在这里插入图片描述

svc实现

首先我们先来根据资源清单生成pod
在这里插入图片描述

ClusterIP实现

随后我们使用相同的方式建立一个ClusterIP

vim myweb-service.yaml
#下面是文件内容
apiVersion: v1
kind: Service
metadata:
    name: myapp
    namespace: defaultspec:  
  type: ClusterIP  
  selector:    
    app: myapp    
    release: stabel  
  ports:  
  - name: http
    port: 8080  
    targetPort: 8080

创建yaml文件
在这里插入图片描述
我们可以发现,svc已经创建成功
在这里插入图片描述
这个时候我们查询一下我们的ipvsadm,可以看到,当访问该ip是默认连接下面三个pod的ip地址
在这里插入图片描述

nodeport实现
apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  type: NodePort
  selector:
    app: myapp
    release: stabel
  ports:
  - name: http
    port: 80
    targetPort: 8080

在这里插入图片描述
这时候我们去外部网络访问:
在这里插入图片描述
成功访问到我的项目,这样就完成了k8s集群对项目的配置。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐