此处汇集了一些配置容器时应该考虑的最佳实践,参考这些建议可以让您更加合理的配置和使用容器。

# “孤本”Pod与副本集、无状态工作负载和普通任务

使用无状态工作负载时,最终运行的单元是Pod。实际上,这些Pod并不直接被无状态工作负载控制,而是受副本集控制管理,副本集控制器会确保Pod数目符合无状态工作负载中声明的数量。而对于普通任务,Pod直接受普通任务控制。

实际上,Kubernetes集群是可以运行不受副本集控制器或普通任务管理的Pod,这样的Pod称为”孤本“Pod。 在实践中,不建议使用“孤本”Pod,因为其不受副本集控制器管理,当节点发生故障时无法被重新调度。

# Pod探针

如果没有设置就绪探针,kubelet默认Pod容器运行后便可以接收流量,如果您的容器需要2分钟才能完成启动,那么这2分钟内的请求都会失败。

如果没有设置存活探针,kubelet无法在Pod运行异常时重启Pod,例如您的容器占用了100%的CPU并无法响应新的请求,配置存活探针后kubelet会重启该Pod。

# Service

# Service地址解析

可以在创建实际的后端工作负载和其他需要访问该工作负载的工作负载之前,先创建工作负载对应的Service。当Kubernetes启动容器时,会将当前所有Service的名称以环境变量的方式注入到容器中,容器在初始化过程中可以使用这些环境变量与外部服务交互。LStack容器服务允许您在创建工作负载的同时创建Service,来保证Service的提前创建。

另一种做法是使用CoreDNS插件来为集群提供DNS解析服务。DNS插件会监听Kubernetes集群中Service变化,为新的Service创建DNS记录。这样Pod便可以在运行过程中通过DNS解析与外部服务交互。通过LStack容器服务创建的集群,已经为您配置好CoreDNS插件,因此您无需过多关注Service解析问题。

# 通过主机端口访问服务

有三种方式可以通过主机端口访问Pod:hostPortnodePortkubectl port-forward

关于容器的hostPort,除非必须,建议不要使用。通过创建节点访问(NodePort)类型的Service便可以从主机端口访问容器,而指定hostPort会限制Pod所能调度的节点范围,因为<hostIP,hostPort,protocol>三元组必须是唯一的,而人为指定hostPort极有可能冲突而导致Pod无法被调度到相应节点。

如果是出于调试目的的访问,您可以使用kubectl port-forward命名将一个本地端口转发到Pod的指定端口。

如果确实需要通过主机端口访问Pod,优先考虑使用节点访问(nodePort)类型的Service而非hostPort

# 外部服务发现和负载均衡

如果您的微服务已经集成了服务发现和负载均衡能力,那么您可以考虑使用Headless ServiceHeadless Service的DNS解析将返回后端Pod的IP地址(可能是多个)而非ClusterIP,这样您便可以脱离Kubernetes的服务发现和负载均衡,转而使用其他的解决方案。

# hostNetwork选项

避免使用hostNetwork选择,原因与hostPort类型。

# 容器镜像拉取策略

imagePullPolicy和镜像tag会影响kubelet拉取镜像时的行为。

  • imagePullPolicy: IfNotPresent: 仅在本地不存在镜像时拉取。
  • imagePullPolucy: Always: 运行容器时,始终拉取镜像。
  • 镜像tag为latest时,无论是否指定,imagePullPolicy默认为Always。
  • 镜像tag不是latest时,无论是否指定,imagePullPolicy默认为IfNotPresent。
  • 改变镜像tag时,imagePullPolicy不会自动变化,如果您将镜像tag改为latest,请确保imagePullPolicy修改为Always。
  • imagePullPolucy: Never: 始终使用本地镜像,不会尝试拉取。

注意:设置imagePullPolucy: Never时,请确保Pod运行节点存在需要的镜像,您可以提前准备镜像,然后将Pod定向调度到该节点。

提示:为确保容器总是使用相同版本的镜像,您可以指定其摘要,将<image-name>:<image-tag>替换为<image-name>@<digest> ,例如 image@sha256:45b23dee08af5e43a7fea6c4cf9c25ccf269ee113168c19722f87876677c5cb2。 摘要唯一地标识出镜像的指定版本,因此除非您更改摘要值,否则 Kubernetes 永远不会更新它。

提示:在生产环境,请谨慎使用latest版本,因为很难追踪镜像的具体版本,也很难回滚版本。

提示:即使设置了imagePullPolicy: Always,kubelet下层的镜像提供器也可能使用缓存机制,例如docker在拉取镜像时,如果各层都已缓存,那么没有镜像层会重新下载。