我们看了看用 创建容器引擎集群。在本篇博文里,我们看看使用容器引擎和 部署容器到集群里。
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语言中文网