我们看了看用 创建容器引擎集群。在本篇博文里,我们看看使用容器引擎和 部署容器到集群里。

Kubernetes

首先,什么是 ? 是一个开源的、管理容器的框架。与平台无关,就是说着你可以在你本机上,在 AWS 或者 Google Cloud,任何其他的平台运行它。(Kubernetes)能让你通过使用声明的配置内容,控制一组容器,和容器的网络规则。

你只需要写个 yaml/json 文件,描述下需要在哪运行哪个容器。定义你的网络规则,比如端口转发。它就会帮你管理服务发现。

Kubernetes 是云场景的重要补充,而且现在正迅速成为云容器管理实际选择。因此了解下是比较好的。

那么我们开始吧!

首先,确保你已经在本地安装了 kubectl cli:

现在确保你连接到集群,并且认证正确。第一步,我们登录进去,确保已被认证。第二步我们设置下项目配置,确保我们使用正确的项目 ID 和可访问区域。

在上面的命令中,你可以将 compute/zone 替换成你选的任何区域,你的项目 id 和集群名称也可以和我的不一样。

下面是个概括描述...

点这你可以看到项目 ID...

现在找下我们的项目 ID...

集群区域 region/zone 和集群名称可以点菜单左上角的 'ComputeEngine',然后选 'VM Instances' 就找到了。 你能看到你的 Kubernetes VM,点进去看更多细节,这能看见和你集群相关的每个内容。

如果你运行下...

No resources found.

然后我需要部署服务了,vessel 服务,user 服务,consignment 服务和 email 服务。好了,很简单!

从 Mongodb 实例开始吧。因为它不属于一个单独的服务,而且这是的平台整体的一部分,我们把这些部署放在 shippy-infrastructure 仓库下。这个仓库我提交到了 Github ,因为包含了很多敏感数据,但是我可以给你们所有的部署文件。

首先,我们需要一个配置创建一个 ssd,用于长期存储。这样当我们重启容器的时候就不会丢失数据。

然后是我们的部署文件(我们通过本文来深入更多细节)...

然后是 service 文件...

还有很多,现在对你来说可能没什么意义。那么我们试试理清一些 Kubernetes 的关键概念。

Nodes

Nodes 是你的物理机或者 VM,你的容器通过 node 做集群,服务通过运行在不同 node/pod 上的一组组容器互相访问。

Pods

Pod 是一组相关的容器。比如,一个 pod 可以包含你的认证服务容器,用户数据库容器,登陆注册用户接口等等。这些容器都是明显有相关性的。Pod 允许你将他们组合在一起,这样他们能互相访问,并且运行在相同的即时网络环境下,你可以把他们当做一个整体。这很酷啊!Pod 是 Kubernetes 里非常不容易理解的特性。

Deployment

Deployment 是用来控制状态的,一个 deployment 就是最终要输出和要保持的状态的描述文件。一个 deployment 是 Kubernetes 的介绍,比如说,我想要三个容器,运行在三个端口,用某些环境变量。Kubernetes 会确保维持这个状态。如果一个容器崩溃了,剩下两个容器,它会再启动一个满足三个容器的需求。

StatefulSet

stateful set 和 deployment 有相似的地方,除了它会用一些存储方式,保持容器相关的状态。比如分布存储的概念。

实际情况里,Mongodb 将数据写入二进制数据存储格式,很多数据库都是这样做的。创建一个可回收的数据库实例,比如 docker 容器。如果容器重启数据会丢失。一般来说你需要在容器启动的时候使用分卷装载数据/文件。

你可以在 Kubernetes 上做这些部署。但是 StatefulSets,在相关的集群点有一些额外的自动化操作。因此这个对 mongodb 容器天然的合适。

Service

服务是一组网络相关的规则,比如端口转发和 DNS 规则,在网络层面上连接你的 pod,控制谁和谁可以通信,谁可以被外部访问。

有两种服务你可能会遇到,一是 load balancer,一是 node port。

load balancer,是一个轮询的负载均衡器,可以给你选的 node 节点创建一个 IP 地址给代理。通过代理把服务暴露给外部。

node port 将 pod 暴露给上层的网络环境,这样他们可以被其他服务, 内部的pod/实例访问。这样对暴露 node 给其他的 pod 来说是有用的。这就是你能用来允许服务和其他服务通信的方式。这就是服务发现的本质。至少是一部分。

现在我们刚看了一点点 Kubernetes 的内容,我们来再多谈些,再挖掘挖掘。值得注意的是,如果你是个在本机上使用 docker ,比如如果你用的是 mac/windows 上的 docker 的 edge 版本,你可以把 Kubernetes 集群钉在本机上。测试时候很有用。

那么我们已经创建了三个文件,一个用于存储,一个用于 stateful set,一个用于我们的服务。最后结果是有 mongodb 容器的副本,stateful 存储和通过 pod 保留给数据存储的服务。我们继续看看,创建,按正确的顺序,因为有些操作是需要依赖前面创建的内容。

等几分钟,你可以查下 mongodb 容器的状态,运行:

$ kubectl describe node

那么我们给集群打开自动扩容,默认是一个池。为了达到目的,需要到 Google Cloud Console,选择 Kubernetes 引擎,编辑你的实例,打开自动扩容,设置最小值和最大值为 2,然后点保存。

$ kubectl get pods

现在我们有了数据库集群,一个自动扩容的 Kubernetes 引擎,我们来部署一些服务吧!

Vessel 服务

vessel 服务很轻量级,没做太多事情,也没有依赖,因此适合上手。

首先,我们稍微改动 vessel 服务上的一些代码片段。

k8s.NewServicemicro.NewService()

Kubernetes 中的微服务

我喜欢 micro 中的一点,因为它对 cloud 有很深理解而构建,能一直适应新技术。Micro 很重视 Kubernetes,因此创建了一个 micro 的 。

实际情况是,所有的库实际上都是 micro,配置了 Kuberntes 的一些合理的默认值,和一个直接集成在 Kubernetes 服务之上的 service selector。也就是说它把服务发现交给了 Kubernetes。默认用 gRPC 作为默认 transport 。 当然你也可以使用环境变量和 plugin 来覆盖这些状态。

在 Micro 的世界里还有很多让人着迷的功能,这也是让我很兴奋的地方。一定要加入 。

现在我们在服务上创建一个部署服务,在这我们要稍微了解下关于每个部分作用的细节。

kind:Deploymentthings

下一步你需要一个标准分区,启动时带着 deployment 的 metadata,名称,多少个这种 pod (副本),需要保持(如果其中一个死掉了,假设我们用的比一个多,控制元的工作就是检查有运行的 pod 数量是我们希望的,如果不在期待状态就再启动一个)。Selector 和 template 暴露了 pod 的某些 metadata,可以允许其他服务发现和连接 pod。

然后你需要另一个标准分区(有点困惑,不过继续往下看呀!)。这次是给我们自己的容器,或者分卷,共享 meta 数据等等。在这个服务里,我们需要启动一个独立容器。容器区域是一个数组,因为我们要启动几个容器作为 pod 的一部分。是为了组合相关容器。

容器的 metadata 一目了然,我们从镜像启动一个 docker 容器,设置一些环境变量,在运行时传入一些命令,暴露一个端口(用于服务查找)。

--selector=static

你可以提交这个选项,继续像之前一样使用微服务。但是我们也可以用到 Kubernetes 的好处。

你也注意到了,我们从一个私有仓库拉取镜像。当使用 Google 的容器工具时,你可以获取一个容器注册,用来创建你的容器镜像,推送下,像下面这样...

现在看我们的服务...

kindtargetPort

现在我们部署下集群里的修改吧。

等几分钟,然后运行...

你应该能看到你的新 pod,新服务了。确保他们的运行状态符合期待效果。

$kubectl proxyhttp://localhost:8001/ui

在这有一点值得提一下,deployment 是原子操作并且是不可更改的,意思是他们必须通过某种方式更新才能被修改。他们有一个唯一的哈希值,如果哈希值没有变化,deployment 是不会更新的。

$ kubectl replace -f ./deployments/deployment.yml
latestvessel-service:
deployments/deployment.tmplUPDATED_AT{{ UPDATED_AT }}

好了,我们成功了,部署了一个服务,运行的和我们想的一样。

我现在给其他服务也做同样的操作。我在仓库里给每个服务做了简短的更新,如下...

给我们的用户服务部署 Postgres ...

Postgres 服务...

Postgres 存储...

部署 micro

现在是服务...

LoadBalancer$ kubectl get servicespending

一旦部署完毕了,让服务调用 micro:

created: true

部署 UI

服务部署的不错,我们来部署下用户接口

现在是服务...

注意到服务是 80 端口上的负载均衡,因为这是一个公共的用户接口,这就是用户如何与我们服务交互的。一看就明白!

最后总结

看我们成功了,用 docker 容器和 Kubernetes 管理我们的容器,成功的将整个工程部署到云端。希望你能从这篇文章发现一些有用的内容,没有觉得太不好消化。

本系列的下一部分,我们将看看把所有这些内容和 CI 进程联系起来,来管理我们的 deployment。

如果你觉得这个系列文章有用,如果你用了广告拦截(没怪你)。请考虑给我的辛苦劳动打个赏吧。共勉! https://monzo.me/ewanvalentine

或者,在 上赞助我下吧。


本文由 原创编译, 荣誉推出

更多GO语言资讯,欢迎关注微信公众号:Go语言中文网