OpenFunction[1] 是一个现代化的云原生 FaaS(函数即服务)框架,它引入了很多非常优秀的开源技术栈,包括 Knative、Tekton、Shipwright、Dapr、KEDA 等,这些技术栈为打造新一代开源函数计算平台提供了无限可能:

  • Shipwright 可以在函数构建的过程中让用户自由选择和切换镜像构建的工具,并对其进行抽象,提供了统一的 API;
  • Knative 提供了优秀的同步函数运行时,具有强大的自动伸缩能力;
  • KEDA 可以基于更多类型的指标来自动伸缩,更加灵活;
  • Dapr 可以将不同应用的通用能力进行抽象,减轻开发分布式应用的工作量。

OpenFunction 最新发布了0.6版本,而且2022 年 4 月 27 日,OpenFunction[1] 顺利通过了云原生计算基金会 CNCF 技术监督委员会(TOC)的投票,正式进入 CNCF 沙箱(Sandbox)托管。OpenFunction 也将真正变成一个由 100% 社区驱动的开源项目。最近我也加入了OpenFunction项目开始规划dotnet的支持开发,dotnet 框架支持的仓库[2],目前完成0.1版本的开发。

经过我这2周时间的摸索,本文将会带领大家快速部署和上手 OpenFunction,并通过一个 demo{hello-world-dotnet} 来体验同步函数是如何运作的,以便对函数计算有一个感性的认知。

OpenFunction CLI 介绍

OpenFunction 从 0.5 版本开始使用全新的命令行工具 ofn[3] 来安装各个依赖组件,它的功能更加全面,支持一键部署、一键卸载以及 Demo 演示的功能。用户可以通过设置相应的参数自定义地选择安装各个组件,同时可以选择特定的版本,使安装更为灵活,安装进程也提供了实时展示,使得界面更为美观。它支持的组件和其依赖的 Kubernetes 版本如下:

ofn 的安装参数 ofn install 解决了 OpenFunction 和 Kubernetes 的兼容问题,会自动根据 Kubernetes 版本选择兼容组件进行安装,同时提供多种参数以供用户选择。

使用 OpenFunction CLI 部署 OpenFunction

有了命令行工具 ofn 之后,OpenFunction 部署起来非常简单。首先需要安装 ofn,以 amd64 版本的 Linux 为例,仅需两步即可:

1、下载 ofn,最新的ofn 是0.5.3

$ wget -c  https://github.com/OpenFunction/cli/releases/download/v0.5.3/ofn_linux_amd64.tar.gz -O - | tar –xz

2、为 ofn 赋予权限并移动到 /usr/local/bin/ 文件夹下。

$ chmod +x ofn && mv ofn /usr/local/bin/

安装好 ofn 之后,仅需一步即可完成 OpenFunction 的安装。虽然使用 --all 选项可以安装所有组件,也可以选择安装指定需要安装的组件,我们的集群里面已经安装了Dapr的情况下,我们就不想额外安装一遍Dapr ,不过如果集群里面已经安装了Dapr的情况下他也不会给重新安装的,具体可以看下图。

安装成功了,之后我们就可以开始运行同步函数了,OpenFunction 还支持异步函数,这部分今天就不演示了,留作后续在dotnet框架里面实现了异步函数的时候再来。

同步函数 demo 示例

OpenFunction 官方仓库提供了多种语言的同步函数示例[4]

这里我们选择 dotnet 的函数示例,先来看一下最核心的部署清单:

apiVersion: core.openfunction.io/v1beta1

kind: Function

metadata:
   name: dotnet-sample
   namespace: default

spec:
   version: "v1.0.0"
   image: "geffzhang/sample-dotnet-func:v1"
   imageCredentials:
     name: push-secret
   port: 8080 # default to 8080
   build:
     builder: "openfunction/gcp-builder:v1"
     env:
       GOOGLE_FUNCTION_TARGET: "helloworld"
       GOOGLE_FUNCTION_SIGNATURE_TYPE: "http"
     srcRepo:
       url: "https://github.com/openfunction/samples.git"
       sourceSubPath: "functions/knative/hello-world-dotnet"
       revision: "release-0.6"
   serving:
     runtime: "knative" # default to knative
     template:
       containers:
         - name: function
           imagePullPolicy: IfNotPresent

Function 是由 CRD 定义的一个 CR,用来将函数转换为最终运行的应用。这个例子里面包含了两个组件:

  • build : 通过 Shipwright 选择不同的镜像构建工具,最终将应用构建为容器镜像;
  • Serving : 通过 Serving CRD 将应用部署到不同的运行时中,可以选择同步运行时或异步运行时。这里选择的是同步运行时 knative。

运行这个示例之前,需要在运行函数的命名空间下创建Secret ,生成一个Secret 来访问您的容器注册表,例如Docker Hub[5]Quay.io[6] 上的一个。这一点非常重要,不然就在Build 阶段就失败了。

REGISTRY_SERVER您可以通过编辑以下命令中的REGISTRY_USER和字段来创建此密钥REGISTRY_PASSWORD,然后运行它。

REGISTRY_SERVER=https://index.docker.io/v1/ REGISTRY_USER= < your_registry_user > REGISTRY_PASSWORD= < your_registry_password >

kubectl create secret –n default docker-registry push-secret \
     --docker-server= $REGISTRY_SERVER \
     --docker-username= $REGISTRY_USER \
     --docker-password= $REGISTRY_PASSWORD

然后将上面的部署清单保存为function-dotnet-sample.yaml ,修改spec.image 字段为您自己的容器注册表地址,使用以下命令创建此函数:

kubectl apply –f  function-dotnet-sample.yaml

在Build 阶段,builder会启动一个 Pod 来构建镜像,这个 Pod 中包含了 4 个容器:

  • step-source-default : 拉取源代码;
  • step-prepare : 设置环境变量;
  • step-create : 构建镜像;
  • step-results : 输出镜像的 digest。

您可以使用以下命令观察函数的过程。

kubectl get functions -n default

NAME              BUILDSTATE   SERVINGSTATE   BUILDER         SERVING         URL                                              AGE

dotnet-sample     Succeeded    Running        builder-hf74t   serving-wh6hs   http://openfunction.io/default/dotnet-sample     54m

URL是OpenFunction Domain提供的可以访问的地址。要通过此 URL 地址访问该功能,您需要确保 DNS 可以解析此地址。使用以下命令在集群中创建一个 pod,并从该 pod 访问该功能

kubectl run  curl --image=radial/busyboxplus:curl -i –tty

[ root@curl:/ ]$ curl http://openfunction.io.svc.cluster.local/default/dotnet-sample/

还可以通过 Knative Services 提供的访问地址触发该功能

kubectl get ksvc

geffzhang@edgevm1:~/openfunctionsamples/functions/knative/hello-world-dotnet$ sudo kubectl get ksvc

NAME                       URL                                                               LATESTCREATED                   LATESTREADY                     READY   REASON

serving-wh6hs-ksvc-m7fc9   http://serving-wh6hs-ksvc-m7fc9.default.20.239.115.228.sslip.io   serving-wh6hs-ksvc-m7fc9-v100   serving-wh6hs-ksvc-m7fc9-v100   True

这个地址是可以直接访问的

访问这个函数时会自动触发运行一个 Pod:

这个 Pod 使用的镜像就是之前 build 阶段构建的镜像。事实上这个 Pod 是由 Deployment 控制的,在没有流量时,这个 Deployment 的副本数是 0。当有新的流量进入时,会先进入 Knative 的 Activator,Activator 接收到流量后会通知 Autoscaler(自动伸缩控制器),然后 Autoscaler 将 Deployment 的副本数扩展到 1,最后 Activator 会将流量转发到实际的 Pod 中,从而实现服务调用。这个过程也叫冷启动

如果你不再访问这个入口,过一段时间之后,Deployment 的副本数就会被收缩为 0:

通过上面的示例,相信大家应该能够体会到一些函数计算的优势,我们只需要专注于业务开发,编写函数代码,并上传到代码仓库,其他的东西不需要关心,就连Dockerfile都不需要编写,不需要了解基础设施,甚至不需要知道容器和 Kubernetes 的存在。函数计算平台会自动为您分配好计算资源,并弹性地运行任务,只有当您需要访问的时候,才会通过扩容来运行任务,其他时间并不会消耗计算资源,可以充分利用dotnet在云原生时代的优势,使用dotnet写函数是很高效的,大家可以体验一下我上面的示例http://serving-wh6hs-ksvc-m7fc9.default.20.239.115.228.sslip.io 。OpenFunction基于Dapr 所提供的各种分布式能力,让我们轻松的实现无服务微服务架构,获得像Azure 容器应用[7] 一样的能力。

相关链接

[1] openFunction: https://github.com/OpenFunction/OpenFunction

[2] functions-framework-dotnet: https://github.com/OpenFunction/functions-framework-dotnet

[3] ofn: https://github.com/OpenFunction/cli

[4] OpenFunction 官方仓库提供了多种语言的同步函数示例:  https://github.com/OpenFunction/samples/tree/main/functions/knative

[5] Docker Hub: https://hub.docker.com/

[6] Quay.io: https://quay.io/

[7] Azure 容器应用: https://www.cnblogs.com/shanyou/p/15509042.html

从同步函数 hello-world-dotnet 开始探索OpenFunction的更多相关文章

  1. java 中多线程的同步函数的运用

    /* * 需求: * 银行有一个金库 * 有两个储户,分别存300元.每次存100 , 存三次 * * 这个是有线程问题的, * * 我们应该通过下边的三个方法来查找问题 * 1.明确哪些代码是多线程 ...

  2. java基础知识回顾之java Thread类学习(六)--java多线程同步函数用的锁

    1.验证同步函数使用的锁----普通方法使用的锁 思路:创建两个线程,同时操作同一个资源,还是用卖票的例子来验证.创建好两个线程t1,t2,t1线程走同步代码块操作tickets,t2,线程走同步函数 ...

  3. Java多线程--同步函数

    /*需求:银行有一个金库有两个储户分别存300元 每次存100元,存3次 目的:该程序是否有安全问题,如果有,如何解决? 如何找问题(很重要)1.明确哪些代码是多线程运行代码2.明确共享数据3.明确多 ...

  4. 多线程---静态同步函数的锁是class(转载)

    /** 如果同步函数被静态修饰,那么他的锁就是该方法所在类的字节码文件对象 类名.class 静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码文件对象. 该对象就是:类名.class   ...

  5. 多线程---同步函数的锁是this(转载)

    class Ticket implements Runnable { private int tick = 100; Object obj = new Object(); boolean flag = ...

  6. nodejs 代码设计模式1:同步函数变异步

    同步函数变异步 1 问题: 1.1 碰到需要调用你刚正在创建的对像. function createServer(data, cb) { data.num = 1; cb(); return data ...

  7. JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制

    JAVA之旅(十四)--静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是clas ...

  8. JAVA之旅(十三)——线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this

    JAVA之旅(十三)--线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this 我们继续上个篇幅接着讲线程的知识点 一.线程的安全性 当我们开启四个窗口(线程 ...

  9. 『审慎』.Net4.6 Task 异步函数 比 同步函数 慢5倍 踩坑经历

    异步Task简单介绍 本标题有点 哗众取宠,各位都别介意(不排除个人技术能力问题) —— 接下来:我将会用一个小Demo 把 本文思想阐述清楚. .Net 4.0 就有了 Task 函数 —— 异步编 ...

随机推荐

  1. Vue部署到云服务器时,访问Nginx代理出现We're sorry but books doesn't work properly without JavaScript enabled. Please enable it to continue.

    出现这个的原因,我这边的是Nginx的问题,因为没有匹配到静态文件的原因 第一个location是始终将访问的url请求定向到 index.html这个主页面 第二个location块是将index. ...

  2. Java中带参数的方法和JavaScript中带参数的函数有什么不同?

    javascript是动态语言,是弱类型语言,其参数的使用很灵活:java则是强类型语言,参数的类型必须明确的

  3. 介绍一下 WebApplicationContext ?

    WebApplicationContext 是 ApplicationContext 的扩展.它具有 Web 应用 程序所需的一些额外功能.它与普通的 ApplicationContext 在解析主题 ...

  4. 时间工具类之"获取相差天数"

    一.时间工具类DateUtils之"获取相差天数" 1 /** 2 * 相差天数 3 * 4 * <p>TODO 方法功能描述 5 * 6 * @param start ...

  5. CommonsCollection2反序列链学习

    CommonsCollection2 1.前置知识 CmonnosCollection2需要用到Javassist和PriorityQueue 1.1.Javassist Javassist是一个开源 ...

  6. Python的数据基础库Numpy怎样对数组进行排序

    Numpy怎样对数组排序 Numpy给数组排序的三个方法: numpy.sort:返回排序后数组的拷贝 array.sort:原地排序数组而不是返回拷贝 numpy.argsort:间接排序,返回的是 ...

  7. 顺利通过EMC实验(18)

  8. 移动端——touch事件

    1.touchstart 当手指触碰屏幕时候触发 dom.addEventListener('touchstart',function(e){}); startX=e.touches[0].clien ...

  9. 一个好用的swagger第三方ui-xiaoymin

    swagger自带的ui界面实在是看的难受 配置完默认访问地址:ip:port/swagger-ui.html 推荐一个好用的第三方ui,界面如图: 使用方法: 1.添加依赖 <dependen ...

  10. 【Android开发】分割字符串工具类

    public class TextUtils { public static String[] results; /** * 分隔符:"." * * @param resource ...