K8s基础入门及实战
Pod 是 k8s 系统中可以创建和管理的最小单元,是资源对象模型中由用户创建或部署的最小资源对象模型,也是在 k8s 上运行容器化应用的资源对象,其他的资源对象都是用来支撑或者扩展 Pod 对象功能的,比如控制器对象是用来管控 Pod 对象的,Service 或者Ingress 资源对象是用来暴露 Pod 引用对象的,PersistentVolume 资源对象是用来为Pod提供存储等等,k8s
近期持续完善中…
Kubernetes组件
Kubernetes主要由以下几个核心组件组成:
控制平面组件(Control Plane Components)
控制平面组件会为集群做出全局决策,比如资源的调度以及检测和响应集群事件,例如当不满足部署的 replicas 字段时, 要启动新的 pod)。控制平面组件可以在集群中的任何节点上运行。 然而,为了简单起见,设置脚本通常会在同一个计算机上启动所有控制平面组件, 并且不会在此计算机上运行用户容器。
- etcd:一致且高度可用的键值存储,用作 Kubernetes 的所有集群数据的后台数据库,保存了整个集群的状态;
- kube-apiserver:API 服务器是 Kubernetes 控制平面的前端,提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制;
- kube-controller-manager:是控制平面的组件, 负责运行控制器进程。控制器包括:
- 节点控制器(Node Controller):负责在节点出现故障时进行通知和响应。
- 任务控制器(Job Controller):监测代表一次性任务的 Job 对象,然后创建 Pods 来运行这些任务直至完成。
- 端点分片控制器(EndpointSlice controller):填充端点分片(EndpointSlice)对象(以提供 Service 和 Pod 之间的链接)。
- 服务账号控制器(ServiceAccount controller):为新的命名空间创建默认的服务账号(ServiceAccount)。
- kube-scheduler:是控制平面的组件, 负责监视新创建的、未指定运行节点(node)的 Pods, 按照预定的调度策略将Pod调度到相应的机器上;
- 调度策略考虑的因素包括单个 Pod 及 Pods 集合的资源需求、软硬件及策略约束、 亲和性及反亲和性规范、数据位置、工作负载间的干扰及最后时限。
Node 组件
节点组件会在每个节点上运行,负责维护运行的 Pod 并提供 Kubernetes 运行环境。
- kubelet:会在集群中每个节点(node)上运行,负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理;
- Container Runtime:容器运行环境是负责运行容器的软件,负责镜像管理以及Pod和容器的真正运行(CRI);
- kube-proxy:负责为Service提供cluster内部的服务发现和负载均衡;
插件(Addons)
除了核心组件,还有一些推荐的Addons:
- kube-dns负责为整个集群提供DNS服务
- Ingress Controller为服务提供外网入口
- Heapster提供资源监控
- Dashboard提供GUI
- Federation提供跨可用区的集群
- Fluentd-elasticsearch提供集群日志采集、存储与查询
调度器
概述
- 一个容器平台的主要功能就是为容器分配运行时所需要的计算,存储和网络资源。容器调度系统负责选择在最合适的主机上启动容器,并且将它们关联起来。它必须能够自动的处理容器故障并且能够在更多的主机上自动启动更多的容器来应对更多的应用访问。目前三大主流的容器平台 Swarm, Mesos 和 Kubernetes 具有不同的容器调度系统。
- Swarm 的特点是直接调度 Docker 容器,并且提供和标准 Docker API 一致的API。
- Mesos 针对不同的运行框架采用相对独立的调度系统,其中 Marathon 框架提供了Docker容器的原生支持。
- Kubernetes 则采用了 Pod 和 Label 这样的概念把容器组合成一个个的互相存在依赖关系的逻辑单元。相关容器被组合成 Pod 后被共同部署和调度,形成服务(Service)。这个是 Kubernetes 和 Swarm,Mesos 的主要区别。
- 相对来说,Kubernetes 采用这样的方式简化了集群范围内相关容器被共同调度管理的复杂性。换一种角度来看,Kubernetes 采用这种方式能够相对容易的支持更强大,更复杂的容器调度算法。
k8s 调度工作方式
- Kubernetes 调度器作为集群的大脑,在如何提高集群的资源利用率、保证集群中服务的稳定运行中也会变得越来越重要
Kubernetes 的资源分为两种属性
- 可压缩资源(例如 CPU 循环,Disk I/O 带宽)都是可以被限制和被回收的,对于一个Pod 来说可以降低这些资源的使用量而不去杀掉 Pod。
- 不可压缩资源(例如内存、硬盘空间)一般来说不杀掉 Pod 就没法回收。未来Kubernetes 会加入更多资源,如网络带宽,存储 IOPS 的支持。
- k8s 调度器
- (1)kube-scheduler 是 kubernetes 系统的核心组件之一,主要负责整个集群资源的调度功能,根据特定的调度算法和策略,将 Pod 调度到最优的工作节点上面去,从而更加合理、更加充分的利用集群的资源,这也是选择使用 kubernetes 一个非常重要的理由。如果一门新的技术不能帮助企业节约成本、提供效率,我相信是很难推进的。
- (2)调度流程:默认情况下,kube-scheduler 提供的默认调度器能够满足我们绝大多数的要求,之前接触的示例也基本上用的默认的策略,都可以保证我们的 Pod 可以被分配到资源充足的节点上运行。但是在实际的线上项目中,可能我们自己会比 kubernetes 更加了解我们自己的应用,比如我们希望一个 Pod 只能运行在特定的几个节点上,或者这几个节点只能用来运行特定类型的应用,这就需要我们的调度器能够可控。
- kube-scheduler 是 kubernetes 的调度器,它的主要作用就是根据特定的调度算法和调度策略将 Pod 调度到合适的 Node 节点上去,是一个独立的二进制程序,启动之后会一直监听 API Server,获取到 PodSpec.NodeName 为空的 Pod,对每个 Pod 都会创建一个binding。
调度主要分为以下几个部分:
- 首先是预选过程,过滤掉不满足条件的节点,这个过程称为 Predicates
- 然后是优选过程,对通过的节点按照优先级排序,称之为 Priorities
- 最后从中选择优先级最高的节点,如果中间任何一步骤有错误,就直接返回错误Predicates 阶段首先遍历全部节点,过滤掉不满足条件的节点,属于强制性规则,这一阶段输出的所有满足要求的 Node 将被记录并作为第二阶段的输入,如果所有的节点都不满足条件,那么 Pod 将会一直处于 Pending 状态,直到有节点满足条件,在这期间调度器会不断的重试。
- 所以我们在部署应用的时候,如果发现有 Pod 一直处于 Pending 状态,那么就是没有满足调度条件的节点,这个时候可以去检查下节点资源是否可用。
- Priorities 阶段即再次对节点进行筛选,如果有多个节点都满足条件的话,那么系统会按照节点的优先级(priorites)大小对节点进行排序,最后选择优先级最高的节点来部署Pod应用。
工作负载
Namespace
Namespace 概述
- Namespace 在很多情况下用于实现多用户的资源隔离,通过将集群内部的资源对象分配到不同的 Namespace 中, 形成逻辑上的分组,便于不同的分组在共享使用整个集群的资源同时还能被分别管理。Kubernetes 集群在启动后,会创建一个名为"default"的Namespace,如果不特别指明 Namespace,则用户创建的 Pod,RC,Service 都将 被系统创建到这个默认的名为 default 的 Namespace 中。
Namespace 查看
kubectl get ns
Pod
Pod 概述
- Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元,是资源对象模型中由用户创建或部署的最小资源对象模型,也是在 k8s 上运行容器化应用的资源对象。
- k8s中其他的资源对象都是用来支撑或者扩展 Pod 对象功能的。比如控制器对象是用来管控 Pod 对象的,Service 或者Ingress 资源对象是用来暴露 Pod 引用对象的,PersistentVolume 资源对象是用来为Pod提供存储等等,k8s 不会直接处理容器而是 Pod,Pod 是由一个或多个container 组成。
- Pod 是 Kubernetes 的最重要概念,每一个 Pod 都有一个特殊的被称为 ”根容器“ 的Pause容器。Pause 容器对应的镜像属于 Kubernetes 平台的一部分,除了Pause 容器,每个Pod还包含一个或多个紧密相关的用户业务容器。Pod 通常不是直接创建的,而是使用工作负载资源创建的。
- 下面是一些管理一个或者多个 Pod 的工作负载资源的示例:
- Deployment:管理集群上的多副本应用。
- StatefulSet:管理某 Pod 集合的部署和扩缩,并为这些 Pod 提供持久存储和持久标识符。
- DaemonSet:确保 Pod 的副本在集群中的一组节点上运行。
- 下面是一些管理一个或者多个 Pod 的工作负载资源的示例:
- 除了应用容器,Pod 还可以包含在 Pod 启动期间运行的 Init 容器。 你也可以在集群支持临时性容器的情况下, 为调试的目的注入临时性容器。
Pod 的分类
普通 Pod
- 普通 Pod 一旦被创建,就会被放入到 etcd 中存储,随后会被 Kubernetes Master 调度到某个具体的 Node 上并进行绑定,随后该 Pod 对应的 Node 上的 kubelet 进程实例化成一组相关的 Docker 容器并启动起来。在默认情况下,当 Pod 里某个容器停止时,Kubernetes 会自动检测到这个问题并且重新启动这个 Pod 里某所有容器, 如果 Pod 所在的Node 宕机,则会将这个 Node 上的所有 Pod 重新调度到其它节点上。
静态 Pod
- 静态 Pod 是由 kubelet 进行管理的仅存在于特定 Node 上的 Pod,它们不能通过API Server进行管理,无法与 ReplicationController、Deployment 或 DaemonSet 进行关联,并且kubelet 也无法对它们进行健康检查。
Pod 中的存储
- 一个 Pod 可以设置一组共享的存储卷。 Pod 中的所有容器都可以访问该共享卷,从而允许这些容器共享数据。 卷还允许 Pod 中的持久数据保留下来,即使其中的容器需要重新启动。
Pod 联网
- 每个 Pod 都在每个地址族中获得一个唯一的 IP 地址。 Pod 中的每个容器共享网络名字空间,包括 IP 地址和网络端口。 Pod 内的容器可以使用 localhost 互相通信。 当 Pod 中的容器与 Pod 之外的实体通信时,它们必须协调如何使用共享的网络资源(例如端口)。
- 在同一个 Pod 内,所有容器共享一个 IP 地址和端口空间,并且可以通过 localhost 发现对方。 他们也能通过如 SystemV 信号量或 POSIX 共享内存这类标准的进程间通信方式互相通信。 不同 Pod 中的容器的 IP 地址互不相同,如果没有特殊配置,就无法通过 OS 级 IPC 进行通信。 如果某容器希望与运行于其他 Pod 中的容器通信,可以通过 IP 联网的方式实现。
- Pod 中的容器所看到的系统主机名与为 Pod 配置的 name 属性值相同。
Pod 生命周期
Pod 也被认为是相对临时性(而不是长期存在)的实体。 Pod 会被创建、赋予一个唯一的 ID(UID), 并被调度到节点,并在终止(根据重启策略)或删除之前一直运行在该节点。
- Pod 自身不具有自愈能力。如果 Pod 被调度到某节点而该节点之后失效, Pod 会被删除;
Pod 阶段
取值 | 描述 |
---|---|
Pending(悬决) | Pod 已被 Kubernetes 系统接受,但有一个或者多个容器尚未创建亦未运行。此阶段包括等待 Pod 被调度的时间和通过网络下载镜像的时间。 |
Running(运行中) | Pod 已经绑定到了某个节点,Pod 中所有的容器都已被创建。至少有一个容器仍在运行,或者正处于启动或重启状态。 |
Succeeded(成功) | Pod 中的所有容器都已成功终止,并且不会再重启。 |
Failed(失败) | Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非 0 状态退出或者被系统终止。 |
Unknown(未知) | 因为某些原因无法取得 Pod 的状态。这种情况通常是因为与 Pod 所在主机通信失败。 |
容器重启策略
- Pod 的 spec 中包含一个 restartPolicy 字段,其可能取值包括 Always、OnFailure 和 Never。默认值是 Always。
工作负载资源
Deployments
ReplicaSet
StatefulSet
DaemonSet
Job
已完成 Job 的自动清理
CronJob
ReplicationController
Label
Label 概述
- Label 是 Kubernetes 系统中另一个核心概念。一个 Label 是一个 key=value 的键值对,其中 key 与 value 由用户自己指 定。Label 可以附加到各种资源对象上,如Node、Pod、Service、RC,一个资源对象可以定义任意数量的 Label, 同一个 Label 也可以被添加到任意数量的资源对象上,Label 通常在资源对象定义时确定,也可以在对象创建后动态添加或删除。
- Label 的最常见的用法是使用 metadata.labels 字段,来为对象添加Label,通过spec.selector 来引用对象
- Label 附加到 Kubernetes 集群中各种资源对象上,目的就是对这些资源对象进行分组管理,而分组管理的核心就 是 Label Selector。Label 与 Label Selector 都是不能单独定义,必须附加在一些资源对象的定义文件上,一般附加 在 RC 和 Service 的资源定义文件中。
服务、负载均衡和联网
Kubernetes 网络模型
- 集群中每一个 Pod 都会获得自己的、 独一无二的 IP 地址, 这就意味着你不需要显式地在 Pod 之间创建链接,你几乎不需要处理容器端口到主机端口之间的映射。 这将形成一个干净的、向后兼容的模型;在这个模型里,从端口分配、命名、服务发现、 负载均衡、 应用配置和迁移的角度来看,Pod 可以被视作虚拟机或者物理主机。
- Kubernetes 强制要求所有网络设施都满足以下基本要求(从而排除了有意隔离网络的策略):
- Pod 能够与所有其他节点上的 Pod 通信, 且不需要网络地址转译(NAT)
- 节点上的代理(比如:系统守护进程、kubelet)可以和节点上的所有 Pod 通信
- Kubernetes 网络解决四方面的问题:
- 一个 Pod 中的容器之间通过本地回路(loopback)通信。
- 集群网络在不同 Pod 之间提供通信。
- Service API 允许你向外暴露 Pod 中运行的应用, 以支持来自于集群外部的访问。
- Ingress 提供专门用于暴露 HTTP 应用程序、网站和 API 的额外功能。
- 你也可以使用 Service 来发布仅供集群内部使用的服务。
服务(Service)
将运行在一组 Pods 上的应用程序公开为网络服务的抽象方法。
- Kubernetes 为 Pod 提供自己的 IP 地址,并为一组 Pod 提供相同的 DNS 名, 并且可以在它们之间进行负载均衡。
定义 Service
- 假定有一组 Pod,它们对外暴露了 9376 端口,同时还被打上 app.kubernetes.io/name=MyApp 标签:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app.kubernetes.io/name: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
- 上述配置创建一个名称为 “my-service” 的 Service 对象,它会将请求代理到使用 TCP 端口 9376,并且具有标签
app.kubernetes.io/name=MyApp
的 Pod 上。 - Kubernetes 为该服务分配一个 IP 地址(有时称为 “集群 IP”),该 IP 地址由服务代理使用。
多端口 Service
- Kubernetes 允许在 Service 对象上配置多个端口定义。 为服务使用多个端口时,必须提供所有端口名称,以使它们无歧义。
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app.kubernetes.io/name: MyApp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9376
- name: https
protocol: TCP
port: 443
targetPort: 9377
无头服务(Headless Services)
- 有时不需要或不想要负载均衡,以及单独的 Service IP。 遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP)的值为 “None” 来创建 Headless Service。
- 对于无头 Services 并不会分配 Cluster IP,kube-proxy 不会处理它们, 而且平台也不会为它们进行负载均衡和路由。 DNS 如何实现自动配置,依赖于 Service 是否定义了选择算符。
发布服务(服务类型)
- 对一些应用的某些部分(如前端),可能希望将其暴露给 Kubernetes 集群外部的 IP 地址。
- Kubernetes ServiceTypes 允许指定你所需要的 Service 类型。
Type 的取值以及行为如下:
- ClusterIP:通过集群的内部 IP 暴露服务,选择该值时服务只能够在集群内部访问。 这也是你没有为服务显式指定 type 时使用的默认值。
- NodePort:通过每个节点上的 IP 和静态端口(NodePort)暴露服务。 为了让节点端口可用,Kubernetes 设置了集群 IP 地址,这等同于你请求 type: ClusterIP 的服务。
- 如果你将 type 字段设置为 NodePort,则 Kubernetes 控制平面将在 --service-node-port-range 标志指定的范围内分配端口(默认值:30000-32767)。 每个节点将那个端口(每个节点上的相同端口号)代理到你的服务中。
- LoadBalancer:使用云提供商的负载均衡器向外部暴露服务。 外部负载均衡器可以将流量路由到自动创建的 NodePort 服务和 ClusterIP 服务上。
- 在使用支持外部负载均衡器的云提供商的服务时,设置 type 的值为 “LoadBalancer”, 将为 Service 提供负载均衡器。 负载均衡器是异步创建的,关于被提供的负载均衡器的信息将会通过 Service 的 status.loadBalancer 字段发布出去。
- 来自外部负载均衡器的流量将直接重定向到后端 Pod 上,不过实际它们是如何工作的,这要依赖于云提供商。
- ExternalName:通过返回 CNAME 记录和对应值,可以将服务映射到 externalName 字段的内容(例如,foo.bar.example.com)。 无需创建任何类型代理。
你也可以使用 Ingress 来暴露自己的服务。 Ingress 不是一种服务类型,但它充当集群的入口点。 它可以将路由规则整合到一个资源中,因为它可以在同一 IP 地址下公开多个服务。
Ingress
- Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。
- Ingress 公开从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源上定义的规则控制。
- 下面是一个将所有流量都发送到同一 Service 的简单 Ingress 示例:
- Ingress 可为 Service 提供外部可访问的 URL、负载均衡流量、终止 SSL/TLS,以及基于名称的虚拟托管。 Ingress 控制器 通常负责通过负载均衡器来实现 Ingress,尽管它也可以配置边缘路由器或其他前端来帮助处理流量。
必须拥有一个
Ingress 控制器
才能满足 Ingress 的要求。 仅创建 Ingress 资源本身没有任何效果。
Ingress 类型
由单个 Service 来完成的 Ingress
- 现有的 Kubernetes 概念允许你暴露单个 Service。 你也可以通过指定无规则的默认后端来对 Ingress 进行此操作。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
spec:
defaultBackend:
service:
name: test
port:
number: 80
简单扇出
- 一个扇出(fanout)配置根据请求的 HTTP URI 将来自同一 IP 地址的流量路由到多个 Service。 Ingress 允许你将负载均衡器的数量降至最低。例如,这样的设置:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: simple-fanout-example
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
pathType: Prefix
backend:
service:
name: service1
port:
number: 4200
- path: /bar
pathType: Prefix
backend:
service:
name: service2
port:
number: 8080
基于名称的虚拟托管
- 基于名称的虚拟主机支持将针对多个主机名的 HTTP 流量路由到同一 IP 地址上。
- Ingress 让后台负载均衡器基于 host 头部字段来路由请求。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service1
port:
number: 80
- host: bar.foo.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
TLS
负载均衡
Ingress 控制器
为了让 Ingress 资源工作,集群必须有一个正在运行的 Ingress 控制器。
- Kubernetes 作为一个项目,目前支持和维护 AWS、 GCE 和 Nginx Ingress 控制器。
存储
Container 中的文件在磁盘上是临时存放的,这给 Container 中运行的较重要的应用程序带来一些问题。 问题之一是当容器崩溃时文件丢失。 kubelet 会重新启动容器,但容器会以干净的状态重启。 第二个问题会在同一 Pod 中运行多个容器并共享文件时出现。
Volume
Volume 概述
- Volume 是 Pod 中能够被多个容器访问的共享目录。Kubernetes 的 Volume 定义在Pod 上,它被一个 Pod 中的多个容器挂载到具体的文件目录下。
- Volume 与 Pod 的生命周期相同,但与容器的生命周期不相关,当容器终止或重启时,Volume 中的数据也不会丢失。要使用volume,pod 需要指定 volume 的类型和内容( 字段),和映射到容器的位置(字段)。
- 使用卷时, 在 .spec.volumes 字段中设置为 Pod 提供的卷,并在 .spec.containers[*].volumeMounts 字段中声明卷在容器中的挂载位置。
- Kubernetes 支持多种类型的 Volume,包括:
emptyDir
、hostPath
、configMap
、nfs
、iscsi
、rbd
、cephfs
、secret
、persistentVolumeClaim
、downwardAPI
等。- configMap: configMap 卷提供了向 Pod 注入配置数据的方法。 ConfigMap 对象中存储的数据可以被 configMap 类型的卷引用,然后被 Pod 中运行的容器化应用使用。
- emptyDir: emptyDir卷创建于 pod 被调度到某个宿主机上的时候,而同一个 pod 内的容器都能读写EmptyDir 中的同一个文件。一旦这个 pod 离开了这个宿主机,EmptyDir 中的数据就会被永久删除。所以目前 EmptyDir 类型的 volume 主要用作临时空间,比如 Web 服务器写日志或者tmp 文件需要的临时目录。
- hostPath:hostPath 卷能将主机节点文件系统上的文件或目录挂载到你的 Pod 中,使得对应的容器能够访问当前宿主机上的指定目录。例如,需要运行一个访问 Docker 系统目录的容器,那么就使用/var/lib/docker 目录作为一个HostDir 类型的 volume;一旦这个 pod 离开了这个宿主机,HostDir 中的数据虽然不会被永久删除,但数据也不会随 pod 迁移到其他宿主机上。
- nfs:nfs 卷能将 NFS (网络文件系统) 挂载到你的 Pod 中。 不像 emptyDir 那样会在删除 Pod 的同时也会被删除,nfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 nfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。
- persistentVolumeClaim:persistentVolumeClaim 卷用来将持久卷(PersistentVolume)挂载到 Pod 中。 持久卷申领(PersistentVolumeClaim)是用户在不知道特定云环境细节的情况下“申领”持久存储的一种方法。
- secret:secret 卷用来给 Pod 传递敏感信息,例如密码。你可以将 Secret 存储在 Kubernetes API 服务器上,然后以文件的形式挂载到 Pod 中,无需直接与 Kubernetes 耦合。 secret 卷由 tmpfs(基于 RAM 的文件系统)提供存储,因此它们永远不会被写入非易失性(持久化的)存储器。
PVC 和 PV
管理存储是管理计算的一个明显问题。PersistentVolume 子系统为用户和管理员提供了一个 API,用于抽象如何根据消费方式提供存储的详细信息。两个新的API 资源:
PersistentVolume
和PersistentVolumeClaim
。
- PersistentVolume(PV) 是集群中的一块存储,可以由管理员事先制备, 或者使用 存储类(Storage Class) 来动态制备。 它是集群中的资源,就像节点是集群资源一样。 PV 是容量插件,如 Volumes,但其生命周期独立于使用PV 的任何单个 pod。 PV 持久卷和普通的 Volume 一样, 也是使用卷插件来实现的,只是它们拥有独立于任何使用 PV 的 Pod 的生命周期。
- PersistentVolumeClaim(PVC) 是由用户进行存储的请求。 它类似于pod。Pod 消耗节点资源,PVC 消耗 PV 资源。Pod 可以请求特定级别的资源(CPU 和内存)。PVC 申领可以请求特定的大小和访问模式(例如,可以一次读/写或多次只读)。
- 虽然 PersistentVolumeClaims 允许用户使用抽象存储资源,但是 PersistentVolumes 对于不同的问题,用户通常需要具有不同属性(例如性能)。群集管理员需要能够提供各种PersistentVolumes 不同的方式,而不仅仅是大小和访问模式,而不会让用户了解这些卷的实现方式。对于这些需求,有 StorageClass 资源。
- StorageClass 为管理员提供了一种描述他们提供的存储的“类”的方法。不同的类可能映射到服务质量级别,或备份策略,或者由群集管理员确定的任意策略。Kubernetes 本身对于什么类别代表是不言而喻的。 这个概念有时在其他存储系统中称为“配置文件”。PVC 和 PV 是一一对应的。
配置
configMap
- ConfigMap 是一种 API 对象,用来将非机密性的数据保存到键值对中。使用时, Pods 可以将其用作环境变量、命令行参数或者存储卷中的配置文件。
- ConfigMap 功能在 Kubernetes1.2 版本中引入,许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。
- ConfigMap API给我们提供了向容器中注入配置信息的机制,ConfigMap 可以被用来保存单个属性,也 可以用来保存整个配置文件或者JSON 二进制大对象。
Secret
Secret 解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者 Pod Spec 中。Secret 可以以 Volume 或者环境变量的方式使用。
- Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象。 这样的信息可能会被放在 Pod 规约中或者镜像中。 使用 Secret 意味着你不需要在应用程序代码中包含机密数据。
Pod 可以用三种方式之一来使用 Secret:
- 作为挂载到一个或多个容器上的卷 中的文件。
- 作为容器的环境变量。
- 由 kubelet 在为 Pod 拉取镜像时使用。
Secret 有三种类型
- Service Account :用来访问 Kubernetes API,由 Kubernetes 自动创建,并且会自动挂载到 Pod 的
/run/secrets/kubernetes.io/serviceaccount
目录中。 - Opaque : base64 编码格式的 Secret,用来存储密码、密钥等。
- kubernetes.io/dockerconfigjson :用来存储私有 docker registry 的认证信息。
安全
集群安全机制 RBAC
基本概念
- RBAC(Role-Based Access Control,基于角色的访问控制)在 k8s v1.5 中引入,在v1.6 版本时升级为 Beta 版本,并成为 kubeadm 安装方式下的默认选项,相对于其他访问控制方式,新的 RBAC 具有如下优势:
- (1)对集群中的资源和非资源权限均有完整的覆盖
- (2)整个 RBAC 完全由几个 API 对象完成,同其他 API 对象一样,可以用kubectl 或API进行操作
- (3)可以在运行时进行调整,无需重启 API Server
- 要使用 RBAC 授权模式,需要在 API Server 的启动参数中加上–authorization-mode=RBAC
监控、日志和调试
探针
探针类型
- K8s 中存在两种类型的探针:
liveness probe
和readiness probe
。
liveness probe(存活探针)
- 用于判断容器是否存活,即 Pod 是否为 running 状态,如果 LivenessProbe 探针探测到容器不健康,则 kubelet 将 kill 掉容器,并根据容器的重启策略是否重启。如果一个容器不包含 LivenessProbe 探针,则 Kubelet 认为容器的 LivenessProbe 探针的返回值永远成功。有时应用程序可能因为某些原因(后端服务故障等)导致暂时无法对外提供服务,但应用软件没有终止,导致 K8S 无法隔离有故障的 pod,调用者可能会访问到有故障的pod,导致业务不稳定。K8S 提供 livenessProbe 来检测应用程序是否正常运行,并且对相应状况进行相应的补救措施。
readiness probe(就绪探针)
- 用于判断容器是否启动完成,即容器的 Ready 是否为 True,可以接收请求,如果ReadinessProbe 探测失败,则容器的 Ready 将为 False,控制器将此Pod 的Endpoint 从对应的 service 的 Endpoint 列表中移除,从此不再将任何请求调度此Pod 上,直到下次探测成功。通过使用 Readiness 探针,Kubernetes 能够等待应用程序完全启动,然后才允许服务将流量发送到新副本。
- 比如使用 tomcat 的应用程序来说,并不是简单地说 tomcat 启动成功就可以对外提供服务的,还需要等待 spring 容器初始化,数据库连接没连上等等。对于spring boot 应用,默认的 actuator 带有/health 接口,可以用来进行启动成功的判断。
每类探针都支持三种探测方法:
- (1)exec:通过执行命令来检查服务是否正常,针对复杂检测或无HTTP 接口的服务,命令返回值为 0 则表示容器健康。
- (2)httpGet:通过发送 http 请求检查服务是否正常,返回 200-399 状态码则表明容器健康。
- (3)tcpSocket:通过容器的 IP 和 Port 执行 TCP 检查,如果能够建立TCP 连接,则表明容器健康。
探针探测的结果
- (1)Success:Container 通过了检查。
- (2)Failure:Container 未通过检查。
- (3)Unknown:未能执行检查,因此不采取任何措施。
Pod 重启策略:
- (1)Always: 总是重启
- (2)OnFailure: 如果失败就重启
- (3)Never: 永远不重启
Kubectl
kubectl 是 Kubernetes 集群的命令行工具,通过 kubectl 能够对集群本身进行管理,并能够在集群上进行容器化应用的安装部署。
查看各个组件的简写
kubectl api-resources
查看所有node
kubectl get nodes
查看所有pod
kubectl get pods
kubectl create 生成yaml
kubectl create deployment web --image=nginx -o yaml --dry-run > nginx.yaml
kubectl get 导出yaml
kubectl get deploy nginx -o=yaml --export > nginx.yaml
创建新的deployment
kubectl create -f nginx.yaml
创建一个service
kubectl create service nodeport nginx --tcp 80:80
另一种方式创建service
kubectl expose deployment nginx --type=NodePort
查看某一个service的详情
kubectl describe services/nginx
查看所有service
kubectl get svc
删除pod和svc
kubectl delete deployments/nginx services/nginx
在master节点上查看slave node的ip
kubectl get nodes -o wide
在master节点上,查看所有pods
kubectl get pods -o wide
实现 Pod 的动态缩放功能
kubectl scale rc nginx --replicas=5
containerd
查看版本
ctr -v
查看已经存在的images
crictl images list
重启containerd服务
systemctl restart containerd
crictl 去 pull 镜像
crictl pull harbor.kingsd.top/ksd/ubuntu:16.04
你知道的越多,你不知道的越多。
更多推荐
所有评论(0)