亚马逊AWS官方博客

Amazon EKS上的 Istio 入门指南

本篇博客翻译自 AWS 英文博客 “Amazon Elastic Container Service for Kubernetes” 中的文章 Getting Started with Istio on Amazon EKS ,原文请点击这里

 

Service Meshes 以安全、可靠和可观察的方式实现服务到服务通信。在这篇博文中, Native Wave 的 CTO Matt Turner 解释了 Service Mesh 的概念,并展示了如何将服务网格 Istio 运行在使用 Amazon EKS 创建的 Kubernetes 集群上,然后解释了 Istio 的一些关键功能以及它如何帮助你的应用程序更具弹性。

更新

Istio

Istio项目刚发布了1.1版本。 Istio 是新概念服务网格的典型实现。服务网格管理微服务之间的流量,工作在 OSI 模型的第7层。这使得它可以深入了解服务请求的语义—如 HTTP 请求主机,方法和路径—实现更加复杂的请求处理。

在这篇关于 Amazon Elastic Container Service for Kubernetes (Amazon EKS) 上 Istio 的文章中,我们将介绍安装,然后演示一个示例。先解释下这篇文章中“航海”的双关语: Istio 在希腊语中是“帆”的意思。

架构

Istio 通过在每个微服务旁边运行一个小型网络代理来工作。 这种所谓的“边车”拦截了所有服务的流量,并且比简单的第3层网络更智能地处理它。 Istio 使用了Envoy代理作为其边车。 Envoy 最初由 Lyft 开发,现在是 CNCF 项目。每个微服务一个边车,所有的边车组成Istio的数据平面。边车的工作由少量核心组件来进行协调,称为控制平面。控制和数据平面的架构在分布式系统中非常常见,从网络交换机到计算农场。

图1— Istio 架构

 

Istio 旨在可以运行在多种环境中,但到目前为止最常见的是 Kubernetes 。在此配置中,Istio 的控制平面组件作为 Kubernetes 本身工作负载运行,与任何其他 Kubernetes 控制器组件一样。另外, Kubernetes Pod 的构造非常适合 Istio 数据平面的边车模型。

回想一下, Pod 是一组紧密耦合的容器,它们共享一个 IP 地址(技术上,一个网络命名空间),这对于网络边车来说是完美的。

Istio 的第7层代理作为与主服务在同一网络环境中运行的另一个容器。这样,它能够拦截、检查和操纵通过 Pod 的所有网络流量,但主服务容器不需要任何改变甚至不知道发生这种情况。这样做的实际效果是 Istio 可以管理任何的服务,无论服务多么老旧,无论使用什么语言编写。

它改造了一个库的所有功能,如 Hystrix 或 Finagle ,虽然这些只是 Java ,但 Istio 是与语言无关的。

 

EKS上的Istio

了解了足够的理论之后,让我们开始使用 Istio 吧!

我的另一篇博文中 ,我介绍了如何将 Istio pre-1.0 版本安装到 Amazon EKS 中。遇到很多问题,但随着 Istio 的1.x版本的更新,这个过程变得更加简单。

配置Amazon EKS集群

首先我们需要一个 Amazon EKS 集群。

如果你还没有,可以通过各种方法进行创建,包括 eksctlAWS控制台Terraform

无论你使用哪种方法,都需要安装客户端 aws-iam-authenticator ; 如果没有,请参阅 aws-iam-authenticator

例如,使用 eksctl 启动简单的 Amazon EKS 集群(测试使用 eksctl  0.1.29),运行如下命令:

eksctl  create cluster \

--region us-west-2 \

--name istio-on-eks \

--nodes=2 \

--ssh-public-key "~/.ssh/id_rsa.pub"

这条命令将创建一个托管(和隐藏)控制平面的 Kubernetes 集群,以及两个 m5.large 类型的工作节点。

这足以容纳 Istio 的控制平面和我们将使用的示例应用程序,而无需等待集群自动缩放器。

eksctl 将新建集群的连接信息添加到你的 ~/.kube/config 并将当前上下文设置为该集群,因此我们可以开始使用它。如果你不想 eksctl 编辑该文件,你可以通过 –kubeconfig 参数设定写入一个独立的文件,你可以选择在终端设置 export KUBECONFIG= 来使用。

Amazon EKS 集群的一个非常好的功能是可以使用您的 AWS IAM 用户和组进行身份验证,而不是具有单独用户集的集群(这是通常的模式)。虽然认证方式不同,授权依然使用相同的 RBAC 系统—只是将现有的 AWS 身份和访问管理(IAM)用户绑定到角色而不是 Kubernetes 内部用户。

要使身份验证成功, kubectl 需要能够将你的 AWS 凭证提供给集群,而不是使用特定的 Kubernetes x509 证书。

要做到这一点, kubectl 需要安装一个插件:

go get -u -v \

github.com/kubernetes-sigs/aws-iam-authenticator/cmd/aws-iam-authenticator

现在让我们检查一切是否正常,并使用 kubectl 获取新集群的节点。关于输出,注意以下一些事情:

  • 主控(master)节点不可见。
  • 工作(worker)节点运行最新版本的 Kubernetes。
  • 工作节点运行的是 Amazon Linux 。这实际上 eksctl 是一种建议; 如果你有特定的要求, Amazon EKS 允许指定工作节点的 AMI ,公布的 Amazon EKS AMI构建规范可帮助你开始创建自定义镜像。

下载Istio部署文件

在写本文时, Istio 的版本为1.1.2。

Istio 提供了一个方便的脚本,可以下载和解压最新的 Istio 版本:

curl -L https://git.io/getLatestIstio | sh -

cd istio-1.*

为了更加安全,可以从Istio GitHub发布页面中获取tar包。

配置Helm

Helm 是一个常用的 Kubernetes 软件包管理器,我们将使用 Helm 将 Istio 安装到 Amazon EKS 集群中。

首先,确保安装了 Helm 。有关您平台的具体说明,请参阅 Helm的综合文档

接下来,你需要部署 Helm 的服务器端组件 Tiller 到你的 Amazon EKS 集群。由于 Kubernetes 的 RBAC 安全机制,这可能变得非常复杂。幸运的是,发布的 Istio 提供了一个简单的配置文件来完成权限设置。

仍然在 istio-1.* 目录中,应用该配置文件,然后部署 Tiller :

kubectl create -f install/kubernetes/helm/helm-service-account.yaml

helm init --service-account tiller

注意:此配置文件可以帮助你,但它不是最佳安全实践的示例。不要在生产集群中执行此操作!Helm关于基于角色的访问控制的文档将告诉你如何安全地设置。

在EKS上安装Istio

我们将再次使用 Helm ,它将安装 Istio 简化为几个命令。这些命令经过 Helm  2.13测试。首先,我们必须完成一些前置任务:

helm install \

--wait \

--name istio-init \

--namespace istio-system \

install/kubernetes/helm/istio-init

然后你可以简单的安装 Helm chart :

helm install \

--wait \

--name istio \

--namespace istio-system \

install/kubernetes/helm/istio \

--values install/kubernetes/helm/istio/values-istio-demo.yaml

对于不熟悉 Helm 的人的说明:我们将 Helm 管理的部署命名为“ istio ”,因为在高级配置中可能部署多个 Istio ; 这为我们提供了一个简单的名称,可用于以后管理和卸载它。我们将它部署在 Kubernetes 自己的命名空间 istio-system 中。

我们在这里使用的唯一特殊的参数是最后一个,它可以实现比基本安装更多的功能,其中一些我们将在本文中探讨。

示例应用程序Bookinfo

Istio 项目提供了一个微服务示例应用程序 Bookinfo ,旨在帮助演示许多 Istio 的功能。

我们已经安装了 Istio ,现在让我们开始 Istio 之旅吧!

安装Bookinfo

Bookinfo 被设计运行在 Kubernetes 中,我们下载的 Istio 版本附带一个 YAML 文件,声明了部署 Bookinfo 所需要的所有集群资源。

回想一下,为了让 Istio 为这些服务添加智能,需要将边车与所有 Bookinfo 的代码一起运行,拦截和管理所有网络流量。

这些边车可以由 Mutating Admission Controller Webhook (由资源类型    MutatingWebhookConfiguration 配置, 已经与 Istio 一起安装 )实现自动注入。 这是一个在 Kubernetes 控制平面上注册的 webhook ,所有新的资源定义都发送到该 webhook 以供检查。这些 webhook 可以检查资源并可能拒绝它们(验证),或者对它们进行更改(改变)。由于 Istio 使用 Mutating Webhook Admission Controller ,整个系统不仅对应用程序的开发人员而且对其运营商也是透明的。

但是, Istio 仍然是灵活选择配置的方式。我们可以将 Bookinfo 安装到 Kubernetes 名称空间 default 中,所以我们需要添加一个标签,告诉 Istio 的 webhook 将 sidecars 注入该命名空间中部署的任何 Pod 。

kubectl label namespace default istio-injection=enabled

 

现在,我们可以部署 BookInfo 应用程序, Mutating Webhook 将修改认为需要注入边车的 Pod 的定义,完成自动注入。

kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml

 

发布Bookinfo

Bookinfo 提供的部署文件没有做的一件事就是将前端服务发布到外部。

这看起来很低级,但网络是复杂的、困难的和特定于环境的。

出于这个原因, Bookinfo 的简单安装将这部分排除在外。

取代比较熟悉的 nginx Ingress Controller , Istio 将为我们处理入口流量(因为这样做,可以添加其所有7层的好处)。

入口流量实际由 Envoy 实例处理(由于各种原因与边车分开),但是,与网格的其余部分一样,这些是由 Istio 控制平面配置的。

虽然 Istio 可以像 nginx Ingress Controller 一样解析 Kubernetes ingress 资源 ,但它还有一些自己的首选的网络资源类型,提供了更多的控制。

由于我们处于可测试集群中,因此我们将使用这些新的入口资源类型 Gateway :

kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml

这些资源与 ingress 资源不同,因为它们配置的路由设备最终放置在 Kubernetes 集群外部的“物理”负载均衡器后面—在我们的例子中是 AWS Elastic Load Balancer 。

以下命令将找到我们最终需要访问的主机和端口,以便从 Internet 访问我们的 Bookinfo 应用程序:

$ export INGRESS_HOST=$(kubectl -n istio-system \

get service istio-ingressgateway \

-o jsonpath='{.status.loadBalancer.ingress[0].hostname}')

$ export INGRESS_PORT=$(kubectl -n istio-system \

get service istio-ingressgateway \

-o jsonpath='{.spec.ports[?(@.name=="http2")].port}')

$ export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT

 

您现在可以使用浏览器访问 http://$GATEWAY_URL/productpage ,展示 Bookinfo 的登陆页面(使用刚才分配的值替换 $GATEWAY_URL ,或者在 Mac 上,open http://$GATEWAY_URL/productpage)。

页面看起来像这样:

图2— Bookinfo 登陆界面

流量路由

在这篇文章中,展示了如何配置 Amazon EKS 集群, 以符合 EKS 的方式,使用 Helm 软件包管理器安装 Istio ,并安装带有 Istio 扩充的微服务示例应用程序。

为了完善这篇文章,让我们快速浏览一下 Istio 的众多功能—一些先进的流量路由,这是因为 Istio 在第7层处理流量。

默认行为

多次访问 http://$GATEWAY_URL/productpage ,或点击刷新。

请注意,右边的评论有时候会有星级评分,有时候会有颜色,有时根本就没有星级。

这是因为这些评论来自单独的评论服务,在我们刚刚部署的系统中 ,它有三个独立的版本,你可以通过 kubectl 查看 pods 看到。

只有一个 Kubernetes Service 对象指向所有这些 pods ,所以其他 Pod 只需使用名称 reviews 就可以调用评论服务。

这样做的结果是,使用了 Kubernetes 基本的轮询负载均衡策略,就像你在滚动升级时那样。

图3—默认路由策略

七层路由

现在让我们控制所有的请求全部路由到评论服务的v1版本。

BookInfo 示例中有一些预先定义的 Istio 配置文件可供我们使用,上述需求就是其中之一。

首先,我们需要告诉 Istio 关于服务存在的不同版本以及如何区分它们(在这种情况下,通过 Kubernetes Deployment 上的标签)。

kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml

让我们来看看该文件中与评论服务相关的部分。

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
 name: reviews
...

它的类型是 DestinationRule ,指定如何与包含服务的工作负载(例如 Pod )进行通信。规则包括在 Pod 之间进行负载平衡的策略,允许任何一个 Pod 的最大连接数等。在这个例子中,我们实际上并没有使用这些,而是告诉 Istio 目的服务( Pods )的不同版本。

... 
spec: 
host: reviews 
...

有疑问的是目的地主机名 reviews ,即我们的 reviews service (在 Kubernetes 上)。 任何标头包含  Host:reviews 的 HTTP 请求将适用此规则。正如我们所说,这是必要的,但不足以区分不同的版本。

...
subsets:
- name: v1
  labels:
   version: v1
- name: v2
  labels:
   version: v2
- name: v3
  labels:
   version: v3

因此,文件的最后一部分设定服务的工作负载应该被视为三个独立的子集。由于 Istio 与 Kubernetes 的紧密集成,它可以通过其 Pod 上的标签识别端点。

定义了评论服务的那些子集,我们就可以告诉 Istio 任何人都访问评论服务的v1版本。

kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml

 

图4—基本路由策略

 

在此文件中,我们定义了一个类型为 VirtualService 的资源,再次匹配访问评论服务的流量并表明所有请求都应该路由到版本v1。更高级的 VirtualService 将匹配 HTTP 路径和方法上的流量,并支持 URL 重写,为我们提供了更多传统反向代理的强大功能。这个简单的例子只匹配 host 标头,所以它看起来与 DestinationRule 非常相似,但是,该资源指定如何访问工作负载, VirtualServices 是设定各种请求要路由到哪一个工作负载上的资源。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: reviews
spec:
 hosts:
 - reviews
 http:
 - route:
   - destination:
      host: reviews
      subset: v1

 

再次点击 BookInfo  页面多次,你会看到评论没有星级。请注意,我们在此处未更改任何 Kubernetes 服务,更不用说删除不需要的版本。其他版本的 pods 可以有星级评论。

Amazon EKS 集群仍然具有普通的 IP 网络,因此在任何语言中您都可以继续使用正常的套接字—这里没有特殊的调用奇怪的 RPC 库。

Productpage 仍然会对“评论”提出 DNS 请求,因此如果没有 Istio ,甚至在 Kubernetes 之外,它仍然可以正常工作。

但是,这意味着,当请求离开 productpage 容器时,其目的地 IP 地址将由 Kubernetes 服务的 ClusterIP 选择 ,随机选择任何版本的一个 Pod 。

那么 Istio 如何处理这个请求呢? 它甚至知道请求的目的地在哪里?

请记住, Istio 了解 HTTP 请求的内容,所以它查看 HTTP 请求中 host: ,然后匹配    VirtualService  ,并将请求只发送到我们想要的评论服务v1版本。

 

高级路由

虽然我承认还有其他方法可以实现我们刚才所做的事情(尽管我认为 Istio 的方式更整洁,更灵活),但这种支持 HTTP 的路由具有更强大的功能。

假设你正在对新版本进行探索性测试—用户正在他的浏览器中访问应用,你可以在边缘寻找错误。

你想拥有 productpage  使用v2的评论服务,但仅限于你。

假设你叫 Jason 。

应用以下文件,再次点击页面刷新按钮。

kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml

 

图5—高级路由策略

 

将此文件(如下所示)与之前的 all-v1 版本进行比较。原始路由规则仍然存在于文件的末尾,但规则按顺序应用,因此我们在旧规则之前插入了一个新规则语句,该规则仅捕获 Jason 的流量并将其指向其他地方。 所有其他流量继续匹配原始默认规则。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: reviews
spec:
 hosts:
  - reviews
 http:
 - match:
 - headers:
    end-user:
     exact: jason
route:
- destination:
   host: reviews
   subset: v2
- route:
  - destination:
     host: reviews
     subset: v1

除了 Jason ,任何人都应该看到评论服务v1版本。

现在来点击右上角的 Sign in 按钮,并以“ Jason ”身份登录(区分大小写,但任何密码都可以—我认为我们发现了一个错误!)。

再刷新一次,你现在应该看到了希望看到的星级评级。

查看最新的 YAML 文件,你将看到网络流量路由现在取决于 HTTP 标头。

试着使用 iptables 实现上面的功能!

当然,你的标准可以是用户代理,登录或注销—可以从 HTTP 标头推断的任何内容(当然还有来自堆栈下游的任何元数据,例如端口号)。

我希望这能让你体验到 Istio 可以做的事情,并向你展示安装也不是那么难。

 

本篇作者

Matt Turner

Matt Turner 是 Native Wave 的首席技术官, Native Wave 是一家使用最好的开源软件设计,构建和管理云原生平台的咨询公司。 Native Wave 与整个企业合作,重新构建和重构应用程序,以充分利用现代云技术。十多年来, Matt 一直在做 Dev ,有时候会做 Ops 。他对“全栈”的看法是 Linux , Kubernetes ,现在也是 Istio 。他为 Kubernetes 和 Istio 提供了许多讲座和研讨会,并且是 Istio London 会议的共同组织者。他的推特@mt165和博客地址https://mt165.co.uk。

 

本文中的内容和观点均为第三方作者的内容和意见, AWS 不对此帖的内容或准确性负责。

 

 

本篇译者

郭跃军

亚马逊 AWS 专业服务团队云架构咨询顾问。在加入 AWS 之前,曾任职于 RedHat 担任 PaaS 咨询顾问,在 PaaS 建设运维、 DevOps 以及微服务改造迁移等有丰富的经验。负责企业级客户的云架构设计和优化、云上自动化运维、容器化平台设计咨询等,对云原生技术有深入的研究和热情。