阿里云容器服务Kubernetes版ACK(Container Service for Kubernetes)集群支持通过界面创建StatefultSet类型的应用,满足您快速创建有状态应用的需求。本例中将创建一个Nginx的有状态应用,并演示StatefulSet应用的特性。

前提条件

使用镜像创建有状态StatefulSet应用前,请确保您已经进行以下操作:

背景信息

StatefulSet包括以下特性:
场景 说明
Pod一致性 包含次序(启动、停止次序)、网络一致性。此一致性与Pod相关,与被调度到哪个node节点无关。
稳定的持久化存储 通过VolumeClaimTemplate为每个Pod创建一个PV。删除、减少副本,不会删除相关的卷。
稳定的网络标志 Pod的hostname模式为:(statefulset名称)−(序号)
稳定的次序 对于N个副本的StatefulSet,每个Pod都在 [0,N)的范围内分配一个数字序号,且是唯一的。

操作步骤

  1. 登录容器服务管理控制台
  2. 在控制台左侧导航栏中,单击集群
  3. 集群列表页面中,单击目标集群名称或者目标集群右侧操作列下的详情
  4. 在集群管理页左侧导航栏中,单击工作负载
  5. 单击有状态页签,在有状态页签中单击使用镜像创建
  6. 应用基本信息页签中,设置应用的基本信息。

    本例中选择有状态类型,创建StatefulSet类型的应用。

    配置项 描述
    应用名称 设置应用的名称。
    命名空间 设置应用部署所处的命名空间,默认使用default命名空间。
    副本数量 应用包含的Pod数量。
    类型 定义资源对象的类型,可选择无状态有状态任务定时定时任务守护进程集
    标签 为该应用添加一个标签,标识该应用。
    注解 为该应用添加一个注解(annotation)。
    时区同步 容器与节点是否使用相同的时区。
  7. 单击下一步进入容器配置页签。
  8. 设置容器相关的配置。
    说明容器配置页签上方,单击添加容器为应用的Pod设置多个容器。
    容器配置的配置项及描述如下。
    • 基本配置设置容器基本信息
      配置项 描述
      镜像名称
      • 您可以单击选择镜像,选择所需的镜像并单击确定。本例中为官方Nginx镜像,可以在搜索页签中,选择Docker镜像,然后在文本框中输入nginx进行搜索。
        • 容器镜像服务:在容器镜像服务页签中,可以选择托管在容器镜像服务ACR中的镜像。需要选择镜像所属地域,以及镜像服务实例。关于ACR的更多信息,请参见ACR 企业版概述
          说明 您可以在容器镜像服务页签,根据名称搜索托管在容器镜像服务ACR中的镜像。
        • Docker官方镜像:在Docker官方镜像页签中,可以选择Docker官方提供的容器镜像。
        • 用户收藏:在用户收藏页签中,可以选择您收藏的Docker官方镜像。
        • 搜索:在搜索页签中,可以分别在ACR的特定地域和Docker官方镜像中搜索容器镜像。
      • 您还可以填写私有镜像。填写的格式为domainname/namespace/imagename:tag

      镜像Tag

      • 您可以单击选择镜像Tag选择镜像的版本。若不指定,默认为最新版。
      • ACK支持以下三种镜像拉取策略(imagePullPolicy):
        • 优先使用本地镜像(ifNotPresent):如果本地有该镜像,则使用本地镜像,本地不存在时拉取镜像。
        • 总是拉取镜像(Always):表示每次部署或扩容都会从容器镜像服务重新拉取镜像,而不会从本地拉取镜像。
        • 仅使用本地镜像(Never):仅使用本地镜像。
        说明 当您选中镜像拉取策略时,默认不设置镜像拉取策略。
      • 单击设置镜像密钥,您可以实现免密拉取镜像,详情请参见使用免密组件拉取容器镜像
      资源限制 可指定该应用所能使用的资源上限,包括CPU、内存和ephemeral-storage三种资源,防止占用过多资源。其中,CPU资源的单位为millicores,即一个核的千分之一;内存的单位为GiB;ephemeral-storage的单位为GiB。
      所需资源 即为该应用预留资源额度,包括CPU和内存两种资源,即容器独占该资源,防止因资源不足而被其他服务或进程争夺资源,导致应用不可用。
      容器启动项
      • stdin:将控制台输入发送到容器。
      • tty:将标准输入控制台作为容器的控制台输入。
      特权容器
      • 选择特权容器,则privileged=true,开启特权模式。
      • 不选择特权容器,则privileged=false,关闭特权模式。
      Init Container 选中该项,表示创建一个Init Container。Init Container包含一些实用的工具,详情请参见Init Containers
    • 端口设置
      设置容器的端口。
      • 名称:设置容器端口名称。
      • 容器端口:设置暴露的容器访问端口或端口名,端口号必须介于1~65535。
      • 协议:支持TCP和UDP。
    • 环境变量
      支持通过键值对的形式为Pod配置环境变量。用于给Pod添加环境标志或传递配置等,具体请参见Pod variable
      • 类型:设置环境变量的类型,支持自定义配置项密钥变量/变量引用。配置项、密钥支持全部文件的引用,以密钥为例。
        选择密钥,选择变量,默认全部文件引用。环境变量
        对应的yaml,则引用了整个Secret。yaml
      • 变量名称:设置环境变量名称。
      • 变量/变量引用:设置变量引用的值。
    • 健康检查

      支持存活检查(liveness)和就绪检查(Readiness)。存活检查用于检测何时重启容器;就绪检查确定容器是否已经就绪,且可以接受流量。关于健康检查的更多信息,请参见Configure Liveness, Readiness and Startup Probes

      请求类型 配置说明
      HTTP请求 即向容器发送一个HTTPget请求,支持的参数包括:
      • 协议:HTTP/HTTPS。
      • 路径:访问HTTP server的路径。
      • 端口:容器暴露的访问端口或端口名,端口号必须介于1~65535。
      • HTTP头:即HTTPHeaders,HTTP请求中自定义的请求头,HTTP允许重复的header。支持键值对的配置方式。
      • 延迟探测时间(秒):即initialDelaySeconds,容器启动后第一次执行探测时需要等待多少秒,默认为3秒。
      • 执行探测频率(秒):即periodSeconds,指执行探测的时间间隔,默认为10秒,最小为1秒。
      • 超时时间(秒):即timeoutSeconds,探测超时时间。默认1秒,最小1秒。
      • 健康阈值:探测失败后,最少连续探测成功多少次才被认定为成功。默认是1,最小值是1。对于存活检查(liveness)必须是1。
      • 不健康阈值:探测成功后,最少连续探测失败多少次才被认定为失败。默认是3,最小值是1。
      TCP连接 即向容器发送一个TCP Socket,kubelet将尝试在指定端口上打开容器的套接字。 如果可以建立连接,容器被认为是健康的,如果不能就认为是失败的。支持的参数包括:
      • 端口:容器暴露的访问端口或端口名,端口号必须介于1~65535。
      • 延迟探测时间(秒):即initialDelaySeconds,容器启动后第一次执行探测时需要等待多少秒,默认为15秒。
      • 执行探测频率(秒):即periodSeconds,指执行探测的时间间隔,默认为10秒,最小为1秒。
      • 超时时间(秒):即timeoutSeconds,探测超时时间。默认1秒,最小1秒。
      • 健康阈值:探测失败后,最少连续探测成功多少次才被认定为成功。默认是1,最小值是1。对于存活检查(liveness)必须是1。
      • 不健康阈值:探测成功后,最少连续探测失败多少次才被认定为失败。默认是3,最小值是1。
      命令行 通过在容器中执行探针检测命令,来检测容器的健康情况。支持的参数包括:
      • 命令行:用于检测容器健康情况的探测命令。
      • 延迟探测时间(秒):即initialDelaySeconds,容器启动后第一次执行探测时需要等待多少秒,默认为5秒。
      • 执行探测频率(秒):即periodSeconds,指执行探测的时间间隔,默认为10秒,最小为1秒。
      • 超时时间(秒):即timeoutSeconds,探测超时时间。默认1秒,最小1秒。
      • 健康阈值:探测失败后,最少连续探测成功多少次才被认定为成功。默认是1,最小值是1。对于存活检查(liveness)必须是1。
      • 不健康阈值:探测成功后,最少连续探测失败多少次才被认定为失败。默认是3,最小值是1。
    • 生命周期

      您可以为容器的生命周期配置启动执行、启动后处理和停止前处理。具体参见配置生命周期

      • 启动执行:为容器设置预启动命令和参数。
      • 启动后处理:为容器设置启动后的命令。
      • 停止前处理:为容器设置预结束命令。
      生命周期
    • 数据卷
      支持增加本地存储和云存储声明(PVC)。
      • 本地存储:支持主机目录(hostpath)、配置项(configmap)、保密字典(secret)和临时目录,将对应的挂载源挂载到容器路径中。更多信息参见volumes
      • 云存储声明(PVC):支持云存储。
      本例中配置了一个云存储类型的数据卷声明disk-ssd,将其挂载到容器的/tmp路径下。配置数据卷
    • 日志配置
      配置日志服务,您可进行采集配置和自定义Tag设置。
      注意 请确保已部署Kubernetes集群,并且在此集群上已安装日志插件。
      配置项 描述
      采集配置 日志库:即在日志服务中生成一个对应的Logstore,用于存储采集到的日志。
      容器内日志路径:支持stdout和文本日志。
      • stdout:表示采集容器的标准输出日志。
      • 文本日志:表示收集容器内指定路径的日志,本例中表示收集/var/log/nginx下所有的文本日志,也支持通配符的方式。
      自定义Tag 您还可设置自定义Tag,设置Tag后,会将该Tag一起采集到容器的日志输出中。自定义Tag可帮助您给容器日志打上Tag,方便进行日志统计和过滤等分析操作。
  9. 完成容器配置后,单击下一步
  10. 可选:进行高级配置。
    • 访问设置
      说明

      针对应用的通信需求,您可灵活进行访问设置:

      • 内部应用:对于只在集群内部工作的应用,您可根据需要创建ClusterIP或NodePort类型的服务,来进行内部通信。
      • 外部应用:对于需要暴露到公网的应用,您可以采用两种方式进行访问设置。
        • 创建LoadBalancer类型的服务:使用阿里云提供的负载均衡服务SLB(Server Load Balancer),该服务提供公网访问能力。
        • 创建路由(Ingress):通过路由(Ingress)提供公网访问能力,详情请参见Ingress

      您可以设置暴露后端Pod的方式。本例中选择ClusterIP服务和路由(Ingress),构建一个公网可访问的Nginx应用。

      配置项 描述
      服务(Service) 服务(Service)右侧,单击创建设置创建服务的配置项。配置项的详情,请参见创建服务。本例中服务类型选择ClusterIP
      路由(Ingress) 路由(Ingress)右侧,单击创建。在弹出的对话框中,为后端Pod配置路由规则。详细的路由配置信息,请参见路由配置说明
      说明 通过镜像创建应用时,您仅能为一个服务创建路由(Ingress)。本例中使用一个虚拟主机名称作为测试域名,您需要在Hosts中添加一条记录。在实际工作场景中,请使用备案域名。
      101.37.224.146   foo.bar.com    #即ingress的IP
      访问设置区域中,您可看到创建完毕的服务和路由,您可单击变更删除进行二次配置。变更或删除路由
    • 伸缩配置
      您可选中是否开启容器组水平伸缩,为了满足应用在不同负载下的需求,容器服务支持服容器组Pod的弹性伸缩,即根据容器CPU和内存资源占用情况自动调整容器组数量。
      说明 若要启用自动伸缩,您必须为容器设置所需资源,否则容器自动伸缩无法生效。
      • 指标:支持CPU和内存,需要和设置的所需资源类型相同。
      • 触发条件:资源使用率的百分比,超过该使用量,容器开始扩容。
      • 最大副本数:该负载类型可扩容的容器数量上限。
      • 最小副本数:该负载类型可缩容的容器数量下限。
    • 调度设置
      您可设置升级方式、节点亲和性、应用亲和性和应用非亲和性,详情请参见Affinity and anti-affinity
      说明 亲和性调度依赖节点标签和Pod标签。您可使用内置的标签进行调度;也可预先为节点、Pod配置相关的标签。
      配置项 描述
      升级方式

      升级方式包括滚动升级(Rollingupdate)和替换升级(Recreate),详细请参见Deployments

      节点亲和性 设置节点亲和性,通过Worker节点的Label标签进行设置。
      节点调度支持硬约束和软约束(Required/Preferred),以及丰富的匹配表达式(In, NotIn, Exists, DoesNotExist. Gt, and Lt):
      • 必须满足,即硬约束,一定要满足,对应requiredDuringSchedulingIgnoredDuringExecution,效果与NodeSelector相同。本例中Pod只能调度到具有对应标签的Worker节点。您可以定义多条硬约束规则,但只需满足其中一条。
      • 尽量满足,即软约束,不一定满足,对应preferredDuringSchedulingIgnoredDuringExecution。本例中,调度会尽量不调度Pod到具有对应标签的Node节点。您还可为软约束规则设定权重,具体调度时,若存在多个符合条件的节点,权重最大的节点会被优先调度。您可定义多条软约束规则,但必须满足全部约束,才会进行调度。
      应用亲和性 决定应用的Pod可以和哪些Pod部署在同一拓扑域。例如,对于相互通信的服务,可通过应用亲和性调度,将其部署到同一拓扑域(如同一个主机)中,减少它们之间的网络延迟。
      根据节点上运行的Pod的标签(Label)来进行调度,支持硬约束和软约束,匹配的表达式有:In, NotIn, Exists, DoesNotExist
      • 必须满足,即硬约束,一定要满足,对应requiredDuringSchedulingIgnoredDuringExecution,Pod的亲和性调度必须要满足后续定义的约束条件。
        • 命名空间:该策略是依据Pod的Label进行调度,所以会受到命名空间的约束。
        • 拓扑域:即TopologyKey,指定调度时作用域,这是通过Node节点的标签来实现的,例如指定为kubernetes.io/hostname,那就是以Node节点为区分范围;如果指定为beta.kubernetes.io/os,则以Node节点的操作系统类型来区分。
        • 选择器:单击选择器右侧的加号按钮,您可添加多条硬约束规则。
        • 查看应用列表:单击应用列表,弹出对话框,您可在此查看各命名空间下的应用,并可将应用的标签导入到亲和性配置页面。
        • 硬约束条件:设置已有应用的标签、操作符和标签值。本例中,表示将待创建的应用调度到该主机上,该主机运行的已有应用具有app:nginx标签。
      • 尽量满足,即软约束,不一定满足,对应preferredDuringSchedulingIgnoredDuringExecution。Pod的亲和性调度会尽量满足后续定义的约束条件。对于软约束规则,您可配置每条规则的权重,其他配置规则与硬约束规则相同。
        说明 权重:设置一条软约束规则的权重,介于1~100,通过算法计算满足软约束规则的节点的权重,将Pod调度到权重最大的节点上。
      应用非亲和性
      决定应用的Pod不与哪些Pod部署在同一拓扑域。应用非亲和性调度的场景包括:
      • 将一个服务的Pod分散部署到不同的拓扑域(如不同主机)中,提高服务本身的稳定性。
      • 给予Pod一个节点的独占访问权限来保证资源隔离,保证不会有其它Pod来分享节点资源。
      • 把可能会相互影响的服务的Pod分散在不同的主机上。
      说明 应用非亲和性调度的设置方式与亲和性调度相同,但是相同的调度规则代表的意思不同,请根据使用场景进行选择。
      调度容忍 容忍被应用于Pod,允许这个Pod被调度到相对应的污点上。
      调度到虚拟节点 设置是否调度到虚拟节点。如果您集群中没有虚拟节点,则无法设置该配置项。
    • 标签和注释
      • Pod标签:为该Pod添加一个标签,标识该应用。
      • Pod注解:为该Pod添加一个注解(annotation)。
  11. 单击创建
  12. 创建成功后,默认进入创建完成页面,会列出应用包含的对象,您可以单击查看应用详情进行查看。

    默认进入有状态副本集详情页面。

  13. 然后单击左上角返回列表,进入有状态副本集列表页面,查看创建的StatefulSet应用。
  14. 可选:选择所需的Nginx应用,单击右侧伸缩,验证服务伸缩性。
    1. 在弹出的对话框中,将容器组数量设置为3,您可发现扩容时,扩容容器组的排序依次递增;反之,进行缩容时,先按Pod次序从高到低进行缩容。这体现StatefulSet中Pod的次序稳定性。
      验证服务伸缩
    2. 单击左侧导航栏中的存储卷 > 存储声明,您可发现,随着应用扩容,会随着Pod创建新的云存储卷。缩容后,已创建的PV/PVC不会删除。

相关操作

在左侧导航栏单击集群,单击目标集群名称或目标集群操作列下的应用管理,在集群管理页左侧导航栏中选择工作负载,单击有状态页签,在有状态页面单击目标应用名称或目标应用操作列下的详情,在应用详情页面您可以编辑伸缩查看Yaml重新部署刷新应用。

  • 编辑:在应用详情页面单击编辑,您可以修改应用信息。
  • 伸缩:在应用详情页面单击伸缩,您可以修改所需容器组数量。
  • 查看Yaml:在应用详情页面单击查看Yaml,您可以更新下载另存为Yaml文件。
  • 重新部署:在应用详情页面单击重新部署,您可以重新部署应用。
  • 刷新:在应用详情页面单击刷新,您可以刷新应用。

后续步骤

连接到Master节点,执行以下命令,验证持久化存储特性。

  1. 在云盘中创建临时文件:
    kubectl exec nginx-1 ls /tmp            #列出该目录下的文件lost+found
    
    kubectl exec nginx-1 touch /tmp/statefulset         #增加一个临时文件statefulset
    
    kubectl exec nginx-1 ls /tmp
    lost+found
    statefulset
  2. 删除Pod,验证数据持久性:
    kubectl delete pod nginx-1
    pod"nginx-1" deleted
  3. 过一段时间,待Pod自动重启后,验证数据持久性,证明StatefulSet应用的高可用性。
    kubectl exec nginx-1 ls /tmp                         #数据持久化存储lost+found
    statefulset