前言
k8s设计理念的核心就是声明式API,而声明式API是基于API资源/对象进行操作,进而实现对各种资源的管理。因此资源是k8s运行的基本单元,市面上对k8s资源的介绍很多,但对资源之间关联关系的描述屈指可数。本文以图解形式介绍k8s资源,以期望对其有整体的把握和更深的认识。
资源分类
资源数量众多,从架构分层和功能场景上大致分为三类:
1. 名称空间级别资源
2. 集群级别资源
3. 元数据型资源
其中,名称空间级别资源又分为
a. 工作负载型资源
b. 服务发现及负载均衡型资源
c. 配置与存储型资源
d. 特殊类型的存储卷
整体视图如下
资源清单(资源描述文件,一般为yaml文件)
含义
K8S中, 一般使用YAML格式的文件来创建符合我们预期的Pod, 这样的YAML文件一般称为资源清单.
必要字段
查看
在k8s集群中查看资源的命令
1. kubectl explain pod命令可以查看资源的模板
2. kubectl explain pod.apiVersion 查看详细字段
汇总如下图
关键资源图解
StatefulSet
StatefulSet 是用来管理有状态应用的工作负载 API 对象。有几个关键点与普通Deployment不一样:
1. 对外暴漏的service应是headless service,特点就是Cluster Ip:None。Headless sevice设计目标是为那些不需要k8s做负载均衡,而是把具体pod选择权交由客户端的场景而服务。在没有条件约束下,客户端直接访问headless service,则请求默认转个第一个pod(图中 POD-0),若想达到客户端选择pod的目的(如MySQL读写分离,需要客户端识别主从,并对应执行读写操作),则需要配置额外的service,为每个pod,如POD-0/POD-1/POD-2,绑定一个service供客户端使用;
2. 使用statefulset的业务一般都有存储的需求,而且同一标签(业务)的不同pod需要对应不同存储,这就需要为每一个pod创建一个存储卷,而且保证存储卷与pod标识唯一关联,这样即使pod重启、更新,由于标识没变,还是挂载同一个存储卷。VolumeClaimTemplate就是为此而设计的。
3. Pod层可以看出,每个pod都有唯一编号(podname-number),pod名+编号就是pod唯一标识,其它资源与pod交互时都以此标识来识别pod,这也是为什么service里必须指定pod唯一标识才能为pod做代理,而不仅仅是标签/pod名。升级和回滚都严格按照编号顺序执行。
4. PVC根据VolumeClaimTemplate动态创建,同时名称和对应pod绑定;
5. StorageClass可以动态创建需要的PV,(注意实际创建需要对应产品制备器(Provisioner)完成,比如使用亚马逊存储,需要部署kubernetes.io/aws-ebs),并绑定PV和PVC。
DeamonSet
DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。当有节点加入集群时, 也会为他们新增一个 Pod 。当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。
DaemonSet 的一些典型用法:
1. 在每个节点上运行集群守护进程
2. 在每个节点上运行日志收集守护进程
3. 在每个节点上运行监控守护进程
默认情况下,DaemonSet会为每个node分配一个pod。
如果你想在指定node上运行DaemonSet的pod,则可以配合节点选择器和亲和性来实现。
1. 如果指定了 .spec.template.spec.nodeSelector,DaemonSet 控制器将在能够与 Node 选择算符匹配的节点上创建 Pod;
2. 还可以指定 .spec.template.spec.affinity,之后 DaemonSet 控制器将在能够与节点亲和性匹配的节点上创建 Pod;
3. 如果都没有指定,则 DaemonSet Controller 将在所有节点上创建 Pod。
StorageClass
StorageClass 为管理员提供了描述存储 "类" 的方法。不同的类型可能会映射到不同的服务质量等级或备份策略,或是由集群管理员制定的任意策略。Kubernetes 本身并不清楚各种类代表的什么。这个类的概念在其他存储系统中有时被称为 "配置文件"。
以上是K8s官方介绍,可能看完还是有点疑惑。简单理解就是StorageClass只是一种声明,告诉k8s我要什么样的存储,同时必须指定一个制备器,来实际创建所需的PV,最后将PV和PVC关联。
说了这么多组件,他们之间关系如何呢,如下图所示
1. 工作负载资源,如Deployment,service,在资源清单中配置PVC;
2. 其中PVC可以指定所需StorageClass,而不是直接指定PV;
3. 当PVC创建/容器访问时,k8s调用StorageClass配置的制备器创建PV;
4. 制备器创建好PV后会被关联到对应的PVC。
为什么说“当PVC创建/容器访问时”,即有两种场景发生PV的制备。其实不止制备,绑定也是有这两个实机,具体取决于配置项:volumeBindingMode。
卷绑定模式
volumeBindingMode 字段控制了卷绑定和动态制备应该发生在什么时候。当未设置时,默认使用 Immediate 模式。
Immediate 模式表示一旦创建了 PersistentVolumeClaim 也就完成了卷绑定和动态制备。对于由于拓扑限制而非集群所有节点可达的存储后端,PersistentVolume 会在不知道 Pod 调度要求的情况下绑定或者制备。
集群管理员可以通过指定 WaitForFirstConsumer 模式来解决此问题。该模式将延迟 PersistentVolume 的绑定和制备,直到使用该 PersistentVolumeClaim 的 Pod 被创建。
ServiceAccount
服务帐户是一种非人类帐户,在 Kubernetes 中,它在 Kubernetes 集群中提供不同的身份。群集内外的应用程序 Pod、系统组件和实体可以使用特定服务帐户的凭据来标识为该服务帐户。此标识在各种情况下都很有用,包括向 API 服务器进行身份验证或实施基于身份的安全策略。
简单来说,ServiceAccount就是用来标识K8s内部、外部组件的身份信息,比如POD1是什么角色,有哪些接口权限,以及每个接口增删改查中哪些操作权限。
默认情况下,k8s会为每个namespace创建一个default serviceAccount 用于集群管理,而你不需要自建service account,集群就可以正常运行。除非有以下几种情况:
1. Pod 需要与 Kubernetes API 服务器通信,例如在以下情况下:
1.1 提供对机密中存储的敏感信息的只读访问权限。
1.2 授予跨命名空间访问权限,例如允许命名空间中的 Pod 示例读取、列出和监视 kube-node-lease 命名空间中的 Lease 对象。
2. Pod 需要与外部服务通信。例如,工作负载 Pod 需要商用云 API 的身份,而商业提供商允许配置合适的信任关系。
3. 使用 imagePullSecret 对私有映像注册表进行身份验证。
4. 外部服务需要与 Kubernetes API 服务器通信。例如,作为 CI/CD 管道的一部分向群集进行身份验证。
5. 在集群中使用第三方安全软件,该软件依赖于不同 Pod 的服务帐户身份将这些 Pod 分组到不同的上下文中。
由于k8s中权限控制默认使用RBAC模型,因此serviceAccount的使用离不开role,clusterRole,roleBinding,clusterRoleBinding。以ClusterRole为例,关系如下:
ConfgMap
ConfigMap 是一种 API 对象,用来将非机密性的数据保存到键值对中。使用时, Pods 可以将其用作环境变量、命令行参数或者存储卷中的配置文件。
Configmap相对简单,官网解释也清楚,下面只图解如何创建以及如何挂载(即使用)。
如何创建-创建源
1. 通过命令行方式
2. 通过yaml文件方式
如何挂载-使用
1. 作为环境变量挂载
2. 作为volume挂载
Configmap结合配置中心使用
Configmap挂载的是配置中心(etcd为例)的地址文件,具体的配置需要应用容器自己和etcd交互获取。
Secret
Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象。这样的信息可能会被放在 Pod 规约中或者镜像中。使用 Secret 意味着你不需要在应用程序代码中包含机密数据。
Secret存储
默认情况下,Kubernetes Secret 未加密地存储在 API 服务器的底层数据存储(etcd)中。任何拥有 API 访问权限的人都可以检索或修改 Secret,任何有权访问 etcd 的人也可以。此外,任何有权限在命名空间中创建 Pod 的人都可以使用该访问权限读取该命名空间中的任何 Secret;这包括间接访问,例如创建 Deployment 的能力。
安全使用secret
为了安全地使用 Secret,请至少执行以下步骤:
为 Secret 启用静态加密。
以最小特权访问 Secret 并启用或配置 RBAC 规则。
限制 Secret 对特定容器的访问。
考虑使用外部 Secret 存储驱动。
Secret的创建和挂载方式和configmap类似,但secret自身也分为多种类型,下面以创建secret为例介绍可以创建哪些secret
由图可以看出,两种方式创建的secret好像对不上?其实yaml方式创建的secret更规范,不仅创建一个可用的secret,还可以通过type区分secret使用场景和目的。而通过kubectl创建的secret侧重于使用,是从功能上划分了三类:
至于两者关系并没有严格的对应关系。
------------------------------
公众号:小金鱼的程序员老爹
欢迎交流讨论