欢迎光临
我们一直在努力

网络研讨会系列:在Kubernetes中部署和扩展微服务

本文补充了关于在云中部署和管理容器化工作负载网络研讨会系列 该系列涵盖容器的基本要素,包括管理容器生命周期,部署多容器应用程序,扩展工作负载以及使用Kubernetes。 它还突出显示了运行有状态应用程序的最佳实践。

本教程包括本系列第五部分中的概念和命令,即在Kubernetes中部署和缩放微服务。

介绍

Kubernetes是一款用于管理容器化应用程序的开源容器编排工具。 在本系列的前一篇教程中,您深入了解Kubernetes ,了解了Kubernetes的构建模块。

在本教程中,您将应用前面教程中的概念来构建,部署和管理Kubernetes中的端到端微服务应用程序。 您将在本教程中使用的示例Web应用程序是一个使用MongoDB作为数据库的Node.js中编写的“待办事项列表”应用程序。 这是我们在教程Building Containerized Applications中使用的同一个应用程序

您将从Dockerfile为此应用程序构建一个容器映像,将映像推送到Docker Hub,然后将其部署到群集中。 然后,您将扩展应用程序以满足更高的需求。

先决条件

要完成本教程,您需要:

第1步 – 使用Dockerfile构建映像

我们将通过将Web应用程序打包到Docker镜像中进行容器化。

首先转到您的主目录,然后使用Git从GitHub上的官方存储库克隆本教程的示例Web应用程序。

cd ~git clone https://github.com/janakiramm/todo-app.git

从Dockerfile构建容器镜像。 使用-t开关为注册表用户名,图像名称和可选标记标记图像。

docker build -t sammy/todo .

输出确认图像已成功构建并进行了适当标记。

Sending build context to Docker daemon  8.238MBStep 1/7 : FROM node:slim ---> 286b1e0e7d3fStep 2/7 : LABEL maintainer = "[email protected]" ---> Using cache ---> ab0e049cf6f8Step 3/7 : RUN mkdir -p /usr/src/app ---> Using cache ---> 897176832f4dStep 4/7 : WORKDIR /usr/src/app ---> Using cache ---> 3670f0147bedStep 5/7 : COPY ./app/ ./ ---> Using cache ---> e28c7c1be1a0Step 6/7 : RUN npm install ---> Using cache ---> 7ce5b1d0aa65Step 7/7 : CMD node app.js ---> Using cache ---> 2cef2238de24Successfully built 2cef2238de24Successfully tagged sammy/todo-app:latest

通过运行docker images命令验证映像是否已创建。

docker images

您可以看到图像的大小以及自创建以来的时间。

REPOSITORY                                       TAG                 IMAGE ID            CREATED             SIZEsammy/todo-app                                   latest              81f5f605d1ca        9 minutes ago       236MB

接下来,将您的映像推送到Docker Hub上的公共注册表中。 为此,请登录您的Docker Hub帐户:

docker login

一旦您提供了您的凭证,请使用Docker Hub用户名标记您的图像:

docker tag your_docker_hub_username/todo-app

然后将您的图片推送到Docker Hub:

docker push

您可以通过在Web浏览器中搜索Docker Hub来验证新图像是否可用。

将Docker映像推送到注册表中,让我们为Kubernetes打包应用程序。

第2步 – 在Kubernetes中部署MongoDB Pod

应用程序使用MongoDB来存储通过Web应用程序创建的待办事项列表。 要在Kubernetes中运行MongoDB,我们需要将它打包为Pod。 当我们启动这个Pod时,它会运行一个MongoDB实例。

创建一个名为db-pod.yaml的新YAML文件:

nano db-pod.yaml

添加下面的代码,它定义了一个基于MongoDB的容器。 我们公开端口27017 ,这是MongoDB使用的标准端口。 请注意,该定义包含标签nameapp 我们将使用这些标签来识别和配置特定的Pod。

DB-pod.yaml
apiVersion: v1kind: Podmetadata:  name: db  labels:    name: mongo    app: todoappspec:      containers:      - image: mongo        name: mongo        ports:        - name: mongo          containerPort: 27017        volumeMounts:          - name: mongo-storage            mountPath: /data/db      volumes:          - name: mongo-storage            hostPath:              path: /data/db

数据存储在名为mongo-storage的卷中,映射到该节点的/data/db位置。 有关卷的更多信息,请参阅官方Kubernetes卷文档

运行以下命令来创建Pod。

kubectl create -f db-pod.yml

你会看到这个输出:

pod "db" created

现在验证Pod的创建。

kubectl get pods

输出显示Pod并指示它正在运行:

NAME      READY     STATUS    RESTARTS   AGEdb   1/1       Running   0          2m

让我们使该Pod可供群集的内部消费者访问。

创建一个名为db-service.yaml的新文件,其中包含定义了MongoDB Service的代码:

DB-service.yaml
apiVersion: v1kind: Servicemetadata:  name: db  labels:    name: mongo    app: todoappspec:  selector:    name: mongo  type: ClusterIP  ports:    - name: db      port: 27017      targetPort: 27017

该服务发现与name: db的标签相同的命名空间中的所有豆荚。 YAML文件的selector部分明确定义了这种关联。

我们通过声明type: ClusterIP指定服务在集群内可见type: ClusterIP

保存文件并退出编辑器。 然后使用kubectl将其提交给群集。

kubectl create -f db-service.yml

你会看到这个输出表明服务已成功创建:

service "db" created

让我们来获取Pod可用的端口。

kubectl get services

你会看到这个输出:

NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)     AGEdb           ClusterIP   10.109.114.243   <none>        27017/TCP   14skubernetes   ClusterIP   10.96.0.1        <none>        443/TCP     47m

从这个输出中,您可以看到服务在端口27017上可用。 该Web应用程序可以通过此服务访问MongoDB。 当它使用主机名db ,Kubernetes内运行的DNS服务会将地址解析到与该服务关联的ClusterIP。 这种机制允许Pod发现并相互通信。

使用数据库Pod和Service,我们为Web应用程序创建一个Pod。

第3步 – 将Node.JS Web App部署为Pod

让我们将您在本教程的第一步中创建的Docker镜像打包为Pod并将其部署到群集。 这将作为最终用户可访问的前端Web应用程序层。

创建一个名为web-pod.yaml的新YAML文件:

nano web-pod.yaml

添加下面的代码,该代码基于sammy/todo-app Docker镜像定义了一个容器。 它通过TCP协议暴露在端口3000上。

网络pod.yaml
apiVersion: v1kind: Podmetadata:  name: web  labels:    name: web    app: todoappspec:  containers:    - image: sammy/todo-app      name: myweb      ports:        - containerPort: 3000

请注意,该定义包含标签nameapp 服务将使用这些标签将入站流量路由到适当的端口。

运行以下命令来创建Pod:

kubectl create -f web-pod.yaml
pod "web" created

我们来验证Pod的创建:

kubectl get pods
NAME      READY     STATUS    RESTARTS   AGEdb        1/1       Running   0          8mweb       1/1       Running   0          9s

请注意,我们将MongoDB数据库和Web应用程序都作为Pods运行。

现在我们将使web Pod可供公共互联网访问。

服务在内部或外部公开一组Pod。 让我们定义一个使web Pod公开可用的服务。 我们将通过一个NodePort来公开它,它是一个通过在集群的每个节点上打开的任意端口访问Pod的方案。

创建一个名为web-service.yaml的新文件,其中包含为应用程序定义Service的代码:

apiVersion: v1kind: Servicemetadata:  name: web  labels:    name: web    app: todoappspec:  selector:    name: web  type: NodePort  ports:   - name: http     port: 3000     targetPort: 3000     protocol: TCP

该服务发现相同名称空间中与名称web匹配的标签的所有窗格。 YAML文件的选择器部分明确定义了这种关联。

我们通过type: NodePort声明来指定服务的类型为NodePort

使用kubectl将其提交给群集。

kubectl create -f web-service.yml

你会看到这个输出表明服务已成功创建:

service "web" created

让我们来获取Pod可用的端口。

kubectl get services
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGEdb           ClusterIP   10.109.114.243   <none>        27017/TCP        12mkubernetes   ClusterIP   10.96.0.1        <none>        443/TCP          59mweb          NodePort    10.107.206.92    <none>        3000:30770/TCP   12s

从这个输出中,我们看到该服务在端口3077030770 我们尝试连接到其中一个工作节点。

通过使用DigitalOcean控制台获取与您的Kubernetes集群关联的其中一个工作节点的公共IP地址。

DigitalOcean控制台显示工作节点

获取IP地址后,使用curl命令向端口30770上的其中一个节点发出HTTP请求:

curl http://your_worker_ip_address:30770

你会看到类似这样的输出:

<!DOCTYPE html><html>  <head>    <title>Containers Todo Example</title>    <link rel='stylesheet' href='/stylesheets/screen.css' />    <!--[if lt IE 9]>    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>    <![endif]-->  </head>  <body>    <div id="layout"><h1 id="page-title">Containers Todo Example</h1><div id="list">  <form action="/create" method="post" accept-charset="utf-8">    <div class="item-new">      <input class="input" type="text" name="content" />    </div>  </form></div>      <div id="layout-footer"></div>    </div>    <script src="/javascripts/ga.js"></script>  </body></html>

您已经定义了Web Pod和一项服务。 现在让我们看看如何使用副本集对其进行缩放。

第5步 – 扩展Web应用程序

副本集确保始终在群集中运行最小数量的Pod。 当Pod被打包为副本集时,Kubernetes将始终运行规范中定义的最小Pod数。

让我们删除当前的Pod并通过副本集重新创建两个Pod。 如果我们让Pod运行,它不会成为Replica Set的一部分。 因此,即使计数只有一个,通过副本集启动Pod也是一个好主意。

首先,删除现有的Pod。

kubectl delete pod web
pod "web" deleted

现在创建一个新的副本集声明。 副本集的定义与Pod相同。 关键区别在于它包含定义需要运行的Pod数量的replica元素。 与Pod一样,它还包含标签作为帮助进行服务发现的元数据。

创建文件web-rs.yaml并将此代码添加到文件中:

apiVersion: extensions/v1beta1kind: ReplicaSetmetadata:  name: web  labels:    name: web    app: todoappspec:  replicas: 2  template:    metadata:      labels:        name: web    spec:      containers:      - name: web        image: sammy/todo-app        ports:        - containerPort: 3000

保存并关闭文件。

现在创建副本集:

kubectl create -f web-rs.yaml
replicaset "web" created

然后检查豆荚的数量:

kubectl get pods
NAME        READY     STATUS    RESTARTS   AGEdb          1/1       Running   0          18mweb-n5l5h   1/1       Running   0          25sweb-wh6nf   1/1       Running   0          25s

当我们通过NodePort访问服务时,请求将被发送到由副本集管理的一个Pod中。

让我们通过删除其中一个Pod来测试副本集的功能,并查看会发生什么情况:

kubectl delete pod web-wh6nf
pod "web-wh6nf" deleted

再看看豆荚:

kubectl get pods
NAME        READY     STATUS              RESTARTS   AGEdb          1/1       Running             0          19mweb-n5l5h   1/1       Running             0          1mweb-wh6nf   1/1       Terminating         0          1mweb-ws59m   0/1       ContainerCreating   0          2s

一旦Pod被删除,Kubernetes创建了另一个来确保所需计数得以维持。

我们可以扩展副本集以运行其他Web Pod。

运行以下命令将Web应用程序缩放到10个Pod。

kubectl scale rs/web --replicas=10
replicaset "web" scaled

检查Pod计数:

kubectl get pods

你会看到这个输出:

NAME        READY     STATUS              RESTARTS   AGEdb          1/1       Running             0          22mweb-4nh4g   1/1       Running             0          21sweb-7vbb5   1/1       Running             0          21sweb-8zd55   1/1       Running             0          21sweb-f8hvq   0/1       ContainerCreating   0          21sweb-ffrt6   1/1       Running             0          21sweb-k6zv7   0/1       ContainerCreating   0          21sweb-n5l5h   1/1       Running             0          3mweb-qmdxn   1/1       Running             0          21sweb-vc45m   1/1       Running             0          21sweb-ws59m   1/1       Running             0          2m

Kubernetes已经启动了web Pod的扩展过程。 当请求通过NodePort进入服务时,它将被路由到副本集中的其中一个Pod。

当流量和负载平息时,我们可以恢复到两个Pod的原始配置。

kubectl scale rs/web --replicas=2
replicaset "web" scaled

该命令终止除两个之外的所有Pod。

kubectl get pods
NAME        READY     STATUS        RESTARTS   AGEdb          1/1       Running       0          24mweb-4nh4g   1/1       Terminating   0          2mweb-7vbb5   1/1       Terminating   0          2mweb-8zd55   1/1       Terminating   0          2mweb-f8hvq   1/1       Terminating   0          2mweb-ffrt6   1/1       Terminating   0          2mweb-k6zv7   1/1       Terminating   0          2mweb-n5l5h   1/1       Running       0          5mweb-qmdxn   1/1       Terminating   0          2mweb-vc45m   1/1       Terminating   0          2mweb-ws59m   1/1       Running       0          4m

要验证副本集的可用性,请尝试删除其中一个副本并检查计数。

kubectl delete pod web-ws59m
pod "web-ws59m" deleted
kubectl get pods
NAME        READY     STATUS              RESTARTS   AGEdb          1/1       Running             0          25mweb-n5l5h   1/1       Running             0          7mweb-ws59m   1/1       Terminating         0          5mweb-z6r2g   0/1       ContainerCreating   0          5s

一旦Pod计数发生变化,Kubernetes就会调整它以匹配YAML文件中定义的计数。 当删除副本集中的某个网络Pod时,会立即创建另一个Pod来维护所需的计数。 通过确保最小数量的Pod一直在运行,从而确保应用程序的高可用性。

您可以使用以下命令删除在本教程中创建的所有对象:

kubectl delete -f db-pod.yaml -f db-service.yaml -f web-rs.yaml -f web-service.yaml
pod "db" deletedservice "db" deletedreplicaset "web" deletedservice "web" deleted

结论

在本教程中,您应用了本系列中涵盖的所有概念来打包,部署和扩展微服务应用程序。

在本系列的下一部分中,您将了解如何通过将它作为StatefulSet运行来使MongoDB高度可用。

赞(0) 打赏
未经允许不得转载:老赵部落 » 网络研讨会系列:在Kubernetes中部署和扩展微服务

评论 抢沙发