【三小时学会Kubernetes!(零) 】系统结构及相关示例微服务介绍

时间:2021-10-19 02:02:55

写在前面

牢牢占据容器技术统治地位的 Kubernetes,其重要性想必不言而喻,我保证本文是最详尽的 Kubernetes 技术文档,从我在后台排版了这么漫长的时间就能看出来。废话不多说 — —

【三小时学会Kubernetes!(零) 】系统结构及相关示例微服务介绍

以下为译文:

为什么银行肯花大价钱雇我做 Kubernetes 如此简单的工作?——我一直很奇怪这一点,因为我觉得任何人都可以在 3 个小时内学会这项技术。

如果你怀疑我说的,就来挑战一下吧!读完本文,你绝对可以学会如何在 Kubernetes 集群上运行基于微服务的应用程序。我保证你可以做到,因为我就是这样向我的客户介绍 Kubernetes 的。

本文的教程与其他资源有何不同?有很大不同。大多数的教程都从最简单的内容讲起:Kubernetes 的概念和 kubectl 的命令。本文则是基于读者了解应用程序的开发、微服务和 Docker 容器等基础之上。

本文中,我们会涉及的内容包括:

  • 在计算机上运行基于微服务的应用程序;
  • 为微服务应用程序的每个服务建立容器映像;
  • Kubernetes 的基本介绍;
  • 在 Kubernetes 管理的集群内部署基于微服务的应用程序。

通过一步步深入学习,让大家能够领会 Kubernetes 的简单易用。只有你了解它的使用环境时,才能轻松掌握 Kubernetes。废话不多说,我们开始吧。

应用程序示范

如下应用程序有一个功能:每次输入接受一个句子;使用文本分析,计算句子所表达的情绪。
【三小时学会Kubernetes!(零) 】系统结构及相关示例微服务介绍

图1:情感分析网络应用

从技术的角度看来,这个应用程序包含 3 个微服务,每个都包含特定功能:

  • SA-Frontend:前端, Nginx 网络服务器,提供 ReactJS 静态文件;
  • SA-WebAp:网络应用, Java 网络应用程序,处理来自前端的请求;
  • SA-Logic:逻辑处理, Python 应用程序,执行情感分析。

你需要知道微服务是无法独立工作的,它们引入了“关注点分离”(separation of concerns),但是它们之间依然需要交互。

【三小时学会Kubernetes!(零) 】系统结构及相关示例微服务介绍

图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 应用程序加载成功。

【三小时学会Kubernetes!(零) 】系统结构及相关示例微服务介绍

图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 网络应用程序监听这个端口!

【三小时学会Kubernetes!(零) 】系统结构及相关示例微服务介绍

图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

【三小时学会Kubernetes!(零) 】系统结构及相关示例微服务介绍

图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。
【三小时学会Kubernetes!(零) 】系统结构及相关示例微服务介绍

图6:微服务架构完成

运行效果:
【三小时学会Kubernetes!(零) 】系统结构及相关示例微服务介绍

在下面一节中,我们将介绍如何在 Docker 容器内启动这些服务,因为这是在 Kubernetes 集群内运行这些服务的前提条件。

来自:CSDN(微信号:CSDNnews),作者:Rinor Maloku,译者:弯月,责编:郭芮