本文共 13336 字,大约阅读时间需要 44 分钟。
本节课程要点
细分为以下八个方面:
首先一起来看一下需求来源。大家应该都有过这样的经验,就是用一个容器镜像来启动一个 container。要启动这个容器,其实有很多需要配套的问题待解决:
在 Kubernetes 里面,它是怎么做这些配置管理的呢?如下图所示:
下面我们来介绍第一个部分,就是 ConfigMap。我们先来介绍 ConfigMap 它是用来做什么的、以及它带来的一个好处。它其实主要是管理一些可变配置信息,比如说我们应用的一些配置文件,或者说它里面的一些环境变量,或者一些命令行参数。
它的好处在于它可以让一些可变配置和容器镜像进行解耦,这样也保证了容器的可移植性。看一下下图中右边的编排文件截图。
主要管理容器运行时所需的配置文件,环境变量,命令行参数等可变配置。用于解耦容器镜像和可变配置,从而保障工作负载(Pod)的可移植性。
apiVersion: v1kind: ConfigMapmetadata: labels: app: flannel tier: node name: kube-flannel-cfg namespace: kube-systemdata: cni-conf.json: | { "name": "cbr0", "type": "flannel", "delegate":{ "isDefaultGateway": true } } net-conf.json: | { "Network": "172.27.0.0/16". "Backend": { "Type": "vxlan" } }
这是 ConfigMap 本身的一个定义,它包括两个部分:一个是 ConfigMap 元信息,我们关注 name 和 namespace 这两个信息。接下来这个 data 里面,可以看到它管理了两个配置文件。它的结构其实是这样的:从名字看ConfigMap中包含Map单词,Map 其实就是 key:value,key 是一个文件名,value 是这个文件的内容。
看过介绍之后,再具体看一下它是怎么创建的。我们推荐用 kubectl 这个命令来创建,它带的参数主要有两个:一个是指定 name,第二个是 DATA。其中 DATA 可以通过指定文件或者指定目录,以及直接指定键值对,下面可以看一下这个例子。
创建命令:kubectl create configmap [NAME] [DATA]
其中DATA:
kubectl create configmap kube-flannel-cfg --from-file=configure-pod-container/configmap/cni-conf.json -n kube-system
kubectl get configmap kube-flannel-cfg -o yamlapiVersion:v1kind: ConfigMapmetadata: labels: app: flannel tier: node name: kube-flannel-cfg namespace: kube-systemdata: cni-conf.json: | # 文件名字作为key { # 文件内容作为value "name": "cbr0", "type": "flannel", "delegate": { "isDefaultGateway": true } }
kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
kubectl get configmap special-config -o yamlapiVersion: v1kind: ConfigMapmetadata: name: special-config namespace: defaultdata: # 输入的键值对 special.how: very special.type: charm
指定文件的话,文件名就是 Map 中的 key,文件内容就是 Map 中的 value。然后指定键值对就是指定数据键值对,即:key:value 形式,直接映射到 Map 的key:value。
创建完了之后,应该怎么使用呢?
ConfigMap主要被Pod使用,一般用于挂载Pod用的配置文件,环境变量 ,命令行参数等。
示例1:(用ConfigMap配置环境变量)
apiVersion:kind: Podmetadata: namp: cm-env-testspec: containers: - name: test-container iamge: k8s.gcr.io/busybox command: ["/bin/sh","-c","env"] env: # 用apecial-config中的specila.how定义环境变量 - name: SPECILA_LEVEL_KEY valueFrom: configMapKeyRef: name: special-config key: special.how restartPolicy: Never
示例2:(用configMap配置管控命令行参数)
apiVersion: v1kind: Podmetadata: name: cm-cmd-testspec: containers: - name: test-container iamge: k8s.gcr.io/busybox command: ["/bin/sh","-c","echo ${SPECILA_LEVEL_KEY}"] env: - name: SPECILA_LEVEL_KEY valueFrom: configMapKeyRef: name: special-config key: SPECIAL_LEVEL restartPolicy: Never
示例3:用ConfigMap挂载配置文件
apiVersion: v1kind: Podmetadata: name: cm-value-testspec: containers: - name: test-container image: k8s.gcr.io/busybox command: ["/bin/sh","-c","ls /etc/config"] valumeMonuts: - name: config-value mountPath: /etc/config valumes: - name: config-valume configMap: name: special-config restartPolicy: Never
如上图所示,主要是在 pod 里来使用 ConfigMap:
现在对 ConfigMap 的使用做一个总结,以及它的一些注意点,注意点一共列了以下五条:
现在我们讲一下 Secret,Secret 是一个主要用来存储密码 token 等一些敏感信息的资源对象。其中,敏感信息是采用 base-64 编码保存起来的,我们来看下图中 Secret 数据的定义。
apiVersion: v1kind: Secret # Secret元数据metadata: name: mysecret namespace: kube-systemtype: Opaquedata: username: YYUYYYLKSD password: sjdfksdklflkll=
元数据的话,里面主要是 name、namespace 两个字段;接下来是 type,它是非常重要的一个字段,是指 Secret 的一个类型。Secret 类型种类比较多,下面列了常用的四种类型:
再接下来是 data,是存储的 Secret 的数据,它也是 key-value 的形式存储的。
接下来我们看一下 Secret 的创建。
有两种创建方式:
Secret创建可以是用户自己创建,也有Secret是系统自动创建
手动创建命令:kubectl create secrt generic [NAME] [DATA] [TYPE]
其中DATA: 可以指定文件/键值对
另外TYPE: 默认为Opaque
指定文件创建:
kubectl create secret generic myregistrykey --from-file=.dockerconfigjson=/root/.docker/config.json –type=kubernetes.io/dockerconfigjson
apiVersion: V1kind: Secretmetadata: name: myregistrykey namespace: defaultdata: .dockerconfigjson: jflsdkjfklsdjflksdjflksjdfkjsdklfjalkqqqqqqqqqqqqqqqqqqqqqqqkljdflksjdfdsftype: kubernetes.io/dockerconfigjson
指定键值对:
kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11
apiVersion: v1data: password: tttttslejkljlk username: ChjsldfiwenkHHkind: Secretmeatdata: name: prod-db-secret namespace: defaulttype: Opaque
上图中两个例子。第一个是通过指定文件,创建了一个拉取私有仓库镜像的 Secret,指定的文件是 /root/.docker/config.json。type 的话指定的是 dockerconfigjson,另外一个我们指定键值对,我们 type 没有指定,默认是 Opaque。键值对是 key:value 的形式,其中对 value 内容进行 base64 加密。创建 Secret 就是这么一个情况。
创建完 Secret 之后,再来看一下如何使用它。它主要是被 pod 来使用,一般是通过 volume 形式挂载到容器里指定的目录,然后容器里的业务进程再到目录下读取 Secret 来进行使用。另外在需要访问私有镜像仓库时,也是通过引用 Secret 来实现。
示例1:(Sectet挂载在用户指定目录下)
apiVersion: v1kind: Podmetadata: name: mypodspec: containers: - name: mypod image: redis volumeMounts: # secret以文件形式挂载在/etc/foo下 - name: foo mountPath: "/etc/foo" readOnly: true volumes: - name: foo secret: # 指定要挂载的secret secrteName: mysecret
示例2:(SeviceAccount用的secret自动挂载在固定目录下(生成ca.crt和token两个文件))
apiVersion: v1kind: Podmetadata: name: nginx-sjdlrkj325-mdfp5 namespace: defaultspec: containers: - iamge: nginx: 1-alpine name: nginx - volumeMounts: # 固定挂载到容器中的/var/run/secret/kubernetes.io/serviceaccount目录下 /var/run/secret/kubernetes.io/serviceaccount name: default-token-666i8 readonly: true serviceAccount: default serviceAccountName: default # 使用namespace默认的serviceaccount volumes: - name: default-token-6lsdkjf secret: defaultMode: 420 # 挂载namespace默认的secret secretName: default-token-6fjsi
我们先来看一下挂载到用户指定目录的方式:
下面看一下用 Secret 来使用私有镜像仓库。首先,私有镜像仓库的信息是存储在 Secret 里面的(具体参照上述的Secret创建章节),然后拉取私有仓库镜像,那么通过下图中两种方法的配置就可以:
指定imagePullSecret
apiVersion: v1kind: Podmetadata: name: private-regspec: containers: - name: private-reg-container image: <你的镜像> imagePullSecret: - name: regcred 你的镜像>
最后来看一下 Secret 使用的一些注意点,下面列了三点:
如果是对 Secret 敏感信息要求很高,对加密这块有很强的需求,推荐可以使用 Kubernetes 和开源的 vault做一个解决方案,来解决敏感信息的加密和权限管理。
接下来,我们讲一下 ServiceAccount。ServiceAccount 首先是用于解决 pod 在集群里面的身份认证问题,身份认证信息是存在于 Secret 里面。
先看一下上面的左侧截图,可以看到最下面的红框里,有一个 Secret 字段,它指定 ServiceAccount 用哪一个 Secret,这个是 K8s 自动为 ServiceAccount 加上的。然后再来看一下上图中的右侧截图,它对应的 Secret 的 data 里有两块数据,一个是 ca.crt,一个是 token。ca.crt 用于对服务端的校验,token 用于 Pod 的身份认证,它们都是用 base64 编码过的。然后可以看到 metadata 即元信息里,其实是有关联 ServiceAccount 信息的(这个 secret 被哪个 ServiceAccount 使用)。最后我们注意一下 type,这个就是 service-account-token 这种类型。
介绍完 ServiceAccount 以及它对应的 secret 后,我们来看一下,pod 是怎么利用 ServiceAccount 或者说它是怎么利用 secret 来访问所属 K8s 集群的。
其实 pod 创建的时候,首先它会把这个 secret 挂载到容器固定的目录下,这是 K8s 功能上实现的。它要把这个 ca.crt 和 token 这两个文件挂载到固定目录下面。
pod 要访问集群的时候,它是怎么来利用这个文件的呢?我们看一下下面的代码截图:
我们在 Go 里面实现 Pod 访问 K8s 集群时,一般直接会调一个 InClusterConfig 方法,来生成这个访问服务 Client 的一些信息。然后可以看一下,最后这个 Config 里面有两部分信息:
再次回到上图左侧。认证完之后 pod 的身份信息会有两部分:一个是 Group,一个是 User。身份认证是就是认证这两部分信息。接着可以使用 RBAC 功能,对 pod 进行一个授权管理。
假如 RBAC 没有配置的话,默认的 pod 具有资源 GET 权限,就是可以从所属的 K8s 集群里 get 数据。如果是需要更多的权限,那么就需要 自行配置 RBAC 。RBAC 的相关知识,我们在后面的课程里面会详细介绍,大家可以关注一下。
下面介绍一下 Resource,即:容器的一个资源配置管理。
目前内部支持类型有三种:CPU、内存,以及临时存储。当用户觉得这三种不够,有自己的一些资源,比如说 GPU,或者其他资源,也可以自己来定义,但配置时,指定的数量必须为整数。目前资源配置主要分成 request 和 limit 两种类型,一个是需要的数量,一个是资源的界限。CPU、内存以及临时存储都是在 container 下的 Resource 字段里进行一个声明。
支持资源类型:
配置方法:
资源配置分为request/limit两种类型
apiVersion: v1kind: Podmetadata: name: frontendspec: containers: - name: wp iamge: wordpress resources: # 申明需要的资源 request: memory: "64Mi" cpu: "250m" ephemeral-storage: "2Gi" limits: memory: "128Mi" cpu: "500m" ephemeral-storage: "4Gi"
举个例子,wordpress 容器的资源需求,一个是 request ,一个是 limits,它分别对需要的资源和资源临界进行一个声明。
根据 CPU 对容器内存资源的需求,我们对 pod 的服务质量进行一个分类,分别是 Guaranteed、Burstable 和 BestEffort。
那么这个服务质量是什么样的呢?资源配置好后,当这个节点上 pod 容器运行,比如说节点上 memory 配额资源不足,kubelet会把一些低优先级的,或者说服务质量要求不高的(如:BestEffort、Burstable)pod 驱逐掉。它们是按照先去除 BestEffort,再去除 Burstable 的一个顺序来驱逐 pod 的。
SecurityContext 主要是用于限制容器的一个行为,它能保证系统和其他容器的安全。这一块的能力不是 Kubernetes 或者容器 runtime 本身的能力,而是 Kubernetes 和 runtime 通过用户的配置,最后下传到内核里,再通过内核的机制让 SecurityContext 来生效。所以这里讲的内容,会比较简单或者说比较抽象一点。
SecurityContext 主要分为三个级别:
权限和访问控制设置项,现在一共列有七项(这个数量后续可能会变化):
最后其实都是落到内核来控制它的一些权限。
上图是对 pod 级别和容器级别配置 SecurityContext 的一个例子,如果大家对这些内容有更多的需求,可以根据这些信息去搜索更深入的资料来学习。
接下来看一下 InitContainer,首先介绍 InitContainer 和普通 container 的区别,有以下三点内容:
根据上面三点内容,我们看一下 InitContainer 的一个用途。它其实主要为普通 container 服务,比如说它可以为普通 container 启动之前做一个初始化,或者为它准备一些配置文件, 配置文件可能是一些变化的东西。再比如做一些前置条件的校验,如网络是否联通。
上面的截图是 flannel 组件的 InitContainer 的一个配置,它的 InitContainer 主要是为 kube-flannel 这个普通容器启动之前准备一些网络配置文件。
转载地址:http://xqzwk.baihongyu.com/