Istio 教程|部署 Service Mesh 简化微服务通信(下)
技术
作者:Jakub Pavlik
译者:小君君
2018-09-20 14:00

 

在下面的教程中,我们将使用 Istio Service Mesh 来演示一个最强大的功能:“请求路由”。Istio Service Mesh 允许将选定 HTTP 标记的特定请求路由到特定目标上,这个功能只有第 7 层代理可以做到。第 4 层负载均衡器或代理是不可以实现该功能的。


在本教程中,我们假设你正在运行 Kubernetes 集群(提示:遵循这些说明,你可以在几分钟内启动新集群,或使用“ Kublr-in-a-box ”来设置本地集群)。对于本教程,具有 1 个主节点和 2 个工作节点的小型集群足已。 

 安装 Istio 控制平面 

 一种选择是遵循官方教程,在 Kubernetes 集群中安装控制平面。安装步骤取决于你的本地机器类型(Mac,Linux,Windows),因此我们不会在此提供本地 istioctl 应用程序和 kubectl 的安装说明,这两个 CLI 工具将用于管理 Kubernetes 和 Istio。
对于那些缺乏耐心但懂行的人来说,这有分不太详细的指导(如果不奏效,可以逐步使用官方指导):

  • 安装 Kubernetes 集群(使用上面列出的任何方法,或使用现有的测试\开发集群)。
  • 在本地安装 kubectl(用它来管理 Kubernetes 集群)。
  • 从 GitHub 发布页面安装 istioctl(将 Envoy 代理注入 Pod 并设置路由规则和策略),安装很简单:
  • 适用于 Mac 或 Linux 运行curl -L https://git.io/getLatestIstio | sh -
  • 在 Windows 上解压缩 zip,并将二进制文件复制到 PATH(可以简单地复制到c:\windows\system32\)或 istioctl.exe 从 /bin/ 目录运行所有命令。

从 /bin/ 目录运行所有命令。

  • 到包含解压缩文件的文件夹,然后通过执行kubectl apply -f install/kubernetes/istio-demo.yaml

       进行安装。
另一种选择是使用 Kublr 创建你的 Kubernetes 集群:在 AWS 或 Azure 上启动集群的简便方法(阅读我们的快速入门即可[1])。
在仪表板中找到以下链接并将配置文件下载到你的~/.kube/config(%USERPROFILE%/.kube/config 在Windows中),然后导航到 Kubernetes 仪表板:
%USERPROFILE%/.kube/config在 Windows 中,然后导入到 Kubernetes 仪表板: 


使用配置文件中的凭据(找到 “username:admin” 并使用此用户及其列出的密码登录仪表板)。你能看到仪表板,并单击侧栏中的默认 “NAMESPACE”, 将显示以下 3 个默认 Namespace: 

Istio 组件将安装到它们自己的 Namespace 中。找到你下载的 Istio 压缩包、解压,然后在文件夹下运行:kubectl apply -f install/kubernetes/istio-demo.yaml你将看到正在创建的许多组件,每个组件都在官方文档中有描述,或者你可以打开 yaml 文件查看注释,每个资源都记录在该文件中。然后我们可以浏览 Namespace 并检查是否所有内容都已成功创建: 


 单击 istio-system 并确保在组件创建期间没有错误或问题。它看起来应该类似于: 


图中大约有 50 个事件,你可以滚动查看“成功”状态,并看到某处是否有错误。如果出现错误,你可以在 Istio GitHub 问题页面上发布错误报告。


我们需要找到 istio-ingress 服务的入口点,以此了解流量发送到的位置。导航到侧栏中的 “istio-system”Namespace。如果它创建后在其他 Namespace 中不可见,只需刷新浏览器页面,选择该 Namespace,单击 “Service” 并找到外部端点,如下图所示: 

这是 AWS 弹性负载均衡器,但你可能会看到 IP 地址,具体取决于集群设置。我们将使用此端点地址访问我们演示的 Web 服务。

使用 Envoy Proxy Sidecar 部署演示 Web 服务 

现在来到本教程最有趣的部分。我们来检查这个 Sevice Mesh 的路由功能。首先,我们将部署两个演示 Web 服务,“蓝色”和“绿色”。将以下内容复制到名为 my-websites.yaml 的 yaml 文件中。

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: web-v1
  namespace: default
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: website
        version: website-version-1
    spec:
      containers:
      - name: website-version-1
        image: aquamarine/kublr-tutorial-images:v1
        resources:
          requests:
            cpu: 0.1
            memory: 200
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: web-v2
  namespace: default
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: website
        version: website-version-2
    spec:
      containers:
      - name: website-version-2
        image: aquamarine/kublr-tutorial-images:v2
        resources:
          requests:
            cpu: 0.1
            memory: 200
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: web-v3
  namespace: default
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: website
        version: website-version-3
    spec:
      containers:
      - name: website-version-3
        image: aquamarine/kublr-tutorial-images:v3
        resources:
          requests:
            cpu: 0.1
            memory: 200
---
apiVersion: v1
kind: Service
metadata:
  name: website
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  selector:
    app: website

请注意,当你想要使用带有 Pod 的 Envoy sidecar 时,应该存在标签“app”中(它用于请求跟踪功能使用),并且服务定义中的 “spec.ports.name” 必须正确命名(http、http2、grpc、redis、mongo)否则 Envoy 将对该服务流量采取行动,把它当成普通的 TCP 一样,这样你将无法使用路由的第 7 层功能!此外,Pod 在集群中只提供一个“Service”。如你所见,定义文件有三个简单的部署,每个部署使用不同版本的 Web 服务(v1 / v2 / v3),以及三个简单的服务,每个服务都指向相应的部署。
现在,我们将使用 “istioctl kube-inject” 命令将所需的 Envoy 代理配置添加到此文件中的 Pod 来定义。它将生成一个新的 yaml 文件,其中包含可供 kubectl 部署的 Envoy sidecar 其他组件,运行:istioctl kube-inject -f my-websites.yaml -o my-websites-with-proxy.yaml如果它按预期进行工作,你将看到此输出:
deployment "web-v1" created
deployment "web-v2" created
deployment "web-v3" created
service "website" created
Let’s inspect the pods to see that the Envoy

我们可以看到每个 Pod 有两个容器,一个是网站容器,另一个是代理 sidecar:

 此外,我们可以通过运行以下命令检查 Envoy 代理日志:kubectl logs <your pod name> istio-proxy你将看到很多输出,最后一行与此类似:

add/update cluster outbound|80|version-1|website.default.svc.cluster.local starting warming
add/update cluster outbound|80|version-2|website.default.svc.cluster.local starting warming
add/update cluster outbound|80|version-3|website.default.svc.cluster.local starting warming
warming cluster outbound|80|version-3|website.default.svc.cluster.local complete
warming cluster outbound|80|version-2|website.default.svc.cluster.local complete
warming cluster outbound|80|version-1|website.default.svc.cluster.local complete

这意味着代理 sidecar 状态良好并在该 Pod 中运行。
现在我们需要部署最小的 Istio 配置资源,将流量路由到我们的服务和 Pod 上,将以下清单保存到名为“website-routing.yaml”的文件中:

---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
 name: website-gateway
spec:
 selector:
   # Which pods we want to expose as Istio router
   # This label points to the default one installed from file istio-demo.yaml
   istio: ingressgateway
 servers:
 - port:
     number: 80
     name: http
     protocol: HTTP
   # Here we specify which Kubernetes service names
   # we want to serve through this Gateway
   hosts:
   - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: website-virtual-service
spec:
 hosts:
 - "*"
 gateways:
 - website-gateway
 http:
 - route:
   - destination:
       host: website
       subset: version-1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
 name: website
spec:
 host: website
 subsets:
 - name: version-1
   labels:
     version: website-version-1
 - name: version-2
   labels:
     version: website-version-2
 - name: version-3
   labels:
     version: website-version-3

Gateway,VirtualService 和 DestinationRule 是自定义的 Istio 资源,用于管理和配置istio-ingressgateway pod的入口行为。我们将在下一个教程中更深入地描述它们,这些教程写明 Istio 配置的技术细节。现在,部署这些资源以便能够访问示例的网站:
kubectl create -f website-routing.yam下一步是访问我们的演示网站。我们部署了三个“版本”,每个版本显示不同的页面文本和颜色,但目前我们只能通过 Istio ingress 访问 v1。而我们访问我们的终端只是为了确保 Web 服务被部署。
通过运行以下命令查找外部端点:

kubectl get services istio-ingressgateway -n istio-system

或者通过浏览 istio-inressgateway 服务找到它,如下所示(我们也在本教程的开头看到它): 



 通过点击它访问外部端点。你可能会看到多个链接,因为一个链接指向 HTTPS,另一个链接指向负载均衡器的 HTTP 端口。如果是这样,请仅使用 HTTP 链接,因为我们没有为本教程设置 TLS,你应该看到演示网站的 v1 页面: 


 我们示例网站中的 Kubernetes 服务仅指向单一部署,而确切配置是我们为网站创建的 Istio VirtualService。它告诉 Envoy 代理将“Web”服务的请求仅路由到标签为“version:website-version-1”的 Pod(服务网站的清单只选择了一个标签“app:website”是来自我们的 Pod ,但是没有说明要选择的“版本”标签 —— 因此,如果没有Envoy 路由策略,Kubernetes 服务本身将在所有具有“app:website”标签的 Pod 中进行循环,包括 v1、2 和 3。你可以通过更改 VirtualService 清单的以下部分并重新部署它来更改我们看到的网站版本:

http:
 - route:
   - destination:
       host: website
       subset: version-1

通常,当需要使用少量流量测试新版本的应用程序时(金丝雀部署),vanilla Kubernetes 方法将创建第二个部署,该部署使用新的 Docker 镜像但使用相同的 Pod标签,这样就可以使“Service”将流量发送到此 Pod 标签中,同时在第二次部署中将新插入的 Pod 与之前的 Pod 进行平衡。它不像 Istio 解决方案那样灵活。你无法轻松将 10% 的流量指向新部署(为了达到精确的 10%,你需要根据所需的百分比保持两个部署之间的 Pod 副本比例,例如 9 个“v1 pods”和 1 个“v2 pod “,或 18 个”v1 pods“和 2 个”v2 pods“),并且不能使用 HTTP 标头将请求路由到特定版本上。
参考文献:[1]https://docs.kublr.com/quickstart/[2]https://kublr.com/blog/implementing-a-service-mesh-with-istio-to-simplify-microservices-communication/
 

77 comCount 0