全书目录

第一章 概述

本文目录

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

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

 

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

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

  1. 【译文连载】 理解Istio服务网格(第一章 概述)

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

  2. 【译文连载】 理解Istio服务网格(第六章 可观测性)

    全书目录 第一章 概述 第二章 安装 第三章 流控 第四章 服务弹性 第五章 混沌测试 ​本文目录 第6章 可观测性 6.1 分布式调用链跟踪(tracing) 6.1.1 基本概念 6.1.2 Ja ...

  3. 【译文连载】 理解Istio服务网格(第七章 安全)

    全书目录 第一章 概述 第二章 安装 第三章 流控 第四章 服务弹性 第五章 混沌测试 第六章 可观测性 本文目录 第7章 安全 7.1 身份认证 7.1.1 Kubernetes上的Istio的身份 ...

  4. 【译文连载】 理解Istio服务网格(第三章 流控)

    第3章 流控.............................................................................................. ...

  5. 【连载】微服务网格Istio(一)

    Istio基础 服务网格是用于描述构成应用程序的微服务网络以及应用之间的交互,服务网格的功能包括服务发现.负载均衡.故障恢复.指标和监控以及更加复杂的运维工作,例如A/B测试.金丝雀发布.限流.访问控 ...

  6. Istio最佳实践:在K8s上通过Istio服务网格进行灰度发布

    Istio是什么? Istio是Google继Kubernetes之后的又一开源力作,主要参与的公司包括Google,IBM,Lyft等公司.它提供了完整的非侵入式的微服务治理解决方案,包含微服务的管 ...

  7. Istio(十一):向istio服务网格中引入虚拟机

    目录 一.模块概览 二.系统环境 三.虚拟机负载 3.1 虚拟机负载 3.2 单网络架构 3.3 多网络架构 3.4 Istio 中如何表示虚拟机工作负载? 四.实战:向istio Mesh中引入虚拟 ...

  8. 初识 Istio - 服务网格管理工具

    What is a service mesh(服务网格)? 微服务在国内流行已经多年了,大多数公司选择了基于容器化技术( Docker )以及容器编排管理平台 ( Kubernetes )落地微服务 ...

  9. 《深入理解java虚拟机》第二章 Java内存区域与内存溢出异常

    第二章 Java内存区域与内存溢出异常 2.2 运行时数据区域  

随机推荐

  1. Android/Unity大乱斗-完整双方集成交互指南

    这是一个很长很长的story!-芝麻粒儿创作 开篇 源码地址:GitHub 本文目的,将Unity集成到Android端,学完本文后你可以做到 Android任意布局加载Unity 3D场景 任意操作 ...

  2. python列表的 + 、* 、in 、 not in 、 len() 、 max() 、 min()

    + 列表拼接 first_list = [1,2,3] + ['a',5] # + 将列表拼接 print(first_list) # [1, 2, 3, 'a', 5] *  列表与数字n相乘 : ...

  3. 七种武器:JavaScript 新特性闪亮登场

    JavaScript(或ECMA Script) 是一门不断发展的语言,有许多关于如何前进的建议和想法.TC39(技术委员会39)是负责定义JS标准和特性的委员会,今年他们非常活跃.以下是目前处于&q ...

  4. 三、JVM之方法区

    一.什么式方法区 方法区,也称非堆(Non-Heap),又是一个被线程共享的内存区域.其中主要存储加载的类字节码.class/method/field等元数据对象.static-final常量.sta ...

  5. svn或git 提交文件排除

    也可以参考  https://blog.csdn.net/chenmintong/article/details/79725324 乌龟git 过滤掉忽略文件(首先右键 某文件 删除并添加到忽略列表 ...

  6. 2018徐州现场赛A

    题目链接:http://codeforces.com/gym/102012/problem/A 题目给出的算法跑出的数据是真的水 #include<iostream> #include&l ...

  7. [bzoj4571] [loj#2016] [Scoi2016] 美味

    Description 一家餐厅有 \(n\) 道菜,编号 \(1\)...\(n\) ,大家对第 \(i\) 道菜的评价值为 \(ai\)( \(1 \leq i \leq n\) ).有 \(m\ ...

  8. 查看jvm内存信息

    Runtime.getRuntime().maxMemory(); //最大可用内存,对应-Xmx Runtime.getRuntime().freeMemory(); //当前JVM空闲内存 Run ...

  9. 使用telnet连接redis

    平时连接redis用的是官方客户端redis-cli, 使用redis-cli最常用的几个参数如下: -h <hostname> Server hostname (default: 127 ...

  10. java.sql.Date与java.sql.Date区别

    public static void main(String[] args) { java.sql.Date createTime = new java.sql.Date(System.current ...