作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
Michele Sciabarra的头像

Michele Sciabarra

Michele是一位拥有20多年经验的系统架构师. 他是一个通晓多种语言的开发人员,但他的专长是Scala和DevOps.

Previously At

DigitalOcean
Share

Kubernetes 新来的孩子来了吗, 承诺帮助将应用程序部署到云中并更快地扩展它们. Today, 在为微服务架构开发时, 选择Scala创建API服务器是非常标准的.

微服务正在用多个独立的服务取代传统的单片后端服务器,这些服务之间相互通信,并拥有自己的进程和资源.

If there is a Scala 应用在你的计划中,你想要 scale 它变成了一朵云,那么你就来对地方了. 在本文中,我将逐步展示如何使用一个通用的Scala应用程序并使用Docker实现Kubernetes来启动该应用程序的多个实例. 最终的结果将是作为多个实例部署的单个应用程序, 并由Kubernetes进行负载平衡.

所有这些都将通过简单地导入 Kubernetes源代码工具包 在Scala应用程序中. Please note, 该工具包隐藏了许多与安装和配置相关的复杂细节, 但是,如果您想分析它的作用,它足够小,易于阅读和理解. 为简单起见,我们将在本地机器上部署所有内容. 但是,相同的配置适用于Kubernetes的实际云部署.

用Kubernetes扩展你的Scala应用

聪明一点,睡个好觉,用Kubernetes扩展你的Docker.

Kubernetes是什么?

在进入实现的血腥细节之前, 让我们讨论一下Kubernetes是什么以及它为什么重要.

你可能已经听说过Docker. 从某种意义上说,它是一个轻量级虚拟机.

Docker提供了将每个服务器部署在隔离环境中的优势, 非常类似于独立虚拟机, 无需管理成熟虚拟机的复杂性.

For these reasons, 它已经成为在云中部署应用程序的最广泛使用的工具之一. Docker镜像非常容易、快速地构建和复制, 比VMWare等传统虚拟机简单得多, VirtualBox, or XEN.

Kubernetes是对Docker的补充,为管理dockerized应用程序提供了一个完整的环境. 通过使用Kubernetes, 您可以轻松部署, configure, orchestrate, manage, 并监控数百甚至数千个Docker应用程序.

Kubernetes是一个由Google开发的开源工具,已经被许多其他供应商采用. Kubernetes可以在Google云平台上本地使用, 但其他供应商也在他们的OpenShift云服务中采用了它. 它可以在亚马逊AWS、微软Azure、RedHat OpenShift甚至更多的云技术上找到. 我们可以说,它很有可能成为部署云应用程序的标准.

Prerequisites

现在我们已经介绍了基础知识,让我们检查一下您是否安装了所有必需的软件. 首先,你需要 Docker. 如果你用的是Windows或Mac,你需要 Docker Toolbox. 如果您使用的是Linux, 您需要安装发行版提供的特定包,或者简单地安装 遵循官方指示.

我们将使用Scala编写代码,这是一种JVM语言. 当然,您需要Java Development Kit and the scala SBT tool 已安装并在全局路径中可用. 如果您已经是一名Scala程序员,那么您很可能已经安装了这些工具.

如果你使用的是Windows或Mac, Docker将默认创建一个名为 default 只有1GB内存,这对于运行Kubernetes来说太小了. 根据我的经验,我对默认设置有问题. 我建议你打开VirtualBox GUI,选择你的虚拟机 default,并将内存至少更改为2048MB.

VirtualBox内存设置

集群化的应用程序

本教程中的说明可以应用于任何Scala应用程序或项目. 这篇文章有一些“肉”要做, 我选择了一个经常使用的示例来演示Scala中的简单REST微服务, called Akka HTTP. 我建议您在尝试在您的应用程序中使用源代码工具包之前,尝试将其应用到建议的示例中. 我已经针对演示应用程序测试了该工具包, 但我不能保证它不会与您的代码发生冲突.

首先,我们从克隆演示应用程序开始:

Git克隆http://github.com/theiterators/akka-http-microservice

接下来,测试是否一切正常:

cd akka-http-microservice
sbt run

Then, access to http://localhost:9000/ip/8.8.8.8,你应该会看到如下图所示:

Akka HTTP微服务正在运行

添加源代码工具包

现在,我们可以用一些Git的魔法来添加源代码:

git远程添加ScalaGoodies http://github.com/sciabarra/ScalaGoodies
git fetch --all
合并ScalaGoodies/kubernetes

这样,您就拥有了包含源工具包的演示,并且可以尝试了. 或者您甚至可以从那里复制并粘贴代码到您的应用程序中.

一旦合并或复制了项目中的文件,就可以开始了.

开始Kubernetes

一旦你下载了工具包,我们需要下载必要的 kubectl 二进制,通过运行:

bin/install.sh

这个安装程序足够聪明(希望如此),可以下载正确的 kubectl 用于OSX、Linux或Windows的二进制文件,具体取决于您的系统. 注意,安装程序可以在我自己的系统上运行. 请务必报告任何问题,以便我可以修复工具包.

安装后 kubectl 你可以在本地的Docker中启动整个Kubernetes. Just run:

bin / start-local-kube.sh

第一次运行, 这个命令将下载整个Kubernetes堆栈的映像, 并且需要一个本地注册表来存储图像. 这可能需要一些时间,所以请耐心等待. 另外请注意,它需要直接访问互联网. 如果您在代理之后,这将是一个问题,因为该工具包不支持代理. 要解决这个问题,必须配置Docker、curl等工具来使用代理. 它足够复杂,我建议获得一个临时的不受限制的访问.

假设您能够成功下载所有内容, 检查Kubernetes是否运行正常, 可以输入如下命令:

Bin /kubectl获取节点

预期的答案是:

姓名身份年龄
127.0.0.1   Ready     2m

当然,年龄可能会有所不同. Also, 因为启动Kubernetes需要一些时间, 您可能需要调用该命令几次才能看到答案. 如果这里没有错误, congratulations, 您已经在本地机器上启动并运行了Kubernetes.

Dockerizing你的Scala应用

现在已经启动并运行了Kubernetes,可以在其中部署应用程序了. 在Docker出现之前,您必须部署整个服务器来运行应用程序. 使用Kubernetes,部署应用程序所需要做的就是:

  • 创建Docker镜像.
  • 将它推送到可以启动它的注册表中.
  • 用Kubernetes启动实例,它将从注册表中获取映像.

Luckily, 它远没有看起来那么复杂, 特别是如果您像许多人一样使用SBT构建工具.

In the kit, 我包含了两个文件,其中包含创建能够运行Scala应用程序的映像所需的所有定义, 或者至少是运行Akka HTTP演示所需的内容. 我不能保证它能与任何其他Scala应用程序一起工作, 但这是一个很好的起点, 并且应该适用于许多不同的配置. 要查找构建Docker镜像的文件有:

docker.sbt
project/docker.sbt

让我们看看里面都有什么. The file project/docker.sbt 包含导入的命令 sbt-docker plugin:

addSbtPlugin("se.Marcuslonnberg“%”sbt-docker“%”1.4.0")

这个插件用SBT为你管理Docker镜像的构建. Docker的定义在 docker.sbt 文件,看起来像这样:

ImageName in docker:= Seq(ImageName("localhost:5000/akkahttp:latest"))

docker中的Dockerfile:= {
  val jarFile: File = sbt.Keys.`package`.(编译、packageBin).value
  val classpath =(编译中的managedClasspath).value
  val mainclass = mainclass.(编译、packageBin).value.getOrElse(sys.错误("期望只有一个主类"))
  var jarTarget = s"/app/${jarFile.getName}"
  val classpathString = classpath.files.map("/app/" + _.getName)
    .mkString(":") + ":" + jarTarget
  new Dockerfile {
    从(anapsix / alpine-java: 8)
    add(classpath.files, "/app/")
    add(使用jarFile jarTarget)
    entryPoint("java", "-cp", classpathString, mainclass)
  }
}

要完全理解这个文件的含义, 你需要对Docker有足够的了解才能理解这个定义文件. However, 我们不讨论Docker定义文件的细节, 因为你不需要完全理解它来构建图像.

使用SBT构建Docker映像的美妙之处在于
SBT会为你收集所有的文件.

注意,类路径是由以下命令自动生成的:

val classpath =(编译中的managedClasspath).value

通常,收集运行应用程序所需的所有JAR文件是相当复杂的. 使用SBT, Docker文件将生成 add(classpath.files, "/app/"). 通过这种方式,SBT为您收集所有JAR文件,并构造一个Dockerfile来运行您的应用程序.

其他命令收集缺失的部分以创建Docker映像. 该映像将使用现有映像APT来构建,以运行Java程序(anapsix / alpine-java: 8,可在Docker Hub的互联网上获得)。. 其他说明是添加运行应用程序的其他文件. 最后,通过指定入口点,我们可以运行它. 还要注意,名称以 localhost:5000 故意的,因为 localhost:5000 我在哪里安装了注册表 start-kube-local.sh script.

使用SBT构建Docker镜像

要构建Docker镜像,你可以忽略Dockerfile的所有细节. 你只需要输入:

sbt dockerBuildAndPush

The sbt-docker 然后插件会为你构建一个Docker镜像, 从互联网上下载所有必要的部分, 然后它会推送到之前启动的Docker注册表, 中的Kubernetes应用程序 localhost. 所以,你所需要做的就是再等一会儿,让你的图像做好准备.

Note, 如果遇到问题, 最好的方法是通过运行以下命令将所有内容重置为已知状态:

bin / stop-kube-local.sh
bin / start-kube-local.sh

这些命令应该停止所有容器并正确地重新启动它们,以使注册表准备好接收构建和推送的映像 sbt.

在Kubernetes中启动服务

既然应用程序已经打包到容器中并推送到注册表中,我们就可以使用它了. Kubernetes使用命令行和配置文件来管理集群. 因为命令行可能变得很长, 还可以复制这些步骤, 我在这里使用配置文件. 源工具包中的所有样本都在文件夹中 kube.

下一步是启动映像的单个实例. 在Kubernetes语言中,一个正在运行的映像被称为A pod. 因此,让我们通过调用以下命令来创建一个pod:

Bin /kubectl create -f kube/akkahttp-pod.yml

现在你可以用命令检查情况:

Bin /kubectl获取pod

You should see:

Name ready status重启年龄
akkahttp 1/1运行0 33秒
k8s-etcd-127.0.0.1 1/1运行0 7d
k8s-master-127.0.0.1 4/4运行0 7d
k8s-proxy-127.0.0.1 1/1运行0 7d

地位实际上可以是不同的, for example, “ContainerCreating”, 它可能需要几秒钟才能变成“正在运行”。. 此外,如果您之前忘记创建图像,您还可以获得另一种状态,例如“错误”.

你也可以用下面的命令检查你的pod是否正在运行:

Bin /kubectl记录akkahttp

你应该看到这样的输出:

[调试][05/30/2016 12:19:53.133] [default-akka.actor.[akka://default/system/IO-TCP/selectors/$a/0]成功绑定到/0:0:0:0:0:0:0:0:9000

现在您已经在容器中启动并运行了服务. 但是,还不能访问该服务. 这种行为是Kubernetes设计的一部分. 你的pod正在运行,但你必须明确地暴露它. 否则,服务将是内部的.

Creating a Service

创建服务并检查结果是执行的问题:

Bin /kubectl create -f kube/akkahttp-service.yaml
Bin /kubectl获取SVC

你应该看到这样的内容:

名称cluster-ip external-ip port (s) age
akkahttp-service 10.0.0.54 9000/TCP 44
kubernetes 10.0.0.1             443/TCP    3m

注意,端口可以是不同的. Kubernetes为该服务分配了一个端口并启动了它. 如果您使用的是Linux,您可以直接打开浏览器并键入 http://10.0.0.54:9000/ip/8.8.8.8 to see the result. 如果您正在使用Windows或Mac与Docker工具箱, IP地址在运行Docker的虚拟机的本地, 不幸的是,现在仍然无法联系到.

我想在这里强调,这不是Kubernetes的问题, 相反,它是Docker工具箱的限制, 这反过来又取决于像VirtualBox这样的虚拟机所施加的限制, 它们的行为就像一台电脑中的另一台电脑. 为了克服这个限制,我们需要创建一个隧道. 为了让事情更简单, 我包含了另一个脚本,它在任意端口上打开一个隧道,以访问我们部署的任何服务. 可以输入如下命令:

bin / forward-kube-local.Sh akkahttp-service 9000

注意,隧道不会在后台运行, 你必须保持终端窗口打开只要你需要它,关闭当你不再需要隧道. 当隧道运行时,您可以打开: http://localhost:9000/ip/8.8.8.8 最后看看应用程序在Kubernetes上的运行情况.

Final Touch: Scale

到目前为止,我们“简单”地将应用程序放到了Kubernetes中. 虽然这是一个令人兴奋的成就,但它并没有为我们的部署增加太多的价值. 我们不需要在服务器上上传和安装,也不需要为它配置代理服务器.

Kubernetes的亮点在于可扩展性. You can deploy two, ten, 或者通过仅更改配置文件中的副本数量来创建应用程序的100个实例. So let’s do it.

我们将停止单个pod并启动一个部署. 那么让我们执行以下命令:

Bin /kubectl delete -f kube/akkahttp-pod.yml
Bin /kubectl create -f kube/akkahttp-deploy.yaml

接下来,检查状态. 同样,您可以尝试几次,因为部署可能需要一些时间来执行:

Name ready status重启年龄
akkahttp-deploy -4229989632-mjp6u 1/1运行0 16秒
akkahttp-deploy -4229989632-s822x 1/1运行0 16秒
k8s-etcd-127.0.0.1 1/1运行0 6d
k8s-master-127.0.0.1 4/4运行0 6d
k8s-proxy-127.0.0.1 1/1运行0 6d

现在我们有两个舱,而不是一个. 这是因为在我提供的配置文件中有这个值 replica: 2,由系统生成两个不同的名称. 我不打算详细介绍配置文件, 因为本文的范围只是为Scala程序员介绍如何快速入门Kubernetes.

不管怎样,现在有两个舱是活动的. 有趣的是,服务和以前一样. 我们将服务配置为在所有标记的pod之间进行负载平衡 akkahttp. 这意味着我们不必重新部署服务, 但是我们可以用一个复制的实例替换单个实例.

我们可以通过再次启动代理来验证这一点(如果你在Windows上并且你已经关闭了它):

bin / forward-kube-local.Sh akkahttp-service 9000

然后,我们可以尝试打开两个终端窗口,查看每个pod的日志. 例如,在第一种类型中:

Bin /kubectl logs -f akkahttp-deployment-4229989632-mjp6u

在第二种类型中:

Bin /kubectl logs -f akkahttp-deploy -4229989632-s822x

当然,请使用系统中的值相应地编辑命令行.

现在,尝试使用两个不同的浏览器访问该服务. 您应该期望看到请求在多个可用服务器之间被分割, 如下图所示:

Kubernets的作用

Conclusion

今天我们只触及了表面. Kubernetes提供了更多的可能性, 包括自动缩放和重新启动, 增量部署, and volumes. Furthermore, 我们用作示例的应用程序非常简单, 无状态,不同的实例不需要相互了解. 在现实世界中,分布式应用程序 do 需要彼此了解, 并且需要根据其他服务器的可用性更改配置. 实际上,Kubernetes提供了一个分布式密钥库(etcd),允许不同的应用程序在部署新实例时相互通信. However, 这个例子特意设计得足够小,并且简化了以帮助您开始, 关注核心功能. 如果您遵循本教程,您应该能够为您的 Scala 应用程序在您的机器上,而不会被大量的细节和迷失在复杂性.

就这一主题咨询作者或专家.
Schedule a call
Michele Sciabarra的头像
Michele Sciabarra

Located in 圣贝内代托德尔特伦托,阿斯科利皮切诺省,意大利

Member since January 8, 2016

About the author

Michele是一位拥有20多年经验的系统架构师. 他是一个通晓多种语言的开发人员,但他的专长是Scala和DevOps.

Toptal作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

Previously At

DigitalOcean

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

Toptal Developers

Join the Toptal® community.