利用Azure Functions和k8s构建Serverless计算平台

题记:昨晚在一个技术社区直播分享了“利用Azure Functions和k8s构建Serverless计算平台”这一话题。整个分享分为4个部分:Serverless概念的介绍、Azure Functions的简单介绍、k8s和KEDA的介绍和最后的演示。

Serverless

Serverless其实包含了两种概念:BaaS(Backend as a Service)和FaaS(Function as a Service)。这次的分享主要针对的是FaaS概念。

FaaS的最大特征就是:无需管理自己的服务器或拥有自己的持续运行的服务应用的情况下运行后端代码。上面加粗的地方其实也揭示了FaaS和PaaS的本质区别:你为了运行后端代码,需不需要拥有一套持续运行的服务端完整应用(不管是WebSite还是Web API)。

另外,FaaS还拥有如下特征:

  • 可以使用任何语言,不需要针对特定框架和函数进行编码

  • 部署方式和传统系统有很大不同

  • 水平伸缩完全自动化、弹性,并由平台供应商管理

  • 函数通常由事件触发,部分平台供应商支持接收HTTP触发

当然判断什么东西不是FaaS也有一些标准:

  • 能否在20ms启动半秒执行完,根本区别在于伸缩性的方式

  • FaaS也可能依赖容器,但是和其他使用容器的应用区别在于伸缩性的自动化、透明和细度

  • 没有传统的Ops,但是应用本身运维过程还是需要,甚至更难(因为不同)

使用FaaS有其优缺点,这里就报喜不报忧,只列一下优点:

  • 降低运维成本

    • 基础设施共享

    • 减少基础设施维护人工成本

  • 降低伸缩成本

    • 按量付费:偶尔请求,流量忽高忽低

    • 优化代码即可省钱

  • 更易运维

    • 伸缩的好处利于降低运维难度

    • 降低打包和部署复杂度

    • 快速投入市场,持续优化

Azure Functions

以官方文档的介绍:Azure Functions 允许你运行小段代码(称为“函数”)且不需要担心应用程序基础结构。 借助 Azure Functions,云基础结构可以提供应用程序保持规模化运行所需的所有最新状态的服务器。函数由特定类型的事件“触发”。 支持的触发器包括对数据更改做出响应、对消息做出响应、按计划运行,或者生成 HTTP 请求的结果。虽然你始终可以直接针对大量服务编写代码,但使用绑定可以简化与其他服务的集成。 使用绑定,你能够以声明方式访问各种 Azure 服务和第三方服务。

Azure Functions包含如下功能:

  • 无服务器应用程序:使用 Functions,可在 Microsoft Azure 上开发无服务器应用程序。

  • 语言选择:使用所选的 C#、Java、JavaScript、Python 和 PowerShell 编写函数。

  • 按使用付费定价模型:仅为运行代码所用的时间付费。

  • 自带依赖项:Functions 支持 NuGet 和 NPM,允许你访问你喜欢的库。

  • 集成的安全性:使用 OAuth 提供程序(如 Azure Active Directory、Facebook、Google、Twitter 和 Microsoft 帐户)保护 HTTP 触发的函数。

  • 简化的集成:轻松与 Azure 服务和软件即服务 (SaaS) 产品/服务进行集成。

  • 灵活开发:直接在门户中编写函数代码,或者通过 GitHub、Azure DevOps Services 和其他受支持的开发工具设置持续集成和部署代码。

  • 有状态无服务器体系结构:使用 Durable Functions 协调无服务器应用程序。

  • 开放源代码:Functions 运行时是开源的,可在 GitHub 上找到。

大家看到了,Azure Functions虽然是来源于微软Azure的技术,但是是使用MIT协议开源的,且已经贡献给.NET Foundation

所以,你可以使用Azure Functions来搭建(甚至定制)自己的Serverless计算平台。开源的不仅是Azure Functions框架本身,还包括了命令行工具(可以支持本地调试)和VSCode的扩展。当然,开发工具除了前面两者,你还是可以使用宇宙第一的IDE:Visual Studio。

下面是相关开源的地址:

  • 框架:https://github.com/Azure/azure-functions-host

  • 命令行工具:https://github.com/Azure/azure-functions-core-tools

  • VSCode扩展:https://github.com/Microsoft/vscode-azurefunctions

只有开源的框架还不行,还需要运行环境,正如大部分开源FaaS框架一样,Azure Functions也把k8s作为运行环境。不过为了达到自动伸缩、不使用就不消耗资源的目标,还需要搭配其他中间件才能达到效果。

k8s和KEDA

众所周知,Kubernetes已经成为最主流的PaaS平台,各大公有云提供商都提供了k8s的服务,比如微软Azure上的AKS或者阿里云的ACK。

为了更好的理解为什么k8s可以作为Serverless完美的运行环境,是需要对如下概念有一些深入的理解的:

  • Pod和Deployment:Pod代表了运行函数的实例,而Deployment用于控制函数的实例数。

  • HPA(Horizontal Pod Autoscaler):k8s内置的水平Pod自动伸缩器,其基于一些度量指标(比如内存、CPU等)来对Deployment的Pod实例数进行伸缩。

  • Helm Charts:一个强大的打包、发布k8s应用的包管理器。我们开发好的函数在编译为Docker Image之后,可以用Helm Charts来打包(当然也可以直接用k8s的yaml文件)。

k8s虽然提供了HPA,但是它无法基于更灵活的事件源来进行伸缩,也无法把Pod的实例数缩到0,或者由0伸到1。这个时候,就需要另外一个开源项目KEDA出场了(贡献者来自微软、AWS等大公司,以及很多社区志愿者)。

KEDA:Kubernetes Event-driven Autoscaling。项目地址在:https://github.com/kedacore/keda。其具有如下特点:

  • 事件驱动

  • 轻而易举实现自动伸缩

  • 内置伸缩器

  • 多种负载类型

  • 社区开源项目

  • 支持Azure Functions

KEDA的架构如下图所示:从这个架构图,我们看到KEDA包含了3个组件,Metric Adapter给k8s的HPA提供度量指标让其进行1-n/n-1的伸缩,Controller控制Pod进行1-0/0-1的伸缩,Scaler侦听配置的触发器所触发的事件。

且支持的伸缩器涵盖了大部分主流云组件或中间件:

  • Apache Kafka

  • AWS CloudWatch

  • AWS Kinesis Stream

  • AWS SQS Queue

  • Azure Blob Storage

  • Azure Event Hubs

  • Azure Monitor

  • Azure Service Bus

  • Azure Storage Queue

  • External

  • GCP Pub/Sub

  • Huawei Cloudeye

  • Liiklus Topic

  • MySQL

  • NATS Streaming

  • PostgreSQL

  • Prometheus

  • RabbitMQ Queue

  • Redis List

演示

既然Azure Functions是开源技术,为了验证技术中立性,在演示过程中特意选择了阿里云的ACK作为运行环境(Kubernetes托管版),并使用RabbitMQ作为伸缩触发器。

同时,我们采用C#/.NET Core来作为函数的开发语言。为什么用这个选择,是因为有第三方对AWS Lambda上的支持的语言进行了性能测试,得到的结论是.NET Core的C#和F#语言性能最高:来源:https://read.acloud.guru/comparing-aws-lambda-performance-of-node-js-python-java-c-and-go-29c1163c2581

环境准备

首先,需要到阿里云上创建一个k8s集群,创建的选项截图如下:

通过如下命令来部署KEDA到k8s:

helm repo add kedacore https://kedacore.github.io/charts
kubectl create namespace keda
helm install keda kedacore/keda --namespace keda

通过如下命令来部署RabbitMQ到k8s:

helm repo add bitnami https://charts.bitnami.com/bitnami
helm install rabbitmq --set rabbitmq.password=PASSWORD,service.type=LoadBalancer bitnami/rabbitmq

这里需要注意(当然也可能是我打开方式不对),阿里云的ACK不能自动创建pv,所以rabbitmq部署后会有问题,所以需要到阿里云的ACK的控制面板里面手动创建pv,并重建rabbitmq所需的同名pvc。

创建Azure Functions项目

访问:https://github.com/Azure/azure-functions-core-tools,安装命令行工具。

在命令行中输入:

func init --docker

来初始化一个带有Dockerfile的Azure Functions项目,worker runtime选择dotnet。

在命令行中输入:

func function create

来创建一个函数,template选择QueueTrigger,输入你想要的函数名称。

使用你喜欢的编辑器(比如VSCode)打开项目文件夹,修改csproj文件中的PackageReference为如下内容:

<ItemGroup><PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.3" /><PackageReference Include="Microsoft.Azure.WebJobs.Extensions.RabbitMQ" Version="0.2.2029-beta" />
</ItemGroup>

修改函数代码为如下内容:

[FunctionName("MyMqFunction")]
public static void Run([RabbitMQTrigger("queue", ConnectionStringSetting = "RabbitMqConnection")] string inputMessage,[RabbitMQ(QueueName = "downstream", ConnectionStringSetting = "RabbitMqConnection")] out string outputMessage,ILogger log)
{Thread.Sleep(5000);outputMessage = inputMessage;log.LogInformation($"RabittMQ output binding function sent message: {outputMessage}");
}

这个函数从一个名为”queue“的队列中读取inputMessage,延迟5秒后,把消息存储到名为”downstream"的队列中。

打开local.settings.json文件,在Values节点下添加RabbitMqConnection:

"Values": {"AzureWebJobsStorage": "UseDevelopmentStorage=true","FUNCTIONS_WORKER_RUNTIME": "dotnet","RabbitMqConnection":"amqp://user:PASSWORD@rabbitmq.default.svc.cluster.local:5672"
},

这里RabbitMQ的地址使用了k8s内部的默认Service地址,为了方便本地调试,你可以获取到RabbitMQ在k8s的公网IP后,给这个域名添加host配置。

在命令行中输入:

func start

就可以进行本地调试了。调试无误,就可以进行发布到k8s的工作了。

以上示例代码可以在这里找到:https://github.com/heavenwing/AzFuncOnK8S

发布函数到k8s并验证伸缩能力

考虑到我用的阿里云拉取Docker Hub比较慢,所以我是编译出Docker Image后,push到了阿里云的镜像仓库当中。另外,我这里还遇到一个问题,就是能在AKS中正常运行的Docker Image在ACK中无法正常运行,出现"Access to the path '/proc/1/map_files' is denied"的错误,我的临时解决办法是修改Dockerfile文件,添加WORKDIR命令。

在把Docker Image推送到镜像仓库后,可以在命令行中输入:

func kubernetes deploy --name azfunconk8s --image-name registry.cn-chengdu.aliyuncs.com/zygcloud/azfunconk8s:latest --dry-run > deploy-funcs.yaml

得到部署的yaml文件后,我们需要对ScaledObject进行一点修改,为rabbitmq的trigger配置添加queueLength,根据需要配置maxReplicaCount属性,如下所示:

apiVersion: keda.k8s.io/v1alpha1
kind: ScaledObject
metadata:name: azfunconk8snamespace: defaultlabels:deploymentName: azfunconk8s
spec:scaleTargetRef:deploymentName: azfunconk8smaxReplicaCount: 20triggers:- type: rabbitmqmetadata:type: rabbitMQTriggerqueueName: queuename: inputMessagehost: RabbitMqConnectionqueueLength: "20"

现在就可以把函数部署到k8s了,在命令行中输入:

kubectl apply -f .\deploy\deploy-funcs.yaml

这个时候应该可以看到k8s出现了名为azfunconk8s的Deployment,且需要实例和运行实例数都是为0:

另外写一个小程序,往RabbitMQ的queue队列里面放一些测试消息,经过30秒(默认pollingInterval时间)那么就会看到这个Deployment的所需实例数在提高,一直提高到你设置的maxReplicaCount。等队列中的消息处理完成,又会看到所需实例数在降低,等没有消息需要处理之后过上5分钟(默认cooldownPeriod时间),所需实例数就会变为0。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/309211.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于 abp vNext 和 .NET Core 开发博客项目 - 终结篇之发布项目

系列文章使用 abp cli 搭建项目给项目瘦身&#xff0c;让它跑起来完善与美化&#xff0c;Swagger登场数据访问和代码优先自定义仓储之增删改查统一规范API&#xff0c;包装返回模型再说Swagger&#xff0c;分组、描述、小绿锁接入GitHub&#xff0c;用JWT保护你的API异常处理和…

对 JsonConvert 的认识太肤浅了,终于还是遇到了问题

一&#xff1a;背景1. 讲故事在开始本文之前&#xff0c;真的好想做个问卷调查&#xff0c;到底有多少人和我一样&#xff0c;对 JsonConvert 的认识只局限在 SerializeObject 和 DeserializeObject 这两个方法上(┬&#xff3f;┬), 这样我也好结伴同行&#xff0c;不再孤单落…

.Net微服务实战之DevOps篇

技术只是基础该系列的两篇文章《.Net微服务实战之技术选型篇》和《.Net微服务实战之技术架构分层篇》都是以技术角度出发描述微服务架构的实施。如果技术选型篇叙述的是工具&#xff0c;那么架构分层篇讲的就是技巧&#xff0c;而本篇要讨论的就是原则。一直以来我会给身边向我…

阿里云挑战赛

文章目录第一题题目&#xff1a;题解&#xff1a;第二题题目题解第三题题目题解第四题题目&#xff1a;题解第五题题目题解第六题题目题解第七题题目&#xff1a;题解第八题题目&#xff1a;题解;题解赛后出第一题 题目&#xff1a; 【单选】filter 方法意图过滤传入的订单列…

使用C#编写STM32对接物联网平台IoTSharp发送遥测数据

在之前的文章中&#xff0c; 我们阐述了如何用C#在STM32上写第一个Hello world &#xff0c; 有朋友抱怨国内介绍文章&#xff0c; 都是一个 Hello world &#xff0c; 然后再也没有音讯&#xff0c; 写到这里我想提一下我的初心&#xff0c; 那就是告诉所有人C#无所不能&…

JavaMVC之JSON

JSON 8.1、什么是JSON&#xff1f; JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式&#xff0c;目前使用特别广泛。采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。易于人阅读和编写…

龙芯团队完成CoreCLR MIPS64移植,在github开源

国产龙芯的软件生态之中.NET不会缺席&#xff0c;毕竟 C# 与 .NetCore/Mono 也是全球几大主流的编程语言和运行平台之一&#xff0c;最近一段时间听到太多的鼓吹政务领域不支持.NET&#xff0c; 大家都明白这是某些人为了自己的利益打压使用.NET技术的公司&#xff0c;我今天写…

来谈一谈专注力的真相

这是头哥侃码的第205篇原创在日常生活&#xff08;或工作&#xff09;中&#xff0c;你有没有遇上过这样的情况&#xff1f;比如你正在跟小伙伴讨论一个技术方案&#xff0c;聊着聊着&#xff0c;突然小A脑袋一抽筋&#xff0c;问你&#xff1a;“老大&#xff0c;咱们这周五晚…

Java访问控制修饰符

访问控制修饰符 Java中&#xff0c;可以使用访问控制符来保护对类、变量、方法和构造方法的访问。 Java 支持 4 种不同的访问权限。 default (即默认&#xff0c;什么也不写&#xff09;: 在同一包内可见&#xff0c;不使用任何修饰符。 使用对象&#xff1a;类、接口、变量…

数据结构与算法专题——第三题 最长公共子序列

一&#xff1a;作用最长公共子序列的问题常用于解决字符串的相似度&#xff0c;是一个非常实用的算法&#xff0c;作为码农&#xff0c;此算法是我们的必备基本功。二&#xff1a;概念举个例子&#xff0c;cnblogs这个字符串中子序列有多少个呢&#xff1f;很显然有27个&#x…

Java实现两个递增有序链表合并成一个递增有序链表和两个非递减有序链表合成一个非递增有序链表

代码如下: package sjjgniub;import java.util.LinkedList; import java.util.Scanner;SuppressWarnings("all") public class LinkList {private class Node{int data;Node next;public Node(){}public Node(int data){this.data data;next null;}}Node head nu…

职场PUA到底有多可怕?

阅读本文大概需要 5.2分钟。“小张&#xff0c;好好干啊&#xff0c;明年一定给你加薪&#xff01;” 。从小张入职这家公司起&#xff0c;这是老板对小张第三次这么说了。小张每天干到晚上12点&#xff0c;任劳任怨&#xff0c;虽然一直没涨过工资&#xff0c;但是老板的不断认…

数据结构与算法专题——第二题 优先队列

前段时间玩小爬虫的时候&#xff0c;我把url都是放在内存队列里面&#xff0c;有时我们在抓取url的时候&#xff0c;通过LCS之类的相似度比较&#xff0c;发现某些url是很重要的&#xff0c;需要后端解析服务器优先处理&#xff0c;针对这种优先级比较大的url&#xff0c;普通的…

数据结构与算法专题——第一题 Bitmap算法

在所有具有性能优化的数据结构中&#xff0c;我想大家使用最多的就是hash表&#xff0c;是的&#xff0c;在定位查找场景上具有O(1)的常量时间&#xff0c;多么的简洁优美&#xff0c;但是在特定的场合下&#xff1a;①&#xff1a;对10亿个不重复的整数进行排序。②&#xff1…

Telegraf和Grafana监控多平台上的SQL Server

问题SQL Server在很多企业中部署在多个平台上(Windows,Linux和Container)&#xff0c;需要一种能支持多平台的解决方案用于收集和展示相关的监控指标。我选择企业中比较流行的监控展示工具Grafana和监控指标收集工具Telegraf进行实现。这也是为了方便与企业中已经在存在监控平台…

酸吗?28岁程序员财务自由宣布退休!

财务自由是我们这代人的共同追求&#xff0c;有程序员28岁就做到了。近期的一条新闻就直接刷屏了&#xff0c;28岁今日头条程序员手握上亿期权宣布退休&#xff0c;引发一片羡慕嫉妒恨。履历如下&#xff1a;2008-2012就读于暨南大学政治与行政管理专业&#xff0c;自学编程。2…

nuget 是如何还原包的

nuget 是如何还原包的Intro一直以来从来都只是简单的用 nuget 包&#xff0c;最近想折腾一个东西&#xff0c;需要自己搞一个 nuget 包的解析&#xff0c;用户指定 nuget 包的名称和版本&#xff0c;然后去解析对应的 nuget 包并添加引用到项目&#xff0c; 于是就想搞明白 nug…

使用Azure AD B2C为ASP.NET Core 设置登录/注册

一&#xff0c;引言上次关于Azure AD B2C 讲到一些概念&#xff0c;有介绍到&#xff0c;Azure AD B2C 也是一种身份验证的解决方案&#xff0c;但是它运行客户使用其首选的社交&#xff0c;企业或者本地账户标识对应用程序和API进行单一登录访问。同样&#xff0c;Azure AD B2…

使用 Azure Function 定时启动云 VM

点击上方蓝字关注“汪宇杰博客”导语微软 Azure 平台的 VM 可以做到定时自动关机&#xff0c;然而只有 DevTest Lab 服务中的 VM 能够定时开机&#xff0c;普通用途的 VM 还没有上线这个功能。但是没关系&#xff0c;我们可以曲线救国&#xff0c;通过最新版的 Azure Function …