kubernetes应用配置分离
ConfigMap的概念与实战
ConfigMap
ContigMap 是一种 AP1 对象,用来将非机密性的数据保存到健值对中。使用时可以用作环境变量、命令行参数或者存储卷中的配置文件。
Config Map 将您的环境配置信息和 容器镜像 解耜,便于应用配置的修改。 当您需要储存机密信息时可以使用 Secret 对象。
注意:
Config Map 并不提供保密或者加密功能。如果你想存储的数据是机密的,请使用 Secret,或者使用其他第三方工具来保证你的数据的私密性,而不是用 ConfigMap。
设计来源
使用 ContigMap 来将你的配置数据和应用程序代码分开。
比如,假设你正在开发一个应用,它可以在你自己的电脑上(用于开发)和在云上(用于实际流量)运行。你的代码里有一段是用于查看环境变量 DATABASE_HOST,在本地运行时,你将这个变量设置为 localhost,在云上,你将其设置为引用 Kubernetes集群中的公开数据库 Service 中的组件。
这让您可以获取在云中运行的容器镜像,并且如果有需要的话,在本地调试完全相同的代码。
ConfigMap对象
ConfigMap 是一个 API 对象,让你可以存储其他对象所需要使用的配置。和其他Kubernetes 对象都有一个spec 不同的是,ContigMap 使用 data 块来存储元素(键名)和它们的值。
GontigMap 的名字必须是一个合法的 DNS 子域名。
Contig Maps和Pods
您可以写一个引用 ConfigMiap 的Pod 的spec,并根据 ContigMap 中的数据在该Pod 中配置容器。这个 Pod 和 ConfigMap 必须要在同一个 命名空间中。
这是一个 ConfigMap 的示例,它的一些键只有一个值,其他键的值看起来像是配置的片段格式。
apiVersion: v1
kind: ConfigMap
metadata:
name: appvar
data:
# 类属性键;每一个键都映射到一个简单的值
player_initial_lives: "3"
ui_properties_file_name: "user-interface.properties"
#
# 类文件键
game.properties: |
enemy.types=aliens,monsters
player.maximum-lives=5
user-interface.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
您可以使用四种方式来使用 ConfigMap 配置Pod 中的容器:
- 容器 entrypoint 的命令行参数
- 容器的环境变量
- 在只读卷里面添加一个文件,让应用来读取
- 编写代码在 Pod 中运行,使用 Kubernetes APl 来读取 ConfigMap, 这些不同的方法适用于不同的数据使用方式。对前三个方法,kubelet 使用 ConfigMap 中的数据在 Pod 中启动容器。
第四种方法意味着你必须编写代码才能读取 ConftigMap 和它的数据。然而,由于您是直接使用 Kubernetes APl, 因此只要ContigMap 发生更改,您的应用就能够通过订阅来获取更新,并且在这样的情况发生的时候做出反应。通过直接进入 Kubernetes API,这个技术也可以让你能够获取到不同的命名空问里的 ConfigMap。
创建configmap
kubectl apply -f 9-1-configmap.yaml
通过环境变量方式使用ContigMap
Kubernetes 在1.6版本引入新字段envFrom,可以实现在Pod环境中将Config Map中所有定义的key=value 自动生成为环境变量,代码格式如下所示。
apiVersion: v1
kind: Pod
metadata:
name: pod-test
spec:
containers:
- name: test
image: busybox
command: [ "/bin/sh", "-c", "env" ]
envFrom:
- configMapRef:
name: appvar
restartPolicy: Never
主要注意的是,环境变量的名称受POSIX命名规范约束,不能以数宇开头。如果配置中包含非法字符,系统将会跳过该条环境变量的创建,并记录一个Event用来提醒用户环境变量无法生成,但并不阻止Pod的启动。
创建 pod 使用 configmap
kubectl apply -f 9-1-podTest.yaml
查看输出的结果,在pod 的日志中会打印出所有环境变量,查看是否包含了上面的 contigmap 的内容
kubectl logs pod-test
Secret秘钥管理实战
Secret
Secret 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 SSH 密钥。将这些信息放在 secret 中比放在Pod 的定义或者 容器镜像 中来说更加安全和灵活。参阅 Secret 设计文档 获取更多详细信息。
Secret概览
Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象。这样的信息可能会被放在 Pod yaml中或者镜像中。用户可以创建 Secret, 同时系统也创建了一些 Secret.
要使用 Secret, Pod 需要引用 Secret。 Pod 可以用三种方式之一来使用 Secret:
- 作为挂载到一个或多个容器上的 卷中的文件。
- 作为容器的环境变量
- 由kubelet 在为 Pod 拉取镜像时使用
创建自己的Secret
使用kubectl创建Secret
Secret 中可以包含 Pod 访问数据库时需要的用户凭证信息。例如,某个数据库连接字符串可能包含用户名和密码。你可以将用户名和密码保存在本地机器的./usernare.txt 和./password.txt 文件里。
创建本例中要使用的文件
echo -n 'admin' > ./username.txt
echo -n '1f2d1e2e67df' > ./password.txt
kubectl create secret 命令将这些文件打包到一个 Secret 中并在 API server 中创建了一个对象。Secret 对象的名称必须是合法的DNS 子域名。
kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
输出类似于:
secret "db-user-pass" created
默认的键名是文件名。你也可以使用 [-from-file=Ikey=Isource] 参数来设置键名。
kubectl create secret generic db-user-pass -from-file=username=./username.txt -from-file=password=./password.txt
说明:
特殊字行 (例t KaTox parse eror: Expeated EOF, got at pootton 1:、\、*、=和!),可能会被你:…zDsb=,则应通过以下
方式执行命令:
kubectl create secret generic dev-db-secret -from-literal=username=devuser -from-literal=password='S!B\*d$zDsb='
您无需对文件中保存 (一from-file)的密码中的特殊字符执行转义操作。
您可以这样检查刚创建的 Secret:
kubectl get secrets
其输出类似于:
NAME TYPE DATA AGE
db-user-pass Opaque 2 51s
你可以查看 Secret 的描述:
kubectl describe secrets/db-user-pass
其输出类似于:
Name: db-user-pass
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password.txt: 12 bytes
username.txt: 5 bytes
说明:默认情况下,kubectl get 和kubect describe 避免显示密码的内容。这是为了防止机密被意外地暴露给旁观者或存储在终端日志中。
Kubernetes配置管理的最佳实践
普通配置
- 定义配置时,请指定最新的稳定 API 版本。
- 在推送到集群之前,配置文件应存储在版本控制中。这允许您在必要时快速回滚配置更改。它还有助于集群重新创建和恢复。
- 使用 YAML 而不是JSON 编写配置文件。虽然这些格式几乎可以在所有场景中互换使用,但 YAML 往往更加用户友好。
- 只要有意义,就将相关对象分组到一个文件中。一个文件通常比几个文件更容易管理。
另请注意,可以在目录上调用许多kubectl命令。例如,你可以在配置文件的目录中调用kubectl apply。
“Naked”Pods 与 Replicaset, Deployment 和Jobs
- 如果可能,不要使用独立的Pods(即,未鄉定到 ReplicaSet 或 Deployment 的 Pod)。如果节点发生故障,将不会重新调度独立的 Pods。
- Deployment 会创建一个 ReplicaSet 以确保所需数量的 Pod 始终可用,并指定替换 Pod 的策略(例如 RolingUpdate),除了一些显式的restartPolicy: Never 场景之外,几乎总是优先考虑直接创建 Pod。 Job 也可能是合适的。
服务
在创建相应的后端工作负载 (Deployment 或 Peplicaset),以及在需要访问它的任何工作负载之前创建 服务。当 Kubernetes启动容器时,它提供指向启动容器时正在运行的所有服务的环境变量。例如,如果存在名为foo 的服务,则所有容器将在其初始环境中获得以下变量。
FOO_SERVICE_HOST=<the host the Service is running on>
FOO_SERVICE_PORT=<the port the Service is running on>
这确实意味着在顺序上的要求-必须在 Pod 本身被创建之前创建 Pod 想要访问的任何 Service, 否则将环境变量不会生效。DNS没有此限制。
一个可选 (尽管强烈推荐)的集群插件 是DNS 服务器。DNS 服务器为新的 Services 监视 Kubernetes APl, 并为每个创建一组DNS 记录。如果在整个集群中启用了DNS,则所有Pods 应该能够自动对 Services 进行名称解析。
除非绝对必要,否则不要为 Pod 指定 hostPort。将Pod 绑定到hostPort时,它会限制 Pod 可以调度的位置数,因为每个shost/P, hostP ort, protocol>组合必须是唯一的。如果您没有明确指定 host/P 和 protocol, Kubernetes 将使用0.0.0.0 作为默认hostlP 和丁CP 作为默认 protocol。
如果您只需要访问端口以进行调试,则可以使用 apiserver proxy或 kubectl port-forward。
如果您明确需要在节点上公开 Pod 的端口,请在使用 hostPort 之前考虑使用 NodePort 服务。
避免使用 hostNetwork,原因与hostPort 相同。
当您不需要 kube-proxy 负载均衡时,使用无头服务 (ClusterlP 被设置为 None)以便于服务发现。
使用标签
定义并使用标签来识别应用程序 或 Deployment 的 语义属性,例如{app:myapp, tier: frontend, phase: test, deployment: v3了。你可以使用这些标签为其他资源选择合适的 Pod;例如,一个选择所有 tier: frontend Pod 的服务,或者 app: myapp 的所有 phase: test 组件。
通过从选择器中省略特定发行版的标签,可以使服务跨越多个 Deployment。 Deployment 可以在不停机的情况下轻松更新正在运行的服务。
Deplovment 描述了对象的期望状态,并且如果对该规范的更改被成功应用,则 Deplovment 控制器以受控速率将实际状态改变为期望状态。
容器镜像
- imagePullPolicy和镜像标签会影响kubelet 何时尝试拉取指定的镜像。
-
iimagePullPolicy: 1fNotPresent:仅当镜像在本地不存在时才被拉取。 -
imagePulPolicy:Always:每次启动Pod 的时候都会拉取镜像。 -
imagePullPolicy 省略时,镜像标签为:latest 或不存在,使用 Always 值。 -
iimagePullPolicy 省略时,指定镜像标签并且不是:latest, 使用lfNotPresent 值。 - imagePullPolicy: Never:假设镜像已经存在本地,不会尝试拉取镜像。
说明:在生产中部署容器时应避免使用 :latest 标记,因为这样更难跟踪正在运行的镜像版本,并且更难以正确回滚。
说明:底层镜像驱动程序的缓存语义能够使即便 imagePullPolicy:Always 的配置也很高效。例如,对于 Docker, 如果镜像已经存在,则拉取尝试很快,因为镜像层都被缓存并且不需要下载。
使用kubectl
- 使用kubectl apply -f。它在中的所有 yampl、ymal和json 文件中查找 Kubernetes 配置,并将其传递给 apply。
- 使用标签选择器进行 get 和delete 操作,而不是特定的对象名称。
文章介绍了Kubernetes中的ConfigMap和Secret对象,如何将配置数据与应用程序分离,以及如何通过环境变量、文件和Pod配置使用它们。还探讨了最佳实践,如版本控制、标签管理、镜像策略和kubectl的使用。
870

被折叠的 条评论
为什么被折叠?



