• 如果可能,不要使用独立的 Pods(即,未绑定到 ReplicaSetDeployment 的 Pod)。 如果节点发生故障,将不会重新调度独立的 Pods。

Deployment 既可以创建一个 ReplicaSet 来确保预期个数的 Pod 始终可用,也可以指定替换 Pod 的策略(例如 RollingUpdate

  • 一个可选(尽管强烈推荐)的集群插件 是 DNS 服务器。DNS 服务器为新的 Services 监视 Kubernetes API,并为每个创建一组 DNS 记录。 如果在整个集群中启用了 DNS,则所有 Pods 应该能够自动对 Services 进行名称解析。

  • 除非绝对必要,否则不要为 Pod 指定 hostPort。 将 Pod 绑定到hostPort时,它会限制 Pod 可以调度的位置数,因为每个 <hostIP, hostPort, protocol>组合必须是唯一的。 如果您没有明确指定 hostIPprotocol,Kubernetes 将使用 0.0.0.0 作为默认 hostIPTCP 作为默认 protocol

如果只需要访问端口以进行调试,则可以使用 apiserver proxykubectl port-forward

如果您明确需要在节点上公开 Pod 的端口,请在使用 hostPort 之前考虑使用 NodePort 服务。

  • 避免使用 hostNetwork,原因与 hostPort 相同。
  • 当您不需要 kube-proxy 负载均衡时,使用 无头服务
    (ClusterIP 被设置为 None)以便于服务发现。

容器镜像

imagePullPolicy和镜像标签会影响 kubelet 何时尝试拉取指定的镜像。

  • imagePullPolicy: IfNotPresent:仅当镜像在本地不存在时才被拉取。
  • imagePullPolicy: Always:每次启动 Pod 的时候都会拉取镜像。
  • imagePullPolicy 省略时,镜像标签为 :latest 或不存在,其值自动被设置为 Always。注意,如果镜像标签的值发生改变,imagePullPolicy 的值不会被更新为 IfNotPresent
  • imagePullPolicy 省略时,指定镜像标签并且不是 :latest,其值自动被设置为 IfNotPresent。注意,如果镜像标签的值之后被移除或者修改为 latestimagePullPolicy 的值不会被更新为 Always
  • imagePullPolicy: Never:假设镜像已经存在本地,不会尝试拉取镜像。

说明

在生产中部署容器时应避免使用 :latest 标记,因为这样更难跟踪正在运行的镜像版本,并且更难以正确回滚。

ConfigMap

ConfigMap 是一种 API 对象,用来将非机密性的数据保存到键值对中。使用时, Pods 可以将其用作环境变量、命令行参数或者存储卷中的配置文件。

ConfigMap 在设计上不是用来保存大量数据的。在 ConfigMap 中保存的数据不可超过 1 MiB

ConfigMap 对象

ConfigMap 是一个 API 对象, 让你可以存储其他对象所需要使用的配置。 和其他 Kubernetes 对象都有一个 spec 不同的是,ConfigMap 使用 databinaryData 字段。这些字段能够接收键-值对作为其取值。databinaryData 字段都是可选的。data 字段设计用来保存 UTF-8 字节序列,而 binaryData 则 被设计用来保存二进制数据作为 base64 编码的字串。

ConfigMap 的名字必须是一个合法的 DNS 子域名

databinaryData 字段下面的每个键的名称都必须由字母数字字符或者 -_. 组成。在 data 下保存的键名不可以与在 binaryData 下 出现的键名有重叠。

ConfigMaps 和 Pods

可以写一个引用 ConfigMap 的 Pod 的 spec,并根据 ConfigMap 中的数据 在该 Pod 中配置容器。这个 Pod 和 ConfigMap 必须要在同一个 名字空间 中。

onfigMap 的示例

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: game-demo
  5. data:
  6. # 类属性键;每一个键都映射到一个简单的值
  7. player_initial_lives: "3"
  8. ui_properties_file_name: "user-interface.properties"
  9. # 类文件键
  10. game.properties: |
  11. enemy.types=aliens,monsters
  12. player.maximum-lives=5
  13. user-interface.properties: |
  14. color.good=purple
  15. color.bad=yellow
  16. allow.textmode=true

可以使用四种方式来使用 ConfigMap 配置 Pod 中的容器:

  1. 在容器命令和参数内
  2. 容器的环境变量
  3. 在只读卷里面添加一个文件,让应用来读取
  4. 编写代码在 Pod 中运行,使用 Kubernetes API 来读取 ConfigMap

对前三个方法,kubelet 使用 ConfigMap 中的数据在 Pod 中启动容器。

第四种方法意味着你必须编写代码才能读取 ConfigMap 和它的数据。然而, 由于你是直接使用 Kubernetes API,因此只要 ConfigMap 发生更改,你的 应用就能够通过订阅来获取更新,并且在这样的情况发生的时候做出反应。 通过直接进入 Kubernetes API,这个技术也可以让你能够获取到不同的名字空间 里的 ConfigMap。

一个 Pod 的示例,它通过使用 game-demo 中的值来配置一个 Pod:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: configmap-demo-pod
  5. spec:
  6. containers:
  7. - name: demo
  8. image: alpine
  9. command: ["sleep", "3600"]
  10. env:
  11. # 定义环境变量
  12. - name: PLAYER_INITIAL_LIVES # 请注意这里和 ConfigMap 中的键名是不一样的
  13. valueFrom:
  14. configMapKeyRef:
  15. name: game-demo # 这个值来自 ConfigMap
  16. key: player_initial_lives # 需要取值的键
  17. - name: UI_PROPERTIES_FILE_NAME
  18. valueFrom:
  19. configMapKeyRef:
  20. name: game-demo
  21. key: ui_properties_file_name
  22. volumeMounts:
  23. - name: config
  24. mountPath: "/config"
  25. readOnly: true
  26. volumes:
  27. # 你可以在 Pod 级别设置卷,然后将其挂载到 Pod 内的容器中
  28. - name: config
  29. configMap:
  30. # 提供你想要挂载的 ConfigMap 的名字
  31. name: game-demo
  32. # 来自 ConfigMap 的一组键,将被创建为文件
  33. items:
  34. - key: "game.properties"
  35. path: "game.properties"
  36. - key: "user-interface.properties"
  37. path: "user-interface.properties"

使用 ConfigMap

ConfigMap 可以作为数据卷挂载。ConfigMap 也可被系统的其他组件使用,而 不一定直接暴露给 Pod。例如,ConfigMap 可以保存系统中其他组件要使用 的配置数据。

ConfigMap 最常见的用法是为同一命名空间里某 Pod 中运行的容器执行配置。 你也可以单独使用 ConfigMap。

在 Pod 中将 ConfigMap 当做文件使用

  1. 创建一个 ConfigMap 对象或者使用现有的 ConfigMap 对象。多个 Pod 可以引用同一个 ConfigMap。
  2. 修改 Pod 定义,在 spec.volumes[] 下添加一个卷。 为该卷设置任意名称,之后将 spec.volumes[].configMap.name 字段设置为对 你的 ConfigMap 对象的引用。
  3. 为每个需要该 ConfigMap 的容器添加一个 .spec.containers[].volumeMounts[]。 设置 .spec.containers[].volumeMounts[].readOnly=true 并将 .spec.containers[].volumeMounts[].mountPath 设置为一个未使用的目录名, ConfigMap 的内容将出现在该目录中。
  4. 更改你的镜像或者命令行,以便程序能够从该目录中查找文件。ConfigMap 中的每个 data 键会变成 mountPath 下面的一个文件名。

下面是一个将 ConfigMap 以卷的形式进行挂载的 Pod 示例:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: mypod
  5. spec:
  6. containers:
  7. - name: mypod
  8. image: redis
  9. volumeMounts:
  10. - name: foo
  11. mountPath: "/etc/foo"
  12. readOnly: true
  13. volumes:
  14. - name: foo
  15. configMap:
  16. name: myconfigmap

如果 Pod 中有多个容器,则每个容器都需要自己的 volumeMounts 块,但针对 每个 ConfigMap,你只需要设置一个 spec.volumes 块。

被挂载的 ConfigMap 内容会被自动更新

当卷中使用的 ConfigMap 被更新时,所投射的键最终也会被更新。 kubelet 组件会在每次周期性同步时检查所挂载的 ConfigMap 是否为最新。 不过,kubelet 使用的是其本地的高速缓存来获得 ConfigMap 的当前值。 高速缓存的类型可以通过 KubeletConfiguration 结构ConfigMapAndSecretChangeDetectionStrategy 字段来配置。

ConfigMap 既可以通过 watch 操作实现内容传播(默认形式),也可实现基于 TTL 的缓存,还可以直接经过所有请求重定向到 API 服务器。 因此,从 ConfigMap 被更新的那一刻算起,到新的主键被投射到 Pod 中去,这一 时间跨度可能与 kubelet 的同步周期加上高速缓存的传播延迟相等。 这里的传播延迟取决于所选的高速缓存类型 (分别对应 watch 操作的传播延迟、高速缓存的 TTL 时长或者 0)。

以环境变量方式使用的 ConfigMap 数据不会被自动更新。 更新这些数据需要重新启动 Pod。

不可变更的 ConfigMap

Kubernetes 特性 不可变更的 Secret 和 ConfigMap 提供了一种将各个 Secret 和 ConfigMap 设置为不可变更的选项。对于大量使用 ConfigMap 的 集群(至少有数万个各不相同的 ConfigMap 给 Pod 挂载)而言,禁止更改 ConfigMap 的数据有以下好处:

  • 保护应用,使之免受意外(不想要的)更新所带来的负面影响。
  • 通过大幅降低对 kube-apiserver 的压力提升集群性能,这是因为系统会关闭 对已标记为不可变更的 ConfigMap 的监视操作。

创建 Secret (todo)

为容器管理资源

为 Pod 中的 Container 指定了资源 请求 时,调度器就利用该信息决定将 Pod 调度到哪个节点上。 当你还为 Container 指定了资源 约束 时,kubelet 就可以确保运行的容器不会使用超出所设约束的资源。 kubelet 还会为容器预留所 请求 数量的系统资源,供其使用。

请求和约束

如果 Pod 运行所在的节点具有足够的可用资源,容器可能(且可以)使用超出对应资源 request 属性所设置的资源量。不过,容器不可以使用超出其资源 limit 属性所设置的资源量。

如果你将容器的 memory 的请求量设置为 256 MiB,而该容器所处的 Pod 被调度到一个具有 8 GiB 内存的节点上,并且该节点上没有其他 Pods 运行,那么该容器就可以尝试使用更多的内存。

说明

如果某 Container 设置了自己的内存限制但未设置内存请求,Kubernetes 自动为其设置与内存限制相匹配的请求值。类似的,如果某 Container 设置了 CPU 限制值但未设置 CPU 请求值,则 Kubernetes 自动为其设置 CPU 请求 并使之与 CPU 限制值匹配。

资源类型

CPU内存都是资源类型。每种资源类型具有其基本单位。 CPU 表达的是计算处理能力,其单位是 Kubernetes CPUs。 内存的单位是字节。 如果你使用的是 Kubernetes v1.14 或更高版本,则可以指定巨页(Huge Page)资源。 巨页是 Linux 特有的功能,节点内核在其中分配的内存块比默认页大小大得多。

Pod 和 容器的资源请求和约束

Pod 中的每个容器都可以指定以下的一个或者多个值:

  • spec.containers[].resources.limits.cpu
  • spec.containers[].resources.limits.memory
  • spec.containers[].resources.requests.cpu

Kubernetes 中的资源单位

CPU 资源的约束和请求以 cpu 为单位

Kubernetes 中的一个 cpu 等于云平台上的 1 个 vCPU/核和裸机 Intel 处理器上的 1 个超线程

spec.containers[].resources.requests.cpu 为 0.5 的 Container 肯定能够获得请求 1 CPU 的容器的一半 CPU 资源。

例子

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: frontend
  5. spec:
  6. containers:
  7. - name: app
  8. image: images.my-company.example/app:v4
  9. env:
  10. - name: MYSQL_ROOT_PASSWORD
  11. value: "password"
  12. resources:
  13. requests:
  14. memory: "64Mi"
  15. cpu: "250m"
  16. limits:
  17. memory: "128Mi"
  18. cpu: "500m"
  19. - name: log-aggregator
  20. image: images.my-company.example/log-aggregator:v6
  21. resources:
  22. requests:
  23. memory: "64Mi"
  24. cpu: "250m"
  25. limits:
  26. memory: "128Mi"
  27. cpu: "500m"