写在前面
牢牢占据容器技术统治地位的 Kubernetes,其重要性想必不言而喻,我保证本文是最详尽的 Kubernetes 技术文档,从我在后台排版了这么漫长的时间就能看出来。废话不多说 — —
以下为译文:
为什么银行肯花大价钱雇我做 Kubernetes 如此简单的工作?——我一直很奇怪这一点,因为我觉得任何人都可以在 3 个小时内学会这项技术。
如果你怀疑我说的,就来挑战一下吧!读完本文,你绝对可以学会如何在 Kubernetes 集群上运行基于微服务的应用程序。我保证你可以做到,因为我就是这样向我的客户介绍 Kubernetes 的。
本文的教程与其他资源有何不同?有很大不同。大多数的教程都从最简单的内容讲起:Kubernetes 的概念和 kubectl 的命令。本文则是基于读者了解应用程序的开发、微服务和 Docker 容器等基础之上。
本文中,我们会涉及的内容包括:
- 在计算机上运行基于微服务的应用程序;
- 为微服务应用程序的每个服务建立容器映像;
- Kubernetes 的基本介绍;
- 在 Kubernetes 管理的集群内部署基于微服务的应用程序。
通过一步步深入学习,让大家能够领会 Kubernetes 的简单易用。只有你了解它的使用环境时,才能轻松掌握 Kubernetes。废话不多说,我们开始吧。
应用程序示范
如下应用程序有一个功能:每次输入接受一个句子;使用文本分析,计算句子所表达的情绪。
图1:情感分析网络应用
从技术的角度看来,这个应用程序包含 3 个微服务,每个都包含特定功能:
- SA-Frontend:前端, Nginx 网络服务器,提供 ReactJS 静态文件;
- SA-WebAp:网络应用, Java 网络应用程序,处理来自前端的请求;
- SA-Logic:逻辑处理, Python 应用程序,执行情感分析。
你需要知道微服务是无法独立工作的,它们引入了“关注点分离”(separation of concerns),但是它们之间依然需要交互。
图2:情感分析网络应用中的数据流
我们可以通过微服务之间的数据流来描述这种交互:
- 客户端应用程序请求初始页面 index.html(index.html 页面会反过来加载 ReactJS 应用程序的脚本);
- 用户与应用程序的交互触发到 Spring 网络应用的请求;
- Spring 网络应用将请求发送给 Python 应用做情感分析;
- Python 应用计算情感值,并返回结果;
- Spring 网络应用将结果返回给 React 应用(然后由 React 应用将结果显示给用户)。
点击此处下载这些应用程序的代码:https://github.com/rinormaloku/k8s-mastery。现在就可以克隆这个代码仓库,接下来我们要做更加精彩的东西。
在计算机上运行基于微服务的应用程序
我们需要启动所需的 3 个服务。让我们从最有意思的部分——前端应用程序开始。
设置 React 的本地部署
为了运行 React 应用程序,首先你需要在计算机上安装 NodeJS 和 NPM。安装好这些后,在终端中进入目录 sa-frontend。然后运行如下命令:
npm install
该命令会将 React 应用程序的所有 Javascript 依赖都下载到文件夹 node_modules 中(package.json 文件中定义了所有依赖)。在所有依赖都解决后,运行如下命令:
npm start
这样就可以了!我们运行了 React 应用程序,现在可以通过默认端口 localhost:3000 访问该应用程序了。你可以*修改代码,并从浏览器中观察即时效果。这里用到了热模块替换(即在运行时用替换模块来减少页面刷新次数)技术,可以减轻前端开发的工作。
准备好 React 应用的产品环境
为了搭建产品环境,我们需要建立应用程序的静态网页,并通过网络服务器提供服务。
为了搭建 React 应用程序,首先在终端中进入目录 sa-frontend。然后运行如下命令:
npm run build
该命令会在项目的文件目录中生成一个名叫“build”的文件夹。该文件夹内包含了 ReactJS 应用程序所需的所有静态文件。
利用 Nginx 提供静态文件
首先安装并启动 Nginx 网络服务器。然后将 sa-frontend/build 目录内的文件移动到 [nginx安装目录]/html。
如此一来,我们就可以通过 [nginx安装目录]/html/index.html 来访问 index.html 文件了,而它是 Nginx 服务的默认文件。
默认情况下,Nginx 网络服务器会监听端口 80。你可以通过修改 [nginx安装目录]/conf/nginx.conf 文件中的 server.listen 字段来指定不同的端口。
打开浏览器,并访问端口 80,可以看到 ReactJS 应用程序加载成功。
图3:Nginx 提供的 React 应用程序服务
在输入框“Type your sentence”(输入句子)中输入句子,然后点击 SEND(发送)按钮,但是页面会返回错误 404(你可以检查浏览器的控制台)。为什么?让我们检查一下代码。
检查代码
我们可以在 App.js 文件中看到,点击“SEND”按钮会触发 analyzeSentence。该方法的代码如下所示(我们对每一段代码进行了编号“#号码”,具体解释如下所示):
analyzeSentence() { fetch('http://localhost:8080/sentiment', { // #1 method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sentence: this.textField.getValue()})// #2 }) .then(response => response.json()) .then(data => this.setState(data)); // #3 }
#1:POST 方法调用的 URL(应用程序应该在该 URL 上监听访问);
#2:发送到应用程序的请求主体如下所示:
{ sentence: “I like yogobella!” }
#3:返回值将更新该组件的状态,而状态的变更将重新渲染这个组件。如果我们收到数据(即包含用户输入的句子和极性的 JSON 对象),那么我们会显示组件 polarityComponent,因为满足条件而且我们可以如下定义该组件:
const polarityComponent = this.state.polarity !== undefined ? <Polarity sentence={this.state.sentence} polarity={this.state.polarity}/> : null;
一切看起来都很好。但是我们还差什么呢?你可能已经发现我们没有在 localhost:8080 上设置任何东西!我们必须启动 Spring 网络应用程序监听这个端口!
图4:缺失的 Spring 网络应用程序微服务
建立 Spring 网络应用程序
为了设置 Spring 网络应用程序,你必须安装 JDK8 和 Maven,并设置它们的环境变量。设置好后,我们继续下个部分。
将应用程序打包成 Jar 文件
在终端中进入 sa-webapp 目录,并运行如下命令:
mvn install
该命令会在目录 sa-webapp 中生成一个名叫 target 的文件夹。target 文件夹内有打包好的 Java 应用程序包:’sentiment-analysis-web-0.0.1-SNAPSHOT.jar’。
启动应用程序
进入 target 目录,并通过如下命令启动应用程序:
java -jar sentiment-analysis-web-0.0.1-SNAPSHOT.jar
等等……出错了。应用程序启动失败,我们可以看到如下异常信息:
Error creating bean with name 'sentimentController': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'sa.logic.api.url' in value "${sa.logic.api.url}"
这里显示的重要信息是 SentimentController 中的 sa.logic.api.url。我们检查一下这段代码。
检查代码
@CrossOrigin(origins = "*") @RestController public class SentimentController { @Value("${sa.logic.api.url}") // #1 private String saLogicApiUrl; @PostMapping("/sentiment") public SentimentDto sentimentAnalysis( @RequestBody SentenceDto sentenceDto) { RestTemplate restTemplate = new RestTemplate(); return restTemplate.postForEntity( saLogicApiUrl + "/analyse/sentiment", // #2 sentenceDto, SentimentDto.class) .getBody(); } }
#1:SentimentController 有一个名叫 saLogicApiUrl 的字段。这个字段的赋值是由 sa.logic.api.url 属性定义的。
#2:saLogicApiUrl 与值“/analyse/sentiment”连接在一起,共同构成了 Sentiment Analysis 请求的 URL。
定义属性
在 Spring 中默认的属性资源是 application.properties(具体位置在 sa-webapp/src/main/resources 中)。但是这不是定义属性的唯一方式,我们可以通过之前的命令完成属性定义:
java -jar sentiment-analysis-web-0.0.1-SNAPSHOT.jar --sa.logic.api.url=WHAT.IS.THE.SA.LOGIC.API.URL
应该由 Python 应用程序运行时定义的值初始化该属性,如此一来 Spring 网络应用程序就可以知道在运行时把信息传递到哪里了。
为了简单起见,我们假设在 localhost:5000 上运行 Python 应用程序。请记得哦!
运行如下命令,然后我们来看看最后一个服务:Python 应用程序。
java -jar sentiment-analysis-web-0.0.1-SNAPSHOT.jar --sa.logic.api.url=http://localhost:5000
图5:缺失的 Python 网络应用程序微服务
建立 Python 应用程序
为了启动 Python 应用程序,首先我们需要安装 Python3 和 Pip,以及设置它们的环境变量。
安装依赖
在终端中进入 sa-logic/sa (代码库),然后运行如下命令:
python -m pip install -r requirements.txt python -m textblob.download_corpora
启动应用
在利用 Pip 安装好依赖后,我们就可以通过运行如下命令启动应用程序了:
python sentiment_analysis.py * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
这意味着应用程序已经启动,并在 localhost 的端口 5000 上监听 HTTP 请求了。
检查代码
让我们检查代码,看看处理逻辑部分的 Python 应用程序在干什么:
from textblob import TextBlob from flask import Flask, request, jsonify app = Flask(__name__) #1 @app.route("/analyse/sentiment", methods=['POST']) #2 def analyse_sentiment(): sentence = request.get_json()['sentence'] #3 polarity = TextBlob(sentence).sentences[0].polarity #4 return jsonify( #5 sentence=sentence, polarity=polarity ) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) #6
#1:实例化一个 Flask 对象;
#2:定义 POST 请求访问的路径;
#3:从请求主体内抽出“sentence”属性;
#4:初始化匿名 TextBlob 对象,并从第一个句子(我们只有一个)中获取极性;
#5:在相应体内返回句子和极性;
#6:运行 flask 对象应用来监听 localhost:5000 上的请求。
所有的服务都设置好,可以互相交流了。试试看重开前端的 localhost:80。
图6:微服务架构完成
运行效果:
在下面一节中,我们将介绍如何在 Docker 容器内启动这些服务,因为这是在 Kubernetes 集群内运行这些服务的前提条件。
来自:CSDN(微信号:CSDNnews),作者:Rinor Maloku,译者:弯月,责编:郭芮