总结归纳Kubernetes | 一站式速查知识,助您轻松驾驭容器编排技术(水平扩展控制)

news2024/11/24 2:19:48

Kubernetes,亦被称为K8s,是业界公认的容器编排巨擘,以其卓越的能力简化了容器化应用的部署、扩展和管理流程。通过其强大的功能,Kubernetes不仅提升了应用的可靠性和可伸缩性,还优化了资源利用率,为开发者和运维人员提供了更加高效、灵活的容器运行环境。

在传统的应用部署模式中,不同环境间的基础设施与配置差异构成了巨大的挑战,使得跨环境部署变得困难重重。然而,Kubernetes的出现彻底改变了这一局面。它通过构建一个统一的容器编排平台,巧妙地将底层基础设施的复杂性进行了抽象,让开发人员能够摆脱繁琐的环境配置问题。在Kubernetes的助力下,应用程序可以在不同环境中实现一致且高效的部署与管理,这不仅极大地提升了应用的可移植性,更为未来的扩展性奠定了坚实的基础。

文章主旨

本篇文章是学习开发使用k8s的必备工具,提供了对无缝部署管理所需的基本命令的快速访问。让我们将其视为快节奏Kubernetes环境中的必备指南,以提高生产力,减少错误,并确保在复杂任务中的高效导航。不仅包含了Kubernetes中最常用的命令,还提供了针对特定任务的实用提示和最佳实践。无论您是经验丰富的Kubernetes管理员还是初学者,这份速查表都将成为您日常工作中的宝贵资源。

通过本系列文章,您可以快速了解如何创建和管理部署(Deployments)、服务(Services)、持久存储(Persistent Storage)以及其他Kubernetes资源。


基础认识

下面是关于Kubernetes所需的关键组件的介绍:

Kubernetes 概念描述
PodKubernetes 中的最小可部署单元,它是运行容器的资源对象。
Node集群中的物理或虚拟机,用于运行 Pod。
Deployment描述一组 Pod 的期望状态,用于管理 Pod 的创建、更新和删除。
Service定义一组 Pod 和访问它们的策略,用于实现服务的发现和负载均衡。
Labels附加到对象上的键值对,用于灵活分类和选择资源。用于标识和分组相关资源。
MasterKubernetes 的控制平面,管理集群的整体状态。包括 API 服务器、etcd、控制器管理器和调度器等组件。

基础架构

Kubernetes 采用高效的客户端-服务器架构,其核心由控制平面(Control Plane)和一组专门用于运行容器的节点(Nodes)构成。这种架构确保了系统的可扩展性、灵活性和可靠性,使得 Kubernetes 成为容器编排领域的佼佼者。

Kubernetes 客户端-服务器架构

Kubernetes 采用客户端-服务器架构,由控制平面(Control Plane)和一组运行容器的节点(Nodes)组成。

在这里插入图片描述

控制平面(Control Plane)

控制平面是 Kubernetes 集群的大脑,负责做出全局决策,如调度工作负载、维护集群的状态等。控制平面主要由以下几个组件组成:

  1. API 服务器(API Server)

    • 提供 RESTful API,供用户和其他组件与 Kubernetes 集群交互。
    • 负责认证、授权和 API 访问控制。
  2. etcd

    • 一个高度可用的键值存储系统,用于持久保存集群的状态。
    • 控制平面组件使用 etcd 存储集群数据,如 Pod、Service、Deployment 等的配置和状态信息。
  3. 控制器管理器(Controller Manager)

    • 负责运行各种控制器,这些控制器是后台进程,用于处理集群中资源对象(如 Pods、ReplicationControllers、Services 等)的创建、更新、删除和复制等操作。
    • 例如,复制控制器(ReplicationController)确保指定数量的 Pod 副本始终在运行。
  4. 调度器(Scheduler)

    • 负责决定新 Pod 应该被调度到哪个 Node 上运行。
    • 考虑各种因素,如资源可用性、硬件限制、Pod 的约束和亲和性等。

节点(Nodes)

节点是 Kubernetes 集群的工作负载运行场所,每个节点都运行着以下组件:

  1. Kubelet

    • 负责管理 Pod 和容器,确保容器按照期望的状态运行。
    • 与 Master 节点上的 API 服务器通信,接收并执行指令。
  2. Kube-proxy

    • 负责实现 Kubernetes Service 的网络代理功能。
    • 它能够处理网络流量,实现 Service 的负载均衡和网络访问。
  3. 容器运行时(Container Runtime)

    • 如 Docker、containerd 或 CRI-O 等。
    • 负责运行和管理容器。

客户端工具

此外,Kubernetes 还提供了一系列客户端工具,如 kubectl,它是 Kubernetes 的命令行界面(CLI),用于与集群进行交互,执行如部署应用、管理资源等操作。

通过这种架构,Kubernetes 能够在控制平面和节点之间实现高效的协调,为用户提供易于使用和灵活强大的容器编排功能。

基础命令

在掌握了Kubernetes的基本术语和架构之后,接下来我们需要熟悉一些关键的基础命令,以便更好地管理Kubernetes集群。这些命令不仅能够帮助我们深入了解集群的状态和配置,还能快速概览可用资源及其版本。通过运用这些命令,我们能够更加高效地管理Kubernetes集群,确保系统的稳定运行和资源的合理利用。

CommandDescription
kubectl cluster-info显示集群中主节点和服务的端点信息。
kubectl version显示客户端和服务器上运行的Kubernetes版本。
kubectl config view获取集群的配置信息。
kubectl api-resources列出所有可用的API资源。
kubectl api-versions列出所有可用的API版本。
kubectl get all --all-namespaces列出所有命名空间中的所有资源。

具体来说,这些命令提供了集群的整体信息,包括版本、配置、API资源等关键要素。通过执行这些命令,我们可以快速了解集群的当前状态,以及哪些资源是可用的。这对于日常维护和故障排除非常有帮助,能够让我们及时发现问题并采取相应的措施。


Pod和容器

Pod是Kubernetes中最小的可部署单元,代表着集群中运行进程的单一实例,作为基本的构建模块,Pod可以容纳一个或多个容器,这些容器共享相同的网络命名空间,从而允许它们通过localhost进行无缝通信。

容器是一种轻量级、独立且可执行的软件包,它封装了运行软件所需的所有依赖,包括代码、运行时环境、库和系统工具。通过容器,应用程序能够获得一个稳定且隔离的运行环境,确保其在不同场景下都能保持一致的表现。

创建、管理 pod 和排除故障的常用命令

CommandDescription
kubectl apply -f <pod_configuration>使用YAML文件中指定的配置来创建或更新Pod。
kubectl get pods列出默认命名空间中的所有Pod。
kubectl get pods --all-namespaces列出所有命名空间中的所有Pod。
kubectl describe pod <pod_name>显示特定Pod的详细信息。
kubectl logs <pod_name>查看特定Pod的日志。
kubectl exec -it <pod_name> -- /bin/bash在正在运行的容器中打开一个交互式shell。
kubectl delete pod <pod_name>删除特定的Pod。
kubectl port-forward <pod_name> <local_port>:<pod_port>将Pod的端口转发到本地机器。

Pod和容器的设计分析

在 Kubernetes 环境中,高效的容器化策略对于应用程序的顺畅部署和管理至关重要。以下是优化容器化应用程序的几个核心设计:

在这里插入图片描述

  • 遵循单一职责原则,确保每个容器都具备明确且特定的功能。这种模块化设计不仅简化了维护流程,还增强了应用程序的稳健性。
  • 尽可能减小容器镜像的大小,通过去除不必要的层级和依赖关系来实现。较小的镜像能够加快部署速度,同时减少资源消耗,从而提升整体性能。
  • 利用环境变量来配置应用程序,以提高其灵活性和可调整性。这种方法允许在不修改容器镜像的情况下轻松调整设置,从而适应不同的环境和需求。
  • 在应用程序中实施健康检查机制,使 Kubernetes 能够准确评估其健康状态。这有助于实现自动修复和确保可靠的应用程序性能,减少潜在的运行时问题。
  • 为容器设置合理的 CPU 和内存等资源限制,以防止资源过度消耗。通过限制容器的资源使用,可以确保公平的资源分配,避免个别行为异常的容器对整个集群产生不良影响。

Pod指令大全快速查找

在这里插入图片描述

创建pod容器的Yaml格式

在 Kubernetes 中,采用多容器 Pod 的策略可以显著增强同一 Pod 内部各容器间的协作与资源共享能力。以下是几种不同的多容器模式的代码示例,以展示其实际应用。

在这里插入图片描述

介绍之前,先给大家总结一个Pod的结构的yaml基础结构图

 

yaml

复制代码

apiVersion:API版本,指定了Pod的配置所遵循的Kubernetes API版本 kind:资源类型,指定为"Pod" metadata:元数据,包含了关于Pod的信息 - name:Pod的名称 - labels:标签,用于标识和选择Pod spec:规格,定义了Pod的规格和配置 - containers:容器列表,包含了Pod中的一个或多个容器 - name:容器名称 - image:容器所使用的镜像 - ports:容器的端口配置 - containerPort:容器内部的端口号 - protocol:协议类型(如TCP、UDP) - volumes:卷列表,用于挂载到Pod中的容器中 - name:卷名称 - emptyDir:空目录,用于将容器的临时数据存储在内存中

这是一个基本的Kubernetes(k8s)Pod的基本结构,你可以根据自己的需要进一步添加和修改配置。

Sidecar容器模式

Sidecar 容器模式是一种创新的容器编排策略,它允许在主应用程序容器的旁边部署一个或多个辅助容器,用以增强或扩展主容器的功能。

 

yaml

复制代码

apiVersion: v1 kind: Pod metadata: name: sidercar-pod spec: containers: - name: main-server image: main-server:1.0 ports: - containerPort: 8081 - name: sidecar-collector image: sidecar-collector:1.0 ports: - containerPort: 8082

这种模式的独特之处在于其能够无缝集成日志收集、监控等额外功能,使应用程序的运行更加高效和可靠。通过 Sidecar 容器,开发人员能够更灵活地管理和维护应用程序,提升整个系统的可扩展性和可维护性。

Adapter容器模式

Adapter 容器模式是一种强大的策略,它专门设计用来在应用程序与特定的后端服务或资源(例如数据库)之间建立适配层。这种模式的目的是将后端通信的复杂性封装在 Adapter 容器中,从而保持主应用程序容器的清晰和简洁。通过 Adapter 容器,开发人员能够将应用程序与后端服务的解耦,提高代码的模块化和可维护性,同时确保应用程序的稳定运行和可扩展性。

 

yaml

复制代码

apiVersion: v1 kind: Pod metadata: name: adapter-pod spec: containers: - name: main-server image: main-server:1.0 ports: - containerPort: 8081 - name: pgdata-adapter image: pgdata:1.0 ports: - containerPort: 8082

适配器容器在数据流向主应用程序之前,会对其进行必要的转换或调整,以确保数据的兼容性和有效性。这一过程旨在消除不同系统间的差异,提供一个统一、无缝的集成点,使应用程序能够无缝地利用后端资源,实现更顺畅、高效的数据流通。

Ambassador容器模式

在这种架构中,Ambassador 容器扮演着至关重要的中介角色,它代表主应用程序处理所有通信和网络相关任务,确保数据的安全、高效和准确传输。

 

yaml

复制代码

apiVersion: v1 kind: Pod metadata: name: Ambassador-pod spec: containers: - name: main-server image: main-server:1.0 ports: - containerPort: 8081 - name: Ambassador-adapter image: Ambassador:1.0 ports: - containerPort: 8082

Ambassador 容器模式类似于Adapter,但更侧重于提供与外部世界(如 API 网关)的通信。使用不同类型的容器,以实现更灵活和强大的应用程序部署和管理。通过结合这些模式,您可以根据应用程序的需求和架构来定制和优化 Pod 的设计。

最后还有一种init模式,配置方式类似,在这里我就不一一列举了,Init 容器在应用程序容器启动之前运行,常用于执行一些前置条件,如配置环境、下载依赖或等待外部资源就绪。有兴趣的小伙伴,可以好好研究一下。

Deployments和ReplicaSets

Deployments与ReplicaSets在Kubernetes 集群中扮演着至关重要的角色,共同管理应用程序的部署、扩展和更新生命周期,部署和副本集共同协作,为 Kubernetes 集群中的应用程序提供了强大而灵活的管理和扩展能力,确保了应用程序的高可用性和稳定性。

  • 部署(Deployment)是 Kubernetes 中的一个核心概念,它提供了一种声明式的方式来定义、更新和管理应用程序的生命周期。通过部署,开发人员可以轻松地指定他们希望运行的应用程序版本和配置,而 Kubernetes 则会负责实际的部署和更新过程。

  • 副本集(ReplicaSet)与部署紧密关联,它充当了一个控制器的角色,确保指定数量的相同 Pod 副本始终在运行状态。这意味着,无论发生何种故障或变化,副本集都会确保有足够的 Pod 副本可用,以满足应用程序的需求和性能要求。

生命周期

Kubernetes 中的部署管理 pod 的部署和扩展,提供了一种声明式方法来定义所需的状态。生命周期包括几个关键阶段:

在这里插入图片描述

  • 部署创建:首先,您需要创建一个部署,其中明确指定所需的副本数量以及 pod 的模板规格。这是部署过程的基础。

  • 副本集生成:一旦部署被创建,Kubernetes 将自动生成一个与之关联的 ReplicaSet。这个 ReplicaSet 的职责是确保始终有指定数量的 pod 副本正在运行。

  • Pod 创建与扩展:根据在部署中定义的模板,ReplicaSet 会负责创建单个 pod。当您需要扩展应用程序时,只需调整所需的副本数量即可。部署会实时监控并确保始终维持正确的 pod 数量。

  • 滚动更新机制:当您需要更新应用程序时,部署系统将采用一种称为滚动更新的策略。这意味着,它会使用更新后的配置来创建新的 ReplicaSet,同时逐步缩减旧的 ReplicaSet。这一过程确保了更新过程中的平滑过渡,避免了服务中断。

  • 终止与完成:最终,旧的 ReplicaSet 会被完全缩减至零,标志着更新过程的结束。此时,整个系统已完全过渡到使用更新后的配置和 pod。

Deployments指令大全快速查找

在这里插入图片描述

部署和管理滚动更新扩展应用程序的方案

扩展部署

  • 扩展至指定数量的副本: kubectl scale deployment <deployment_name> --replicas=<num>
  • 根据CPU使用率自动扩展: kubectl autoscale deployment <deployment_name> --cpu-percent=<percentage> --min=<min_replicas> --max=<max_replicas

管理滚动更新

  • 使用新镜像更新部署: kubectl set image deployment/<deployment_name> <container_name>=<new_image>
  • 监控滚动更新进度: kubectl rollout status deployment/<deployment_name>
  • 回滚到先前版本:kubectl rollout undo deployment/<deployment_name>
  • 暂停和恢复滚动更新:kubectl rollout pause deployment/<deployment_name>kubectl rollout resume deployment/<deployment_name>
  • 自定义更新策略:kubectl apply -f customer-deployment-strategy.yaml

这些命令为快速扩展部署、满足需求以及有效管理滚动更新提供了便捷的参考。无论您需要调整副本数量,还是希望运用不同的策略来协调更新,这份详尽的指南都将助您一臂之力,极大地简化 Kubernetes环境中的部署流程。

创建和更新ReplicaSet的案例

创建ReplicaSet

配置文件定义了一个名为 demo-replicaset 的 ReplicaSet,其主要职责是确保运行三个 pod 副本。每个 pod 都基于一个模板创建,该模板包含了一个名为 demo-container 的容器,该容器使用 demo-image:latest 镜像。

 

yaml

复制代码

apiVersion: apps/v1 kind: ReplicaSet metadata: name: demo-replicaset spec: replicas: 3 selector: matchLabels: app: demo template: metadata: labels: app: demo spec: containers: - name: demo-container image: demo-image:latest

这样的配置有助于确保应用程序的高可用性和可扩展性,当某个pod出现故障或被删除时,ReplicaSet会自动启动新的 pod 以替代它。

更新ReplicaSet
 

yaml

复制代码

apiVersion: apps/v1 kind: ReplicaSet metadata: name: demo-replicaset spec: replicas: 5 # Update the number of replicas selector: matchLabels: app: demo template: metadata: labels: app: demo spec: containers: - name: demo-container image: updated-demo-image:latest # Update the container image

YAML 配置现在针对名为 'demo-replicaset' 的现有 ReplicaSet 进行了更新。新的配置将所需的副本数量调整至 5 个,同时,Pod 模板也经过了更新,现在使用 'updated-demo-image:latest' 作为容器镜像。这些更改将确保 ReplicaSet 能够以更高的可用性和灵活性运行,以满足不断变化的业务需求。"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1494941.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MM配置1-定义、复制、删除、检查工厂

配置步骤&#xff0c;如下图&#xff1a; 双击“复制&#xff0c;删除&#xff0c;检查工厂选项” 点击“复制”按钮&#xff0c;输入参考工厂&#xff0c;和要新建的工厂 复制完成后&#xff0c;返回到上一界面&#xff0c;双击“定义工厂”选项 选中新建的1070工厂&#xff0…

java常用技术栈,java面试带答案

前言 我们从一个问题引入今天的主题。 在日常业务开发中&#xff0c;我们可能经常听到 DBA 对我们说“不要”&#xff08;注意&#xff1a;不是禁止&#xff09;使用 join&#xff0c;那么为什么 DBA 对 join 这么抵触呢&#xff1f;是 join 本身有问题&#xff0c;还是我们使…

HarmonyOS 数据持久化之首选项 preferences

接下来 我们来说说数据持久化的问题 我们平时处理的数据都是在内存中处理的 我们应用一点重启 所有数据都消失了 肯恩是不符合一些场景的 harmonyos中 提供了比较多的解决方案 最多的两种是 用户首选项 关系型数据库 本文的话 我们就来看看 用户首选项 首先&#xff0c;什么…

Android开发新手入门教程,android笔试面试题

前言 尤其是在最近一段时间内&#xff0c;感觉一天天的时间过得又慢又快&#xff0c;慢的是感觉复工了以后在公司的8.9个小时简直算是煎熬了&#xff0c;快的是常常感觉时间一天天&#xff0c;一月月的过去了&#xff0c;可是发现自己还在原路踏步走。看似每天忙成狗&#xff…

【数学建模】层次分析

1.建立递阶层次结构模型 2.构造出各层次中的所有判断矩阵 对指标的重要性进行两两比较&#xff0c;构造判断矩阵&#xff0c;科学求出权重 矩阵中元素aij的意义是&#xff0c;第i个指标相对第j个指标的重要程度 对角线1&#xff0c;aijaji1 矛盾——>一致性检验

win11配置Mask DINO小白踩坑记录

win11配置Mask DINO踩坑记录 1 准备工作2 创建python环境和安装detectron22.1 安装前提2.2 安装流程2.2.1 cl.exe的错误2.2.2 SetuptoolsDeprecationWarning的错误 3 MaskDINO运行3.1 运行demo 前情提要&#xff1a;需要复现Mask DINO&#xff0c;但是实验室没有Linux的电脑&am…

+++

解法&#xff1a; 显然a可以为aik&#xff08;i为整数&#xff09;&#xff0c;b可以为bjk(j为整数&#xff09;。 若aikbjk。假定i>j&#xff0c;那么a<b。可以得到b-a(i-j)k 我是傻逼&#xff0c;不放代码了 #include<iostream> #include<vector> #inc…

Tomcat基础与Nginx的动静分离

一、TOMCAT基础功能 &#xff08;一&#xff09;自动解压war包 在配置文件中讲到&#xff0c;当接受到请求后&#xff0c;会匹配符合要求的Host&#xff0c;在配置文件中的Host只有一个&#xff0c;且规定了自动解压war包 自动解压war包 .war&#xff1a;WebApp打包,类zip格…

【ESP32 IDF】SPI层次结构SPI协议与SPI控制器结构

文章目录 前言一、SPI 程序层次1.1 硬件原理图1.2 硬件框图1.3 软件层次 二、SPI协议2.1 硬件连线2.2 如何访问SPI设备2.3 SPI 框图 总结 前言 SPI&#xff08;Serial Peripheral Interface&#xff09;是一种常见的串行通信协议&#xff0c;用于在微控制器和外部设备之间进行…

Qt QtCreator打开pro项目时出现假死现象

在Windows系统下&#xff0c;QtCreator打开pro项目时出现假死现象&#xff0c;左侧项目树形图无法展开&#xff0c;项目根节点一直在转圈。尝试关掉所有QtCreator进程&#xff0c;重新打开pro也是无济于事。 解决方案&#xff1a; 打开“运行”窗口&#xff08;快捷键&#x…

鸿蒙文章专题-2021年鸿蒙相关的文章废弃

#原因 至于为什么说2021年我的鸿蒙专栏的文章废弃了&#xff0c;只是说没有了参考意义&#xff0c;是因为鸿蒙4.0以前的版本语言从以Java为主过渡为以ArkTS为主。以前的Java版本的工程已经无法再使用了&#xff0c;后续的开发都必须以ArkTS开发语言为主。 其中而且整个项目结构…

操作教程|使用MeterSphere对恒生UFX系统进行压力测试

恒生UFX&#xff08;United Finance Exchange&#xff0c;统一金融交换&#xff09;系统&#xff08;以下简称为“UFX系统”&#xff09;&#xff0c;是一款帮助证券公司统一管理外部接入客户的系统&#xff0c;该系统整体上覆盖了期货、证券、基金、银行、信托、海外业务等各类…

Python 服务实现可观测性最佳实践

前言 本次实践主要是介绍 Python 服务通过无侵入的方式接入观测云进行全面的可观测。 环境信息 系统环境&#xff1a;主机环境开发语言&#xff1a;Python2.7APM 探针包&#xff1a;ddtrace 接入方案 准备工作 安装 DataKit 主机安装 DataKit # 需要把token 改成观测云…

xss.haozi.me靶机 通关

0x00 没有任何过滤可以直接注入<img srcx οnerrοralert(1)> 0x01 使用了testarea标签将我们的输入内容以普通的字符串进行展示 但是我们可以将标签进行闭合 </textarea><img srcx οnerrοralert(1)> 0x02 我们依然可以先闭合之后添加属性a" οncl…

Mendix 使用OIDC组件实现SSO|Azure Microsoft Entra ID 集成(原名:AD)

引言 在快节奏的软件开发领域&#xff0c;Mendix作为一款领先的低代码开发平台&#xff0c;为企业提供了快速构建、部署和迭代应用程序的能力。这种灵活性和效率使得Mendix成为了推动数字化转型的强大工具。随着企业应用数量的激增&#xff0c;单点登录&#xff08;SSO&#x…

【debug】element-ui时间控件回显后不可编辑且显示为空

问题&#xff1a;使用element-ui的时间控件回显数据&#xff0c;编辑数据没有反应&#xff1a;点时间和“确认”按钮都没反应。 输入框中会显示数据&#xff0c;但提交时的校验显示为空。 <el-form-item label"开始时间" prop"limitStartTime"><…

【数据结构】堆的TopK问题

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解堆的TopK问题&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 一. 前言二. TopK三. 代码 一. 前言 TOP-K问题&#xff1a;即求数据结合中前K个最大的元…

专业145+总分410+西工大西北工业大学827信号与系统考研经验电子信息与通信工程,海航,真题,大纲,参考书。

经过一年的努力&#xff0c;分数终于出来。今年专业课827信号与系统145&#xff08;很遗憾差了一点点满分&#xff0c;没有达到Jenny老师的最高要求&#xff09;&#xff0c;数一130&#xff0c;英语和政治也都比较平衡&#xff0c;总分410分&#xff0c;当然和信息通信考研Jen…

类变量和类方法【静态变量 static】

类变量和类方法【静态变量 static】 类变量什么是类变量如何定义类变量如何访问类变量类变量使用注意事项和细节 类方法类方法的基本介绍类方法的调用类方法应用案例类方法经典的使用场景类方法使用注意事项和细节 类变量 什么是类变量 类变量&#xff0c;也叫静态属性/静态变…

Vue点击切换组件颜色

例如我有一个这样的组件&#xff0c;我希望在点击组件之后由蓝色变成橙色 先把原来的代码附上(简化掉了叉号&#xff09;&#xff1a; <div v-for"(item, index) in words" :key"index" class"scrollbar-demo-item"><span>{{ item …