Kubernetes指南,第1部分:应用程序,微服务和容器

根据我们的要求,Habr创建了Kubernetes中心,我们很高兴在其中发布第一本出版物。 订阅!

Kubernetes很容易。 为什么银行要为我在这方面的工作支付很多钱,而任何人都可以在几个小时内掌握这项技术?



如果您怀疑Kubernetes可以这么快地学习,建议您自己尝试一下。 也就是说,掌握了这些材料之后,您将能够在Kubernetes集群中基于微服务运行应用程序。 我可以保证,因为正是通过这里使用的方法,我训练Kubernetes与我们的客户一起工作。 该手册与其他手册有何区别? 实际上-很多东西。 因此,大多数这些材料都是从对简单事物的解释开始的-Kubernetes的概念和kubectl团队的功能。 这些材料的作者认为,他们的读者熟悉应用程序开发,微服务和Docker容器。 我们将走另一条路。 首先,让我们讨论一下如何在计算机上运行基于微服务的应用程序。 然后考虑为每个微服务组装容器映像。 之后,我们将了解Kubernetes,并分析在Kubernetes管理的集群中基于微服务的应用程序的部署。

这种方法与Kubernetes的渐进方法相结合,将给普通人以深刻的理解,以便了解Kubernetes中所有事物的排列方式多么简单。 当然,Kubernetes是一种简单的技术,只要任何想学习它的人都知道在何处以及如何使用它。

现在,不用多说,让我们开始讨论我们将使用的应用程序。

实验应用


我们的应用程序将仅执行一项功能。 它接受一个句子作为输入,然后使用文本分析的方式对该句子进行情感分析,并接收该句子的作者对某个对象的情感态度的估计值。

这是该应用程序的主窗口。


Web应用程序用于文本情感分析

从技术角度来看,该应用程序包含三个微服务,每个微服务都可以解决一组特定的任务:

  • SA-Frontend是提供React静态文件的Nginx Web服务器。
  • SA-WebApp是基于Java的Web应用程序,可处理来自前端的请求。
  • SA-Logic是执行文本情感分析的Python应用程序。

重要的是要注意,微服务不是孤立存在的。 它们实现了“职责分离”的思想,但是它们需要彼此交互。


应用数据流

在上图中,您可以看到系统的编号阶段,说明了应用程序中的数据流。 让我们对其进行分析:

  1. 浏览器从服务器请求index.html文件(服务器随后下载React应用程序包)。
  2. 用户与应用程序进行交互,这将导致对基于Spring的Web应用程序的调用。
  3. 该Web应用程序将文本分析请求重定向到Python应用程序。
  4. Python应用程序分析文本的色调,并返回结果作为对请求的响应。
  5. Spring应用程序将响应发送到React应用程序(然后,它向用户显示文本分析的结果)。

所有这些应用程序的代码都可以在这里找到。 我建议您现在将这个存储库复制到您自己,因为我们前面有许多有趣的实验。

在本地计算机上启动基于微服务的应用程序


为了使应用程序正常工作,我们需要运行所有三个微服务。 让我们从最有趣的内容开始-前端应用程序。

React配置React进行本地开发


为了运行React应用程序,您需要在计算机上安装Node.js和NPM平台。 安装完所有这些之后,通过终端进入sa-frontend项目文件夹并运行以下命令:

 npm install 

由于执行了此命令,React-application的依赖项(有关其条目位于package.json文件中)将被加载到node_modules文件夹中。 将依赖项下载到同一文件夹后,运行以下命令:

 npm start 

仅此而已。 现在,React应用程序正在运行,可以通过浏览器中的localhost:3000地址来访问它。 您可以在他的代码中进行更改。 您将立即在浏览器中看到这些更改的效果。 这归功于所谓的“热”模块更换。 因此,前端开发变成了一个简单而有趣的任务。

React准备React应用程序以输出到生产


为了真正使用React应用程序,我们需要将其转换为一组静态文件,并使用Web服务器将其提供给客户端。

要再次构建React应用程序,请使用终端,进入sa-frontend文件夹并运行以下命令:

 npm run build 

这将在项目文件夹中创建一个build目录。 它将包含React应用程序正常工作所需的所有静态文件。

using使用Nginx工具提供静态文件


首先,您需要安装并运行Nginx Web服务器。 在这里您可以下载它并找到安装和启动说明。 然后,您需要将sa-frontend/build文件夹的内容复制到[your_nginx_installation_dir]/html文件夹。

通过这种方法,可以在[your_nginx_installation_dir]/html/index.html获得在React应用程序构建期间生成的index.html文件。 默认情况下,这是Nginx服务器在访问文件时发出的文件。 服务器配置为侦听端口80 ,但是您可以根据需要通过编辑文件[your_nginx_installation_dir]/conf/nginx.conf

现在打开浏览器并转到localhost:80 。 您将看到React应用程序页面。


Nginx服务器服务的React应用程序

如果您现在在“ Type your sentence字段中Type your sentence ,然后单击“ Send按钮,则不会发生任何事情。 但是,如果您查看控制台,则可以在其中看到错误消息。 为了准确了解这些错误发生的位置,让我们分析应用程序代码。

▍分析前端应用程序代码


查看了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。 可以理解,该地址包含一个正在等待此类请求的应用程序。

2.请求正文发送到应用程序。 这是一个示例请求正文:

 {   sentence: "I like yogobella!" } 

3.收到对请求的响应后,组件状态将更新。 这将导致组件重新渲染。 如果我们接收到数据(即包含输入数据和计算出的文本分数的JSON对象),则将输出Polarity组件,因为将满足相应的条件。 这是我们描述组件的方式:

 const polarityComponent = this.state.polarity !== undefined ?   <Polarity sentence={this.state.sentence}             polarity={this.state.polarity}/> :   null; 

该代码似乎运行良好。 毕竟这是怎么了? 如果您假设在应用程序尝试发送POST请求的地址处,到目前为止没有任何东西可以接受和处理该请求,那么您将完全正确。 也就是说,要处理到达地址http://localhost:8080/sentiment请求,我们需要运行一个基于Spring的Web应用程序。


我们需要一个可以接受POST请求的Spring应用程序。

▍设置基于Spring的Web应用程序


为了部署Spring应用程序,您将需要JDK8和Maven以及正确配置的环境变量。 安装完所有这些之后,您可以继续进行我们的项目。

the将应用程序打包到jar文件中


使用终端转到sa-webapp文件夹,然后输入以下命令:

 mvn install 

执行此命令后,将在sa-webapp文件夹中创建target目录。 将有一个Java应用程序打包在一个由sentiment-analysis-web-0.0.1-SNAPSHOT.jar表示的jar文件中。

▍启动Java应用程序


转到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}" 

对于我们来说,最重要的是提到不可能确定sa.logic.api.url的含义。 让我们分析发生错误的代码。

application Java应用程式程式码分析


这是发生错误的代码段。

 @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. entimentController有一个saLogicApiUrl字段。 其值由sa.logic.api.url属性设置。
  2. 字符串saLogicApiUrl与值/analyse/sentiment连接在一起。 它们共同构成了访问执行文本分析的微服务的地址。

▍设置属性值


在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 Web应用程序执行文本分析请求所需的位置。

为了不使我们的生活复杂化,我们决定将Python应用程序在localhost:5000上可用,并尽量不要忘记它。 结果,启动Spring应用程序的命令将如下所示:

 java -jar sentiment-analysis-web-0.0.1-SNAPSHOT.jar --sa.logic.api.url=http://localhost:5000 


我们的系统缺少Python应用程序

现在我们只需要启动Python应用程序,系统就会按预期运行。

▍配置Python应用程序


为了运行Python应用程序,您必须安装Python 3和Pip,并且需要正确设置适当的环境变量。

dependencies安装依赖项


转到项目文件夹sa-logic/sa并运行以下命令:

 python -m pip install -r requirements.txt python -m textblob.download_corpora 

▍开始申请


安装依赖项后,我们准备启动该应用程序:

 python sentiment_analysis.py 

执行此命令后,我们将收到以下通知:

 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) 

这意味着该应用程序正在运行,并且正在localhost:5000/等待请求localhost:5000/

▍代码研究


考虑一下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对象,并获取请求正文中第一个句子的polarity值(在我们的示例中,这是传递给分析的唯一句子)。
  5. 响应的返回,其中包含建议的文本和为此计算的polarity索引。
  6. 启动Flask应用程序,该应用程序的地址为0.0.0.0:5000 (您也可以使用localhost:5000的设计访问它)。

现在组成应用程序的微服务正在运行。 它们被配置为彼此交互。 这是工作阶段的应用程序图。


组成应用程序的所有微服务都处于正常状态。

现在,在继续之前,请在浏览器中打开React应用程序,并尝试使用它来分析一些建议。 如果一切正确,单击“ Send按钮后,您将在文本框下方看到分析结果。

在下一部分中,我们将讨论如何在Docker容器中运行我们的微服务。 为了准备在Kubernetes集群中启动应用程序,这是必需的。

Docker容器


Kubernetes是一个用于自动化容器化应用程序的部署,扩展和管理的系统。 它也被称为“容器协调器”。 如果Kubernetes使用容器,则在使用该系统之前,我们必须首先获取这些容器。 但是首先,让我们谈谈什么是容器。 也许可以在Docker 文档中找到关于它是什么的最佳答案:

容器映像是一个轻量级的,独立的,可执行的程序包,其中包含一个应用程序,其中包括运行该映像所需的一切:应用程序代码,运行时,系统工具和库以及设置。 容器化程序可以在Linux和Windows环境中使用,并且无论基础结构如何,它们都将始终相同。

这意味着容器可以在包括生产服务器在内的任何计算机上运行,​​并且在任何环境中,包含在其中的应用程序将以相同的方式运行。

为了探索容器的功能并将它们与其他启动应用程序的方式进行比较,请考虑使用虚拟机和容器为React应用程序提供服务的示例。

using使用虚拟机服务React应用程序静态文件


尝试通过虚拟机组织对静态文件的维护,我们将遇到以下缺点:

  1. 资源利用率低下,因为每个虚拟机都是成熟的操作系统。
  2. 取决于平台。 在某些本地计算机上可以运行的内容在生产服务器上可能无法运行。
  3. 基于虚拟机的解决方案的缓慢且资源密集的扩展。


在虚拟机上运行的Nginx静态服务器Web服务器

如果使用容器来解决类似的问题,那么与虚拟机相比,可以注意到它们的以下优势:

  1. 高效利用资源:使用Docker处理操作系统。
  2. 平台独立性。 开发人员可以在其计算机上运行的容器可以在任何地方使用。
  3. 通过使用图像层进行轻量级部署。


在容器中运行的Nginx静态服务器Web服务器

我们仅在几个方面对虚拟机和容器进行了比较,但这甚至足以感觉到容器的优势。 在此处了解有关Docker容器的更多信息。

▍组装一个React应用程序的容器镜像


Docker容器的主要构建模块是Dockerfile 。 在该文件的开头,记录容器的基本映像,然后包括一系列指令,这些指令指示将创建满足特定应用程序需求的容器的顺序。

在开始使用Dockerfile ,让我们回顾一下为准备React应用程序文件上载到Nginx服务器而做的事情:

  1. 构建一个React应用程序包( npm run build )。
  2. 启动Nginx服务器。
  3. build目录的内容从sa-frontend项目文件夹复制到nginx/html服务器文件夹。

在下面,您可以看到创建容器与在本地计算机上执行的上述操作之间的相似之处。

▍准备用于SA-Frontend的Dockerfile


SA-Frontend应用程序的Dockerfile中将包含的指令仅包含两个命令。 事实是Nginx开发团队为Nginx准备了一个基本映像 ,我们将使用它来创建映像。 这是我们需要描述的两个步骤:

  1. 制作Nginx图像所需的图像基础。
  2. 必须将sa-frontend/build文件夹的内容复制到nginx/html image文件夹。

如果我们从此描述移至Dockerfile ,它将看起来像这样:

 FROM nginx COPY build /usr/share/nginx/html 

如您所见,这里的所有内容都非常简单,而文件的内容甚至具有很高的可读性和可理解性。 该文件告诉系统将已经拥有的所有内容都获取到nginx图像,并将build目录的内容复制到nginx/html目录。

在这里,您可能会遇到一个问题,即我在哪里知道确切需要从build文件夹复制文件的位置,即/usr/share/nginx/html的路径是哪里。 实际上,并没有什么复杂的。 事实是相关信息可以图像描述中找到。

▍构建映像并将其上传到存储库


在使用完成的图像之前,我们需要将其发送到图像存储库。 为此,我们将使用免费的云平台托管Docker Hub映像。 在工作的这个阶段,您需要执行以下操作:

  1. 安装Docker
  2. 在Docker Hub网站上注册。
  3. 通过在终端中运行以下命令登录帐户:

     docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD" 

现在,您需要使用终端进入sa-frontend目录,并在其中运行以下命令:

 docker build -f Dockerfile -t $DOCKER_USER_ID/sentiment-analysis-frontend . 

此后,在类似命令中,需要在Docker Hub上用您的用户名替换$DOCKER_USER_ID 。 例如,命令的这一部分可能看起来像这样: rinormaloku/sentiment-analysis-frontend

同时,可以通过从其中删除-f Dockerfile来缩短此命令,因为该文件已经存在于执行该命令的文件夹中。

为了将完成的图像发送到存储库,我们需要以下命令:

 docker push $DOCKER_USER_ID/sentiment-analysis-frontend 

执行完毕后,请检查Docker Hub上的存储库列表,以了解映像是否已成功发送到云。

▍启动容器


现在,任何人都可以下载并运行一个名为$DOCKER_USER_ID/sentiment-analysis-frontend的映像。 为此,您需要运行以下命令序列:

 docker pull $DOCKER_USER_ID/sentiment-analysis-frontend docker run -d -p 80:80 $DOCKER_USER_ID/sentiment-analysis-frontend 

现在启动了容器,我们可以继续工作,创建我们需要的其他图像。 但是,在继续之前,让我们80:80构造,该构造在映像启动命令中可以找到,并且似乎难以理解。

  • 第一个数字80是主机端口号(即本地计算机)。
  • 第二个数字80是应将请求重定向到的容器的端口。

请考虑以下插图。


端口转发

系统将请求从<hostPort>端口重定向到<containerPort>端口。 也就是说, 80计算机端口80访问将重定向到容器的端口80

由于端口80在本地计算机上打开的,因此您可以从此计算机在localhost:80访问应用程序。 如果您的系统不支持Docker,则可以在Docker虚拟机上运行该应用程序,其地址将类似于<docker-machine ip>:80 。 为了找出Docker虚拟机的IP地址,可以使用docker-machine ip

在此阶段,成功启动前端应用程序容器后,您应该能够在浏览器中打开其页面。

▍.dockerignore文件


收集SA-Frontend应用程序的映像,我们会注意到此过程非常缓慢。 发生这种情况的原因是必须将映像的构建上下文发送到Docker守护程序。 代表构建上下文的目录由docker build的最后一个参数指定。 在我们的情况下,此命令的末尾是一个句点。 这导致以下结构包含在程序集上下文中:

 sa-frontend: |   .dockerignore |   Dockerfile |   package.json |   README.md +---build +---node_modules +---public \---src 

但是在这里存在的所有文件夹中,我们只需要build文件夹。 下载其他任何东西都是浪费时间。 可以通过告诉Docker忽略哪些目录来加快构建速度。 为了做到这一点,我们需要一个.dockerignore文件。 如果您熟悉.gitignore文件,那么此文件的结构肯定看起来很熟悉。 它列出了图像组合系统可能忽略的目录。 在我们的例子中,该文件的内容如下所示:

 node_modules src public 

.dockerignore文件必须与Dockerfile位于同一文件夹中。 现在,组装图像将需要几秒钟的时间。

现在让我们看一下Java应用程序。

▍为Java应用程序构建容器映像


您知道什么,但是您已经了解了创建容器映像所需的一切。这就是为什么本节很短的原因。

打开Dockerfile项目文件夹中的文件sa-webapp如果您阅读此文件的文本,则在其中仅会遇到两个以关键字ENV开头的新结构EXPOSE

 ENV SA_LOGIC_API_URL http://localhost:5000 … EXPOSE 8080 

ENV Docker. , URL API , .

EXPOSE Docker , . . , Dockerfile SA-Frontend . , , , Dockerfile .

, . — README.md sa-webapp .

▍ Python-


Dockerfile sa-logic , . , , , README.md sa-logic .


- , ? . .

  1. sa-logic 5050 :

     docker run -d -p 5050:5000 $DOCKER_USER_ID/sentiment-analysis-logic 
  2. sa-webapp 8080 . , , Python- Java-, SA_LOGIC_API_URL :

     $ docker run -d -p 8080:8080 -e SA_LOGIC_API_URL='http://<container_ip or docker machine ip>:5000' $DOCKER_USER_ID/sentiment-analysis-web-app 

, IP- Docker — README .

sa-frontend :

 docker run -d -p 80:80 $DOCKER_USER_ID/sentiment-analysis-frontend 

, localhost:80 .

, sa-webapp , Docker, App.js sa-frontend , IP- analyzeSentence() , . .

.




: Kubernetes?


Dockerfile , , Docker. , , .dockerignore . Docker. , Kubernetes. . :
, - . . , sa-webapp sa-logic . , ?

Source: https://habr.com/ru/post/zh-CN438982/


All Articles