Java 仍是开发企业应用程序最流行的语言之一。那么，为什么 无服务器 serverless 开发人员对它望而却步？几十年来，企业已经在各类平台上开发了关键业务应用程序，包括物理服务器、虚拟机和云环境。这些应用程序在各行各业都有一个共同点，那就是无论需求如何，它们都需要持续可用（24x7x365），保证稳定性、可靠性和性能。因此，即使实际资源利用率低于 50%，每个企业都必须付出高额成本维护基础架构（如 CPU、内存、磁盘、网络等）。无服务器架构是为了帮助解决这些问题而产生的。无服务器允许开发人员按需构建和运行应用程序，保证高可用性，不必在多云和混合云环境中管理服务器。在幕后，无服务器拓扑中仍有很多服务器，但它们是从应用程序开发中抽象出来的。相反，云提供商使用无服务器进行资源管理，例如配置、维护、联网和扩展服务器实例。由于其高效性，无服务器开发模式现在是一些企业的需求，这些企业希望按需启动服务，而不是一直运行服务。许多新建的开源项目用来在 Kubernetes 集群上通过 Linux 容器包来管理无服务器应用程序。CNCF 的《交互式无服务器全景》 是一份关于开源项目、工具、框架和公共云平台的指南，帮助 DevOps 团队处理无服务器应用程序。开发人员可以编写代码，然后将其快速部署到各种无服务器环境中。然后，无服务器应用程序响应需求，并根据需要自动伸缩扩展。你可能想知道什么编程语言和运行环境最适合无服务器应用程序开发，以便与上图中的技术集成。这个问题不只一个答案，但是让我们退一步来讨论在企业生产环境中开发业务应用程序最流行的应用程序运行环境：Java。据 Developer Economics 称，截至 2020 年第三季度，仍有 800 多万家企业开发人员在使用 Java 来实现其业务需求。然而，根据 2020 年的一项调查，Java（占比 6%）显然不是有前瞻意识的开发人员的首选，他们使用当前云服务做开发。来自 NewRelic 无服务器基准报告的数据（Daniel Oh, CC BY-SA 4.0）资源使用、响应时间和延迟在无服务器开发中至关重要。公有云提供商提供的无服务器产品通常是按需计量的，只有在无服务器应用程序启动时，才会通过事件驱动的执行模式收费。因此，当无服务器应用程序闲置或缩减为零时，企业无需支付任何费用。带有容器的 Java 状态在这种背景下，你可能会问：“既然现有业务应用程序很可能是在 Java 技术上开发的，那么开发人员为什么不尝试使用 Java 栈进行无服务器应用程序开发呢？”隐藏的真相是：很难在新的不可变更的基础设施（例如 Kubernetes 这样的容器平台）中优化 Java 应用程序。该图描述了 Java 进程与竞争的语言、框架（如 Node.js 和 Go）之间内存资源使用的差异。Java HotSpot 占用资源最大，其中包括每个 Java 虚拟机 Java Virtual Machine （JVM）实例分配的堆内存。中间显示了 Node.js 每个进程要比 Java 小得多。最后，Go 是一种流行的云服务编程语言，因为它的内存消耗最低。如你所见，当你在这张图从左到右走，你会看到更密的节点。这就是开发人员在云、容器和 Kubernetes 上编写无服务器应用程序时回避 Java（包括 Spring Boot，一种顽固的微服务 Java 框架）的原因。下一步是什么？企业可以通过实现无服务器应用程序获得明显的好处，但是资源密度问题导致他们避免使用 Java 堆栈在 Kubernetes 上开发无服务器应用程序开发。但是选择其他语言会给全球数百万 Java 开发人员带来学习负担。因此，在本系列的下一篇文章中，我将指导你如何开始使用 Java 无服务器函数，而不是使用其他语言。via: https://opensource.com/article/21/5/what-serverless-java作者：Daniel Oh 选题：lujun9972 译者：DCOLIVERSUN 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
我在 $work 建立了一个基于 Kubernetes 的平台已经快一年了，而且有点像 Kubernetes 的布道者了。真的，我认为这项技术太棒了。然而我并没有对它的运营和维护的困难程度抱过什么幻想。今年早些时候我读了这样的一篇文章，并对其中某些观点深以为然。如果我在一家规模较小的、有 10 到 15 个工程师的公司，假如有人建议管理和维护一批 Kubernetes 集群，那我会感到害怕的，因为它的运维开销太高了！尽管我现在对 Kubernetes 的一切都很感兴趣，但我仍然对“ 无服务器 Serverless ”计算会消灭运维工程师的说法抱有好奇。这种好奇心主要来源于我希望在未来仍然能有一份有报酬的工作 —— 如果我们前景光明的未来不需要运维工程师，那我得明白到底是怎么回事。我已经在 Lamdba 和Google Cloud Functions 上做了一些实验，结果让我印象十分深刻，但我仍然坚信无服务器解决方案只是解决了一部分问题。我关注 AWS Fargate 已经有一段时间了，这就是 $work 的开发人员所推崇为“无服务器计算”的东西 —— 主要是因为 Fargate，用它你就可以无需管理底层节点而运行你的 Docker 容器。我想看看它到底意味着什么，所以我开始尝试从头开始在 Fargate 上运行一个应用，看看是否可以成功。这里我对成功的定义是一个与“生产级”应用程序相近的东西，我想应该包含以下内容：一个在 Fargate 上运行的容器配置信息以环境变量的形式下推“秘密信息” 不能是明文的位于负载均衡器之后有效的 SSL 证书的 TLS 通道我以“基础设施即代码”的角度来开始整个任务，不遵循默认的 AWS 控制台向导，而是使用 terraform 来定义基础架构。这很可能让整个事情变得复杂，但我想确保任何部署都是可重现的，任何想要遵循此步骤的人都可发现我的结论。上述所有标准通常都可以通过基于 Kubernetes 的平台使用一些外部的附加组件和插件来实现，所以我确实是以一种比较的心态来处理整个任务的，因为我要将它与我的常用工作流程进行比较。我的主要目标是看看Fargate 有多容易，特别是与 Kubernetes 相比时。结果让我感到非常惊讶。AWS 是有开销的我有一个干净的 AWS 账户，并决定从零到部署一个 webapp。与 AWS 中的其它基础设施一样，我必须首先使基本的基础设施正常工作起来，因此我需要先定义一个 VPC。遵循最佳实践，因此我将这个 VPC 划分为跨可用区（AZ）的子网，一个公共子网和私有子网。这时我想到，只要这种设置基础设施的需求存在，我就能找到一份这种工作。AWS 是免运维的这一概念一直让我感到愤怒。开发者社区中的许多人理所当然地认为在设置和定义一个设计良好的 AWS 账户和基础设施是不需要付出多少工作和努力的。而这种想当然甚至发生在开始谈论多帐户架构之前就有了——现在我仍然使用单一帐户，我已经必须定义好基础设施和传统的网络设备。这里也值得记住，我已经做了很多次，所以我很清楚该做什么。我可以在我的帐户中使用默认的 VPC 以及预先提供的子网，我觉得很多刚开始的人也可以使用它。这大概花了我半个小时才运行起来，但我不禁想到，即使我想运行 lambda 函数，我仍然需要某种连接和网络。定义 NAT 网关和在 VPC 中路由根本不会让你觉得很“Serverless”，但要往下进行这就是必须要做的。运行简单的容器在我启动运行了基本的基础设施之后，现在我想让我的 Docker 容器运行起来。我开始翻阅 Fargate 文档并浏览 入门 文档，这些就马上就展现在了我面前：等等，只是让我的容器运行就至少要有三个步骤？这完全不像我所想的，不过还是让我们开始吧。任务定义“ 任务定义 Task Definition ”用来定义要运行的实际容器。我在这里遇到的问题是，任务定义这件事非常复杂。这里有很多选项都很简单，比如指定 Docker 镜像和内存限制，但我还必须定义一个网络模型以及我并不熟悉的其它各种选项。真需要这样吗？如果我完全没有 AWS 方面的知识就进入到这个过程里，那么在这个阶段我会感觉非常的不知所措。可以在 AWS 页面上找到这些 参数 的完整列表，这个列表很长。我知道我的容器需要一些环境变量，它需要暴露一个端口。所以我首先在一个神奇的 terraform 模块 的帮助下定义了这一点，这真的让这件事更容易了。如果没有这个模块，我就得手写 JSON 来定义我的容器定义。首先我定义了一些环境变量：container_environment_variables = [ { name = "USER" value = "${var.user}" }, { name = "PASSWORD" value = "${var.password}" } ]然后我使用上面提及的模块组成了任务定义：module "container_definition_app" { source = "cloudposse/ecs-container-definition/aws" version = "v0.7.0" container_name = "${var.name}" container_image = "${var.image}" container_cpu = "${var.ecs_task_cpu}" container_memory = "${var.ecs_task_memory}" container_memory_reservation = "${var.container_memory_reservation}" port_mappings = [ { containerPort = "${var.app_port}" hostPort = "${var.app_port}" protocol = "tcp" }, ] environment = "${local.container_environment_variables}" }在这一点上我非常困惑，我需要在这里定义很多配置才能运行，而这时什么都没有开始呢，但这是必要的 —— 运行 Docker 容器肯定需要了解一些容器配置的知识。我 之前写过 关于 Kubernetes 和配置管理的问题的文章，在这里似乎遇到了同样的问题。接下来，我在上面的模块中定义了任务定义（幸好从我这里抽象出了所需的 JSON —— 如果我不得不手写JSON，我可能已经放弃了）。当我定义模块参数时，我突然意识到我漏掉了一些东西。我需要一个 IAM 角色！好吧，让我来定义：resource "aws_iam_role" "ecs_task_execution" { name = "${var.name}-ecs_task_execution" assume_role_policy = <<EOF { "Version": "2008-10-17", "Statement": [ { "Action": "sts:AssumeRole", "Principal": { "Service": "ecs-tasks.amazonaws.com" }, "Effect": "Allow" } ] } EOF } resource "aws_iam_role_policy_attachment" "ecs_task_execution" { count = "${length(var.policies_arn)}" role = "${aws_iam_role.ecs_task_execution.id}" policy_arn = "${element(var.policies_arn, count.index)}" }这样做是有意义的，我需要在 Kubernetes 中定义一个 RBAC 策略，所以在这里我还未完全错失或获得任何东西。这时我开始觉得从 Kubernetes 的角度来看，这种感觉非常熟悉。resource "aws_ecs_task_definition" "app" { family = "${var.name}" network_mode = "awsvpc" requires_compatibilities = ["FARGATE"] cpu = "${var.ecs_task_cpu}" memory = "${var.ecs_task_memory}" execution_role_arn = "${aws_iam_role.ecs_task_execution.arn}" task_role_arn = "${aws_iam_role.ecs_task_execution.arn}" container_definitions = "${module.container_definition_app.json}" }现在，为了运行起来我已经写了很多行代码，我阅读了很多 ECS 文档，我所做的就是定义一个任务定义。我还没有让这个东西运行起来。在这一点上，我真的很困惑这个基于 Kubernetes 的平台到底增值了什么，但我继续前行。服务服务，一定程度上是将容器如何暴露给外部，另外是如何定义它拥有的副本数量。我的第一个想法是“啊！这就像一个 Kubernetes 服务！”我开始着手映射端口等。这是我第一次在 terraform 上跑：resource "aws_ecs_service" "app" { name = "${var.name}" cluster = "${module.ecs.this_ecs_cluster_id}" task_definition = "${data.aws_ecs_task_definition.app.family}:${max(aws_ecs_task_definition.app.revision, data.aws_ecs_task_definition.app.revision)}" desired_count = "${var.ecs_service_desired_count}" launch_type = "FARGATE" deployment_maximum_percent = "${var.ecs_service_deployment_maximum_percent}" deployment_minimum_healthy_percent = "${var.ecs_service_deployment_minimum_healthy_percent}" network_configuration { subnets = ["${values(local.private_subnets)}"] security_groups = ["${module.app.this_security_group_id}"] } }当我必须定义允许访问所需端口的安全组时，我再次感到沮丧，当我这样做了并将其插入到网络配置中后，我就像被扇了一巴掌。我还需要定义自己的负载均衡器？什么？当然不是吗？负载均衡器从未远离老实说，我很满意，我甚至不确定为什么。我已经习惯了 Kubernetes 的服务和 Ingress 对象，我一心认为用 Kubernetes 将我的应用程序放到网上是多么容易。当然，我们在 $work 花了几个月的时间建立一个平台，以便更轻松。我是 external-dns 和 cert-manager 的重度用户，它们可以自动填充 Ingress 对象上的 DNS 条目并自动化 TLS 证书，我非常了解进行这些设置所需的工作，但老实说，我认为在 Fargate 上做这件事会更容易。我认识到 Fargate 并没有声称自己是“如何运行应用程序”这件事的全部和最终目的，它只是抽象出节点管理，但我一直被告知这比 Kubernetes 更加容易。我真的很惊讶。定义负载均衡器（即使你不想使用 Ingress 和 Ingress Controller）也是向 Kubernetes 部署服务的重要组成部分，我不得不在这里再次做同样的事情。这一切都让人觉得如此熟悉。我现在意识到我需要：一个负载均衡器一个 TLS 证书一个 DNS 名字所以我着手做了这些。我使用了一些流行的 terraform 模块，并做了这个：# Define a wildcard cert for my app module "acm" { source = "terraform-aws-modules/acm/aws" version = "v1.1.0" create_certificate = true domain_name = "${var.route53_zone_name}" zone_id = "${data.aws_route53_zone.this.id}" subject_alternative_names = [ "*.${var.route53_zone_name}", ] tags = "${local.tags}" } # Define my loadbalancer resource "aws_lb" "main" { name = "${var.name}" subnets = [ "${values(local.public_subnets)}" ] security_groups = ["${module.alb_https_sg.this_security_group_id}", "${module.alb_http_sg.this_security_group_id}"] } resource "aws_lb_target_group" "main" { name = "${var.name}" port = "${var.app_port}" protocol = "HTTP" vpc_id = "${local.vpc_id}" target_type = "ip" depends_on = [ "aws_lb.main" ] } # Redirect all traffic from the ALB to the target group resource "aws_lb_listener" "main" { load_balancer_arn = "${aws_lb.main.id}" port = "80" protocol = "HTTP" default_action { target_group_arn = "${aws_lb_target_group.main.id}" type = "forward" } } resource "aws_lb_listener" "main-tls" { load_balancer_arn = "${aws_lb.main.id}" port = "443" protocol = "HTTPS" certificate_arn = "${module.acm.this_acm_certificate_arn}" default_action { target_group_arn = "${aws_lb_target_group.main.id}" type = "forward" } }我必须承认，我在这里搞砸了好几次。我不得不在 AWS 控制台中四处翻弄，以弄清楚我做错了什么。这当然不是一个“轻松”的过程，而且我之前已经做过很多次了。老实说，在这一点上，Kubernetes 看起来对我很有启发性，但我意识到这是因为我对它非常熟悉。幸运的是我能够使用托管的 Kubernetes 平台（预装了 external-dns 和 cert-manager），我真的很想知道我漏掉了 Fargate 什么增值的地方。它真的感觉不那么简单。经过一番折腾，我现在有一个可以工作的 ECS 服务。包括服务在内的最终定义如下所示：data "aws_ecs_task_definition" "app" { task_definition = "${var.name}" depends_on = ["aws_ecs_task_definition.app"] } resource "aws_ecs_service" "app" { name = "${var.name}" cluster = "${module.ecs.this_ecs_cluster_id}" task_definition = "${data.aws_ecs_task_definition.app.family}:${max(aws_ecs_task_definition.app.revision, data.aws_ecs_task_definition.app.revision)}" desired_count = "${var.ecs_service_desired_count}" launch_type = "FARGATE" deployment_maximum_percent = "${var.ecs_service_deployment_maximum_percent}" deployment_minimum_healthy_percent = "${var.ecs_service_deployment_minimum_healthy_percent}" network_configuration { subnets = ["${values(local.private_subnets)}"] security_groups = ["${module.app_sg.this_security_group_id}"] } load_balancer { target_group_arn = "${aws_lb_target_group.main.id}" container_name = "app" container_port = "${var.app_port}" } depends_on = [ "aws_lb_listener.main", ] }我觉得我已经接近完成了，但后来我记起了我只完成了最初的“入门”文档中所需的 3 个步骤中的 2 个，我仍然需要定义 ECS 群集。集群感谢 定义模块，定义要所有这些运行的集群实际上非常简单。module "ecs" { source = "terraform-aws-modules/ecs/aws" version = "v1.1.0" name = "${var.name}" }这里让我感到惊讶的是为什么我必须定义一个集群。作为一个相当熟悉 ECS 的人，你会觉得你需要一个集群，但我试图从一个必须经历这个过程的新人的角度来考虑这一点 —— 对我来说，Fargate 标榜自己“ Serverless”而你仍需要定义集群，这似乎很令人惊讶。当然这是一个小细节，但它确实盘旋在我的脑海里。告诉我你的 Secret在这个阶段，我很高兴我成功地运行了一些东西。然而，我的原始的成功标准缺少一些东西。如果我们回到任务定义那里，你会记得我的应用程序有一个存放密码的环境变量：container_environment_variables = [ { name = "USER" value = "${var.user}" }, { name = "PASSWORD" value = "${var.password}" } ]如果我在 AWS 控制台中查看我的任务定义，我的密码就在那里，明晃晃的明文。我希望不要这样，所以我开始尝试将其转化为其他东西，类似于 Kubernetes 的Secrets管理。AWS SSMFargate / ECS 执行 secret 管理 secret management 部分的方式是使用 AWS SSM（此服务的全名是 AWS 系统管理器参数存储库 Systems Manager Parameter Store，但我不想使用这个名称，因为坦率地说这个名字太愚蠢了）。AWS 文档很好的涵盖了这个内容，因此我开始将其转换为 terraform。指定秘密信息首先，你必须定义一个参数并为其命名。在 terraform 中，它看起来像这样：resource "aws_ssm_parameter" "app_password" { name = "${var.app_password_param_name}" # The name of the value in AWS SSM type = "SecureString" value = "${var.app_password}" # The actual value of the password, like correct-horse-battery-stable }显然，这里的关键部分是 “SecureString” 类型。这会使用默认的 AWS KMS 密钥来加密数据，这对我来说并不是很直观。这比 Kubernetes 的 Secret 管理具有巨大优势，默认情况下，这些 Secret 在 etcd 中是不加密的。然后我为 ECS 指定了另一个本地值映射，并将其作为 Secret 参数传递：container_secrets = [ { name = "PASSWORD" valueFrom = "${var.app_password_param_name}" }, ] module "container_definition_app" { source = "cloudposse/ecs-container-definition/aws" version = "v0.7.0" container_name = "${var.name}" container_image = "${var.image}" container_cpu = "${var.ecs_task_cpu}" container_memory = "${var.ecs_task_memory}" container_memory_reservation = "${var.container_memory_reservation}" port_mappings = [ { containerPort = "${var.app_port}" hostPort = "${var.app_port}" protocol = "tcp" }, ] environment = "${local.container_environment_variables}" secrets = "${local.container_secrets}"出了个问题此刻，我重新部署了我的任务定义，并且非常困惑。为什么任务没有正确拉起？当新的任务定义（版本 8）可用时，我一直在控制台中看到正在运行的应用程序仍在使用先前的任务定义（版本 7）。解决这件事花费的时间比我预期的要长，但是在控制台的事件屏幕上，我注意到了 IAM 错误。我错过了一个步骤，容器无法从 AWS SSM 中读取 Secret 信息，因为它没有正确的 IAM 权限。这是我第一次真正对整个这件事情感到沮丧。从用户体验的角度来看，这里的反馈非常糟糕。如果我没有发觉的话，我会认为一切都很好，因为仍然有一个任务正在运行，我的应用程序仍然可以通过正确的 URL 访问 —— 只不过是旧的配置而已。在 Kubernetes 里，我会清楚地看到 pod 定义中的错误。Fargate 可以确保我的应用不会停止，这绝对是太棒了，但作为一名运维，我需要一些关于发生了什么的实际反馈。这真的不够好。我真的希望 Fargate 团队的人能够读到这篇文章，改善这种体验。就这样了到这里就结束了，我的应用程序正在运行，也符合我的所有标准。我确实意识到我做了一些改进，其中包括：定义一个 cloudwatch 日志组，这样我就可以正确地写日志了添加了一个 route53 托管区域，使整个事情从 DNS 角度更容易自动化修复并重新调整了 IAM 权限，这里太宽泛了但老实说，现在我想反思一下这段经历。我写了一个关于我的经历的 推特会话，然后花了其余时间思考我在这里的真实感受。代价经过一夜的反思，我意识到无论你是使用 Fargate 还是 Kubernetes，这个过程都大致相同。最让我感到惊讶的是，尽管我经常听说 Fargate “更容易”，但我真的没有看到任何超过 Kubernetes 平台的好处。现在，如果你正在构建 Kubernetes 集群，我绝对可以看到这里的价值 —— 管理节点和控制面板只是不必要的开销，问题是 —— 基于 Kubernetes 的平台的大多数消费者都没有这样做。如果你很幸运能够使用 GKE，你几乎不需要考虑集群的管理，你可以使用单个 gcloud 命令来运行集群。我经常使用 Digital Ocean 的 Kubernetes 托管服务，我可以肯定地说它就像操作 Fargate 集群一样简单，实际上在某种程度上它更容易。必须定义一些基础设施来运行你的容器就是此时的代价。谷歌本周可能刚刚使用他们的 Google Cloud Run 产品改变了游戏规则，但他们在这一领域的领先优势远远领先于其他所有人。从这整个经历中，我可以肯定的说：大规模运行容器仍然很难。它需要思考，需要领域知识，需要运维和开发人员之间的协作。它还需要一个基础来构建 —— 任何基于 AWS 的操作都需要事先定义和运行一些基础架构。我对一些公司似乎渴望的 “NoOps” 概念非常感兴趣。我想如果你正在运行一个无状态应用程序，你可以把它全部放在一个 lambda 函数和一个 API 网关中，这可能不错，但我们是否真的适合在任何一种企业环境中这样做？我真的不这么认为。公平比较令我印象深刻的另一个现实是，技术 A 和技术 B 之间的比较通常不太公平，我经常在 AWS 上看到这一点。这种实际情况往往与 Jeff Barr 博客文章截然不同。如果你是一家足够小的公司，你可以使用 AWS 控制台在 AWS 中部署你的应用程序并接受所有默认值，这绝对更容易。但是，我不想使用默认值，因为默认值几乎是不适用于生产环境的。一旦你开始剥离掉云服务商服务的层面，你就会开始意识到最终你仍然是在运行软件 —— 它仍然需要设计良好、部署良好、运行良好。我相信 AWS 和 Kubernetes 以及所有其他云服务商的增值服务使得它更容易运行、设计和操作，但它绝对不是免费的。Kubernetes 的争议最后就是：如果你将 Kubernetes 纯粹视为一个容器编排工具，你可能会喜欢 Fargate。然而，随着我对 Kubernetes 越来越熟悉，我开始意识到它作为一种技术的重要性 —— 不仅因为它是一个伟大的容器编排工具，而且因为它的设计模式 —— 它是声明性的、API 驱动的平台。 在整个 Fargate 过程期间发生的一个简单的事情是，如果我删除这里某个东西，Fargate 不一定会为我重新创建它。自动缩放很不错，不需要管理服务器和操作系统的补丁及更新也很棒，但我觉得因为无法使用 Kubernetes 自我修复和 API 驱动模型而失去了很多。当然，Kubernetes 有一个学习曲线，但从这里的体验来看，Fargate 也是如此。总结尽管我在这个过程中遭遇了困惑，但我确实很喜欢这种体验。我仍然相信 Fargate 是一项出色的技术，AWS 团队对 ECS/Fargate 所做的工作确实非常出色。然而，我的观点是，这绝对不比 Kubernetes “更容易”，只是……难点不同。在生产环境中运行容器时出现的问题大致相同。如果你从这篇文章中有所收获，它应该是这样的：不管你选择的哪种方式都有运维开销。不要相信你选择一些东西你的世界就变得更轻松。我个人的意见是：如果你有一个运维团队，而你的公司要为多个应用程序团队部署容器 —— 选择一种技术并围绕它构建流程和工具以使其更容易。人们说的一点肯定没错，用点技巧可以更容易地使用某种技术。在这个阶段，谈到 Fargate，下面的漫画这总结了我的感受：via: https://leebriggs.co.uk/blog/2019/04/13/the-fargate-illusion.html作者：Lee Briggs 选题：lujun9972 译者：Bestony 校对：wxy, 临石（阿里云智能技术专家）本文由 LCTT 原创编译，Linux中国 荣誉推出
以及，对于 无服务器 Serverless 架构，什么时候该用，什么时候不该用呢？如果将如今互联网体验中最方便实用的那一部分去掉，那么留下来的基本就是 客户端-服务端 client-server 模式了。这一个模式在互联网建立初期就已经在使用了，直到目前都没有太大的变化，也就是说，这个模式仍然在为我们服务。那么，当人们谈论 无服务器 Serverless 架构的时候，到底是指什么呢？其实，无服务器架构并不是说不使用服务器了。恰恰相反，客户端-服务端模式仍然在其中发挥着重要的作用。无服务器架构实际上指的是能够让开发者在不需要关心服务器上架、为操作系统打补丁、创建容器镜像这些工作的情况下，就能够完成编码、部署和创建应用这一整套流程的架构。无服务器架构的三个重要意义一些缺乏开发经验的人员现在要参与到开发工作中来了。无服务器架构能够让他们尽量只学习必要的工作内容，把更多的时间放在更具创造性的开发工作中。开发者不再需要重复造轮子。运行和维护服务器、为操作系统打补丁、创建容器等这一系列工作，都可以由更专业的无服务器架构提供商来完成。最现实的一点是，如果不使用无服务器架构，那么在服务器管理方面，总需要有一个作最终决策的人。当服务器发生崩溃时，或是需要在服务器上执行某些操作时，总是需要这样一个统领全局的人来作出决策。因此最佳的方案是使用无服务器架构。什么时候该用或者不该用无服务器架构？听起来无服务器架构是个好东西。但事实上，无服务器架构并不是万能的，在使用之前还需要考虑以下这些因素：成本使用范围时间控制方式其中值得注意的是控制方式。现在已经有一些项目为开发者提供了操作和控制无服务器架构计算环境的工具了，Apache OpenWhisk 就是其中之一。为什么要将无服务器架构开源？关于这方面的更多内容，可以观看无服务器架构方面的专家 Saron Yitbarek 在 Command Line Heroes 节目中的访谈。via: https://opensource.com/article/18/12/serverless-podcast-command-line-heros作者：Jen Wike Huger 选题：lujun9972 译者：HankChow 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
本文将介绍如何借助 minikube 在 Kubernetes 1.8 上搭建 OpenFaaS（让 Serverless Function 变得更简单）。minikube 是一个 Kubernetes 分发版，借助它，你可以在笔记本电脑上运行 Kubernetes 集群，minikube 支持 Mac 和 Linux 操作系统，但是在 MacOS 上使用得更多一些。本文基于我们最新的部署手册 Kubernetes 官方部署指南安装部署 Minikube1、 安装 xhyve driver 或 VirtualBox ，然后在上面安装 Linux 虚拟机以部署 minikube 。根据我的经验，VirtualBox 更稳定一些。2、 参照官方文档 安装 minikube 。3、 使用 brew 或 curl -sL cli.openfaas.com | sudo sh 安装 faas-cli。4、 通过 brew install kubernetes-helm 安装 helm 命令行。5、 运行 minikube ：minikube start。Docker 船长小贴士：Mac 和 Windows 版本的 Docker 已经集成了对 Kubernetes 的支持。现在我们使用 Kubernetes 的时候，已经不需要再安装额外的软件了。在 minikube 上面部署 OpenFaaS1、 为 Helm 的服务器组件 tiller 新建服务账号：kubectl -n kube-system create sa tiller \ && kubectl create clusterrolebinding tiller \ --clusterrole cluster-admin \ --serviceaccount=kube-system:tiller 2、 安装 Helm 的服务端组件 tiller：helm init --skip-refresh --upgrade --service-account tiller 3、 克隆 Kubernetes 的 OpenFaaS 驱动程序 faas-netes：git clone https://github.com/openfaas/faas-netes && cd faas-netes 4、 Minikube 没有配置 RBAC，这里我们需要把 RBAC 关闭：helm upgrade --install --debug --reset-values --set async=false --set rbac=false openfaas openfaas/ （LCTT 译注：RBAC（Role-Based access control）基于角色的访问权限控制，在计算机权限管理中较为常用，详情请参考以下链接：https://en.wikipedia.org/wiki/Role-based_access_control ）现在，你可以看到 OpenFaaS pod 已经在你的 minikube 集群上运行起来了。输入 kubectl get pods 以查看 OpenFaaS pod：NAME READY STATUS RESTARTS AGE alertmanager-6dbdcddfc4-fjmrf 1/1 Running 0 1m faas-netesd-7b5b7d9d4-h9ftx 1/1 Running 0 1m gateway-965d6676d-7xcv9 1/1 Running 0 1m prometheus-64f9844488-t2mvn 1/1 Running 0 1m 30,000ft：该 API 网关包含了一个 用于测试功能的最小化 UI，同时开放了用于功能管理的 RESTful API 。 faas-netesd 守护进程是一种 Kubernetes 控制器，用来连接 Kubernetes API 服务器来管理服务、部署和密码。Prometheus 和 AlertManager 进程协同工作，实现 OpenFaaS Function 的弹性缩放，以满足业务需求。通过 Prometheus 指标我们可以查看系统的整体运行状态，还可以用来开发功能强悍的仪表盘。Prometheus 仪表盘示例：构建/迁移/运行和很多其他的 FaaS 项目不同，OpenFaaS 使用 Docker 镜像格式来进行 Function 的创建和版本控制，这意味着可以在生产环境中使用 OpenFaaS 实现以下目标：漏洞扫描（LCTT 译注：此处我觉得应该理解为更快地实现漏洞补丁）持续集成/持续开发滚动更新你也可以在现有的生产环境集群中利用空闲资源部署 OpenFaaS。其核心服务组件内存占用大概在 10-30MB 。OpenFaaS 一个关键的优势在于，它可以使用容器编排平台的 API ，这样可以和 Kubernetes 以及 Docker Swarm 进行本地集成。同时，由于使用 Docker 存储库 registry 进行 Function 的版本控制，所以可以按需扩展 Function，而没有按需构建 Function 的框架的额外的延时。新建 Functionfaas-cli new --lang python hello 以上命令创建文件 hello.yml 以及文件夹 handler，文件夹有两个文件 handler.py、requirements.txt 可用于你可能需要的 pip 模块。你可以随时编辑这些文件和文件夹，不需要担心如何维护 Dockerfile —— 我们为你通过以下方式维护：分级创建非 root 用户以官方的 Docker Alpine Linux 版本为基础进行镜像构建 (可替换)构建你的 Function先在本地创建 Function，然后推送到 Docker 存储库。 我们这里使用 Docker Hub，打开文件 hello.yml 然后输入你的账号名：provider: name: faas gateway: http://localhost:8080 functions: hello: lang: python handler: ./hello image: alexellis2/hello 现在，发起构建。你的本地系统上需要安装 Docker 。faas-cli build -f hello.yml 把封装好 Function 的 Docker 镜像版本推送到 Docker Hub。如果还没有登录 Docker hub ，继续前需要先输入命令 docker login 。faas-cli push -f hello.yml 当系统中有多个 Function 的时候，可以使用 --parallel=N 来调用多核并行处理构建或推送任务。该命令也支持这些选项： --no-cache、--squash 。部署及测试 Function现在，可以部署、列出、调用 Function 了。每次调用 Function 时，可以通过 Prometheus 收集指标值。$ export gw=http://$(minikube ip):31112 $ faas-cli deploy -f hello.yml --gateway $gw Deploying: hello. No existing function to remove Deployed. URL: http://192.168.99.100:31112/function/hello 上面给到的是部署时调用 Function 的标准方法，你也可以使用下面的命令：$ echo test | faas-cli invoke hello --gateway $gw 现在可以通过以下命令列出部署好的 Function，你将看到调用计数器数值增加。$ faas-cli list --gateway $gw Function Invocations Replicas hello 1 1 提示：这条命令也可以加上 --verbose 选项获得更详细的信息。由于我们是在远端集群（Linux 虚拟机）上面运行 OpenFaaS，命令里面加上一条 --gateway 用来覆盖环境变量。 这个选项同样适用于云平台上的远程主机。除了加上这条选项以外，还可以通过编辑 .yml 文件里面的 gateway 值来达到同样的效果。迁移到 minikube 以外的环境一旦你在熟悉了在 minikube 上运行 OpenFaaS ，就可以在任意 Linux 主机上搭建 Kubernetes 集群来部署 OpenFaaS 了。继续学习我们的 Github 上面有很多手册和博文，可以带你轻松“上车”，把我们的页面保存成书签吧：openfaas/faas 。2017 哥本哈根 Dockercon Moby 峰会上，我做了关于 Serverless 和 OpenFaaS 的概述演讲，这里我把视频放上来，视频不长，大概 15 分钟左右。最后，别忘了关注 OpenFaaS on Twitter 这里有最潮的新闻、最酷的技术和 Demo 展示。via: https://medium.com/@alexellisuk/getting-started-with-openfaas-on-minikube-634502c7acdf作者：Alex Ellis 译者：mandeler 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
Up：在几秒钟内部署无服务器应用程序
去年，我为 Up 规划了一份蓝图，其中描述了如何以最小的成本在 AWS 上为大多数构建块创建一个很棒的无服务器环境。这篇文章则是讨论了 Up 的初始 alpha 版本。为什么关注 无服务器 serverless ？对于初学者来说，它可以节省成本，因为你可以按需付费，且只为你使用的付费。无服务器方式是自愈的，因为每个请求被隔离并被视作“无状态的”。最后，它可以无限轻松地扩展 —— 没有机器或集群要管理。部署你的代码就行了。大约一个月前，我决定开始在 apex/up 上开发它，并为动态 SVG 版本的 GitHub 用户投票功能写了第一个小型无服务器示例程序 tj/gh-polls。它运行良好，成本低于每月 1 美元即可为数百万次投票服务，因此我会继续这个项目，看看我是否可以提供开源版本及商业的变体版本。其长期的目标是提供“你自己的 Heroku” 的版本，支持许多平台。虽然平台即服务（PaaS）并不新鲜，但无服务器生态系统正在使这种方案日益萎缩。据说，AWS 和其他的供应商经常由于他们提供的灵活性而被人诟病用户体验。Up 将复杂性抽象出来，同时为你提供一个几乎无需运维的解决方案。安装你可以使用以下命令安装 Up，查看这篇临时文档开始使用。或者如果你使用安装脚本，请下载二进制版本。（请记住，这个项目还在早期。）curl -sfL https://raw.githubusercontent.com/apex/up/master/install.sh | sh 只需运行以下命令随时升级到最新版本：up upgrade 你也可以通过 NPM 进行安装：npm install -g up 功能这个早期 alpha 版本提供什么功能？让我们来看看！请记住，Up 不是托管服务，因此你需要一个 AWS 帐户和 AWS 凭证。如果你对 AWS 不熟悉，你可能需要先停下来，直到熟悉流程。我遇到的第一个问题是：up(1) 与 apex(1) 有何不同？Apex 专注于部署功能，用于管道和事件处理，而 Up 则侧重于应用程序、API 和静态站点，也就是单个可部署单元。Apex 不为你提供 API 网关、SSL 证书或 DNS，也不提供 URL 重写，脚本注入等。单命令无服务器应用程序Up 可以让你使用单条命令部署应用程序、API 和静态站点。要创建一个应用程序，你只需要一个文件，在 Node.js 的情况下，./app.js 监听由 Up 提供的 PORT'。请注意，如果你使用的是package.json，则会检测并使用start和build` 脚本。const http = require('http') const { PORT = 3000 } = process.env http.createServer((req, res) => { res.end('Hello World\n') }).listen(PORT) 额外的运行时环境也支持开箱可用，例如用于 Golang 的 “main.go”，所以你可以在几秒钟内部署 Golang、Python、Crystal 或 Node.js 应用程序。package main import ( "fmt" "log" "net/http" "os" ) func main() { addr := ":" + os.Getenv("PORT") http.HandleFunc("/", hello) log.Fatal(http.ListenAndServe(addr, nil)) } func hello(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello World from Go") } 要部署应用程序输入 up 来创建所需的资源并部署应用程序本身。这里没有模糊不清的地方，一旦它说“完成”了那就完成了，该应用程序立即可用 —— 没有远程构建过程。后续的部署将会更快，因为栈已被配置：使用 up url --open 测试你的程序，以在浏览器中浏览它，up url --copy 可以将 URL 保存到剪贴板，或者可以尝试使用 curl：curl `up url` Hello World 要删除应用程序及其资源，只需输入 up stack delete：例如，使用 up staging 或 up production 和 up url --open production 部署到预发布或生产环境。请注意，自定义域名尚不可用，它们将很快可用。之后，你还可以将版本“推广”到其他环境。反向代理Up 的一个独特的功能是，它不仅仅是简单地部署代码，它将一个 Golang 反向代理放在应用程序的前面。这提供了许多功能，如 URL 重写、重定向、脚本注入等等，我们将在后面进一步介绍。基础设施即代码在配置方面，Up 遵循现代最佳实践，因此对基础设施的更改都可以在部署之前预览，并且 IAM 策略的使用还可以限制开发人员访问以防止事故发生。一个附带的好处是它有助于自动记录你的基础设施。以下是使用 Let's Encrypt 通过 AWS ACM 配置一些（虚拟）DNS 记录和免费 SSL 证书的示例。{ "name": "app", "dns": { "myapp.com": [ { "name": "myapp.com", "type": "A", "ttl": 300, "value": ["35.161.83.243"] }, { "name": "blog.myapp.com", "type": "CNAME", "ttl": 300, "value": ["34.209.172.67"] }, { "name": "api.myapp.com", "type": "A", "ttl": 300, "value": ["54.187.185.18"] } ] }, "certs": [ { "domains": ["myapp.com", "*.myapp.com"] } ] } 当你首次通过 up 部署应用程序时，需要所有的权限，它为你创建 API 网关、Lambda 函数、ACM 证书、Route53 DNS 记录等。ChangeSets 尚未实现，但你能使用 up stack plan 预览进一步的更改，并使用 up stack apply 提交，这与 Terraform 非常相似。详细信息请参阅配置文档。全球部署regions 数组可以指定应用程序的目标区域。例如，如果你只对单个地区感兴趣，请使用：{ "regions": ["us-west-2"] } 如果你的客户集中在北美，你可能需要使用美国和加拿大所有地区：{ "regions": ["us-*", "ca-*"] } 最后，你可以使用 AWS 目前支持的所有 14 个地区：{ "regions": ["*"] } 多区域支持仍然是一个正在进行的工作，因为需要一些新的 AWS 功能来将它们结合在一起。静态文件服务Up 默认支持静态文件服务，并带有 HTTP 缓存支持，因此你可以在应用程序前使用 CloudFront 或任何其他 CDN 来大大减少延迟。当 type 为 static 时，默认情况下的工作目录是 .，但是你也可以提供一个 static.dir：{ "name": "app", "type": "static", "static": { "dir": "public" } } 构建钩子构建钩子允许你在部署或执行其他操作时定义自定义操作。一个常见的例子是使用 Webpack 或 Browserify 捆绑 Node.js 应用程序，这大大减少了文件大小，因为 node 模块是很大的。{ "name": "app", "hooks": { "build": "browserify --node server.js > app.js", "clean": "rm app.js" } } 脚本和样式表插入Up 允许你插入脚本和样式，无论是内联方式或声明路径。它甚至支持一些“罐头”脚本，用于 Google Analytics（分析）和 Segment，只需复制并粘贴你的写入密钥即可。{ "name": "site", "type": "static", "inject": { "head": [ { "type": "segment", "value": "API_KEY" }, { "type": "inline style", "file": "/css/primer.css" } ], "body": [ { "type": "script", "value": "/app.js" } ] } } 重写和重定向Up 通过 redirects 对象支持重定向和 URL 重写，该对象将路径模式映射到新位置。如果省略 status 参数（或值为 200），那么它是重写，否则是重定向。{ "name": "app", "type": "static", "redirects": { "/blog": { "location": "https://blog.apex.sh/", "status": 301 }, "/docs/:section/guides/:guide": { "location": "/help/:section/:guide", "status": 302 }, "/store/*": { "location": "/shop/:splat" } } } 用于重写的常见情况是 SPA（单页面应用程序），你希望不管路径如何都提供 index.html，当然除非文件存在。{ "name": "app", "type": "static", "redirects": { "/*": { "location": "/", "status": 200 } } } 如果要强制实施该规则，无论文件是否存在，只需添加 "force": true 。环境变量密码将在下一个版本中有，但是现在支持纯文本环境变量：{ "name": "api", "environment": { "API_FEATURE_FOO": "1", "API_FEATURE_BAR": "0" } } CORS 支持CORS 支持允许你指定哪些（如果有的话）域可以从浏览器访问你的 API。如果你希望允许任何网站访问你的 API，只需启用它：{ "cors": { "enable": true } } 你还可以自定义访问，例如仅将 API 访问限制为你的前端或 SPA。{ "cors": { "allowed_origins": ["https://myapp.com"], "allowed_methods": ["HEAD", "GET", "POST", "PUT", "DELETE"], "allowed_headers": ["Content-Type", "Authorization"] } } 日志对于 $0.5/GB 的低价格，你可以使用 CloudWatch 日志进行结构化日志查询和跟踪。Up 实现了一种用于改进 CloudWatch 提供的自定义查询语言，专门用于查询结构化 JSON 日志。你可以查询现有日志：up logs 跟踪在线日志：up logs -f 或者对其中任一个进行过滤，例如只显示耗时超过 5 毫秒的 200 个 GET/HEAD 请求：up logs 'method in ("GET", "HEAD") status = 200 duration >= 5' 查询语言是非常灵活的，这里有更多来自于 up help logs 的例子### 显示过去 5 分钟的日志 $ up logs ### 显示过去 30 分钟的日志 $ up logs -s 30m ### 显示过去 5 小时的日志 $ up logs -s 5h ### 实时显示日志 $ up logs -f ### 显示错误日志 $ up logs error ### 显示错误和致命错误日志 $ up logs 'error or fatal' ### 显示非 info 日志 $ up logs 'not info' ### 显示特定消息的日志 $ up logs 'message = "user login"' ### 显示超时 150ms 的 200 响应 $ up logs 'status = 200 duration > 150' ### 显示 4xx 和 5xx 响应 $ up logs 'status >= 400' ### 显示用户邮件包含 @apex.sh 的日志 $ up logs 'user.email contains "@apex.sh"' ### 显示用户邮件以 @apex.sh 结尾的日志 $ up logs 'user.email = "*@apex.sh"' ### 显示用户邮件以 tj@ 开始的日志 $ up logs 'user.email = "tj@*"' ### 显示路径 /tobi 和 /loki 下的错误日志 $ up logs 'error and (path = "/tobi" or path = "/loki")' ### 和上面一样，用 in 显示 $ up logs 'error and path in ("/tobi", "/loki")' ### 更复杂的查询方式 $ up logs 'method in ("POST", "PUT") ip = "207.*" status = 200 duration >= 50' ### 将 JSON 格式的错误日志发送给 jq 工具 $ up logs error | jq 请注意，and 关键字是暗含的，虽然你也可以使用它。冷启动时间这是 AWS Lambda 平台的特性，但冷启动时间通常远远低于 1 秒，在未来，我计划提供一个选项来保持它们在线。配置验证up config 命令输出解析后的配置，有默认值和推断的运行时设置 - 它也起到验证配置的双重目的，因为任何错误都会导致退出状态 > 0。崩溃恢复使用 Up 作为反向代理的另一个好处是执行崩溃恢复 —— 在崩溃后重新启动服务器，并在将错误的响应发送给客户端之前重新尝试该请求。例如，假设你的 Node.js 程序由于间歇性数据库问题而导致未捕获的异常崩溃，Up 可以在响应客户端之前重试该请求。之后这个行为会更加可定制。适合持续集成很难说这是一个功能，但是感谢 Golang 相对较小和独立的二进制文件，你可以在一两秒中在 CI 中安装 Up。HTTP/2Up 通过 API 网关支持 HTTP/2，对于服务很多资源的应用和站点可以减少延迟。我将来会对许多平台进行更全面的测试，但是 Up 的延迟已经很好了：错误页面Up 提供了一个默认错误页面，如果你要提供支持电子邮件或调整颜色，你可以使用 error_pages 自定义。{ "name": "site", "type": "static", "error_pages": { "variables": { "support_email": "support@apex.sh", "color": "#228ae6" } } } 默认情况下，它看上去像这样：如果你想提供自定义模板，你可以创建以下一个或多个文件。特定文件优先。error.html – 匹配任何 4xx 或 5xx5xx.html – 匹配任何 5xx 错误4xx.html – 匹配任何 4xx 错误CODE.html – 匹配一个特定的代码，如 404.html查看文档阅读更多有关模板的信息。伸缩和成本你已经做了这么多，但是 Up 怎么伸缩？目前，API 网关和 AWS 是目标平台，因此你无需进行任何更改即可扩展，只需部署代码即可完成。你只需按需支付实际使用的数量并且无需人工干预。AWS 每月免费提供 1,000,000 个请求，但你可以使用 http://serverlesscalc.com 来插入预期流量。在未来 Up 将提供更多的平台，所以如果一个成本过高，你可以迁移到另一个！未来目前为止就这样了！它可能看起来不是很多，但它已经超过 10,000 行代码，并且我刚刚开始开发。看看这个问题队列，假设项目可持续发展，看看未来会有什么期待。如果你发现这个免费版本有用，请考虑在 OpenCollective 上捐赠我，因为我没有任何工作。我将在短期内开发早期专业版，对早期用户有年费优惠。专业或企业版也将提供源码，因此可以进行内部修复和自定义。via: https://medium.freecodecamp.org/up-b3db1ca930ee作者：TJ Holowaychuk 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
互联网世界新概念层出不穷，往往今天流行的概念和技术，明天就被取代和推翻。比如说，以前大家都说什么 服务器 Server 、 SQL 数据库 SQL Database 和 前端 Frontend ，而现在已经开始流行 ServerLess、No-SQL 了。当然，ServerLess 不是说不要服务器了，而是指一些运行在无状态的容器的服务器端逻辑，比如 AWS 的 Lambda 的 FaaS。而 No-SQL 则是一种非关系型数据库。而这位所谓的专家，什么都 “No” 和 “Less” 了，然后，就在办公室里面从早坐到晚，正在践行了“Codeless”（没代码）的日子。via: http://turnoff.us/geek/codeless/作者：Daniel Stori 译者：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
无服务 serverless 是 托管服务 managed service 发展方向的又一步，并且与 Ansible 的无代理体系结构相得益彰。Ansible 被设计为实际工作中的最简化的部署工具。这意味着它不是一个完整的编程语言。你需要编写定义任务的 YAML 模板，并列出任何需要自动完成的任务。大多数人认为 Ansible 是一种更强大的“处于 for 循环中的 SSH”，在简单的使用场景下这是真的。但其实 Ansible 是任务，而非 SSH。在很多情况下，我们通过 SSH 进行连接，但它也支持 Windows 机器上的 Windows 远程管理（WinRM），以及作为云服务的通用语言的 HTTPS API 之类的东西。在云中，Ansible 可以在两个独立的层面上操作： 控制面 control plane 和 实例资源 on-instance resource 。控制面由所有没有运行在操作系统上的东西组成。包括设置网络、新建实例、供给更高级别的服务，如亚马逊的 S3 或 DynamoDB，以及保持云基础设施安全和服务客户​​所需的一切。实例上的工作是你已经知道 Ansible 可以做的：启动和停止服务、配置文件 模版化 templating 、安装软件包以及通过 SSH 执行的所有与操作系统相关的操作。现在，什么是 无服务 serverless 呢？这要看你问谁，无服务要么是对公有云的无限延伸，或者是一个全新的范例，其中所有的东西都是 API 调用，以前从来没有这样做过。Ansible 采取第一种观点。在 “无服务” 是专门术语之前，用户不得不管理和配置 EC2 实例、虚拟私有云 （VPC） 网络以及其他所有内容。无服务是托管服务方向迈出的另一步，并且与 Ansible 的无代理体系结构相得益彰。在我们开始 Lambda 示例之前，让我们来看一个简单的配置 CloudFormation 栈任务：- name: Build network cloudformation: stack_name: prod-vpc state: present template: base_vpc.yml编写这样的任务只需要几分钟，但它是构建基础架构所涉及的最后的半手动步骤 - 点击 “Create Stack” - 这将 playbook 与其他放在一起。现在你的 VPC 只是在建立新区域时可以调用的另一项任务了。由于云提供商是你帐户中发生些什么的真相来源，因此 Ansible 有许多方法来取回并使用 ID、名称和其他参数来过滤和查询运行的实例或网络。以 cloudformation_facts 模块为例，我们可以从我们刚刚创建的模板中得到子网 ID、网络范围和其他数据。- name: Pull all new resources back in as a variable cloudformation_facts: stack_name: prod-vpc register: network_stack对于无服务应用，除了 DynamoDB 表，S3 bucket 和其他任何其他功能之外，你肯定还需要一个 Lambda 函数的补充。幸运的是，通过使用 lambda 模块， Lambda 函数可以以上次任务的堆栈相同的方式创建：- lambda: name: sendReportMail zip_file: "{{ deployment_package }}" runtime: python3.6 handler: report.send memory_size: 1024 role: "{{ iam_exec_role }}" register: new_function如果你有其他想用来交付无服务应用的工具，这也是可以的。开源的无服务框架有自己的 Ansible 模块，它也可以工作：- serverless: service_path: '{{ project_dir }}' stage: dev register: sls - name: Serverless uses CloudFormation under the hood, so you can easily pull info back into Ansible cloudformation_facts: stack_name: "{{ sls.service_name }}" register: sls_facts这不是你需要的全部，因为无服务项目也必须存在，你将在那里大量的定义你的函数和事件源。对于此例，我们将制作一个响应 HTTP 请求的函数。无服务框架使用 YAML 作为其配置语言（和 Ansible 一样），所以这应该看起来很熟悉。# serverless.yml service: fakeservice provider: name: aws runtime: python3.6 functions: main: handler: test_function.handler events: - http: path: / method: get在 AnsibleFest 中，我将介绍这个例子和其他深入的部署策略，以最大限度地利用你已经拥有的 playbook 和基础设施，还有新的无服务实践。无论你是否能到，我希望这些例子可以让你开始使用 Ansible，无论你是否有任何服务要管理。AnsibleFest 是一个单日会议，汇集了数百名 Ansible 用户、开发人员和行业合作伙伴。加入我们吧，这里有产品更新、鼓舞人心的交谈、技术深度潜水，动手演示和整天的网络。（题图： opensource.com）via: https://opensource.com/article/17/8/ansible-serverless-applications作者：Ryan Scott Brown 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
今年像动态插件，Serverless Go 以及 HTTP/2 这些创新对你的开发意味着什么？Go 1.8 刚刚发布，它有几个新功能，包括：HTTP/2 PushHTTP 服务器平滑关闭插件缺省 GOPATH这些新功能的影响力取决于你和开发团队如何使用 Go。 自从 Go 1.0 于 2012 年发布以来，其简单性、并发性和内置支持使其保持普及度不断增长，所以对“Go 擅长什么”的答案一直在增长。这里我会提供一些想法，包括新到来的版本及 Go 世界最近其它吸引我的地方。这不是一个详尽的列表，所以请让我知道你认为在 2017 年 Go 还会发生哪些重要的事。Go 的超级可部署性 + 插件 = 容器、任何东西？1.8 版本已经发布，我已经与其中几个人交谈过添加动态插件会如何影响像容器之类的事物，动态插件是为了加载在编译时不是程序一部分的共享库的代码。 动态插件使容器中的高并发微服务变得更加简单。 你可以轻松地以外部进程的方式加载插件，同时具备在容器中微服务的所有好处：保护你的主进程不会崩溃，并且没有任何东西会搞乱你的内存空间。 对插件的动态支持应该是在 Go 中使用容器的福音。关于专家现场 Go 培训，请注册 Go Beyond the Basics。跨平台支持仍在吸引开发人员在 Go 开源之后的 7 年里，它已被全球采用。Daniel Whitenack 是一名数据科学家和工程师，他为 Jupyter 维护 Go 内核，告诉我最近他在西伯利亚做数据科学和 Go 语言培训，（是的，在西伯利亚！数据科学和 Go - 之后再细讲一下...）并 “很惊讶地看到那里 Go 社区是如此活跃和积极。” 人们继续在项目中采取 Go 的另一个很大的原因是交叉编译，对此，几个 Go 专家解释说这在 Go 1.5 版本中变得更容易了。来自其他语言（如 Python）的开发人员应该发现，在没有 VM 的目标平台上，能够为多个操作系统构建捆绑的、可部署的应用程序是在 Go 中工作的关键。在 1.8 版本中对跨平台的支持，再加上提升了 15% 的编译速度，你就可以看到为什么 Go 是初创公司最喜欢的语言。有兴趣了解 Go 的基础知识吗？查看 Go 基础学习路径 让 O’Reilly 专家来带你开始。Go 解释器在开发中；再见 Read-Eval-Print-Loop有一些聪明的家伙正在做一个 Go 解释器，我一定会持续关注它。如你所知的那样，有几个 Read-Eval-Print-Loop（REPL）的解决方案可以用来评估表达式，以确保代码如你预期的工作，但那些方法通常意味着容忍一些不便，或需要费力从几个方案中找到一个适合你的用例的。有一个健壮、一致的解释器就太好了，一旦我了解到更多消息，我会告诉你们。在开发中使用 Go 复杂特性？观看 O'Reilly 的视频训练 中级 Go 。Go 的 serverless - 会是什么样子？是的，现在围绕 serverless 架构（功能即服务（FaaS））有很多炒作。但有时候也有些捉摸不定的地方，那么关于 Go 的 serverless 发生了什么？我们能在今年看到一个 Go 语言原生支持的 serverless 服务么？AWS Lambda 是最知名的 serverless 提供商，不过 Google 最近也推出了 Google Cloud Functions。这两个 FaaS 解决方案使你可以在无须管理服务器的情况下运行代码，你的代码存储在别人为你管理的服务器集群上，并且仅在触发事件调用它时运行。AWS Lambda 目前支持 JavaScript、Python 和 Java，还可以启动 Go、Ruby 和 bash 进程。 Google Cloud Functions 只支持 JavaScript，但很可能不久将支持 Java 和 Python。许多物联网设备已经使用 serverless 方案，随着 Go 越来越多地被创业公司采用，serverless 似乎是一个可能的增长点，所以我在关注这些 serverless 解决方案中 Go 的开发情况。已经有几个框架可以支持 AWS Lambdas：λ Gordon - 使用 CloudFormation 创建、连接及部署 AWS LambdasApex - 构建、部署及管理 AWS Lambda 函数Sparta - AWS Lambda 微服务的 Go 框架还有一个 AWS Lambda 替代品支持 Go：Iron.io：建立在 Docker 和 Go 之上；语言未知；支持 Golang、Python、Ruby、PHP 和 .NET有关 serverless 架构的更多信息，请观看 Mike Roberts 在旧金山 O'Reilly 软件架构会议上的演讲主题：serverless介绍。数据科学中的 Go我在本文开头暗示了这一点：也许令人惊讶的是很多人都在使用 Go 进行数据科学和机器学习。关于它是否适合还有一些争论，但基于像 《Gopher 学院之 2016 年终》那样的年度文章中，你会注意到 30 篇文章中至少有 4 篇是关于机器学习或分布式数据处理，它们正在像我们走来。我之前关于 Go 的易部署性的观点可能是数据科学家使用 Go 的一个关键原因：他们可以更轻松地在易读而可用于生产环境的应用程序中向他人展示数据模型。与此相结合的是 Go 的广泛使用（正如我前面提到的，它正变得越来越流行！），而且有数据专家创建“可用并且与其它程序配合”的程序。任何使用 Go 构建的应用数据科学家会在公司其他部分使用相同的语言，或者至少它非常适合现代架构。更多关于 Go 的数据科学，Daniel Whitenack 写了一个很好的概述，解释了如何使用它： Data Science Gophers。作者简介：O'Reilly Media 的监督编辑，与编辑团队合作，涵盖各种各样的编程主题。via: https://medium.com/@sconant/5-things-to-watch-in-go-programming-in-2017-39cd7a7e58e3#.8t4to5jr1作者：Susan Conant 译者：geekpi 校对：jasminepeng本文由 LCTT 原创编译，Linux中国 荣誉推出
通过 AWS 的 Lambda 和 API Gateway 走向 Serverless
近来，在计算领域出现了很多关于 serverless 的讨论。serverless 是一个概念，它允许你提供代码或可执行程序给某个服务，由服务来为你执行它们，而你无需自己管理服务器。这就是所谓的 执行即服务 （ execution-as-a-service ） ，它带来了很多机会，同时也遇到了它独有的挑战。简短回忆下计算领域的发展早期，出现了……好吧，这有点复杂。很早的时候，出现了机械计算机，后来又有了埃尼阿克 ENIAC（Electronic Numerical Integrator And Computer，很早的电子计算机)，但是都没有规模生产。直到大型机出现后，计算领域才快速发展。上世纪 50 年代 - 大型机上世纪 60 年代 - 微型机1994 - 机架服务器2001 - 刀片服务器本世纪初 - 虚拟服务器2006 - 服务器云化2013 - 容器化2014 - serverless（计算资源服务化）这些日期是大概的发布或者流行日期，无需和我争论时间的准确性。计算领域的演进趋势是执行的功能单元越来越小。每一次演进通常都意味着运维负担的减小和运维灵活性的增加。发展前景喔，Serverless！但是，serverless 能给我们带来什么好处? 我们将面临什么挑战呢?未执行代码时无需付费。我认为，这是个巨大的卖点。当无人访问你的站点或用你的 API 时，你无需付钱。没有持续支出的基础设施成本，仅仅支付你需要的部分。换句话说，这履行了云计算的承诺：“仅仅支付你真正用的资源”。无需维护服务器，也无需考虑服务器安全。服务器的维护和安全将由你的服务提供商来处理（当然，你也可以架设自己的 serverless 主机，只是这似乎是在向错误的方向前进）。由于你的执行时间也是受限的，安全补丁也被简化了，因为完全不需要重启。这些都应该由你的服务提供商无缝地处理。无限的可扩展性。这是又一个大的好处。假设你又开发了一个 Pokemon Go, 与其频繁地把站点下线维护升级，不如用 serverless 来不断地扩展。当然，这也是个双刃剑，大量的账单也会随之而来。如果你的业务的利润强依赖于站点上线率的话，serverless 确实能帮上忙。强制的微服务架构。这也有两面性，一方面，微服务似乎是一种好的构建灵活可扩展的、容错的架构的方式。另一方面，如果你的业务没有按照这种方式设计，你将很难在已有的架构中引入 serverless。但是现在你被限制在他们的平台上受限的环境。你只能用服务提供商提供的环境，你想在 Rust 中用 serverless？你可能不会太幸运。受限的预装包。你只有提供商预装的包。但是你或许能够提供你自己的包。受限的执行时间。你的 Function 只可以运行这么长时间。如果你必须处理 1TB 的文件，你可能需要有一个解决办法或者用其他方案。强制的微服务架构。参考上面的描述。受限的监视和诊断能力。例如，你的代码在干什么? 在 serverless 中，基本不可能在调试器中设置断点和跟踪流程。你仍然可以像往常一样记录日志并发出统计度量，但是这带来的帮助很有限，无法定位在 serverless 环境中发生的难点问题。竞争领域自从 2014 年出现 AWS Lambda 以后，serverless 的提供商已经增加了一些。下面是一些主流的服务提供商:AWS Lambda - 起步最早的OpenWhisk - 在 IBM 的 Bluemix 云上可用Google Cloud FunctionsAzure Functions这些平台都有它们的相对优势和劣势（例如，Azure 支持 C#，或者紧密集成在其他提供商的平台上）。这里面最大的玩家是 AWS。通过 AWS 的 Lambda 和 API Gateway 构建你的第一个 API我们来试一试 serverless。我们将用 AWS Lambda 和 API Gateway 来构建一个能返回 Jimmy 所说的“Guru Meditations”的 API。所有代码在 GitHub 上可以找到。API文档：POST / { "status": "success", "meditation": "did u mention banana cognac shower" } 怎样组织工程文件文件结构树:. ├── LICENSE ├── README.md ├── server │ ├── __init__.py │ ├── meditate.py │ └── swagger.json ├── setup.py ├── tests │ └── test_server │ └── test_meditate.py └── tools ├── deploy.py ├── serve.py ├── serve.sh ├── setup.sh └── zip.sh AWS 中的信息（想了解这里究竟在做什么的详细信息，可查看源码 tools/deploy.py）。API。实际构建的对象。它在 AWS 中表示为一个单独的对象。执行角色。在 AWS 中，每个 Function 作为一个单独的角色执行。在这里就是 meditations。角色策略。每个 Function 作为一个角色执行，每个角色需要权限来干活。我们的 Lambda Function 不干太多活，故我们只添加一些日志记录权限。Lambda Function。运行我们的代码的地方。Swagger。 Swagger 是 API 的规范。API Gateway 支持解析 swagger 的定义来为 API 配置大部分资源。部署。API Gateway 提供部署的概念。我们只需要为我们的 API 用一个就行（例如，所有的都用生产或者 yolo等)，但是得知道它们是存在的，并且对于真正的产品级服务，你可能想用开发和暂存环境。监控。在我们的业务崩溃的情况下（或者因为使用产生大量账单时），我们想以云告警查看方式为这些错误和费用添加一些监控。注意你应该修改 tools/deploy.py 来正确地设置你的 email。代码Lambda Function 将从一个硬编码列表中随机选择一个并返回 guru meditations，非常简单：import logging import random logger = logging.getLogger() logger.setLevel(logging.INFO) def handler(event, context): logger.info(u"received request with id '{}'".format(context.aws_request_id)) meditations = [ "off to a regex/", "the count of machines abides", "you wouldn't fax a bat", "HAZARDOUS CHEMICALS + RKELLY", "your solution requires a blood eagle", "testing is broken because I'm lazy", "did u mention banana cognac shower", ] meditation = random.choice(meditations) return { "status": "success", "meditation": meditation, } deploy.py 脚本这个脚本相当长，我没法贴在这里。它基本只是遍历上述“AWS 中的信息”下的项目，确保每项都存在。我们来部署这个脚本只需运行 ./tools/deploy.py。基本完成了。不过似乎在权限申请上有些问题，由于 API Gateway 没有权限去执行你的 Function，所以你的 Lambda Function 将不能执行，报错应该是“Execution failed due to configuration error: Invalid permissions on Lambda function”。我不知道怎么用 botocore 添加权限。你可以通过 AWS console 来解决这个问题，找到你的 API, 进到 /POST 端点，进到“integration request”，点击“Lambda Function”旁边的编辑图标，修改它，然后保存。此时将弹出一个窗口提示“You are about to give API Gateway permission to invoke your Lambda function”， 点击“OK”。当你完成后，记录下 ./tools/deploy.py 打印出的 URL，像下面这样调用它，然后查看你的新 API 的行为：$ curl -X POST https://a1b2c3d4.execute-api.us-east-1.amazonaws.com/prod/ {"status": "success", "meditation": "the count of machines abides"} 本地运行不幸的是，AWS Lambda 没有好的方法能在本地运行你的代码。在这个例子里，我们将用一个简单的 flask 服务器来在本地托管合适的端点，并调用 handler 函数。from __future__ import absolute_import from flask import Flask, jsonify from server.meditate import handler app = Flask(__name__) @app.route("/", methods=["POST"]) def index(): class FakeContext(object): aws_request_id = "XXX" return jsonify(**handler(None, FakeContext())) app.run(host="0.0.0.0") 你可以在仓库中用 ./tools/serve.sh 运行它，像这样调用：$ curl -X POST http://localhost:5000/ { "meditation": "your solution requires a blood eagle", "status": "success" } 测试你总是应该测试你的代码。我们的测试方法是导入并运行我们的 handler 函数。这是最基本的 python 测试方法：from __future__ import absolute_import import unittest from server.meditate import handler class SubmitTestCase(unittest.TestCase): def test_submit(self): class FakeContext(object): aws_request_id = "XXX" response = handler(None, FakeContext()) self.assertEquals(response["status"], "success") self.assertTrue("meditation" in response) 你可以在仓库里通过 nose2 运行这个测试代码。更多前景和 AWS 服务的无缝集成。通过 boto，你可以完美地轻易连接到任何其他的 AWS 服务。你可以轻易地让你的执行角色用 IAM 访问这些服务。你可以从 S3 取文件或放文件到 S3，连接到 Dynamo DB，调用其他 Lambda Function，等等。访问数据库。你也可以轻易地访问远程数据库。在你的 Lambda handler 模块的最上面连接数据库，并在handler 函数中执行查询。你很可能必须从它的安装位置上传相关的包内容才能使它正常工作。可能你也需要静态编译某些库。调用其他 webservices。API Gateway 也是一种把 webservices 的输出从一个格式转换成另一个格式的方法。你可以充分利用这个特点通过不同的 webservices 来代理调用，或者当业务变更时提供后向兼容能力。via: http://blog.ryankelly.us/2016/08/07/going-serverless-with-aws-lambda-and-api-gateway.html作者：Ryan Kelly 译者：messon007 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
当今世界会时不时地出现一波波科技浪潮，将以前的技术拍死在海滩上。针对 serverless 应用的概念我们已经谈了很多，它是指将你的应用程序按功能来部署，这些功能在被用到时才会启动。你不用费心去管理服务器和程序规模，因为它们会在需要的时候在一个集群中启动并运行。但是 serverless 并不意味着没有 Docker 什么事儿，事实上 Docker 就是 serverless 的。你可以使用 Docker 来容器化这些功能，然后在 Swarm 中按需求来运行它们。serverless 是一项构建分布式应用的技术，而 Docker 是它们完美的构建平台。从 servers 到 serverless那如何才能写一个 serverless 应用呢？来看一下我们的例子，5个服务组成的投票系统：投票系统由下面5个服务组成：两个 web 前端一个后台处理投票的进程一个计票的消息队列一个数据库后台处理投票的进程很容易转换成 serverless 构架，我们可以使用以下代码来实现：import dockerrun client = dockerrun.from_env() client.run("bfirsh/serverless-record-vote-task", [voter_id, vote], detach=True) 这个投票处理进程和消息队列可以用运行在 Swarm 上的 Docker 容器来代替，并实现按需自动部署。我们也可以用容器替换 web 前端，使用一个轻量级 HTTP 服务器来触发容器响应一个 HTTP 请求。Docker 容器代替长期运行的 HTTP 服务器来挑起响应请求的重担，这些容器可以自动扩容来支撑更大访问量。新的架构就像这样：红色框内是持续运行的服务，绿色框内是按需启动的容器。这个架构里需要你来管理的长期运行服务更少，并且可以自动扩容（最大容量由你的 Swarm 决定）。我们可以做点什么？你可以在你的应用中使用3种技术：在 Docker 容器中按需运行代码。使用 Swarm 来部署集群。通过使用 Docker API 套接字在容器中运行容器。结合这3种技术，你可以有很多方法搭建你的应用架构。用这种方法来部署后台环境真是非常有效，而在另一些场景，也可以这么玩，比如说：由于存在延时，使用容器实现面向用户的 HTTP 请求可能不是很合适，但你可以写一个负载均衡器，使用 Swarm 来对自己的 web 前端进行自动扩容。实现一个 MongoDB 容器，可以自检 Swarm 并且启动正确的分片和副本（LCTT 译注：分片技术为大规模并行检索提供支持，副本技术则是为数据提供冗余）。下一步怎么做我们提供了这些前卫的工具和概念来构建应用，并没有深入发掘它们的功能。我们的架构里还是存在长期运行的服务，将来我们需要使用 Swarm 来把所有服务都用按需扩容的方式实现。希望本文能在你搭建架构时给你一些启发，但我们还是需要你的帮助。我们提供了所有的基本工具，但它们还不是很完善，我们需要更多更好的工具、库、应用案例、文档以及其他资料。我们在这里发布了工具、库和文档。如果想了解更多，请贡献给我们一些你知道的资源，以便我们能够完善这篇文章。玩得愉快。更多关于 Docker 的资料New to Docker? Try our 10 min online tutorialShare images, automate builds, and more with a free Docker Hub accountRead the Docker 1.12 Release NotesSubscribe to Docker WeeklySign up for upcoming Docker Online MeetupsAttend upcoming Docker MeetupsWatch DockerCon EU 2015 videosStart contributing to Dockervia: https://blog.docker.com/2016/06/building-serverless-apps-with-docker/作者：Ben Firshman 译者：bazz2 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出