随笔- 180  评论- 702  文章- 49 

【译文连载】 理解Istio服务网格(第二章 安装)

全书目录

第一章 概述

本文目录

1.命令行工具安装

2. Kubernetes/OpenShift安装

3. Istio安装

4.示例Java微服务安装

4.1 源码概览

4.2 编译和部署customer服务

4.3 编译和部署Preference服务

4.4 编译和部署recommendation服务

 

本章中,我们会介绍如何在Kubernetes上安装Istio。Istio并没有和Kubernets绑定,实际上,它合适很多种基础架构平台。但是,Kubernetes因为原生支持边车部署(sidecar deployment)概念,因此它是运行Istio的最佳平台之一。你可以使用任何版本的Kubernetes。本章中,我们将使用Minishift,这是一个可以让你的OpenShift安装并运行在本地虚拟机上的工具,而OpenShift则是一个面向开发者的Kubernetes企业发行版。

1. 命令行工具安装

​作为一个开发者,你可能已有了各种工具,但为了清晰起见,我们还是给个本书所需的工具列表:

  • Minishift:这是minikube的红帽发行版

  • VirtualBox:提供虚拟机的虚拟化工具

  • Mac/Windows环境上的Docker:Docker客户端

  • Kubectl:本书中我们主要会使用oc命令行,它基本上能替代kubectl,并可互换着使用。

  • Oc:minishift oc-env 命令行会输出oc命令行的路径,因此你不用单独下载了。

  • OpenJDK:你需要能访问javac和java命令行工具

  • Maven:用于编译Java项目

  • Stern:为了方便查看日志

  • Siege:用于第四章中的Istio压力测试

  • Git:通过 git clone 命令下载示例代码

  • istioctl:会通过下文中的部署被安装

  • curl和tar:要在bash中用到

2. OpenShift/Kubernetes安装

在安装环境之前,你应该很清楚你将创建很多服务。你将安装Istio控制平面、一些支持性能指标和可视化的应用程序,以及示例应用程序服务。为此,用于运行Kubernetes的虚拟机(VM)需要有足够的资源。我们建议使用8 GB内存和3个CPU核的虚拟机,但本书中包含的示例在4 GB内存和2个CPU核虚拟机上也能成功运行。 

Minishift安装好以后,你可以引导环境了,通过运行以下命令行:

    #!/bin/bash
    export MINISHIFT_HOME=~/minishift_1.27.0
    export PATH=$MINISHIFT_HOME:$PATH
    minishift profile set tutorial
    minishift config set memory 8GB
    minishift config set cpus 3
    minishift config set vm-driver virtualbox
    minishift config set image-caching true
    minishift addon enable admin-user
    minishift addon enable anyuid
    minishift config set openshift-version v3.11.0
    minishift start

然后,你可以进行环境配置了,然后就可以访问Minishift、Docker守护进程以及登录Kubernetes集群了:

    eval $(minishift oc-env)
    eval $(minishift docker-env)
    oc login $(minishift ip):8443 -u admin -p admin

如果一切顺利,你能运行下面的命令:

oc get node
    NAME        STATUS    AGE       VERSION
    localhost   Ready     5m        v1.11.0+d4cacc0

这时,你可以运行下面命令以访问web console: 

minishift dashboard

如果遇到错误,请查看Istio Tutorial for Java Microservices网站中的步骤,甚至提交一个Github 问题。

3. Istio安装

Istio发行版中包括命令行工具、安装文件和示例应用。运行下面的命令以下载Istio 1.0.4版本并解压缩:

curl -L https://github.com/istio/istio/releases/download/1.0.4/istio-1.0.4/-osx.tar.gz | tar xzcd istio-1.0.4

现在你要开始准备OpenShift/Kubernetes环境了。Istio使用ValidatingAdmissionWebhook来校验Istio配置,使用MutatingAdmissionWebhook去自动向用户pod中插入边车代理。运行下面的命令去更新Minishift的默认配置:

minishift openshift config set --target=kube --patch '{
        "admissionConfig": {
            "pluginConfig": {
                "ValidatingAdmissionWebhook": {
                    "configuration": {
                        "apiVersion": "v1",
                        "kind": "DefaultAdmissionConfig",
                        "disable": false
} }, 
                "MutatingAdmissionWebhook": {
                    "configuration": {
                        "apiVersion": "v1",
                        "kind": "DefaultAdmissionConfig",
                        "disable": false
} } 
} } 
}' 

现在开始安装Istio。在Istio发行版的根目录中,运行以下命令:

oc apply -f install/kubernetes/helm/istio/templates/crds.yaml
oc apply -f install/kubernetes/istio-demo.yaml
oc project istio-system

这会安装所有Istio控制平面组件,包括Pilot、Mixer(实际的Mixer pod的名称为telemetry和policy)和Citadel。还会安装一些附加服务,包括用于统计信息收集的Prometheus,用于分布式跟踪的Jaeger,用于统计信息展示的Grafana,用于服务简单可视化的Servicegraph等。这些服务会在第6章中介绍。

最后,因为我们用的是OpenShift,你可以将这些服务通过Router发布出去,这样你就不用配置复杂的节点端口了。

oc expose svc servicegraph
oc expose svc grafana
oc expose svc prometheus
oc expose svc tracing

现在,所有Istio控制平面组件和相关服务都已经运行起来了。你可以运行下面的命令来查看它们:

oc get pods
NAME
grafana-59b787b9b             1/1   Running     0        3m
istio-citadel-78df8c67d9         1/1   Running     0        3m
istio-cleanup-secrets            0/1   Completed   0        3m
istio-egressgateway-674686c846   1/1   Running     0        3m
istio-galley-58f566cb66          1/1   Running     0        3m
istio-grafana-post-install          0/1   Completed   0        3m
istio-ingressgateway-6bbdd58f8c   1/1   Running     0        3m
istio-pilot-56b487ff45            2/2   Running     0        3m
istio-policy-68797d879           2/2   Running     0        3m
istio-security-post-install          0/1   Completed   0        3m
istio-sidecar-injector-b88dfb954    1/1   Running     0        3m
istio-telemetry-68787476f4        2/2   Running     0        3m
istio-tracing-7596597bd7          1/1   Running     0        3m
prometheus-76db5fddd5           1/1   Running     0        3m
servicegraph-fc55fc579            1/1   Running     0        3m

最后要做的是让istioctl在命令行中能运行。istioctl是Istio命令行工具,能用于手工插入istio-proxy边车代理容器,以及创建、更新和删除Istio资源。当解压Istio发行版后,会有一个/bin文件夹,其中就有istioctl二进制文件。你可以把它加入到PATH路径中。

export ISTIO_HOME=~/istio-1.0.4
export PATH=$ISTIO_HOME/bin:$PATH

现在,你能在命令行中运行istioctl命令查看它的版本了。

istioctl version
Version: 1.0.4
GitRevision: a44d4c8bcb427db16ca4a439adfbd8d9361b8ed3
User: root@0ead81bba27d
Hub: docker.io/istio
GolangVersion: go1.10.4
BuildStatus: Clean

现在,我们去安装示例服务。

 

4.示例Java微服务安装

 要展现Istio的能力,你需要使用一些互相交互和通信的微服务。接下来我们要用到的微服务是一个简单的客户服务网站。在这些场景中,这个网站会允许客户为网站的特定方面设置优先项(preference),而这些优先项会从一个推荐引擎中获得。微服务之间的通信流如下所示:

Customer ⇒ Preference ⇒ Recommendation 

从现在开始,你要有本书用到的源代码。你可以从the Istio Tutorail for Java Microservies 网站(https://github.com/redhat-developer-demos/istio-tutorial)下载源码,转至book-1.0.4分支,如下所示:

git clone https://github.com/redhat-developer-demos/istio-tutorial.git
cd istio-tutorial
git checkout book-1.0.4 

4.1源码概览 

浏览刚才所下载的源码的istio-tutorial子目录,你会看到customer、preference和recommendation这三个目录。每个目录都包含了相关服务的源代码,这些源码会展示Istio的能力。 

Customer和perference服务都是用Java Sprint Boot实现的简单直接REST服务。例如,这是customer服务的端点:   

@Value("${preferences.api.url:http://preference:8080}")
    private String remoteURL;
    @RequestMapping("/")
        public ResponseEntity<String> getCustomer(
          @RequestHeader("User-Agent")
            String userAgent,
          @RequestHeader(value = "user-preference",
                         required = false)
            String userPreference) {
           try {
              /* Carry user-agent as baggage */
              tracer.activeSpan()
                .setBaggageItem("user-agent", userAgent);
              if (userPreference != null &&
                  !userPreference.isEmpty()) {
                  tracer.activeSpan().setBaggageItem(
                    "user-preference", userPreference);
              }
              ResponseEntity<String> responseEntity =
                restTemplate.getForEntity(remoteURL, String.class);
              String response = responseEntity.getBody();
              return ResponseEntity.ok(String.format(
                RESPONSE_STRING_FORMAT, response.trim()));
            } catch (HttpStatusCodeException ex) {...
            } catch (RestClientException ex) {...}
} 

异常处理部分我们暂且省略。你可以看到,这个HTTP端点只是简单地调用了由 remoteURL指定的preference服务,并将preference服务的回复加上一个固定字符串RESPONSE_STRING_FORMATI再返回。注意,这里除了Spring RestTemplate之外没用到其它库。我们没有做更多的封装比如断路器、重试、客户端侧的负载均衡等等。我们也没有添加额外的请求跟踪和镜像功能。只有最纯粹的代码!我们就是希望你写出强壮的业务逻辑代码,而不用添加对应用网络的处理代码。 

在前面的例子中,我们暂时略过了异常处理部分,但这部分也是非常重要的。大多数编程语言提供了探测和处理异常的机制。当你在代码中调用一个可能会失败的函数时,你需要关注所抛出的异常并进行适当的处理。在customer HTTP端点这个例子中,你试图通过网络调用preference服务。这个调用可能会失败,因此你需要将调用代码封装进异常处理代码块。在异常处理部分,你可以做各种有趣的应对措施,比如从缓存中读取数据或调用另一个函数。有时,开发人员会在获取不到preference服务的返回时返回已缓存好的数据。 

也许你已经看到下面这句跟“user-agent”有关的代码了:

tracer.activeSpan().setBaggageItem("user-agent", userAgent);

Istio允许基于HTTP头部信息做路由决策,只有你将HTTP头部信息传入去调用服务。在这个例子中,我们需要确保“user-agent”在preference和recommendation中是可见的。第三章的第29页“基于HTTP头进行路由”部分会详细介绍流量控制。 

在我们的customer示例中,我们已经在pox.xml中添加了特定的 opentracing-spring-cloud-starter和jaeger-tracersolver依赖。这些依赖使得你能在Java代码中添加与OpenTracing API之间的交互逻辑。 

在本书用到的例子和用户场景中,我们使用了CNCF联盟的Jaeger Tracing项目。可访问其官网去了解它的更多信息,本书第6章也会介绍Istio的可观察性。 

大致浏览代码后,我们可以编译应用并在Kubernetes/OpenShift集群中的容器中运行它们了。 

注意:本书主要使用oc而不是kubectl命令行工具。就像OpenShift是Kubernetes的超集一样,oc还是kubectl的超集。在几乎所有场景中,两个命令行的用法完全相同,但是,还有两个主要场景中它们有些不同。第一个有关OpenShift的项目(project)概念,它对应Kubernetes中的命名空间(namespace)。第二个跟安全有关,OpenShift中的oc login和minishift默认都是安全的。 

开始部署服务之前,确保你创建了所需的项目,并应用了必要的安全权限:

oc new-project tutorial
oc adm policy add-scc-to-user privileged -z default -n tutorial

这条oc adm 命令向tutorial命名空间中的default服务账号添加了privileged安全上下文限定(SCC)。 

4.2编译和部署customer服务 

现在,我们来编译和部署customer服务。先登录进Minishift,再使用下面的命令检查下你的登录状态:

oc status
oc whoami

然后确认你的docker工具指向Minishift的Docker守护进程了:

eval $(minishift docker-env)
docker images

你将看到本地Docker守护进程的仓库中的一些Istio和OpenShift镜像。转至cutomer目录,编译代码:

cd customer/java/springboot
mvn clean package

现在代码编译好了。下一步是将应用打包为Docker镜像,这样你就能在Kubernetes/OpenShift中运行它了:

docker build -t example/customer .

这会将customer服务打包进一个Docker镜像。你可以运行下面的命令来查看所生成的镜像:

docker images | grep example

在cusomter/Kubernetes目录中,有两个Kubernetes资源文件Deployment.yml和Service.yml。现在我们要部署customer微服务,并插入Istio边车代理。这次我们用手工方式插入边车。运行下面的命令来插入边车代理:

istioctl kube-inject -f ../../kubernetes/Deployment.yml

检查该命令的输出,并与之前没修改过的Deployment.yml文件做对比。你会发现输出中被添加了以下内容:      

- args:
            - proxy
            - sidecar
            - --configPath
            - /etc/istio/proxy
            - --binaryPath
            - /usr/local/bin/envoy
            - --serviceCluster
            - customer
            - --drainDuration
            - 45s
            - --parentShutdownDuration
            - 1m0s
            - --discoveryAddress
            - istio-pilot.istio-system:15007
            - --discoveryRefreshDelay
            - 1s
            - --zipkinAddress
            - zipkin.istio-system:9411
            - --connectTimeout
            - 10s
            - --proxyAdminPort
            - "15000"
            - --controlPlaneAuthPolicy
            - NONE
            ...
            image: docker.io/istio/proxyv2:1.0.4
            imagePullPolicy: IfNotPresent
            name: istio-proxy

其中你能看到第二个容器被插入了,其名称为istio-proxy。现在可以创建新的部署和Kubernetes服务了:

oc apply -f <(istioctl kube-inject -f ../../kubernetes/Deployment.yml) -n tutorial
oc create -f ../../kubernetes/Service.yml -n tutorial

新的pod被创建出来了:

oc get pods
NAME                READY     STATUS  RESTARTS  AGE
customer-6564ff969f-jqkkr   2/2       Running   0          2m

因为插入了一个istio-proxy边车容器,所以你在READY列看到了“2/2”。你还可以用其它命令去查看更多信息,比如:

oc get deployment customer -o yaml
oc describe pod customer-6564ff969f-jqkkr
oc logs customer-6564ff969f-jqkkr -c customer

注意oc logs命令中的 –c customer 参数,因为pod中存在两个容器,因此你需要指定待查看日志的容器名称。

 因为customer服务要在Kubernetes/OpenShift集群外被访问,因此需要添加route对象,使用下面的命令:

oc expose service customer
curl customer-tutorial.$(minishift ip).nip.io

这里我们用的是nip.io服务。在curl命令行的输出中,你将看到以下错误,因为preference和recommendation服务还没有被部署:

customer => I/O error on GET request for "http://preference:8080": preference: Name or service not known

 现在你可以部署本例中的其它服务了。 

4.3编译和部署Preference服务 

跟编译和部署customer服务的方法一样,本节中你会编译、打包和部署preference服务:

cd preference/java/springboot
mvn clean package
docker build -t example/preference:v1 .

然后为preference服务插入Istio边车代理,并创建服务对象:

oc apply -f <(istioctl kube-inject -f ../../kubernetes/Deployment.yml) -n tutorial
oc create -f ../../kubernetes/Service.yml 

现在,再次使用curl工具去访问customer服务:

curl customer-tutorial.$(minishift ip).nip.io

你依然会看到错误,但这次有些不同:

customer => 503 preference => I/O error on GET request for    "http://recommendation:8080": recommendation: Name or...

 这个错误是因为preference服务访问不到recommendation服务。因此,下一步中,我们需要编译和部署recommendation服务。 

4.4编译和部署recommendation服务 

要让这些服务都运行起来的最后一步是部署recommendation服务。为了尝试不同的做法,我们采用recommendation服务的Vert.x代码。跟前述方法一样,采用以下步骤来编译、打包和部署recommendation服务:

cd recommendation/java/vertx
mvn clean package
docker build -t example/recommendation:v1 .
oc apply -f <(istioctl kube-inject -f ../../kubernetes/Deployment.yml) -n tutorial
oc create -f ../../kubernetes/Service.yml
oc get pods -w

查看输出中READY列为“2/2”。再次用curl访问customer服务,你会看到更好的结果了:

curl customer-tutorial.$(minishift ip).nip.io
customer => preference => recommendation v1 from '66b7c9779c': 1

成功了!三个服务之间的调用链如愿正常工作了。如果你运行curl多次,你会看到最后面的数字依次递增。66b7c9779c是recommendation服务的pod的UID。它由Java代码从HOSTNAME环境变量中获取到。从代码角度看,pod其实就是一个计算机,代码运行在其中。 

运行下面的命令去查看pod的名称:

oc get pod -l app=recommendation
NAME                      READY STATUS  RESTARTS AGE
recommendation-v1-66b7c9779c   2/2   Running      0        2m

现在三个服务之间的调用没问题了,接下来,我们将继续讨论Istio的更多核心能力,以及解决服务之间各种问题的强大能力。

 

书籍英文版下载链接为 https://developers.redhat.com/books/introducing-istio-service-mesh-microservices/,作者 Burr Sutter 和 Christian Posta

 

本中文译稿版权由本人所有。水平有限,错误肯定是有的,还请海涵。

  

 感谢您的阅读,欢迎关注我的微信公众号:

posted on 2020-02-18 09:50  SammyLiu  阅读(...)  评论(...编辑  收藏