如何使用 Istio 和 Kubernetes 进行金丝雀部署

介绍

在引入新版本的服务时,在逐步淘汰旧版本的过程中,通常需要将受控的用户流量的百分比转移到新版本的服务。

Kubernetes集群操作员可以自行使用标签部署进行指定部署。 然而,这一技术有某些局限性:流量分配和复制计数是结合的,这实际上意味着复制比率必须人工控制,以便限制流量到金丝雀放行. 换句话说,要将10%的交通量用于金丝雀部署,你需要有一个10个舱位的集合,一个舱位接收10%的用户流量,另外9个舱位接收其余的.

使用 Istio服务网格部署可以通过允许复制件数和流量管理之间的清晰分离来解决这个问题。Istio网格允许精细的流量控制,将流量分布和管理从复制件规模化中分离出来。

在本教程中,您将使用 Istio 和 Kubernetes 创建一个 Canary 部署,您将部署两个版本的演示应用程序 Node.js,并使用 Virtual ServiceDestination Rule 资源来配置流量路由到新版本和旧版本。

前提条件

<$>[注] 注: 我们强烈建议为此设置使用至少8GB可用内存和4vCPU的集群。

  • 联合国 kubectl' 命令行工具安装在一个开发服务器上,并配置到连接到您的集群。 您可以在 [官方文档] (https://kubernetes.io/docs/tasks/tools/install-kubectl/ 中读取更多关于安装 kubectl` 的内容。
  • 安装在您的开发服务器上。 如果您与 Ubuntu 18.04 合作, 请遵循 [如何在 Ubuntu 18. 04 上安装和使用 Docker (https://andsky.com/tech/tutorials/how-to-install-and-use-docker-on-ubuntu-18-04) 步骤 1 和 2 ; 否则, 请遵循 [正式文件] (https://docs.docker.com/install/) , 以了解安装其他操作系统的信息 。 如链接教程步骤2所描述的,请将您的非根用户添加到 docker 组中 。
  • ADocker Hub账户。 有关如何设置的概述,请参见 [本引言 (https://docs.docker.com/docker-hub/)到多克枢纽.
  • Istio按照[如何安装和使用Istio With Kubernetes(https://andsky.com/tech/tutorials/how-to-install-and-use-istio-with-kubernetes)中的指示安装和配置。 您还应当启用和配置用于外部访问的 [Grafana] (https://grafana.com/ ) 遥测加通。 .

步骤1 - 包装应用程序

在前提教程中, How To Install and Use Istio With Kubernetes,你 创建了一个节点演示的Docker图像运行一个鲨鱼信息应用程序,并将此图像推到Docker Hub。

我们的原始演示应用程序在其 Shark Info 页面上强调了一些关于鲨鱼的友好事实:

Shark Info Page

但是,我们决定在我们新的加拿大版本中强调一些更可怕的事实:

Scary Shark Info Page

我们的第一步是将这个应用程序的第二个版本的代码克隆到一个名为node_image的目录中。 使用以下命令,将 nodejs-canary-app repositoryDigitalOcean Community GitHub 帐户克隆出来。

1git clone https://github.com/do-community/nodejs-canary-app.git node_image

导航到node_image目录:

1cd node_image

该目录包含了我们最新版本的鲨鱼信息应用程序的文件和文件夹,该目录为用户提供关于鲨鱼的信息,就像原始应用程序一样,但强调了可怕的事实。

要测试应用程序代码和 Dockerfile 是否按预期工作,您可以使用 docker build 命令构建和标记图像,然后使用图像运行演示容器。

用以下命令构建图像:

1docker build -t your_dockerhub_username/node-demo-v2 .

命令中的 . 表示构建背景是当前的目录. 我们已将图像命名为 node-demo-v2,以参考在 How To Install and Use Istio With Kubernetes中所创建的 node-demo 图像。

一旦构建过程完成,您可以将您的图像列为 docker images:

1docker images

您将看到以下输出,确认图像构建:

1[secondary_label Output]
2REPOSITORY TAG IMAGE ID CREATED SIZE
3your_dockerhub_username/node-demo-v2 latest 37f1c2939dbf 5 seconds ago 77.6MB
4node 10-alpine 9dfa73010b19 2 days ago 75.3MB

接下来,您将使用docker run创建一个基于此图像的容器,我们将包含三个旗帜以此命令:

  • -p:这将发布集装箱上的端口,并将其地图到我们的主机上的端口。我们将使用端口 80在主机上,但如果您有其他过程在该端口上运行的情况下,您可以随意修改该端口。

运行以下命令来构建容器:

1docker run --name node-demo-v2 -p 80:8080 -d your_dockerhub_username/node-demo-v2

检查您的运行容器用 docker ps :

1docker ps

您将看到确认您的应用程序容器正在运行的输出:

1[secondary_label Output]
2CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
349a67bafc325 your_dockerhub_username/node-demo-v2   "docker-entrypoint.s…"   8 seconds ago Up 6 seconds 0.0.0.0:80->8080/tcp node-demo-v2

您现在可以在浏览器中访问您的服务器 IP 来测试您的设置:http://your_server_ip`. 您的应用程序将显示以下定位页面:

Application Landing Page

点击获取鲨鱼信息按钮,进入恐怖鲨鱼信息:

Scary Shark Info Page

现在你已经测试了应用程序,你可以停止运行容器. 再次使用docker ps来获取你的CONTAINER ID:

1docker ps
1[secondary_label Output]
2CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
349a67bafc325 your_dockerhub_username/node-demo-v2   "docker-entrypoint.s…"   About a minute ago Up About a minute 0.0.0.0:80->8080/tcp node-demo-v2

请确保将这里列出的CONTAINER ID替换为自己的应用程序CONTAINER ID:

1docker stop 49a67bafc325

现在您已经测试了图像,您可以将其推到 Docker Hub. 首先,请在前提条件下登录您创建的 Docker Hub 帐户:

1docker login -u your_dockerhub_username

当被提示时,请输入您的 Docker Hub 帐户密码. 以此方式登录将创建一个 ~/.docker/config.json 文件,在您的非根用户的主目录中与您的 Docker Hub 凭证。

使用 docker push 命令将应用程序图像推到 Docker Hub。 请记住用自己的 Docker Hub 用户名替换 your_dockerhub_username:

1docker push your_dockerhub_username/node-demo-v2

现在你有两个应用程序图像存储到Docker Hub:node-demo图像和node-demo-v2。我们现在将修改你在前提教程中创建的宣言(How To Install and Use Istio With Kubernetes)(https://andsky.com/tech/tutorials/how-to-install-and-use-istio-with-kubernetes),以将流量引导到你的应用程序的加拿大版本。

步骤 2 — 更改应用部署

How To Install and Use Istio With Kubernetes,您为您的应用程序 ServiceDeployment对象创建了一个应用程序 manifest specifications

当您遵循前提教程中的设置指示时,您创建了一个名为istio_project的目录和两个yaml示例:node-app.yaml,其中包含服务和部署对象的规格,以及node-istio.yaml,其中包含您的Istio虚拟服务和网关资源的规格。

现在导航到istio_project目录:

1cd
2cd istio_project

使用nano或您最喜欢的编辑器打开node-app.yaml,以便对您的应用程序进行更改:

1nano node-app.yaml

目前,檔案看起來如下:

 1[label ~/istio_project/node-app.yaml]
 2apiVersion: v1
 3kind: Service
 4metadata:
 5  name: nodejs
 6  labels: 
 7    app: nodejs
 8spec:
 9  selector:
10    app: nodejs
11  ports:
12  - name: http
13    port: 8080 
14---
15apiVersion: apps/v1
16kind: Deployment
17metadata:
18  name: nodejs
19  labels:
20    version: v1
21spec:
22  replicas: 1
23  selector:
24    matchLabels:
25      app: nodejs
26  template:
27    metadata:
28      labels:
29        app: nodejs
30        version: v1
31    spec:
32      containers:
33      - name: nodejs
34        image: your_dockerhub_username/node-demo
35        ports:
36        - containerPort: 8080

对于本文件的内容的完整解释,请参阅 步骤 3如何安装和使用Istio与Kubernetes

我们已经在我们的部署元数据模板字段中包含了版本标签,随后我们可以为第二个部署对象添加规格,这将代表我们的应用程序的第二个版本,并快速更改我们的第一个部署对象的名称

首先,更改现有部署对象的名称为nodejs-v1:

1[label ~/istio_project/node-app.yaml]
2...
3apiVersion: apps/v1
4kind: Deployment
5metadata:
6  name: nodejs-v1
7  labels:
8    version: v1
9...

接下来,在本部署的规格下方,添加您第二次部署的规格。

 1[label ~/istio_project/node-app.yaml]
 2...
 3---
 4apiVersion: apps/v1
 5kind: Deployment
 6metadata:
 7  name: nodejs-v2
 8  labels:
 9    version: v2
10spec:
11  replicas: 1
12  selector:
13    matchLabels:
14      app: nodejs
15  template:
16    metadata:
17      labels:
18        app: nodejs
19        version: v2
20    spec:
21      containers:
22      - name: nodejs
23        image: your_dockerhub_username/node-demo-v2
24        ports:
25        - containerPort: 8080

与第一个部署一样,本部署使用版本标签来指定与本部署相符的应用程序版本.在这种情况下,v2将区分与本部署相关的应用程序版本,而v1则与我们的第一个部署相符。

我们还确保了由v2部署管理的 Pods将运行我们在上一个步骤中构建的node-demo-v2卡纳里图像。

保存并关闭文件,当你完成编辑。

隨著您的應用程式變更,您可以繼續對您的 node-istio.yaml 檔案進行變更。

第3步:使用虚拟服务衡量流量并添加目的地规则

How To Install and Use Istio With Kubernetes中,您创建了网关和虚拟服务对象,以允许外部流量进入 Istio 网格,并将其路由到您的应用程序服务中。

打开node-istio.yaml文件:

1nano node-istio.yaml

目前,檔案看起來如下:

 1[label ~/istio_project/node-istio.yaml]
 2apiVersion: networking.istio.io/v1alpha3
 3kind: Gateway
 4metadata:
 5  name: nodejs-gateway
 6spec:
 7  selector:
 8    istio: ingressgateway 
 9  servers:
10  - port:
11      number: 80
12      name: http
13      protocol: HTTP
14    hosts:
15    - "*"
16---
17apiVersion: networking.istio.io/v1alpha3
18kind: VirtualService
19metadata:
20  name: nodejs
21spec:
22  hosts:
23  - "*"
24  gateways:
25  - nodejs-gateway
26  http:
27  - route:
28    - destination:
29        host: nodejs

对于本宣言中的规格的完整解释,请参阅 步骤 4如何安装和使用Istio与Kubernetes

目前,这个资源通过我们的nodejs-gateway向我们的nodejs应用程序服务路由流量进入网格,我们想做的是配置一条路由规则,将 80% 的流量发送到我们的原始应用程序,20%发送到更新的版本。

作为我们在原始宣言中所做的,我们将为我们的应用程序子集添加目的地字段,而不是向一个单一的目的地:原始版本(‘v1’)和加纳语(‘v2’)。

对虚拟服务进行以下添加以创建此路由规则:

 1[label ~/istio_project/node-istio.yaml]
 2...
 3apiVersion: networking.istio.io/v1alpha3
 4kind: VirtualService
 5metadata:
 6  name: nodejs
 7spec:
 8  hosts:
 9  - "*"
10  gateways:
11  - nodejs-gateway
12  http:
13  - route:
14    - destination:
15        host: nodejs
16        subset: v1
17      weight: 80
18    - destination:
19        host: nodejs
20        subset: v2
21      weight: 20

我们添加的策略包括两个目的地:我们nodejs服务的子集运行我们的应用程序的原始版本v1和运行的canary子集``v2

接下来,我们将添加一个目的地规则,该规则将在流量被路由到相应的服务后应用于流量。

在您的虚拟服务定义下方添加以下代码:

 1[label ~/istio_project/node-istio.yaml]
 2...
 3---
 4apiVersion: networking.istio.io/v1alpha3
 5kind: DestinationRule
 6metadata:
 7  name: nodejs
 8spec:
 9  host: nodejs
10  subsets:
11  - name: v1
12    labels:
13      version: v1
14  - name: v2
15    labels:
16      version: v2

我们的规则确保我们的服务子集v1v2的流量以适当的标签到达Pod:版本:v1版本:v2

但是,如果我们愿意,我们也可以在子集级别应用特定的交通政策,从而在我们的加那利地区部署中提供进一步的具体性。

保存并关闭文件,当你完成编辑。

随着应用程序宣言的修订,您已经准备好应用配置更改,并使用Grafana远程测量插件检查应用程序流量数据。

步骤 4 — 应用配置更改和访问流量数据

应用程序宣言正在更新,但我们仍然需要将这些更改应用到我们的Kubernetes集群中。我们将使用命令 kubectl apply 来应用我们的更改,而不会完全重写现有配置。

将配置应用于您的应用程序服务和部署对象:

1kubectl apply -f node-app.yaml

您将看到以下结果:

1[secondary_label Output]
2service/nodejs unchanged
3deployment.apps/nodejs-v1 created
4deployment.apps/nodejs-v2 created

接下来,将您所做的配置更新应用于 `node-istio.yaml',其中包括对虚拟服务和新目的地规则的更改:

1kubectl apply -f node-istio.yaml

您将看到以下结果:

1[secondary_label Output]
2gateway.networking.istio.io/nodejs-gateway unchanged
3virtualservice.networking.istio.io/nodejs configured
4destinationrule.networking.istio.io/nodejs created

但是,在这样做之前,先检查,以确保您有grafana服务运行:

1kubectl get svc -n istio-system | grep grafana
1[secondary_label Output]
2grafana ClusterIP 10.245.233.51    <none>           3000/TCP 4d2h

也检查相关的Pods:

1kubectl get svc -n istio-system | grep grafana
1[secondary_label Output]
2grafana-67c69bb567-jpf6h 1/1 Running 0 4d2h

最后,检查grafana-gateway网关和grafana-vs虚拟服务:

1kubectl get gateway -n istio-system | grep grafana
1[secondary_label Output]
2grafana-gateway 3d5h
1kubectl get virtualservice -n istio-system | grep grafana
1[secondary_label Output]
2grafana-vs   [grafana-gateway]   [*]     4d2h

如果您看不到这些命令的输出,请查看 如何安装和使用 Istio 与 Kubernetes的步骤 25,这些步骤讨论如何在安装 Istio 时启用 Grafana 远程扩展,以及如何启用 HTTP 访问 Grafana 服务。

您现在可以在浏览器中访问您的应用程序。 要做到这一点,您需要与您的istio-ingressgateway服务相关的外部 IP,这是一个 LoadBalancer 服务类型。 在 How To Install and Use Istio With Kubernetes中写我们的Gateway 宣言时,我们与这个控制器匹配了我们的nodejs-gateway通道。 有关通道宣言的更多细节,请参阅该教程的 Step 4

使用以下命令获取istio-ingressgateway服务的外部 IP:

1kubectl get svc -n istio-system

你会看到这样的输出:

 1[secondary_label Output]
 2NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)                                                                                                                                      AGE
 3grafana ClusterIP 10.245.85.162    <none>            3000/TCP 42m
 4istio-citadel ClusterIP 10.245.135.45    <none>            8060/TCP,15014/TCP 42m
 5istio-galley ClusterIP 10.245.46.245    <none>            443/TCP,15014/TCP,9901/TCP 42m
 6istio-ingressgateway LoadBalancer 10.245.171.39 ingressgateway_ip 15020:30707/TCP,80:31380/TCP,443:31390/TCP,31400:31400/TCP,15029:30285/TCP,15030:31668/TCP,15031:32297/TCP,15032:30853/TCP,15443:30406/TCP 42m
 7istio-pilot ClusterIP 10.245.56.97     <none>            15010/TCP,15011/TCP,8080/TCP,15014/TCP 42m
 8istio-policy ClusterIP 10.245.206.189   <none>            9091/TCP,15004/TCP,15014/TCP 42m
 9istio-sidecar-injector ClusterIP 10.245.223.99    <none>            443/TCP 42m
10istio-telemetry ClusterIP 10.245.5.215     <none>            9091/TCP,15004/TCP,15014/TCP,42422/TCP 42m
11prometheus ClusterIP 10.245.100.132   <none>            9090/TCP 42m

istio-ingressgateway应该是唯一具有TYPE``LoadBalancer的服务,也是唯一具有外部IP的服务。

在您的浏览器中导航到此外部 IP: http://ingressgateway_ip

你应该看到下面的登陆页面:

Application Landing Page

点击获取鲨鱼信息按钮,您将看到两个鲨鱼信息页面之一:

Shark Info Page

Scary Shark Info Page

点击此页面上更新几次. 您应该比更可怕的版本更频繁地看到更友好的鲨鱼信息页面。

一旦你通过刷新五次或六次产生了一些负荷,你可以转向你的Grafana仪表板。

在您的浏览器中,导航到以下地址,再次使用您的istio-ingressgateway外部IP和在Grafana Gateway中定义的端口: http://ingressgateway_ip:15031

您将看到以下登陆页面:

Grafana Home Dash

点击页面顶部的 主页 将带您到一个具有 ** istio** 文件夹的页面. 要查看下载选项的列表,请点击 ** istio** 文件夹图标:

Istio Dash Options Dropdown Menu

从此选项列表中,单击 Istio 服务仪表板

这将带你到一个定位页面,另一个下载菜单:

Service Dropdown in Istio Service Dash

从可用的选项列表中选择nodejs.default.svc.cluster.local

如果您导航到页面的服务工作负载部分,您将能够查看目的地和响应代码中的接收请求:

Service Workloads Dashboards

在这里,你会看到200和304 HTTP响应代码的组合,表示成功的OK未修改响应.标记为nodejs-v1的响应应该超过标记为nodejs-v2的响应,这表明流量正在根据我们在宣言中定义的参数向我们的应用程序子集路由。

结论

在本教程中,您使用 Istio 和 Kubernetes 部署了 Node.js 演示应用程序的谷歌版本,您创建了虚拟服务和目的地规则资源,使您能够将 80% 的流量发送到原始应用程序服务和 20% 到更新的版本。

有关 Istio 交通管理的更多信息,请参阅文档中的相关 高级概述,以及使用 Istio 的 bookinfohelloworld样本应用的具体示例。

Published At
Categories with 技术
comments powered by Disqus