《精通Docker第三版》完整目录:
第一章 Docker概览
第二章 创建容器镜像
第三章 存储和发布镜像
第四章 管理容器
第五章 Docker Compose
第六章 Windows容器
第七章 Docker Machine
第八章 Docker Swarm
第九章 Docker和Kubernetes
第十章 在公有云上运行Docker
第十一章 Portainer – 一个Docker的GUI
第十二章 Docker安全
第十三章 Docker工作流
第十四章 Docker进阶
到目前为止,我们使用了Digital Ocean来在云端基础设施上启动容器。本章中,我们会来学习使用Docker提供的这些工具来在Amazon Web Services以及Microsoft Azure上启动Docker Swarm集群。然后我们会学习Amazon Web Services, Microsoft Azure和Google Cloud提供的容器解决方案。
本章将涵盖如下内容:
- Docker Cloud
- 亚马逊ECS和AWS Fargate
- 微软Azure应用服务
- 微软Azure, 谷歌云和Amazon Web Services上Kubernetes
技术准备
本章中,我们将使用各类云提供商,所以要一起操作的话会需要有每个平台的活跃账号。同样,本章中的截图来自我个人偏好的操作系统macOS。还有我们所要运行的命令可以在所有讨论过的三种操作系统上使用,除非有明确的说明。
我们会来看一些云提供商所提供的用于帮助管理它们的服务的命令行工具,但本章不是对这些工具如何使用的明细文档,扩展阅读部分会提供一些文档链接来获取更详细的使用指南。
观看如下视频来查看代码的实时操作效果:
Docker Cloud
在我们了解其它服务之前,我觉得最好是先快速的讨论下Docker Cloud ,因为仍会有大量的提及Docker曾提供的这个云管理服务。
Docker Cloud由好几种Docker服务组成。包括用于构建和托管镜像的Docker服务,是另一个提供应用、节点和Docker Swarm管理的服务。2018年5月1日,所有管理远程节点的服务都关闭了。
Docker建议那傅这一服务管理节点的Docker Cloud用户将他们的Docker社区版(CE)或企业版(EE)迁移到自己的硬件云上。Docker还推荐了Azure容器服务和谷歌Kubernetes引擎。
因此,出于这一原因,我们不再像 精通Docker 前两版那样讨论Docker的托管服务了。
但考虑到我们所讨论过的内容,下一部分可能会带来困惑。虽然Docker停止了所有托管的云管理服务,它仍然提供协助你在主流公有云提供商上管理Docker Swarm集群的工具。
云端Docker
这一部分,我们会来了解Docker的两个模板云服务。它们都启动和目标平台深度集成的Docker Swarm集群,构建时也遵循了Docker的最佳实践。我们先来学习Amazon Web Services(AWS)模板。
AWS上的Docker社区版
AWS的Docker社区版(现在称为Docker for AWS)是由Docker创建的一个亚马逊CloudFormation模板,它设计用于在AWS上以Docker最佳实践和推荐来轻松启动Docker Swarm模式集群。
ℹ️CloudFormation是一个由Amazon提供的服务,允许你在模板文件中定义基础设置,然后可分享或进行版本控制。
我们需要做的第一件事,也是在启动Docker for AWS前所需的唯一配置,是确保我们有分配给启动集群所在区域账号的SSH密钥。获取密钥,只需访问https://console.aws.amazon.com/登录AWS控制台,或者使用组织的自定义登录页面。登录后,进入页面左上解角Service菜单,并找到EC2服务。
要确保你在所希望的区域,可以使用右上角用户名与Support 菜单之间的地区切换器。在选择了对应区域之后,点击Key Pairs(密钥对),它在左边菜单Network & Security下面。进行Key Pairs页面后,你会看到当前的密钥对。如果没有显示或无法进行访问,可以点击 Create Key Pair或Import Key Pair并按提示操作。
可以在 Docker商店中找到Docker for AWS:https://hub.docker.com/editions/community/docker-ce-aws。Docker for AWS有两个选项:稳定版和Edge版。
Edge版包含一些未来Docker版本的实验功能,因此我们将来使用Docker for AWS稳定版。为此我们只需点击按钮,你就会直接进入AWS控制台的CloudFormation并已加载了Docker模板。
你可以查看原生模板,当前由3100行代码,通过访问https://editions-us-east-1.s3.amazonaws.com/aws/stable/Docker.tmpl可进行查看,或者可以在CloudFormation设计器中可视化显示模板。从如下的视图中可以看到启动集群需要做很多事情:
这种方法的好处在于你无需担心它们的编译。Docker替你省却了所有这些此前所提到的基础设施和服务的相关工作。
第一步是启动已经理清的集群。你只需在Select Template页面点击Next即可:
接下来,我们需要指定集群的一些细节信息。除了SSH密钥外,我们将会保留所有项为默认值:
- Stack name: Docker
- Number of Swarm managers: 3
- Number of Swarm worker nodes: 5
- Which SSH key to use: 从列表中选择你的密钥
- Enable daily resource cleanup: No
- Use CloudWatch for container logging: Yes
- Create EFS prerequisites for CloudStore: No
- Swarm manager instance type: t2.micro
- Manager ephemeral storage volume size: 20
- Manager ephemeral storage volume type: Standard
- Agent worker instance type: t2.micro
- Worker ephemeral storage volume size: 20
- Worker ephemeral storage volume type: Standard
- Enable EBS I/O optimization? No
- Encrypt EFS objects? False
检查所有项都OK后,点击Next按钮。在下一步中,我们可以保持所有设置不变并点击Next按钮进入review页面。在review页面上,你可以看到一个可查看预估费用的链接:
译者注:未能有幸看到费用预估的链接,上图来自原书
可以看到,我们集群每月预估费用为$113.46。
小贴士:查看成本的链接我有时会成功-并不是每次启动模板时都会出现,如果你根据前面的列表已经回答了所胡问题却没出现这一链接的话,那么你的费用和我的差不多。
在启动集群前最后要做的事是勾选 I acknowledge that AWS CloudFormation might create IAM resources并点击Create按钮。可以猜到会需要一点时间来启动这一集群,你可以在AWS控制台中选择CloudFormation stack并选择Events选择卡来查看启动的状态:
大约15分钟后,你应该可以看到状态由CREATE_IN_PROGRESS变成了CREATE_COMPLETE。看到后,点击Outputs选项卡,你应该可以看到一组 URL 和链接:
要登录到我们的Swarm集群中,点击Managers旁的一链接,进入EC2实例列表,这是我们的manager节点。选择其中一个实例,然后记录下其对外的DNS地址。在终端中,通过SSH连接节点,用户名使用docker。例如,我运行如下命令来登录并获取所有的节点列表:
1 2 |
$ ssh docker@ec2-54-183-23-46.us-west-1.compute.amazonaws.com $ docker node ls |
译者注:进行如上操作需要上传本地对公密钥
小贴士:如是你在添加密钥从AWS控制台下载了SSH密钥,应该在将以上命令修改为包含下载密钥的路径,例如,ssh -i /path/to/private.key docker@ec2-54-183-23-46.us-west-1.compute.amazonaws.com。
译者注:建议将文件重命名为 pem 并将权限设置为只读,如chmod 400 masteringdocker.pem
以上登录和获取所有节点列表的命令结果如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$ ssh -i /Users/alan/Downloads/masteringdocker.pem docker@ec2-54-183-23-46.us-west-1.compute.amazonaws.com The authenticity of host 'ec2-54-183-23-46.us-west-1.compute.amazonaws.com (54.183.23.46)' can't be established. ECDSA key fingerprint is SHA256:v43PbXx6TY6ceHmOyOs7KkanURRaHDb2rvPZhEP9Lrs. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'ec2-54-183-23-46.us-west-1.compute.amazonaws.com,54.183.23.46' (ECDSA) to the list of known hosts. Welcome to Docker! ~ $ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION ug3ooxmus12tsopjl3x7abx6u * ip-172-31-2-118.us-west-1.compute.internal Ready Active Reachable 18.09.2 sl7tzi5ctvbaaxpudyvhjwhxu ip-172-31-3-104.us-west-1.compute.internal Ready Active 18.09.2 qx09ttxh468kin8yzo3ty8cq1 ip-172-31-7-168.us-west-1.compute.internal Ready Active Leader 18.09.2 d24yzkcvtcl96hnihm1ntf8j0 ip-172-31-11-24.us-west-1.compute.internal Ready Active 18.09.2 mpv7tmvinsy1t8tsmnhp0viaj ip-172-31-22-42.us-west-1.compute.internal Ready Active 18.09.2 pcmfog0ig3al99sn0e9p6rntq ip-172-31-25-100.us-west-1.compute.internal Ready Active 18.09.2 uu7saaq7oelj853xyzv07kc15 ip-172-31-26-186.us-west-1.compute.internal Ready Active Reachable 18.09.2 qmagy3u7yc2cfabl4oxb8y4w2 ip-172-31-31-20.us-west-1.compute.internal Ready Active 18.09.2 ~ $ |
至此,你可以将其视作任意其它Docker Swarm集群。例如,我们可以运行如下命令来启动和对集群服务扩容:
1 2 3 4 |
$ docker service create --name cluster --constraint "node.role == worker" -p 80:80/tcp russmckendrick/cluster $ docker service scale cluster=6 $ docker service ls $ docker service inspect --pretty cluster |
译者补充:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
~ $ docker service create --name cluster --constraint "node.role == worker" - p 80:80/tcp russmckendrick/cluster r5d5y75fwb6wuag6plyad5uem overall progress: 1 out of 1 tasks 1/1: running verify: Service converged ~ $ docker service scale cluster=6 cluster scaled to 6 overall progress: 6 out of 6 tasks 1/6: running 2/6: running 3/6: running 4/6: running 5/6: running 6/6: running verify: Service converged ~ $ docker service ls ID NAME MODE REPLICAS IMAGE PORTS r5d5y75fwb6w cluster replicated 6/6 russmckendrick/cluster:latest *:80->80/tcp ~ $ docker service inspect --pretty cluster ID: r5d5y75fwb6wuag6plyad5uem Name: cluster Service Mode: Replicated Replicas: 6 Placement: Constraints: [node.role == worker] UpdateConfig: Parallelism: 1 On failure: pause Monitoring Period: 5s Max failure ratio: 0 Update order: stop-first RollbackConfig: Parallelism: 1 On failure: pause Monitoring Period: 5s Max failure ratio: 0 Rollback order: stop-first ContainerSpec: Image: russmckendrick/cluster:latest@sha256:702d320906c5dd4429dfc488e4402e3f12737eea30f1d11ed2cf02d75b74294c Init: false Resources: Endpoint Mode: vip Ports: PublishedPort = 80 Protocol = tcp TargetPort = 80 PublishMode = ingress |
现在你已经启动了服务,可以使用CloudFormation页面Outputs选项卡中给定的DefaultDNSTarget来作为URL查看你的应用。这是一个亚马逊弹性负载均衡器,我们的所有节点都在它背后。
例如,我的DefaultDNSTarget是Docker-ExternalLoa-YE80FVEZ1H67-53688158.us-west-1.elb.amazonaws.com。将其输入浏览器会显示集群应用:
在完成了集群操作之后,回到AWS控制台的CloudFormation页面,选择你的栈,然后从Actions的下拉菜单中选择Delete Stack。这会删除所有的 AWS中Docker集群的记录,并且不会再收取任何费用。
小贴士:请确保检查删除栈时没有任何问题,如过这一过程遇到了任何问题,没有成功删除的资源还会继续收费。
Azure上的Docker社区版
接下来我们有Azure的Docker社区版,我将称其为Docker for Azure。这使用Azure资源管理(ARM)模板来定义Docker Swarm集群。使用ARMViz工具,我们可以可视化地看到集群长什么样:
译者注:可视化工具地址:http://armviz.io/designer;模板文件地址:https://download.docker.com/azure/stable/Docker.tmpl
可以看到,它会启动虚拟机、带有公网 IP 的负载均衡器以及存储。在启动集群之前,我们需要查看一些我们的Azure账号的信息:
- AD Service principle ID
- AD Service principle key
要生成所要求的信息,我们将使用在容器内运行的帮助脚本。运行脚本,我们需要一个有效Azure订阅的admin权限。只需运行如下命令来运行脚本:
1 |
$ docker run -ti docker4x/create-sp-azure sp-name |
这会给到你一个 URLhttps://microsoft.com/devicelogin以及要输入的验证码。访问该 URL 并输入验证码:
你时你会在命令行中登入账号,并询问想使用哪一个订阅。帮助脚本的完整输出如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
$ docker run -ti docker4x/create-sp-azure docker-sp info: Executing command login -info: To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code GT54G382D to authenticate. |info: Added subscription Pay-As-You-Go info: Setting subscription "Pay-As-You-Go" as default + info: login command OK The following subscriptions were retrieved from your Azure account 1) e21c7015-9647-4995-8b3d-7b82c37exxxx:Pay-As-You-Go Please select the subscription option number to use for Docker swarm resources: 1 Using subscription e21c7015-9647-4995-8b3d-7b82c37exxxx info: Executing command account set info: Setting subscription to "Pay-As-You-Go" with id "e21c7015-9647-4995-8b3d-7b82c37exxxx". info: Changes saved info: account set command OK Creating AD application docker-sp Created AD application, APP_ID=0a314b29-c005-4748-b05b-13497ab3xxxx Creating AD App ServicePrincipal Created ServicePrincipal ID=bbcc7186-4f38-48dd-9593-1b575addxxxx Waiting for account updates to complete before proceeding ... Creating role assignment for bbcc7186-4f38-48dd-9593-1b575add76ef for subscription e21c7015-9647-4995-8b3d-7b82c37exxx info: Executing command role assignment create ... Wait before retrying ... Role assignment creation failed for Azure. we generated the following: AD ServicePrincipal App ID: 0a314b29-c005-4748-b05b-13497abxxxx AD ServicePrincipal App Secret: oRz1dFaCUlInmEEGXuBKXItrjIycxxxx |
译者注:Alan在操作时帮助脚本会提示Role assignment creation failed for Azure的错误,但可以生成AD ServicePrincipal App ID和 Secret,相关信息也可在 Azure Active Directory(AD 正是它的缩写)>App registrations 下进行查看,后续待进一步测试再更新
在输出的最后是你所需要的信息,因此请记录下来。
ℹ️在写本书时,在Docker商店的Azure的Docker社区版页面上使用 Docker for Azure (Stable)按钮存在已知的问题。现在我们需要使用该模板的老版本。你可以通过运行如下链接:https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fdownload.docker.com%2Fazure%2Fstable%2F18.03.0%2FDocker.tmpl
这会打开Azure portal并展示一个可以输入一些信息的页面:
- Subscription: 从下拉列表中选择你希望使用的订阅
- Resource group: 先择你想要使用的资源组或新建一个
- Location: 选择想要在哪里启动Docker Swarm集群
- Ad Service Principle App ID: 这由刚刚运行的帮助脚本生成
- Ad Service Principle App Secret: 这由刚刚运行的帮助脚本生成
- 启动Ext Logs: Yes
- 启动System Prune: No Linux SSH
- Public Key: 输入你本地SSH key的公钥部分
- Linux Worker数: 2
- Linux Worker虚拟机大小: Standard_D2_v2
- Manager数: 1
- Manager虚拟机大小: Standard_D2_v2
- Swarm名称: dockerswarm
同意相关条款厃点击页面底部的Purchase按钮。通过点击顶部菜单通知区的Deployment in Progress链接来查看启动的进度,可以看类似下面的内容:
TODO
完成之后,你会看到在所选择或创建的资源组下有几个服务。其中之一是 dockerswarm-externalSSHLoadBalancerpublic-ip。向资源内进行追踪,你会看到可以用于SSH连接到Swarm Manager的 IP 地址。运行如下命令来进行连接:
1 2 |
$ ssh docker@52.232.99.223 -p 50000 $ docker node ls |
注意我们使用的是5000端口而不是标准的22端口。你会看到如下内容:
TODO
登录到manager节点之后,然后你可以使用如下命令来启动应用:
1 2 3 4 |
$ docker service create --name cluster --constraint "node.role == worker" -p 80:80/tcp russmckendrick/cluster $ docker service scale cluster=6 $ docker service ls $ docker service inspect --pretty cluster |
启动之后,进入dockerswarm-externalLoadBalancer-public-ip,这会显示该应用。在完成你的集群之后,我们会建议删除资源组而不是深度去删除单个资源:
TODO
ℹ️记住在资源活跃时即使不使用也是收费的。
和 AWS 集群一样,请确保完全删除了这些资源,否则你会收到不想要花费的账单。
云端Docker总结
可以看到,使用Docker所提供的模板在Azure和 AWS 上启动Swarm集群非常的简单明了。虽然这些模板很棒,如果你刚开始的话,从Docker所能得到的支持非常之少。我会建议如果你想要在公有云上以轻易的方式启动生产环境容器的话,可以了解我们下面将要讨论的一些解决方案。
Amazon ECS和AWS Fargate
AWS 提供了一些其它的容器方案,我们这部要看的是亚马逊弹性容器服务(ECS) 的一部,称为AWS Fargate。
曾经,Amazon ECS 启动EC2实例。启动之后,Amazon ECS代理与容器运行时一起部署来避免需要启动EC2实例,这样我们仅需启动容器,而不用担心管理集群或EC2实例带来的开销。
我们会走一点捷径来进行Amazon ECS的第一次运行。你可以通过访问https://console.aws.amazon.com/ecs/home#/firstRun这一链接。这会带我们走完在Fargate中启动容器的4步。
Amazon ECS使用如下组件:
- 容器定义
- 任务定义
- 服务
- 集群
启动AWS Fargate托管的容器的第一步是配置前两个组件,即容器和任务定义。
容器定义是对容器的基本设置定义。把它看作在使用Docker客户端命令行启动容器时所添加的标记,例如,为容器命名,定义要使用的镜像,设置网络等等。
在我们的例子中,有三个自定义的选择和一个自定义选项。点击自定义选项中的Configure按钮并输入如下信息:
- Container name: cluster-container
- Image: russmckendrick/cluster:latest
- Memory Limits (MiB): 保留默认值
- Port mappings: 输入80并保留选择 tcp
然后,点击Update按钮。在任务定义中,点击Edit按钮并输入如下内容:
- Task definition name: cluster-task
- Network mode: 应为awsvpc,此项不可修改
- Task execution role: 保留为ecsTaskExecutionRole
- Compatibilities: 默认应为FARGATE,无法进行编辑
- Task memory and Task CPU: 这两项都保留为默认值
完成更新后,点击Save按钮。现在你可以点击页面底部的Next按钮。这会带我们进入第二步来定义服务。
服务运行关联有容器的任务。默认的服务就可以,所以点击Next按钮进入到第三步来启动进程。这一步是集群创建的地点。同样默认值就可以了,点击Next页面进入回顾页面。
这里可以在服务启动前最后再检查一遍任务、服务和集群定义。如果一切都没有问题,就点击Create按钮。自此你会进入一个查看组成AWS Fargate集群的各个AWS服务的进度:
在所有的状态由pending变成complete时,就可以点击View service按钮进入Service总览页面:
现在,我们只需知道容器的公网 IP 即可。点击Tasks选项卡,然后点击任务的唯一 ID。在该页面的Network版块,你就可以看到该任务的内网和公网 IP 地址。在浏览器中输入公网 IP 地址就会看到我们熟悉的应用:
你会看到显示的容器名为容器的主机名,并且包含内网 IP 地址。还可以通过点击Logs选项卡来查看容器的日志:
那么它的费用是多少呢?整月运行容器的费用大约是$14,约为$0.019每小时。
这个费用表示如果你全天候地运行一些任务的话,Fargate可能不是一种运行容器高性价比的方式。取而代之你可能杨要选择Amazon ECS EC2,通过它可以将更多的容器打包到资源或Amazon EKS服务中,本章后面我们将会一起学习。但是,要快速启动并终止容器,Fargate是非常棒的,可以无障碍地启动容器并且所需支持的资源也非常的少。
完成Fargate容器之后,你应该删除该集群。这会删除与集群关联的所有服务。在删除了集群之后,进入任务定义页面,需要话取消任务的注册(deregister)。
接下来,我们来看Azure应用服务。
Microsoft Azure应用服务
微软Azure应用服务全面管理平台,让你可以部署自己的应用,剩下的交由Azure来处理它们所运行的平台的管理。在启动应用服务时有一些选项。你可以运行.NET, .NET Core, Node.js, PHP, Python和Ruby编写的应用,或者从容器镜像仓库中直接启动镜像。
在这个快速的流程熟悉中,我们将从Docker Hub启动集群镜像。访问https://portal.azure.com/登录Azure portal并在左侧菜单选择App Services。
在进入的页面中,点击+Add按钮。有一些选项可供选择:
我们将要启动一个Web应用,因此点击该图标。展开之后,点击Create按钮。
译者注:当前版本点击+Add即为 Web 应用,无需进行选择
在打开的页面中,有一些选项,填写如下:
- App Name: 选择应用的唯一名称
- Subscription: 选择一个有效的订阅
- Resource Group: 保留Create new选项选取
- OS: 保留为Linux
- Publish: 选择Docker Image
- App Service plan/location: 默认选取的是最贵的方案,因此点击这里会进行一个可以创建新方案的页面。点击Create new来进行创建,为新方案命名亲选择一个位置,最后选择价格 bwxu。对我们而言Dev/Test方案就足够了。选定之后,点击Apply。
- Configure container: 点击这里会进入容器选项。这里有多个选项:单容器、Docker Compose或Kubernetes。现在我们会启动一个单容器。点击Docker Hub选项并输入russmckendrick/cluster:latest。输入之后,就可以点Apply按钮了。
所有信息都填好后,你就可以点击Create来启动这一Web应用服务。启动之后。你应该可以通过Azure提供的URL来访问服务,我的链接为https://masteringdocker.azurewebsites.net/。在浏览器中打开这一链接会显示集群应用:
可以看到,这次显示的是容器 ID 而非在AWS Fargate上启动容器时的主机名全称。这一配置的容器费用约为每小时$0.05或每月$36.50。只需删除资源组即可删除该容器。
Microsoft Azure, Google Cloud和AWS上的Kubernetes
最后我们要来看的是在这三大主流公有云上启动Kubernetes集群是多么的容易。在上一章中,我们使用Docker桌面应用内置的功能在本地启动了一个Kubernetes集群。我们来看在公有去上启动Kubernetes最快速的方式,先从微软Azure开始。
Azure Kubernetes服务
Azure Kubernetes服务 (AKS),启动和配置服务极其简单。我将使用Azure在本地机器上的命令行工具,你也可以通过内置在Azure Portal上的Azure云端Shell的命令行工具。
我们需要做的第一件事是创建一个资源组来启动AKS集群。运行如下命令来创建一个名为MasteringDockerAKS的资源组。
1 |
$ az group create --name MasteringDockerAKS --location eastus |
译者注:Mac 上安装 Azure CLI – brew update && brew install azure-cli,然后执行 az login 登录账号
现在我们已经有了资源组,可以通过运行如下命令来启动一个两节点的Kubernetes集群:
1 2 3 4 5 |
$ az aks create --resource-group MasteringDockerAKS \ --name MasteringDockerAKSCluster \ --node-count 2 \ --enable-addons monitoring \ --generate-ssh-keys |
启动集群会花费几分钟。启动之后,我们将需要拷贝配置,这样我们可以使用本地的kubectl拷贝与集群进行交互。要这样我们需运行如下命令:
1 2 3 |
$ az aks get-credentials \ --resource-group MasteringDockerAKS \ --name MasteringDockerAKSCluster |
这会配置本地的kubectl拷贝与你所启动的AKS集群进行对话。此时你应该可以在Docker菜单的Kubernetes上看到该集群:
运行如下命令会显示与 kubectl 客户端进行对话的服务端版本以及节点的详细信息:
1 2 |
$ kubectl version $ kubectl get nodes |
可以在以下看到上述的命令的输出:
1 2 3 4 5 6 7 |
$ kubectl version Client Version: version.Info{Major:"1", Minor:"12", GitVersion:"v1.12.2", GitCommit:"17c77c7898218073f14c8d573582e8d2313dc740", GitTreeState:"clean", BuildDate:"2018-11-26T13:25:32Z", GoVersion:"go1.11.2", Compiler:"gc", Platform:"darwin/amd64"} Server Version: version.Info{Major:"1", Minor:"12", GitVersion:"v1.12.7", GitCommit:"6f482974b76db3f1e0f5d24605a9d1d38fad9a2b", GitTreeState:"clean", BuildDate:"2019-03-25T02:41:57Z", GoVersion:"go1.10.8", Compiler:"gc", Platform:"linux/amd64"} $ kubectl get nodes NAME STATUS ROLES AGE VERSION aks-nodepool1-16496708-0 Ready agent 9m8s v1.12.7 aks-nodepool1-16496708-1 Ready agent 9m v1.12.7 |
现在的我集群已启动并运行了,我们需要启动一个应用。所幸Weave有一个优秀的开源微服务demo,它会启动一个销售袜子的演示商店。我们只需运行如下命令来启动这个demo:
1 2 |
$ kubectl create namespace sock-shop $ kubectl apply -n sock-shop -f "https://github.com/microservices-demo/microservices-demo/blob/master/deploy/kubernetes/complete-demo.yaml?raw=true" |
大约会花费5分钟来启动demo。你可以通过运行如下命令来查看各个pod的状态:
1 |
$ kubectl -n sock-shop get pods |
一切都启动并运行时,你应该可以看到如下输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ kubectl -n sock-shop get pods NAME READY STATUS RESTARTS AGE carts-55f7f5c679-xfxhv 1/1 Running 0 114s carts-db-5c55874946-ctzkm 1/1 Running 0 116s catalogue-5764fdf6d-cklr4 1/1 Running 0 110s catalogue-db-66ff5bbbf5-bwqkw 1/1 Running 0 112s front-end-f99dbcb9c-hx4h6 1/1 Running 0 106s orders-7b69bf5686-s9dl7 1/1 Running 0 100s orders-db-7bc46bdb98-8h8l8 1/1 Running 0 103s payment-79769c5874-h5q6j 1/1 Running 0 97s queue-master-56894bf9b8-pd5pv 1/1 Running 0 94s rabbitmq-bf496c754-p4z9c 1/1 Running 0 91s shipping-7d6f7bf67b-92sxw 1/1 Running 0 88s user-7d4d7c9675-xqm4t 1/1 Running 0 82s user-db-5d6b6cd769-lcfch 1/1 Running 0 85s |
现在我们的应用已启动,我需要一种访问的方式。通过运行如下命令来查看这一服务:
1 |
$ kubectl -n sock-shop get services |
这会显示 一个称为front-end(前台)的服务。我们将创建一个负载均衡器并与服务关联,运行如下命令来实现:
1 |
$ kubectl -n sock-shop expose deployment front-end --type=LoadBalancer --name=front-end-lb |
你可以通过运行如下命令来查看负载均衡器的状态:
1 2 |
$ kubectl -n sock-shop get services front-end-lb $ kubectl -n sock-shop describe services front-end-lb |
启动之后,可以看到类似下面的信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
$ kubectl -n sock-shop get services front-end-lb NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE front-end-lb LoadBalancer 10.0.230.116 40.114.36.58 8079:31717/TCP 104s $ kubectl -n sock-shop describe services front-end-lb Name: front-end-lb Namespace: sock-shop Labels: name=front-end Annotations: <none> Selector: name=front-end Type: LoadBalancer IP: 10.0.230.116 LoadBalancer Ingress: 40.114.36.58 Port: <unset> 8079/TCP TargetPort: 8079/TCP NodePort: <unset> 31717/TCP Endpoints: 10.244.1.8:8079 Session Affinity: None External Traffic Policy: Cluster Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal EnsuringLoadBalancer 110s service-controller Ensuring load balancer Normal EnsuredLoadBalancer 22s service-controller Ensured load balancer |
从前面的输出中可以看到,我的商店 IP地址为40.114.36.58,端口为8079。在浏览器中打开http://40.114.36.58:8079/,会显示如下页面:
在商店中点击查看完效果之后,可以通过运行如下命令来删除它:
1 |
$ kubectl delete namespace sock-shop |
运行如下命令来删除AKS集群和资源组:
1 |
$ az group delete --name MasteringDockerAKS --yes --no-wait |
记得在Azure portal中检查是否删除了所有想要删除的服务,以免产生额外费用。最后,你可以通过运行如下命令来从本地kubectl配置来删除配置:
1 2 |
$ kubectl config delete-cluster MasteringDockerAKSCluster $ kubectl config delete-context MasteringDockerAKSCluster |
下面我们要来看在Google Cloud上启动一个类似的集群。
Google Kubernetes引擎
Google Kubernetes引擎,不难猜到它在Google的云平台上紧密集成。跳过细节,我们直接进入并启动一个集群。我假定你已有一个Google Cloud账号,项目已经启动付款,并安装了Google云SDK 且配置好与你的项目进行交互。
只需运行如下命令来启动集群:
1 |
$ gcloud container clusters create masteringdockergke --num-nodes=2 --zone us-west2-a |
译者注:区域列表参见https://cloud.google.com/compute/docs/regions-zones/,另安装后需配置:
1 2 |
gcloud auth login gcloud config set project xxx |
集群启动之后,你的kubectl配置会自动更新并且上下文设置为新启动的集群。你可以运行如下命令来查看各节点的信息:
1 2 |
$ kubectl version $ kubectl get nodes |
1 2 3 4 5 6 7 |
$ kubectl version Client Version: version.Info{Major:"1", Minor:"12", GitVersion:"v1.12.2", GitCommit:"17c77c7898218073f14c8d573582e8d2313dc740", GitTreeState:"clean", BuildDate:"2018-11-26T13:25:32Z", GoVersion:"go1.11.2", Compiler:"gc", Platform:"darwin/amd64"} Server Version: version.Info{Major:"1", Minor:"11+", GitVersion:"v1.11.8-gke.6", GitCommit:"394ee507d00f15a63cef577a14026096c310698e", GitTreeState:"clean", BuildDate:"2019-03-30T19:31:43Z", GoVersion:"go1.10.8b4", Compiler:"gc", Platform:"linux/amd64"} $ kubectl get nodes NAME STATUS ROLES AGE VERSION gke-masteringdockergke-default-pool-cdb07da6-4w11 Ready <none> 54s v1.11.8-gke.6 gke-masteringdockergke-default-pool-cdb07da6-f0jx Ready <none> 52s v1.11.8-gke.6 |
此时我们的集群已启动并运行,我们通过重启前面已使用过的命令来启动一个演示商店:
1 2 3 4 5 6 |
$ kubectl create namespace sock-shop $ kubectl apply -n sock-shop -f "https://github.com/microservices-demo/microservices-demo/blob/master/deploy/kubernetes/complete-demo.yaml?raw=true" $ kubectl -n sock-shop get pods $ kubectl -n sock-shop get services $ kubectl -n sock-shop expose deployment front-end --type=LoadBalancer --name=front-end-lb $ kubectl -n sock-shop get services front-end-lb |
同样,在front-end-lb服务创建之后,你应该能找到外网 IP 地址和端口来使用:
1 2 3 |
$ kubectl -n sock-shop get services front-end-lb NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE front-end-lb LoadBalancer 10.59.253.149 35.236.10.205 8079:32658/TCP 3m |
在浏览器输入这些信息会打开商店:
只需运行如下命令来删除集群:
1 2 |
$ kubectl delete namespace sock-shop $ gcloud container clusters delete masteringdockergke --zone us-west2-a |
这也会从kubectl删除该上下文和集群。
Amazon的Kubernetes弹性容器服务
我们要来看的最后一个Kubernetes服务是Amazon的Kubernetes弹性容器服务,或简称为EKS。这是我们所讲解的三个服务中最近才启动的服务。事实上,你可以说Amazon加入Kubernetes大家庭的时间非常晚。
不幸的是,Amazon的命令行工具并不像Azure和Google Cloud一样友好。因此,我将使用一个名为eksctl的工具,由Weave所编写,也即出自我们使用使用的演示商店的相同作者之手。可以在本章最后的扩展阅读版块查看eksctl以及Amazon命令行工具的更多细节信息。
译者注:运行如下命令来执行eksctl的安装
1 2 3 4 5 |
brew tap weaveworks/tap brew install weaveworks/tap/eksctl # 同时还应完成如下安装和配置 brew install aws-iam-authenticator aws configure |
要启动我们的Amazon EKS集群,我们需要运行如下命令:
1 |
$ eksctl create cluster |
集群的启动会花费几分钟时间,但在整个过程中你会在命令行中收到反馈。同时eksctl使用的是CloudFormation,你也可以在AWS控制台中查看进度。完成之后,你应该会看到类似如下输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
$ eksctl create cluster [ℹ] using region us-west-2 [ℹ] setting availability zones to [us-west-2b us-west-2a us-west-2c] [ℹ] subnets for us-west-2b - public:192.168.0.0/19 private:192.168.96.0/19 [ℹ] subnets for us-west-2a - public:192.168.32.0/19 private:192.168.128.0/19 [ℹ] subnets for us-west-2c - public:192.168.64.0/19 private:192.168.160.0/19 [ℹ] nodegroup "ng-ba54802f" will use "ami-0923e4b35a30a5f53" [AmazonLinux2/1.12] [ℹ] creating EKS cluster "scrumptious-hideout-1556451947" in "us-west-2" region [ℹ] will create 2 separate CloudFormation stacks for cluster itself and the initial nodegroup [ℹ] if you encounter any issues, check CloudFormation console or try 'eksctl utils describe-stacks --region=us-west-2 --name=scrumptious-hideout-1556451947' [ℹ] 2 sequential tasks: { create cluster control plane "scrumptious-hideout-1556451947", create nodegroup "ng-ba54802f" } [ℹ] building cluster stack "eksctl-scrumptious-hideout-1556451947-cluster" [ℹ] deploying stack "eksctl-scrumptious-hideout-1556451947-cluster" [ℹ] buildings nodegroup stack "eksctl-scrumptious-hideout-1556451947-nodegroup-ng-ba54802f" [ℹ] --nodes-min=2 was set automatically for nodegroup ng-ba54802f [ℹ] --nodes-max=2 was set automatically for nodegroup ng-ba54802f [ℹ] deploying stack "eksctl-scrumptious-hideout-1556451947-nodegroup-ng-ba54802f" [✔] all EKS cluster resource for "scrumptious-hideout-1556451947" had been created [✔] saved kubeconfig as "/Users/alan/.kube/config" [ℹ] adding role "arn:aws:iam::563147367726:role/eksctl-scrumptious-hideout-155645-NodeInstanceRole-1MH1H9ZCSHPH8" to auth ConfigMap [ℹ] nodegroup "ng-ba54802f" has 1 node(s) [ℹ] node "ip-192-168-95-226.us-west-2.compute.internal" is not ready [ℹ] waiting for at least 2 node(s) to become ready in "ng-ba54802f" [ℹ] nodegroup "ng-ba54802f" has 2 node(s) [ℹ] node "ip-192-168-49-75.us-west-2.compute.internal" is ready [ℹ] node "ip-192-168-95-226.us-west-2.compute.internal" is ready [ℹ] kubectl command should work with "/Users/alan/.kube/config", try 'kubectl get nodes' [✔] EKS cluster "scrumptious-hideout-1556451947" in "us-west-2" region is ready |
作为启动的一部分,eksctl将会配置你本地的kubectl上下文,这表示你可以运行如下命令:
1 2 |
$ kubectl version $ kubectl get nodes |
1 2 3 4 5 6 7 |
$ kubectl version Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.1", GitCommit:"b7394102d6ef778017f2ca4046abbaa23b88c290", GitTreeState:"clean", BuildDate:"2019-04-19T22:12:47Z", GoVersion:"go1.12.4", Compiler:"gc", Platform:"darwin/amd64"} Server Version: version.Info{Major:"1", Minor:"12+", GitVersion:"v1.12.6-eks-d69f1b", GitCommit:"d69f1bf3669bf00b7f4a758e978e0e7a1e3a68f7", GitTreeState:"clean", BuildDate:"2019-02-28T20:26:10Z", GoVersion:"go1.10.8", Compiler:"gc", Platform:"linux/amd64"} $ kubectl get nodes NAME STATUS ROLES AGE VERSION ip-192-168-49-75.us-west-2.compute.internal Ready <none> 87s v1.12.7 ip-192-168-95-226.us-west-2.compute.internal Ready <none> 88s v1.12.7 |
我们已启动和运行了集群,可以像之前一样启动演示商店:
1 2 3 4 5 6 |
$ kubectl create namespace sock-shop $ kubectl apply -n sock-shop -f "https://github.com/microservices-demo/microservices-demo/blob/master/deploy/kubernetes/complete-demo.yaml?raw=true" $ kubectl -n sock-shop get pods $ kubectl -n sock-shop get services $ kubectl -n sock-shop expose deployment front-end --type=LoadBalancer --name=front-end-lb $ kubectl -n sock-shop get services front-end-lb |
你可能会注意到在运行以上命令时显示的外部 IP 有些怪异:
1 2 3 |
$ kubectl -n sock-shop get services front-end-lb NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE front-end-lb LoadBalancer 10.100.158.214 ae18c05dc69ad11e9a3fc06b4d6cb3c1-11594909.us-west-2.elb.amazonaws.com 8079:30574/TCP 11s |
这是因为它是一个DNS名称而不是IP地址。运行如下命令来查看完整URL:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$ kubectl -n sock-shop describe services front-end-lb Name: front-end-lb Namespace: sock-shop Labels: name=front-end Annotations: <none> Selector: name=front-end Type: LoadBalancer IP: 10.100.158.214 LoadBalancer Ingress: ae18c05dc69ad11e9a3fc06b4d6cb3c1-11594909.us-west-2.elb.amazonaws.com Port: <unset> 8079/TCP TargetPort: 8079/TCP NodePort: <unset> 30574/TCP Endpoints: 192.168.48.239:8079 Session Affinity: None External Traffic Policy: Cluster Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal EnsuringLoadBalancer 64s service-controller Ensuring load balancer Normal EnsuredLoadBalancer 61s service-controller Ensured load balancer |
在浏览器中输入URL和端口,会如你所料的显示演示商店:
运行如下命令来删除集群:
1 2 |
$ kubectl delete namespace sock-shop $ eksctl get cluster |
这会显示运行中的集群名称。获取名称后,运行如下命令,请确保填写你自己的集群:
1 |
$ eksctl delete cluster --name=scrumptious-hideout-1556451947 |
终端的输出如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 |
$ eksctl get cluster NAME REGION scrumptious-hideout-1556451947 us-west-2 $ eksctl delete cluster --name=scrumptious-hideout-1556451947 [ℹ] using region us-west-2 [ℹ] deleting EKS cluster "scrumptious-hideout-1556451947" [✔] kubeconfig has been updated [ℹ] 2 sequential tasks: { delete nodegroup "ng-ba54802f", delete cluster control plane "scrumptious-hideout-1556451947" [async] } [ℹ] will delete stack "eksctl-scrumptious-hideout-1556451947-nodegroup-ng-ba54802f" [ℹ] waiting for stack "eksctl-scrumptious-hideout-1556451947-nodegroup-ng-ba54802f" to get deleted [ℹ] will delete stack "eksctl-scrumptious-hideout-1556451947-cluster" [✔] all cluster resources were deleted |
Kubernetes总结
至此就完结了我们在Microsoft Azure, Google Cloud和 AWS 上有关Kubernetes的简短学习。我们讲解了一些要点。第一点是我们使用命令行中几步启动并管理我们的集群,在启动Amazon EKS时我们使用了第三方工具。
第二点也是最重要的点是在我们使用kubectl访问集群时,在三个平台上的体验完全一致。我们无需访问云提供商的网页控制面板来修改或重审设置。所有的操作都使用相同命令完成,部署相同代码和服务时无需思考或考虑云提供商上任何单独的服务。
我们甚至可以在本地通过Docker使用完全相同的命令运行演示商店。只需要启动你的Kubernetes集群,确保选择了本地Docker上下文,然后运行如下命令:
1 2 3 4 5 6 |
$ kubectl create namespace sock-shop $ kubectl apply -n sock-shop -f "https://github.com/microservices-demo/microservices-demo/blob/master/deploy/kubernetes/complete-demo.yaml?raw=true" $ kubectl -n sock-shop get pods $ kubectl -n sock-shop get services $ kubectl -n sock-shop expose deployment front-end --type=LoadBalancer --name=front-end-lb $ kubectl -n sock-shop get services front-end-lb |
可以从输出看到,这里的负载均衡 IP 是localhost。在浏览器中输入http://localhost:8079并打开会进入到商店:
可以通过运行如下命令来删除商店:
1 |
$ kubectl delete namespace sock-shop |
这种级别的跨多供应商甚至是本地机器的一致性,在以往不通过大量的工作和配置或闭源订阅服务务是不可能实现的。
总结
本章中,我们学习了如何使用Docker自己所提供的工具在云服务商那里部署Docker Swarm 集群。我们还学习公有云提供的两种服务来在Docker工具集之外运行容器。
最后,我们学习了在不同的云上启动Kubernetes集群并运行相同的demo应用。虽然与我们运行的命令无关,三种公有云上使用的是不同版本的Docker来作为容器引擎。在读者读到本文时这可能不再如此,因为理论上他们可以在不受什么影响的情况下切的到其它引擎。
下一章中,我们将要再次加到Docker并来学习Portainer,一个管理Docker安装的网页端界面。
课后问题
- 是非题:Docker for AWS和Docker for Azure为你启动Kubernetes集群来在其上启动容器。
- 如果使用Amazon Fargate哪个服务你无需直接管理?
- 我们需要在Azure中启动什么类型的服务?
- 启动之后,我们需要运行什么命令来为演示袜店创建命名空间?
- 我们如何查找负载均衡器的完整细节?
扩展阅读
有关Docker云服务的关闭信息参见如下链接:
- Docker云迁移通知和常见问题:https://success.docker.com/article/cloud-migration
- 此处省去一个广告链接
有关Docker for AWS和Docker for Azure模板服务的更多信息参见如下链接:
- AWS CloudFormation: https://aws.amazon.com/cloudformation/
- Azure ARM模板: https://azure.microsoft.com/en-gb/resources/templates/
- ARM模板可视化工具 http://armviz.io/
我们用于启动容器的云服务参见如下链接:
- Amazon ECS: https://aws.amazon.com/ecs/
- AWS Fargate: https://aws.amazon.com/fargate/
- Azure Web应用: https://azure.microsoft.com/en-gb/services/app-service/web/
三种Kubernetes服务参见如下链接:
- Azure Kubernetes服务: https://azure.microsoft.com/en-gb/services/kubernetes-service/
- Google Kubernetes引擎: https://cloud.google.com/kubernetes-engine/
- Amazon的Kubernetes弹性容器服务: https://aws.amazon.com/eks/
本章中的种类命令行工具的快速入门参见如下链接:
- Azure CLI: https://docs.microsoft.com/en-us/cli/azure/?view=azure-cli-latest
- Google Cloud SDK: https://cloud.google.com/sdk/
- AWS命令行界面: https://aws.amazon.com/cli/
- eksctl – 一个Amazon EKS的CLI: https://eksctl.io/
最后,有关演示商店的详细信息,参见如下链接: