305 阅读 2020-09-22 09:18:02 上传
以下文章来源于 认知语言学


需求来源
背景问题
第一,比如说一些可变的配置。因为我们不可能把一些可变的配置写到镜像里面,当这个配置需要变化的时候,可能需要我们重新编译一次镜像,这个肯定是不能接受的;
第二就是一些敏感信息的存储和使用。比如说应用需要使用一些密码,或者用一些 token;
第三就是我们容器要访问集群自身。比如我要访问 kube-apiserver,那么本身就有一个身份认证的问题;
第四就是容器在节点上运行之后,它的资源需求;
第五个就是容器在节点上,它们是共享内核的,那么它的一个安全管控怎么办?
最后一点我们说一下容器启动之前的一个前置条件检验。比如说,一个容器启动之前,我可能要确认一下 DNS 服务是不是好用?又或者确认一下网络是不是联通的?那么这些其实就是一些前置的校验。
Pod 的配置管理

可变配置就用 ConfigMap; 敏感信息是用 Secret; 身份认证是用 ServiceAccount 这几个独立的资源来实现的; 资源配置是用 Resources; 安全管控是用 SecurityContext; 前置校验是用 InitContainers 这几个在 spec 里面加的字段,来实现的这些配置管理。

ConfigMap
ConfigMap 介绍

ConfigMap 创建
ConfigMap 使用

第一种是环境变量。环境变量的话通过 valueFrom,然后 ConfigMapKeyRef 这个字段,下面的 name 是指定 ConfigMap 名,key 是 ConfigMap.data 里面的 key。这样的话,在 busybox 容器启动后容器中执行 env 将看到一个 SPECIAL_LEVEL_KEY 环境变量;
第二个是命令行参数。命令行参数其实是第一行的环境变量直接拿到 cmd 这个字段里面来用;
最后一个是通过 volume 挂载的方式直接挂到容器的某一个目录下面去。上面的例子是把 special-config 这个 ConfigMap 里面的内容挂到容器里面的 /etc/config 目录下,这个也是使用的一种方式。
ConfigMap 注意要点
ConfigMap 文件的大小。虽然说 ConfigMap 文件没有大小限制,但是在 ETCD 里面,数据的写入是有大小限制的,现在是限制在 1MB 以内;
第二个注意点是 pod 引入 ConfigMap 的时候,必须是相同的 Namespace 中的 ConfigMap,前面其实可以看到,ConfigMap.metadata 里面是有 namespace 字段的;
第三个是 pod 引用的 ConfigMap。假如这个 ConfigMap 不存在,那么这个 pod 是无法创建成功的,其实这也表示在创建 pod 前,必须先把要引用的 ConfigMap 创建好;
第四点就是使用 envFrom 的方式。把 ConfigMap 里面所有的信息导入成环境变量时,如果 ConfigMap 里有些 key 是无效的,比如 key 的名字里面带有数字,那么这个环境变量其实是不会注入容器的,它会被忽略。但是这个 pod 本身是可以创建的。这个和第三点是不一样的方式,是 ConfigMap 文件存在基础上,整体导入成环境变量的一种形式;
最后一点是:什么样的 pod 才能使用 ConfigMap?这里只有通过 K8s api 创建的 pod 才能使用 ConfigMap,比如说通过用命令行 kubectl 来创建的 pod,肯定是可以使用 ConfigMap 的,但其他方式创建的 pod,比如说 kubelet 通过 manifest 创建的 static pod,它是不能使用 ConfigMap 的。

Secret
Secret 介绍

第一种是 Opaque,它是普通的 Secret 文件; 第二种是 service-account-token,是用于 service-account 身份认证用的 Secret; 第三种是 dockerconfigjson,这是拉取私有仓库镜像的用的一种 Secret; 第四种是 bootstrap.token,是用于节点接入集群校验用的 Secret。
Secret 创建

系统创建:比如 K8s 为每一个 namespace 的默认用户(default ServiceAccount)创建 Secret;
用户手动创建:手动创建命令,推荐 kubectl 这个命令行工具,它相对 ConfigMap 会多一个 type 参数。其中 data 也是一样,它也是可以指定文件和键值对的。type 的话,要是不指定,就默认是 Opaque 类型。
Secret 使用

第一种方式:如上图左侧所示,用户直接指定,把 mysecret 挂载到容器 /etc/foo 目录下面; 第二种方式:如上图右侧所示,系统自动生成,把 serviceaccount-secret 自动挂载到容器 /var/run/secrets/kubernetes.io/serviceaccount 目录下,它会生成两个文件,一个是 ca.crt,一个是 token。这是两个保存了认证信息的证书文件。
使用私有镜像库
第一种方式:如下图左侧所示,直接在 pod 里面,通过 imagePullSecrets 字段来配置; 第二种方式是自动注入。用户提前在 pod 会使用的 serviceaccount 里配置 imagePullSecrets,Pod 时系统自动注入这个 imagePullSecrets。

Secret 使用注意要点
第一个是 Secret 的文件大小限制。这个跟 ConfigMap 一样,也是 1MB;
第二个是 Secret 采用了 base-64 编码,但是它跟明文也没有太大区别。所以说,如果有一些机密信息要用 Secret 来存储的话,还是要很慎重考虑。也就是说谁会来访问你这个集群,谁会来用你这个 Secret,还是要慎重考虑,因为它如果能够访问这个集群,就能拿到这个 Secret。
如果是对 Secret 敏感信息要求很高,对加密这块有很强的需求,推荐可以使用 Kubernetes 和开源的 vault做一个解决方案,来解决敏感信息的加密和权限管理。
第三个就是 Secret 读取的最佳实践,建议不要用 list/watch,如果用 list/watch 操作的话,会把 namespace 下的所有 Secret 全部拉取下来,这样其实暴露了更多的信息。推荐使用 GET 的方法,这样只获取你自己需要的那个 Secret。

ServiceAccount
ServiceAccount 介绍

举例:Pod 里的应用访问它所属的 K8s 集群

一个是 tlsClientConfig,这个主要是用于 ca.crt 校验服务端; 第二个是 Bearer Token,这个就是 pod 的身份认证。在服务端,会利用 token 对 pod 进行一个身份认证。

Resource
容器资源配合管理

Pod 服务质量 (QoS) 配置
Guaranteed :pod 里面每个容器都必须有内存和 CPU 的 request 以及 limit 的一个声明,且 request 和 limit 必须是一样的,这就是 Guaranteed; Burstable:Burstable 至少有一个容器存在内存和 CPU 的一个 request; BestEffort:只要不是 Guaranteed 和 Burstable,那就是 BestEffort。

SecurityContext
SecurityContext 介绍
第一个是容器级别,仅对容器生效; 第二个是 pod 级别,对 pod 里所有容器生效; 第三个是集群级别,就是 PSP,对集群内所有 pod 生效。
第一个就是通过用户 ID 和组 ID 来控制文件访问权限; 第二个是 SELinux,它是通过策略配置来控制用户或者进程对文件的访问控制; 第三个是特权容器; 第四个是 Capabilities,它也是给特定进程来配置一个 privileged 能力; 第五个是 AppArmor,它也是通过一些配置文件来控制可执行文件的一个访问控制权限,比如说一些端口的读写; 第六个是一个对系统调用的控制; 第七个是对子进程能否获取比父亲更多的权限的一个限制。


InitContainer
InitContainer 介绍
InitContainer 首先会比普通 container 先启动,并且直到所有的 InitContainer 执行成功后,普通 container 才会被启动;
InitContainer 之间是按定义的次序去启动执行的,执行成功一个之后再执行第二个,而普通的 container 是并发启动的;
InitContainer 执行成功后就结束退出,而普通容器可能会一直在执行。它可能是一个 longtime 的,或者说失败了会重启,这个也是 InitContainer 和普通 container 不同的地方。


本文总结
ConfigMap 和 Secret: 首先介绍了 ConfigMap 和 Secret 的创建方法和使用场景,然后对 ConfigMap 和 Secret 的常见使用注意点进行了分类和整理。最后介绍了私有仓库镜像的使用和配置;
Pod 身份认证: 首先介绍了 ServiceAccount 和 Secret 的关联关系,然后从源码角度对 Pod 身份认证流程和实现细节进行剖析,同时引出了 Pod 的权限管理(即 RBAC 的配置管理);
容器资源和安全:首先介绍了容器常见资源类型 (CPU/Memory) 的配置,然后对 Pod 服务质量分类进行详细的介绍。同时对 SecurityContext 有效层级和权限配置项进行简要说明;
InitContainer: 首先介绍了 InitContainer 和普通 container 的区别以及 InitContainer 的用途。然后基于实际用例对 InitContainer 的用途进行了说 明。









