Istio技术实践专题(1) Service Mesh Istio 基本概念和架构基础

Istio被称作Kubernetes的最佳云原生拍档。从今天起,我们推出“Istio技术实践”系列专题,在本专题中,我们将通过技术文章+视频授课的方式,为大家详细阐述Istio微服务治理,及在企业级云平台中的解决方案和实践。

什么是Service Mesh?

Service Mesh译作“服务网格”,作为服务间通信的基础设施层,Willian Morgan(Linkerd 的CEO)是这样定义Service Mesh的:

服务网格是一个用于处理服务间通信的基础设施层,它负责为构建复杂的云原生应用传递可靠的网络请求。在实践中,服务网格通常实现为一组和应用程序部署在一起的轻量级的网络代理,但对应用程序来说是透明的。

Service Mesh 实际是处于 TCP/IP 之上的一个抽象层,它假设底层的 L3/L4 网络能够点对点地传输字节(当然,它也假设网络环境是不可靠的,所以 Service Mesh 必须具备处理网络故障的能力)。

Service Mesh 有如下几个特点:

  • 多语言支持:
  • 支持几乎所有的语言,可以自由选择编程语言;
  • 业务开发变革 降低入门门槛,提高稳定性;
  • 业务开发团队从框架依赖中解放出来,回归业务;
  • 强化运维管理 对系统强大的管理和控制力;
  • 微服务治理的功能不再和应用有关。

​ Service Mesh架构图

微服务体系带来的问题

实际上,微服务并非一好百好,本质上是以运维的复杂度为代价获得敏捷性。分布式和微服务系统会带来哪些挑战呢?

首当其冲是定位和调试困难。

当遇到bug或者性能问题,原来的方式基本都是逐级排查,从客户遇到问题的地方开始。因为一个深层次的微服务会引起一系列的上层微服务出现问题。如果发现两个服务之间的整体调用性能不好,这个时候哪怕你找到某一次性能差的日志或数据,基于这个数据和日志找出来的原因不一定是root cause。这种排查问题的方式就像烽火台,你只看到了最近的烽火台,并不知道起点在哪。

第二,测试时数据会有遗漏,缺少完整的测试数据。

最好的测试数据是线上的真实数据。但是线上的请求采集下来还需要独立开发相应的程序,整体实现很麻烦。另外,如果测试微服务的错误处理,对于QA的黑盒测试来说,这还需要一个可配置的错误生成器。这点对于测试也是一个独立的工作。

第三,缺少上线流程。

我们原来使用独立的微服务作为开关,来判断是否加载新功能。在新的功能代码外层加上调用该微服务的代码,根据返回值来判断是否执行新功能代码,上线完成后再把开关代码删掉,的确有点麻烦。上线前需要修改源码增加控制,上线完成后还需要在源码中删除这些逻辑。没有简单、无侵入的金丝雀和灰度发布的实现方式。

第四,微服务间的网络调用策略配置不灵活。

不同的客户环境需要使用不同的网络策略,例如重试,超时等等设置,如果对应的设置没有通过配置文件暴露出来,就只能对代码进行修改。而且这些代码在业务代码里,统一的维护和升级都需要独立的流程。

诸如以上这些问题还有很多,涉及到成百上千个服务的通信、管理、部署、版本、安全、故障转移、策略执行、遥测和监控等,要解决这些微服务架构带来的问题并非易事。而Istio 提供了一个完整的解决方案,通过为整个服务网格提供行为洞察和操作控制来满足微服务应用的多样化需求,解决了开发人员和运维人员在向分布式微服务架构过渡时所面临的挑战。

什么是Istio?

Istio是目前受Google/IBM 等大厂支持和推进的 Service Mesh开源框架组合。官方对 Istio 的介绍:

An open platform to connect, secure, control and observe services.

翻译过来,就是”连接、安全加固、控制和观察服务的开放平台“。Istio提供一种简单的方式来建立已部署的服务的网络,具备负载均衡,服务到服务认证,监控等功能,而不需要改动任何服务代码。

Istio 允许连接、保护、控制和观测微服务,在较高的层次上,Istio 有助于降低这些部署的复杂性,并减轻开发团队的压力。它是一个完全开源的服务网格,可以透明地分层到现有的分布式应用程序上。它也是一个平台,包括允许它集成到任何日志记录平台、遥测或策略系统的 API。Istio 的多样化功能集能够成功高效地运行分布式微服务架构,并提供保护、连接和监控微服务的统一方法。

Istio 适用于容器或虚拟机环境(特别是 k8s),兼容异构架构;

Istio 使用 sidecar(边车模式)代理服务的网络,不需要对业务代码本身做任何的改动;

HTTP、gRPC、WebSocket 和 TCP 流量的自动负载均衡;

Istio 通过丰富的路由规则、重试、故障转移和故障注入,可以对流量行为进行细粒度控制;支持访问控制、速率限制和配额;

Istio 对出入集群入口和出口中所有流量的自动度量指标、日志记录和跟踪。

Istio系统架构

Istio 分为两个平面:数据平面和控制平面。

  • 数据平面:

    数据平面由一组 sidecar 的代理(Envoy)组成。这些代理调解和控制微服务之间的所有网络通信,并且与控制平面的 Mixer 通讯,接受调度策略。

  • 控制平面:

    控制平面通过管理和配置 Envoy 来管理流量。此外,控制平面配置 Mixers来实施路由策略并收集检测到的监控数据。

如上图,

数据平面由一组以 Sidecar 方式部署的智能代理(Envoy)组成。这些代理可以调节和控制微服务及 Mixer 之间所有的网络通信。

控制平面负责管理和配置代理来路由流量。此外,控制平面配置 Mixer 以实施策略和收集遥测数据。

Pilot是整个架构中的抽象层,将对接K8S等资源调度器的步骤进行抽象并以适配器的形式展现,并和用户以及Sidecar交互。

Galley负责验证资源配置。

Citadel用于生成身份,及密钥和证书管理。

核心功能包括流量控制、安全控制、可观测性、多平台支持、可定制化。

Istio 安全架构

Istio中80%的组件都参与到了安全的功能里面。

Istio 安全目标:

  • 默认安全
  • 深度防御
  • 零信任网络

Istio 安全组件:

  • citadel,管理密钥、证书
  • Sidecar,实现安全通信
  • Pilot,授权策略分发
  • Mixer,管理授权和审计

感谢参考

https://www.alauda.cn/news/blog_detail/id/416.html

Istio技术实践专题(2) Istio 核心组件介绍

上一篇文章中,我们讲到Istio的基本概念、架构基础。Istio 作为 Service Mesh 领域的集大成者, 提供了流控、安全、遥测等模型,其功能复杂,模块众多,本篇文章会对Istio 1.6.1 的各组件进行分析,帮助大家了解Istio各组件的职责、以及相互的协作关系。

Istio架构回顾

  • 数据平面:

    数据平面由一组 sidecar 的代理(Envoy)组成。这些代理调解和控制微服务之间的所有网络通信,并且与控制平面的 pilot通讯,接受调度策略。

  • 控制平面:

    控制平面通过管理和配置 Envoy 来管理流量。此外,控制平面pilot下发xds规则来实施路由策略,mixer收集检测到的监控数据。

虽然Istio 支持多个平台, 但将其与 Kubernetes 结合使用,其优势会更大, Istio 对Kubernetes 平台支持也是最完善的, 本文将基于Istio + Kubernetes 进行展开。

下面就来介绍Istio 架构中每个组件的功能及工作方式。

Istio核心组件

Sidecar ( 在 Istio 中,默认的 Sidecar 是 Envoy )

Envoy 是使用 C++ 开发的高性能代理,用于调解服务网格中所有服务的入站和出站流量。在 Istio 中,Envoy 被用于 Sidecar ,和对应的应用服务部署在同一个 Kubernetes 的 Pod 中。

Envoy 调解所有出入应用服务的流量。所有经过 Envoy 的流量行为都会调用 Mixer(只是report功能,check功能可以通过配置关闭),为Mixer 提供一组描述请求和请求周围环境的 Attribute 。根据 Envoy 的配置和 Attribute,Mixer 会调用各种后台的基础设施资源。而这些 Attribute 又可以在 Mixer 中用于决策使用何种策略,并发送给监控系统,以提供整个网格行为的信息。

Pilot

Pilot 为 Sidecar 提供“服务发现”功能,并管理高级路由( 如 A/B 测试和金丝雀部署 )和故障处理( 超时、重试、熔断器等 )的流量。Pilot 将这些“高级”的流量行为转换为详尽的 Sidecar (即 Envoy) 配置项,并在运行时将它们配置到 Sidecar 中。

Pilot 将服务发现机制提炼为供数据面使用的 API ,即任何 Sidecar 都可以使用的标准格式。这种松耦合的设计模式使 Istio 能在多种环境( Kubernetes、Consul 和 Nomad )下运行,同时保持用于流量管理操作的相同。

除了服务发现, Pilot 更重要的一个功能是向数据面下发规则,包括VirtualService 、DestinationRule 、Gateway 、ServiceEntry 等流量治理规则,也包括认证授权等安全规则。Pilot 负责将各种规则转换成Envoy 可识别的格式,通过标准的XDS 协议发送给Envoy,指导Envoy 完成功作。在通信上, Envoy 通过gRPC 流式订阅Pilot 的配置资源。如下图所示, Pilot 将VirtualService 表达的路由规则分发到Evnoy 上, Envoy 根据该路由规则进行流量转发。

Mixer

Mixer 是一个独立于平台的组件,通过从 Sidecar 和一些其他服务处收集数据,进而在整个 Service Mesh 上控制访问和执行策略。Sidecar 请求级别的 Attribute 被发送到 Mixer 进行评估。

Mixer 中还包括一个灵活的插件,使其能接入各种主机环境和基础设施的后段,并得到 Sidecar 代理和 Istio 所管理的服务。

Mixer 的设计具有以下特点:

  • 无状态:Mixer 本身是无状态的,它没有持久化存储的管理功能。
  • 高可用:Mixer 被设计成高度可用的组件,任何单独的 Mixer 实例实现 > 99.999% 的正常运行时间。
  • 缓存和缓冲:Mixer 能够积累大量短暂的瞬间状态。

Mixer 是Istio 独有的一种设计,不同于Pilot ,在其他平台上总能找到类似功能的服务组件。从调用时机上来说,Pilot 管理的是配置数据,在配置改变时和数据面交互即可;然而,对于Mixer 来说,在服务间交互时Envoy 都会对Mixer 进行一次调用,因此这是一种实时管理。当然,在实现上通过在Mixer 和Proxy 上使用缓存机制,可保证不用每次进行数据面请求时都和Mixer 交互。

Istio-telemetry

Istio-telemetry是专门用于收集遥测数据的Mixer服务组件;

如下图所示 所示,当网格中的两个服务间有调用发生时,服务的代理Envoy 就会上报遥测数据给Istio-telemetry服务组件,Istio-telemetry 服务组件则根据配置将生成访问Metric等数据分发给后端的遥测服务。数据面代理通过Report 接口上报数据时访问数据会被批量上报。

Istio-policy

Istio-policy 是另外一个Mixer 服务,和Istio-telemetry 基本上是完全相同的机制和流程。

如图所示,数据面在转发服务的请求前调用Istio-policy 的Check接口检查是否允许访问, Mixer 根据配置将请求转发到对应的Adapter 做对应检查,给代理返回允许访问还是拒绝。可以对接如配额、授权、黑白名单等不同的控制后端,对服务间的访问进行可扩展的控制。

Citadel

Citadel 通过内置身份和凭证管理提供“服务间”和“最终用户”身份验证。Citadel 可用于升级服务网格中未加密的流量,并能够为运维人员提供基于服务标识( 如 Kubernetes 中 Pod 的标签或版本号 )而不是网络层的强制执行策略。

Citadel 一直监听Kube-apiserver ,以Secret 的形式为每个服务都生成证书密钥,并在Pod 创建时挂载到Pod 上,代理容器使用这些文件来做服务身份认证,进而代理两端服务实现双向TLS认证、通道加密、访问授权等安全功能,这样用户就不用在代码里面维护证书密钥了。如下图所示,frontend 服务对forecast 服务的访问用到了HTTP 方式,通过配置即可对服务增加认证功能, 双方的Envoy 会建立双向认证的TLS 通道,从而在服务间启用双向认证的HTTPS 。

Istio-galley

Istio-galley 并不直接向数据面提供业务能力,而是在控制面上向其他组件提供支持。Galley 作为负责配置管理的组件,验证配置信息的格式和内容的正确性,并将这些配置信息提供给管理面的Pilot和Mixer服务使用,这样其他管理面组件只用和Galley 打交道,从而与底层平台解耦。在新的版本中Galley的作用越来越核心

Istio-sidecar-injector

Istio-sidecar-injector 是负责向动注入的组件,只要开启了自动注入,在Pod 创建时就会自动调用Istio-sidecar-injector 向Pod 中注入Sidecar 容器。

在Kubernetes环境下,根据自动注入配置, Kube-apiserver 在拦截到Pod 创建的请求时,会调用自动注入服务Istio-sidecar-injector生成Sidecar 容器的描述并将其插入原Pod的定义中,这样,在创建的Pod 内除了包括业务容器,还包括Sidecar 容器。这个注入过程对用户透明,用户使用原方式创建工作负载。

Istio-ingressgateway

Istio-ingressgateway 就是入口处的Gateway ,从网格外访问网格内的服务就是通过这个Gateway 进行的。Istio-ingressgateway 比较特别,是一个Loadbalancer 类型的Service,不同于其他服务组件只有一两个端口, Istio-ingressgateway 开放了一组端口,这些就是网格内服务的外部访问端口.如下图 所示,网格入口网关Istio-ingressgateway 的负载和网格内的Sidecar 是同样的执行体,也和网格内的其他Sidecar 一样从Pilot处接收流量规则并执行。。Istio 通过一个特有的资源对象Gateway 来配置对外的协议、端口等。

感谢参考

https://www.alauda.cn/news/blog_detail/id/417.html

Istio技术实践专题(3) 在K8s集群上部署Istio的三种方式

近两年微服务架构成为企业应用架构的流行趋势,除了互联网企业,传统企业也纷纷选择拥抱微服务。加之容器Kubernetes、DevOps、微服务云原生技术“黄金三角”的互相赋能,微服务架构成为当前企业IT架构设计的首选。

Isito是Service Mesh的产品化落地,是目前最受欢迎的服务网格,功能丰富、成熟度高。本文主要根据官网文档整理而成,介绍Istio针对单集群的三种主流部署安装方式:使用Istioctl安装、使用Helm自定义安装、独立Operator安装。多集群安装部署暂不涉及,在今后的文章中我们再做详细阐述。

使用 Istioctl 安装

使用默认配置文件安装 Istio

最简单的方法是安装 default Istio 配置文件使用以下命令:

$ istioctl manifest apply

此命令用于在配置好的 Kubernetes 集群上安装 default 配置文件。default 配置文件是建立生产环境的起点,这与旨在评估广泛的 Istio 功能特性的较大的 demo 配置文件不同。

如果要在 default 配置文件之上启用 Grafana dashboard,用下面的命令设置 addonComponents.grafana.enabled 配置参数:

$ istioctl manifest apply --set addonComponents.grafana.enabled=true

可以像使用 helm 一样在 istioctl 中配置 --set 标志。唯一的区别是必须为配置路径增加 values. 前缀,因为这是 Helm 透传 API 的路径,如下所述。

$ istioctl manifest apply --set addonComponents.grafana.enabled=true

可以像使用 helm 一样在 istioctl 中配置 —set 标志。这其中唯一的区别是必须为配置路径增加 values. 前缀,因为这是 Helm 透传 API 的路径,如下所述。

附件操作命令案例详解

从外部Chart安装

通常,istioctl 使用内置 Chart 生成安装清单。这Chart 会和与 istioctl 一起发布,用于审核和自定义,它们 放置在 install/kubernetes/operator/charts 目录下。除了使用内置 Chart 外,istioctl 还可以使用外部 Chart 生成安装清单。要选择外部 Chart ,请配置 installPackagePath 参数(接收本地文件系统路径):

$ istioctl manifest apply --set installPackagePath=< base directory where installed >/istio-releases/istio-1.6.1/install/kubernetes/operator/chart

如果使用 istioctl 1.6.1 二进制文件,该命令执行结果与通过 istioctl manifest apply 安装相同,因为它指向的 Chart 与内置 Chart 相同。除了试验或测试新特性之外,我们建议使用内置 Chart 而不是外部提供,以确保 istioctl 二进制文件与 Chart 的兼容性。

安装其他配置文件(demo)

可以通过在命令行上设置配置文件名称安装其他 Istio 配置文件到群集中。例如,可以使用以下命令,安装 demo 配置文件:

$ istioctl manifest apply --set profile=demo

显示可用配置文件的列表

您可以使用以下 istioctl 命令来列出 Istio 配置文件名称:

$ istioctl profile list
Istio configuration profiles:
remote
default
demo
empty
minimal
preview

显示配置文件的配置

您可以查看配置文件的配置设置。通过以下命令查看 default 配置文件的设置:

$ apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
addonComponents:
grafana:
enabled: true
k8s:
replicaCount: 1
istiocoredns:
enabled: false
kiali:
enabled: true
k8s:
replicaCount: 1
prometheus:
enabled: true
k8s:
replicaCount: 1
tracing:
enabled: true
...

查看整个配置的子集

查看整个配置的子集,可以使用 --config-path 标志,这一标志仅选择部分给定路径下的配置:

$ istioctl profile dump --config-path components.pilot demo |head -30
2020-08-15T08:17:59.939333Z info proto: tag has too few fields: "-"
enabled: true
k8s:
env:
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
- name: GODEBUG
value: gctrace=1
- name: PILOT_TRACE_SAMPLING
value: "100"
- name: CONFIG_NAMESPACE
value: istio-config
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 1
periodSeconds: 3
timeoutSeconds: 5
resources:
requests:
cpu: 10m
memory: 100Mi
...

显示配置文件中的差异

profile diff 子命令可用于显示配置文件之间的差异,在将更改应用于集群之前,这对于检查自定义的效果很有用。您可以使用以下命令显示default和 demo 配置文件之间的差异:

$ istioctl profile diff default demo

安装前生成清单

您可以在安装 Istio 之前使用 manifest generate 子命令生成清单,而不是 manifest apply。例如,使用以下命令为 default 配置文件生成清单:

$ istioctl manifest generate > $HOME/generated-manifest.yaml

根据需要检查清单,然后使用以下命令应用清单:

$ kubectl apply -f $HOME/generated-manifest.yaml

由于集群中的资源不可用,此命令可能显示暂时错误。

验证安装成功

使用 verify-install 命令检查 Istio 安装是否成功,它将集群上的安装与您指定的清单进行比较。

如果未在部署之前生成清单,请运行以下命令以现在生成它:

$ istioctl manifest generate <your original installation options> > $HOME/generated-manifest.yamlerated-manifest.yaml

然后运行以下 verify-install 命令以查看安装是否成功:

$ istioctl verify-install -f $HOME/generated-manifest.yaml

使用 Helm 自定义安装

这种安装方式使用 Helm charts 自定义 Istio 控制平面和 Istio 数据平面的 sidecar。你只需使用 helm template 生成配置并使用 kubectl apply 命令安装它, 或者你可以选择使用 helm install 让 Tiller 来完全管理安装。

通过这些说明, 您可以选择 Istio 内置的任何一个 配置文件 并根据的特定的需求进行进一步的自定义配置。

添加 Helm chart 仓库

下面的命令使用了包含 Istio 发行版镜像的 Helm charts。如果要使用 Istio 发行版 Helm chart ,建议使用下面的命令添加 Istio 发行版仓库:

$ helm repo add istio.io https://storage.googleapis.com/istio-release/releases/1.6.1/charts/

安装步骤

将目录切换到 Istio 发行版的根目录,然后在以下两个选项中选择一种安装方式:

  1. 如果不使用 Tiller 部署 Istio,请查看方案 1。

  2. 如果选择 Helm 的 Tiller pod 来管理 Istio 发行版, 请查看方案 2。

默认情况下,Istio 使用 LoadBalancer 服务类型。而有些平台是不支持 LoadBalancer 服务的。对于不支持 LoadBalancer 服务类型的平台, 执行下面的步骤时,可以在 Helm 命令中加入 --set gateways.istio-ingressgateway.type=NodePort 选项,使用 NodePort 来替代 LoadBalancer 服务类型。

方案 1: 使用 helm template 命令安装

在集群没有安装 Tiller 的情况下,可以选择此方案。

  1. 为 Istio 组件创建命名空间 istio-system:
$ kubectl create namespace istio-system
  1. 使用 kubectl apply 安装所有 Istio 的 自定义资源 (CRDs) :
$ helm template install/kubernetes/helm/istio-init --name istio-init --namespace istio-system | kubectl apply -f -
  1. 等待所有的 Istio CRD 创建完成:
$ kubectl -n istio-system wait --for=condition=complete job --all
  1. 选择配置文件,部署与选择的配置文件相对应的 Istio 核心组件。我们建议在生产环境使用默认的配置文件:

    可以添加一个或多个 --set = 来进一步自定义 helm 命令的安装选项 。

    • default:

      $ helm template install/kubernetes/helm/istio --name istio --namespace istio-system | kubectl apply -f -
    • demo:

      $ helm template install/kubernetes/helm/istio --name istio --namespace istio-system \  --values install/kubernetes/helm/istio/values-istio-demo.yaml | kubectl apply -f -
    • minimal:

      $ helm template install/kubernetes/helm/istio --name istio --namespace istio-system \   --values install/kubernetes/helm/istio/values-istio-minimal.yaml | kubectl apply -f -
    • sds:

      $ helm template install/kubernetes/helm/istio --name istio --namespace istio-system \   --values install/kubernetes/helm/istio/values-istio-sds-auth.yaml | kubectl apply -f -
  2. Istio CNI enabled:

    • 安装 Istio CNI 组件:
    $ helm template install/kubernetes/helm/istio-cni --name=istio-cni --namespace=kube-system | kubectl apply -f -

    将 --set istio_cni.enabled=true 设置追加到 helm 命令上,来启用 Istio CNI件。以 Istio 默认配置文件为例:

    $ helm template install/kubernetes/helm/istio --name istio --namespace istio-system \   --set istio_cni.enabled=true | kubectl apply -f -

方案 2: 在 Helm 和 Tiller 环境中使用 helm install 命令安装

这个方案使用 Helm 和 Tiller 来对 Istio 的生命周期进行管理。

  1. 请确保集群的 Tiller 设置了 cluster-admin 角色的 Service Account。如果没有定义,可以执行下面命令创建:

    $ kubectl apply -f manifests/UPDATING-CHARTS.md
  2. 使用 Service Account 在集群上安装 Tiller:

    $ helm init --service-account tiller
  3. 安装 istio-init chart,来启动 Istio CRD 的安装过程:

    $ helm install install/kubernetes/helm/istio-init --name istio-init --namespace istio-system
  4. 等待所有Istio CRD 创建完成:

    $ kubectl -n istio-system wait --for=condition=complete job --all
  5. 选择一个配置文件,然后部署与选择的配置文件相对应的 istio 的核心组件。我们建议在生成环境部署中使用默认配置文件:

    添加一个或多个 --set = 来进一步定义 Helm 命令的 安装选项。

    • default:

      $ helm install install/kubernetes/helm/istio --name istio --namespace istio-system
    • demo:

      - $ helm install install/kubernetes/helm/istio --name istio --namespace istio-system \   --values install/kubernetes/helm/istio/values-istio-demo.yaml
    • minimal:

      - $ helm install install/kubernetes/helm/istio --name istio --namespace istio-system \   --values install/kubernetes/helm/istio/values-istio-minimal.yaml
    • sds:

    $ helm install install/kubernetes/helm/istio --name istio --namespace istio-system \   --values install/kubernetes/helm/istio/values-istio-sds-auth.yaml
  6. Istio CNI enabled:

    安装 Istio CNI chart:

    $ helm install install/kubernetes/helm/istio-cni --name istio-cni --namespace kube-system

    将 --set istio_cni.enabled=true 设置追加到 helm 命令上,来启用 Istio CNI 插件。以 Istio 默认配置文件为例:

    $ helm install install/kubernetes/helm/istio --name istio --namespace istio-system --set istio_cni.enabled=true
  7. 验证安装

    1. 查询配置文件的组件表,验证是否已部署了与选择的配置文件相对应的 Kubernetes 服务:
    $ kubectl get svc -n istio-system
    1. 确保相应的 Kubernetes Pod 已部署并且 STATUS 是 Running:
    $ kubectl get pods -n istio-system
    
    

卸载

对于使用 helm template 命令安装的 Istio,使用如下命令卸载:

  • default:
$ helm template install/kubernetes/helm/istio --name istio --namespace istio-system | kubectl delete -f -$ kubectl delete namespace istio-system
  • demo:
$ helm template install/kubernetes/helm/istio --name istio --namespace istio-system \   --values install/kubernetes/helm/istio/values-istio-demo.yaml | kubectl delete -f -$ kubectl delete namespace istio-system
  • minimal:
$ helm template install/kubernetes/helm/istio --name istio --namespace istio-system \   --values install/kubernetes/helm/istio/values-istio-minimal.yaml | kubectl delete -f -$ kubectl delete namespace istio-system

sds:

$ helm template install/kubernetes/helm/istio --name istio --namespace istio-system \   --values install/kubernetes/helm/istio/values-istio-sds-auth.yaml | kubectl delete -f -$ kubectl delete namespace istio-system

Istio CNI enabled:

$ helm template install/kubernetes/helm/istio --name istio --namespace istio-system \
--set istio_cni.enabled=true | kubectl delete -f $ helm template install/kubernetes/helm/istio-cni --name=istio-cni --namespace=kube-system | kubectl delete -f -

对于使用的 Helm 和 Tiller 安装的 Istio, 使用如下命令卸载:

$ helm delete --purge istio

$ helm delete --purge istio-init

$ helm delete --purge istio-cni

$ kubectl delete namespace istio-system

删除 CRD 和 Istio 配置

在Istio 的设计中,自定义资源以 CRD 形式存在于 Kubernetes 环境之中。CRD 中包含了运维过程中产生的运行时配置。正因如此,我们建议运维人员应该显式的对其进行删除,从而避免意外操作。

istio-init Chart 包含了 istio-init/files 目录中的所有原始 CRD。下载该 Chart 之后,可以简单使用 kubectl 删除 CRD。要永久删除 Istio 的 CRD 以及所有 Istio 配置, 请运行如下命令:

$ kubectl delete -f install/kubernetes/helm/istio-init/files

三、安装独立 Operator

该指南将指引使用独立的 Istio operator 来安装 Istio。唯一的依赖就是一个 Kubernetes 集群和 kubectl 命令行工具。

如果要安装生产环境的 Istio,我们还是建议您参考使用 istioctl 安装。

前提条件

  • 执行必要的平台特定设置。

  • 检查 Pods 和 Services 需求。

  • 部署 Istio operator。

$ kubectl apply -f https://preliminary.istio.io/operator.yaml

这条命令会在 istio-operator 命名空间中创建以下资源,并运行 Istio operator :

  • operator 自定义资源

  • operator 控制器 deployment

  • operator 指标信息 service

  • operator 必要的 RBAC 规则

安装

运行以下命令用 operator 安装 Istio demo 配置文件:

$ kubectl create ns istio-system
$ kubectl apply -f - <<EOF
apiVersion: install.istio.io/v1alpha1
kind: IstioControlPlane
metadata:
namespace: istio-operator
name: example-istiocontrolplane
spec:
profile: demo
EOF

控制器会检测 IstioControlPlane 资源,然后按照指定的(demo)配置安装 Istio 组件。

使用以下命令来确认 Istio 控制面板服务是否部署:

$ kubectl get svc -n istio-system

$ kubectl get pods -n istio-system

更新

现在,控制器已经运行,可以通过编辑或替换 IstioControlPlane 资源改变 Istio 的配置。控制器将会检测该变化,并更新 Istio 的安装。运行以下命令将安装切换为 default 配置:

$ kubectl apply -f -<<EOF
apiVersion: install.istio.io/v1alpha1
kind:IstioControlPlane
metadata:
namespace: istio-operator
name: example-istiocontrolplanespec:
profile:default
EOF

可以启用或禁用指定的特性或组件。例如,禁用遥测特性:

$ kubectl apply -f -<<EOF
apiVersion: install.istio.io/v1alpha1
kind:IstioControlPlane
metadata:
namespace: istio-operator
name: example-istiocontrolplane
spec:
profile:default
telemetry:
enabled:false
EOF

卸载

删除 Istio operator 和 Istio 部署:

$ kubectl -n istio-operator get IstioControlPlane example-istiocontrolplane -o=json | jq '.metadata.finalizers = null' | kubectl delete -f -
$ kubectl delete ns istio-operator --grace-period=0 --force
$ kubectl delete ns istio-system --grace-period=0 --force

Istio技术实践专题(4) 应用接入Istio的正确姿势

上一篇文章中,我们介绍了Istio针对单集群的三种主流部署安装方式:使用Istioctl安装、使用Helm自定义安装、独立Operator安装。本文将向大家介绍kubernetes 中的应用接入Istio。主要包括kubernetes 中应用接入Istio使用实例、应用技巧、基本知识点总结和需要注意事项。

用什么姿势接入 istio?

虽然 istio 能解决那么多的问题,但是引入 istio 并不是没有代价的。最大的问题是 istio 的复杂性,强大的功能也意味着 istio 的概念和组件非常多,要想理解和掌握 istio ,并成功在生产环境中部署需要非常详细的规划。一般情况下,集群管理团队需要对 kubernetes 非常熟悉,了解常用的使用模式,然后采用逐步演进的方式把 istio 的功能分批掌控下来。

我们设定以下目标:

  • istio部署

  • dfb相关服务部署

  • 网关功能

  • 流量分配,按比例,header

  • 超时,重试

Istio的几个基本资源对象:

  1. VirtualService配置影响流量路由的参数,VirtualService 定义了对特定目标服务的一组流量规则。如其名字所示, VirtualService在形式上表示一个虚拟服务,将满足条件的流量都转发到对应的服务后端,这个服务后端可以是一个服务,也可以是在Dest in at i onRu l e 中定义的服务的子集。

  2. DestinationRule配置目标规则,DestinationRule定义了在路由发生后应用于服务流量的策略。这些规则指定负载平衡的配置,边车的连接池大小以及离群值检测设置,以从负载平衡池中检测和清除不正常的主机。

  3. Gateway服务网关,入口.Gateway描述了一个负载均衡器,该负载均衡器在网格的边缘运行,以接收传入或传出的HTTP / TCP连接。

  4. Service Entry外部服务配置,通过ServiceEntry,可以在Istio的内部服务注册表中添加其他条目,以便网格中自动发现的服务可以访问/路由到这些手动指定的服务。

网关功能:Gateway

Gateway 在网格边缘接收外部访问,并将流量转发到网格内的服务。Istio 通过Gateway将网格内的服务发布成外部可访问的服务,还可以通过Gateway 配置外部访问的端口、协议及与内部服务的映射关系。

网关功能常见的应用:

  1. 将网格内的HTTP 服务发布为HTTP 外部访问

  2. 将网格内的HTTPS 服务发布为HTTPS 外部访问

  3. 将网格内的HTTP 服务发布为HTTPS 外部访问

  4. 将网格内的HTTP 服务发布为双向HTTPS 外部访问

  5. 将网格内的HTTP 服务发布为HTTPS 外部访问和HTTPS 内部访问

在实践中。我们更多需要的是1,3两个场景。

在dfb服务中,dfb-login 作为最外层的前端,是几个服务中唯一和外部用户产生交互的服务。因此我们通过网关功能,将dfb-login 通过域名暴露给用户。

创建gateway 的yml文件:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: login-gateway
namespace: dfb-istio
spec:
selector:
istio: ingressgateway
servers:
- port:
name: https
number: 443
protocol: HTTPS
hosts:
- istio-login.dfb.com
tls:
mode: SIMPLE
privateKey: /etc/istio/ingressgateway-certs/dfb.pem
serverCertificate: /etc/istio/ingressgateway-certs/dfb.pem
- port:
name: http
number: 80
protocol: HTTP
hosts:
- istio-login.dfb.com

创建virtualservice.yml:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: dfb-login
namespace: dfb-istio
spec:
hosts:
- '*'
gateways:
- login-gateway
http:
- uri:
prefix: /
- route:
- destination:
host: dfb-login.dfb-istio.svc.cluster.local

我们创建了两个资源对象,一个VirtualService 用来描述流量的路由关系所有url 前缀为/ 的请求都route 到后端dfb-login.dfb-istio.svc.cluster.local 服务

这个virtuaservice 通过gateways 字段和我们申明的另一个gateway 资源相互绑定。在Gateway 资源对象中。定义了入口的域名,协议,以及TLS 相关的配置。在istio 中。默认的ingressgateway 会监听gateway 资源对象的变更。多个ingressgateway 通过selector 进行选择.默认ingressgateway 是一个loadbalancer的service 。

我们将这个ingressgateway 修改为宿主机网络,并固定到一个单独的节点。这样我们就可以通过将域名解析到这个node节点的方式访问部署好的入口。

流量分配:按比例,根据请求内容

我们设置了两个版本的login 服务。V1 版本用户登录后显示的余额是从数据库取出来的。V2版本则是0。根据这两个版本的差异来判断流量的流向。

首先通过DestinationRule定义两个版本:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: dfb-login
namespace: dfb-istio
spec:
host: dfb-login
subsets:
- labels:
version: v1
name: v1
- labels:
version: v2
name: v2

根据比例:

修改在网关功能中创建的virtualservice

kind: VirtualService
apiVersion: networking.istio.io/v1alpha3
metadata:
name: dfb-login
namespace: dfb-istio
spec:
hosts:
- '*'
gateways:
- login-gateway
http:
- match:
- uri:
prefix: /
route:
- destination:
host: dfb-login.dfb-istio.svc.cluster.local
subset: v1
weight: 50
- destination:
host: dfb-login.dfb-istio.svc.cluster.local
subset: v2
weight: 50

此时多次刷新页面。可以看到用户的现金账户余额在0 和真实额度之间变动。

根据请求内容决定路由:

kind: VirtualService
apiVersion: networking.istio.io/v1alpha3
metadata:
name: dfb-login
namespace: dfb-istio
spec:
hosts:
- '*'
gateways:
- login-gateway
http:
- match:
- headers:
version:
exact: v2
route:
- destination:
host: dfb-login.dfb-istio.svc.cluster.local
subset: v2
- route:
- destination:
host: dfb-login.dfb-istio.svc.cluster.local
subset: v1

修改上文yml 。通过postman请求dfb服务/home页面。默认情况下会路由指向V1版本的login服务。在请求头添加version=v2的header。则会转到v2的服务。

超时,重试功能

我们首先在扩容dfb-api 这个服务为2个pod,在其中一个pod中拦截用户资产接口, 直接返回500 ,另一个pod 正常返回。此时在dfb-login服务中请求。我们可以发现,接口500 和200 状态码交替出现。

location =/user/account/list/338fbcd2-1be6-4dde-9918-84b7629b1ba5 {
return500;
}

此时应用下面的重试规则,再次调用接口。此时接口状态码一直返回200。

kind: VirtualService
apiVersion: networking.istio.io/v1alpha3
metadata:
name: dfb-api
namespace: dfb-istio
spec:
hosts:
- dfb-api.dfb-istio.svc.cluster.local
gateways: ~
http:
- route:
- destination:
host: dfb-api.dfb-istio.svc.cluster.local
port:
number: 80
weight: 100
retries:
attempts: 3
perTryTimeout: 2s
retryOn: 5xx,gateway-error,connect-failure,refused-stream

通过jaeger查看调用链,可以看到调用了两次dfb-api。虽然中间调用失败了,但是最终的状态码是200。

Istio技术实践专题(5) 应用服务网关

上一篇文章中,我们向大家介绍了kubernetes 中的应用接入Istio。主要包括kubernetes 中应用接入Istio使用实例、应用技巧、基本知识点总结和需要注意事项。

从本篇开始,我们将以视频课程的方式,基于灵雀云的微服务治理平台Alauda Service Mesh(简称:ASM)向大家演示Istio的微服务治理方案。

本节课程将从以下几方面介绍Istio服务网关:

  • 微服务网关基本作用
  • Istio gateway介绍
  • Istio gateway crd
  • xds匹配流程
  • asm的网关

Istio Gateway视频课程来了!

https://v.qq.com/x/page/o0956kx1h0k.html

Istio技术实践专题(6) Istio监控与跟踪

上一篇文章中,我们以视频课程的方式,向大家介绍了Istio服务网关。主要包括微服务网关基本作用、Istio gateway介绍、Istio gateway crd、xds匹配流程、asm的网关等知识点。

容器化微服务需要管理和维护的服务变得越来越多,服务之间的调用关系越来越复杂,包括服务发现、负载平衡、故障恢复、监控度量和调用链路追踪在内的服务治理变得越来越重要。

Istio为网格内的所有服务通信生成详细的遥测。遥测技术提供了服务行为的可观察性,允许运营商对其应用程序进行故障排除、维护和优化,而不会给服务开发人员带来任何额外负担。

本篇,我们将介绍Istio监控与跟踪的几个要点,并演示其实践操作:

  • 服务网格的服务拓扑kiali

  • 服务网格的调用链跟踪

  • 全链路监控jaeger

  • 仪表方式展示grafana

“ Istio监控与跟踪”视频讲解,一起学起来!

https://v.qq.com/x/page/l0963xxmv9i.html

Istio技术实践专题(7) 30分钟讲透Istio访问与控制

本文为Istio系列专题之七--Istio访问与控制。Istio通过身份认证、授权、多重安全策略,来保证微服务的安全,实现代码无侵入性。

有时我们需要对微服务间的相互访问进行控制,比如满足某些条件的微服务是否能调用特定的微服务,使用 Istio 可以很方便地实现。

“Istio访问与控制”视频公开课

微服务架构虽然提供了更好的灵活性、可伸缩性以及服务复用的能力,但微服务也有特殊的安全需求,istio 作为服务网格的开放平台,安全性是其不容忽视的一点,本节课程我们主要从以下两点阐释:

  • 安全策略:

    为了提供灵活的服务访问控制,需要双向 TLS 和细粒度的访问策略。

    Istio 提供两种类型的身份验证:传输身份验证和来源身份验证。通过配置不同级别的认证策略,可以快速控制不同的安全访问粒度。

  • 黑白名单:

    控制工作负载的访问权限,提高服务访问的安全性。

    黑白名单是作用于服务端Service,用于限定访问过来的请求。

https://v.qq.com/x/page/f0968fw6huq.html

"Istio访问与控制"视频分享

Istio技术实践专题(8) Istio流量控制 Destination Rule

主题Istio的流量策略。

虚拟服务(Virtual Service)以及目标规则(Destination Rule)是 Istio 流量路由的两大基石。后面我们会专门讲一个灰度发布的专题,Virtual Service和灰度发布会一起讲,今天主要讲述Destination Rule的功能和应用,分三个部分来阐述:

设置负载均衡

熔断策略

连接池策略

流量管理的本质就是采用策略控制流量的流向和大小。Istio流量管理模型依赖于随服务一起部署的 Envoy 代理,网格发送和接收的所有流量(数据平面流量)都通过 Envoy 进行代理。基于此模型可以轻松引导和控制网格周围的流量,而无需对服务进行任何更改。

Istio 自身的服务注册表维护了一组服务以及这些服务背后真正的执行端点,Istio使用服务注册表产生 Envoy 配置。使用此服务注册表,Envoy 代理就可以将流量定向到相关服务。

虽然 Istio 的基本服务发现和负载均衡已经提供了一个有效的服务网格,但 Istio 提供的功能远不止这么多。在许多情况下,都希望对网格流量进行更加细粒度的控制。比如,可能希望将流量以百分比分配到不同的服务版本,作为 A/B 测试的一部分,或者将不同的负载均衡策略应用于特定服务实例版本,又或者你可能还想将特殊规则应用于进出网格的流量等等。以上这些都可以通过使用 Istio 流量管理 API ——虚拟服务(Virtual Service)以及目标规则(Destination Rule)实现。

“Istio流量策略控制” 视频公开课

今天我们主要讨论Destination Rule。前面我们提到的负载均衡、熔断策略、连接池策略都是配置在Destination Rule上的。

Destination Rule定义在发生路由后应用于服务流量的策略。这些规则指定负载平衡的配置,Sidecar的连接池大小以及离群值检测设置,以从负载平衡池中检测和清除不正常的主机。我们可以将虚拟服务视为将流量如何路由到给定目标地址,然后使用目标规则来配置该目标的流量。在评估虚拟服务路由规则之后,目标规则将应用于流量的“真实”目标地址。

Destination rules 是 Istio 流量路由的关键功能,它不能独自使用,必须跟 Virtual Service 共同发挥作用。当 Destination rules 跟 Virtual Service 共同使用的时候,Virtual Service 决定将流量路由到逻辑地址,而 Destination rules 则决定流量路由到物理地址。

视频中,我们会详细介绍Destination Rule的功能和应用。

视频详解“Istio流量控制”

https://v.qq.com/x/page/w0972p3lquh.html

Istio技术实践专题(9) 收官-路由控制与灰度发布

Istio路由控制与灰度发布。

上一期我们讲到,虚拟服务(Virtual Service)以及目标规则(Destination Rule)是 Istio 流量路由的两大基石。虚拟服务可以将流量路由到 Istio 服务网格中的服务。每个虚拟服务由一组路由规则组成,这些路由规则按顺序进行评估。

如果没有 Istio virtual service,仅仅使用 k8s service 的话,那么只能实现最基本的流量负载均衡转发,但是就不能实现类似按百分比来分配流量等更加复杂、丰富、细粒度的流量控制了。

使用Istio的流量管理模型,本质上是将流量与基础设施扩容进行解耦,让运维人员可以通过Pilot指定流量遵循什么规则,而不是指定哪些pods/VM应该接收流量。通过将流量从基础设施扩展中解耦,就可以让 Istio 提供各种独立于应用程序代码之外的流量管理功能。这些功能都是通过部署的Envoy sidecar代理来实现的。

在使用 Istio实现灰度发布的情况下,流量路由和副本部署是两个完全独立的功能。服务的 pod 数量可以根据流量负载灵活伸缩,与版本流量路由的控制完全无关。这在自动缩放的情况下能够更加简单地管理金丝雀版本。

Istio收官之讲:路由控制与灰度发布

在灵雀云ASM平台中单独做了自动化灰度发布的功能。我们创建灰度规则时,将复制原服务版本(金丝雀)配置,创建出后缀为primary的服务版本(主版本),同时流量将全部切换至主版本,金丝雀版本实例数调度为0。通过更新金丝雀版本配置触发灰度发布,灰度发布时,调度金丝雀版本实例,并按照发布规则将流量切换至配置更新后的金丝雀版本。发布完成后,将金丝雀配置复制到主版本,金丝雀实例重新调度为0,由主版本提供最新服务。

在发布过程中,流量将每隔“流量增加周期”,按照“每次流量增加比例”分配至灰度版本,直至比例达到100%。同时通过“指标配置”监控灰度版本的流量状态。若本次增加流量的平均请求成功率小于“最小请求成功比例”,或者平均响应时间大于“最大响应时间”,则异常次数加1,且暂停下个周期流量的增加。暂停期过后,在下次调度开始时,再次检查流量是否满足指标配置。若流量异常总次数达到“触发回滚异常次数”,则进行回滚。

本期视频分为上下两辑:

Istio路由控制与灰度发布(上)

https://v.qq.com/x/page/r0976bxupp5.html

Istio路由控制与灰度发布(下)

https://v.qq.com/x/page/a0976m1p7sj.html

至此,“从小白到专家Istio技术实践”专题已更新九集,课程圆满完结!

假如你需要微服务架构中引入 Istio,并用它来解决微服务治理中的诸多难题,那么,本系列的内容不可错过!

灵雀云Istio技术实践专题整理的更多相关文章

  1. 【从小白到专家】Istio技术实践专题(四):应用接入Istio的正确姿势

    上一篇文章中,我们介绍了Istio针对单集群的三种主流部署安装方式:使用Istioctl安装.使用Helm自定义安装.独立Operator安装.本文将向大家介绍kubernetes中的应用接入Isti ...

  2. 【从小白到专家】收官!Istio技术实践之九:路由控制与灰度发布

    本期是Istio技术实践专题的最后一个模块,主题是Istio的路由控制与灰度发布.上一期我们讲到,虚拟服务(Virtual Service)以及目标规则(Destination Rule)是 Isti ...

  3. 灵雀云CTO陈恺:从“鸿沟理论”看云原生,哪些技术能够跨越鸿沟?

    灵雀云CTO陈恺:从“鸿沟理论”看云原生,哪些技术能够跨越鸿沟? 历史进入2019年,放眼望去,今天的整个技术大环境和生态都发生了很大的变化.在己亥猪年春节刚刚过去的早春时节,我们来梳理和展望一下整个 ...

  4. 灵雀云入选Gartner 2020中国ICT技术成熟度曲线报告,容器技术处于顶峰

    近日,全球权威咨询分析机构Gartner发布了"2020中国ICT技术成熟度曲线(Hype Cycle for ICT in China, 2020 )"报告,灵雀云作为国内容器和 ...

  5. 灵雀云Kube-OVN:基于OVN的开源Kubernetes网络实践

    近日,灵雀云发布了基于OVN的Kubernetes网络组件Kube-OVN,并正式将其在Github上开源.Kube-OVN提供了大量目前Kubernetes不具备的网络功能,并在原有基础上进行增强. ...

  6. K8S的网络接口CNI及灵雀云的实践

    K8S的网络模型 我们从底层网络来看,分为三个层面.首先是Pod之间的多个容器的网络互通.我们知道,K8S的Pod可以由多个容器组成,这个层面网络互通是比较简单的,因为所有的容器都是共享一个网卡,可以 ...

  7. Gartner容器市场指南中国语境:容器成为新常态,灵雀云等本地厂商在选择中占据优势

    在2019年2月“ China Summary Translation: 'Market Guide for Container Management Software'”的报告中,Gartner认为 ...

  8. 灵雀云CTO陈恺应邀出席国泰君安信息产业投资峰会,探讨全球科技产业新格局

    2019年7月9-10日,国泰君安信息产业投资峰会在上海陆家嘴举办.作为国内容器PaaS领域的龙头公司,灵雀云受邀出席本次大会,在“数字化转型从云做起”的论坛中,CTO陈恺发表了<云原生助力企业 ...

  9. 重大升级!灵雀云发布全栈云原生开放平台ACP 3.0

    云原生技术的发展正在改变全球软件业的格局,随着云原生技术生态体系的日趋完善,灵雀云的云原生平台也进入了成熟阶段.近日,灵雀云发布重大产品升级,推出全栈云原生开放平台ACP 3.0.作为面向企业级用户的 ...

随机推荐

  1. VSCode & SQL

    VSCode & SQL MySQL MySQL https://marketplace.visualstudio.com/items?itemName=formulahendry.vscod ...

  2. js 垃圾回收 & js GC

    js 垃圾回收 & js GC js GC / js Garbage Collector https://developer.mozilla.org/en-US/docs/Web/JavaSc ...

  3. React In Depth

    React In Depth React Component Lifecycle https://reactjs.org/docs/react-component.html https://react ...

  4. js 生成Excel

    https://www.npmjs.com/package/xlsx 安装依赖 npm install xlsx Example import * as XLSX from "xlsx&qu ...

  5. 为什么 Python 的 f-string 可以连接字符串与数字?

    本文出自"Python为什么"系列,归档在 Github 上:https://github.com/chinesehuazhou/python-whydo 毫无疑问,Python ...

  6. nvidia-smi command not found Ubuntu 16.04

    issue:     nvidia-smi command not found Ubuntu 16.04 https://askubuntu.com/questions/902636/nvidia-s ...

  7. Java ThreadPoolExecutor详解

    ThreadPoolExecutor是Java语言对于线程池的实现.池化技术是一种复用资源,减少开销的技术.线程是操作系统的资源,线程的创建与调度由操作系统负责,线程的创建与调度都要耗费大量的资源,其 ...

  8. ElasticSearch URI 查询

    公号:码农充电站pro 主页:https://codeshellme.github.io 1,URI 查询格式 URI 查询的一般格式如下: GET /index_name/_search?q=key ...

  9. 二分图最小点覆盖构造方案+König定理证明

    前言 博主很笨 ,如有纰漏,欢迎在评论区指出讨论. 二分图的最大匹配使用 \(Dinic\) 算法进行实现,时间复杂度为 \(O(n\sqrt{e})\),其中, \(n\)为二分图中左部点的数量, ...

  10. Redis6.0.9主从搭建

    所谓主从,大家都知道主是写数据,而从是进行数据的拷贝. 1:配置 主节点 127.0.0.1 6379 从节点 127.0.0.1 6378 先将单机版的配置文件赋值两份出来,原先的配置中主要改动有: ...