最佳实践


1 )普通配置

  • 定义配置时,请指定最新的稳定 API 版本
  • 在推送到集群之前,配置文件应存储在版本控制中
    • 这允许您在必要时快速回滚配置更改
    • 它还有助于集群重新创建和恢复
  • 使用 YAML 而不是 JSON 编写配置文件
    • 虽然这些格式几乎可以在所有场景中互换使用
    • 但 YAML往往更加用户友好
  • 只要有意义,就将相关对象分组到一个文件中 (推荐)
    • 一个文件通常比几个文件更容易管理
    • 另请注意,可以在目录上调用许多kubectl命令 (相比于上面,不推荐)
      • 例如,你可以在配置文件的目录中调用 kubectl apply

2 )关于“Naked”Pods 与 ReplicaSet,Deployment 和 Jobs

  • 如果可能,不要使用独立的 Pods
    • 即,未绑定到 ReplicaSet 或 Deployment 的 Pod
    • 如果节点发生故障,将不会重新调度独立的 Pods
  • Deployment 会创建一个 ReplicaSet 以确保所需数量的 Pod 始终可用
    • 并指定替换 Pod 的策略(例如 RollingUpdate)
    • 除了一些显式的restartPolicy: Never 场景之外
    • 几乎总是优先考虑直接创建 Pod
    • Job 也可能是合适的

3 )服务

  • 在创建相应的后端工作负载(Deployment 或 ReplicaSet)

  • 以及在需要访问它的任何工作负载之前创建服务

  • 当 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 API,并为每个创建一组 DNS 记录
    • 如果在整个集群中启用了 DNS,则所有 Pods 应该能够自动对 Services 进行名称解析
      • Service 有虚拟ip, 这些ip会被注册在域名服务器DNS上
      • 所有worknode上的pod都能找到集群内的所有Service
  • 除非绝对必要,否则不要为 Pod 指定 hostPort

    • 就是 worknode 节点挂掉,Pod就没法调度了
    • 将 Pod 绑定到hostPort时,它会限制 Pod 可以调度的位置数
    • 因为每个 <hostIP, hostPort, protocol> 组合必须是唯一的
    • 如果没有明确指定 hostIP 和 protocol 时,
    • K8s 将使用 0.0.0.0 作为默认 hostIP 和 TCP 作为默认 protocol
    • 如果只需要访问端口以进行调试,则可以使用 apiserver proxy或 kubectl port-forward
  • 如果明确需要在节点上公开 Pod 的端口

    • 请在使用 hostPort 之前考虑使用 NodePort 服务
  • 避免使用 hostNetwork

    • 原因与 hostPort 相同。
  • 当不需要 kube-proxy 负载均衡时

    • 使用 无头服务(ClusterIP 被设置为 None)
    • 以便于服务发现

4 )使用标签

  • 定义并使用标签来识别应用程序 或 Deployment 的 语义属性

    • 例如 { app: myapp, tier: frontend, phase: test, deployment: v3 }
      • 这种属于应用分组,好处是互不影响
    • 你可以使用这些标签为其他资源选择合适的 Pod
    • 例如,一个选择所有 tier: frontend Pod 的服务
    • 或者 app: myapp 的所有 phase: test 组件
  • 通过从选择器中省略特定发行版的标签

    • 可以使服务跨越多个 Deployment
    • Deployment 可以在不停机的情况下轻松更新正在运行的服务
  • Deployment 描述了对象的期望状态,并且如果对该规范的更改被成功应用

    • 则 Deployment 控制器以受控速率将实际状态改变为期望状态

5 )容器镜像

  • imagePullPolicy和镜像标签会影响kubelet何时尝试拉取指定的镜像
    • imagePullPolicy: IfNotPresent:仅当镜像在本地不存在时才被拉取
    • imagePullPolicy: Always:每次启动 Pod 的时候都会拉取镜像
    • imagePullPolicy 省略时,镜像标签为 :latest 或不存在,使用 Always 值
    • imagePullPolicy 省略时,指定镜像标签并且不是 :latest,使用 IfNotPresent 值
    • imagePullPolicy: Never:假设镜像已经存在本地,不会尝试拉取镜像
  • 说明
    • 在生产中部署容器时应避免使用 :latest 标记
    • 因为这样更难跟踪正在运行的镜像版本,并且更难以正确回滚
    • 底层镜像驱动程序的缓存语义能够使即便 imagePullPolicy: Always 的配置也很高效
    • 例如,对于 Docker,如果镜像已经存在,则拉取尝试很快,因为镜像层都被缓存并且不需要下载

6 )使用 kubectl

  • 选择使用 $ kubectl apply -f 更灵活
  • 使用标签选择器进行 get 和 delete 操作,而不是特定的对象名称

7 )kubectl apply -f 和 kubectl create -f 区别

  • 行为差异

    • kubectl create -f
      • 这个命令用于根据提供的配置文件(通常是 YAML 或 JSON 格式)创建 Kubernetes 对象
      • 如果对应的资源已经存在,它会返回错误
      • 因此,在使用 create 命令之前,你需要确保资源对象不存在,或者先删除原有的资源对象
    • kubectl apply -f
      • 这个命令也是用于根据配置文件应用 Kubernetes 对象
      • 但是,如果资源对象已经存在,apply 命令会尝试更新对应的字段值和配置,而不是报错
      • 如果资源对象不存在,apply 命令会自动创建资源对象
      • 因此,apply 命令提供了更大的灵活性,既可以用于创建新对象,也可以用于更新现有对象
  • 记录差异

    • kubectl apply 命令通过将先前应用的配置写入资源的注释来维护配置记录
    • 这有助于计算下一次调用时的差异,从而精确地知道需要应用哪些更改
    • 这种机制使得 apply 命令在处理复杂的混合 IT 场景时特别有用
    • 相比之下,kubectl create 命令不会维护这样的记录
    • 它只是简单地根据提供的配置文件创建资源对象。
  • 其他选项

    • kubectl apply 还提供了许多可选的参数
    • 如 --force、–validate 和 --record 等,这些参数可以使更新操作更加精确和可控
    • 例如,–force 参数可以强制应用配置,即使某些字段可能会导致无效的资源定义
    • kubectl create 命令通常没有这么多可选参数,它主要关注于根据配置文件创建资源对象
  • 总的来说

    • kubectl apply -f 和 kubectl create -f 在行为、记录和其他选项方面存在显著差异
    • 选择使用哪个命令取决于你的具体需求,例如是否需要更新现有资源对象,是否需要维护配置记录等
    • 在大多数情况下,kubectl apply 可能是一个更灵活和强大的选择
    • 因为它既可以用于创建新对象,也可以用于更新现有对象
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐