diff --git a/translations/cn/README.md b/translations/cn/README.md new file mode 100644 index 0000000..36e479f --- /dev/null +++ b/translations/cn/README.md @@ -0,0 +1,187 @@ +# openfaas-workshop + +这是一个自定进度的研讨会,学习如何使用 OpenFaaS 构建、部署和运行无服务器函数。 + +![](https://github.com/openfaas/media/raw/master/OpenFaaS_Magnet_3_1_png.png) + +在这个研讨会中,你将首先把 OpenFaaS 部署到你的笔记本电脑或使用 Docker for Mac 或 Windows 的远程集群。然后你将对 OpenFaaS 的用户界面、CLI 和函数商店进行测试。在用 Python 构建、部署和调用你自己的无服务器函数之后,你将继续学习以下内容:用 pip 管理依赖关系,通过安全secret处理 API 令牌,用 Prometheus 监控函数,异步调用函数以及将函数连接起来创建应用程序。实验的高潮是让你创建自己的 GitHub 机器人,可以自动响应问题。同样的方法可以通过 IFTTT.com 连接到在线事件流--这将使你能够建立机器人、自动回复器以及与社交媒体和物联网设备的集成。 + +最后,实验室涵盖了更多的高级主题,并给出了进一步学习的建议。 + +**译文** + +* [日本語](./translations/ja) +* [简体中文](./translations/cn) + +## 免费学习,作为 GitHub 赞助商表示感谢 + +OpenFaaS 连同这些材料都是免费提供的,需要时间和精力来维护。 + +* 成为[OpenFaaS on GitHub](https://github.com/sponsor/openfaas)的赞助商。 + +## 要求 + +我们在[Lab 1](./lab1.md)中讲解了如何安装这些需求。请在参加讲师指导的研讨会之前做[Lab 1](./lab1.md)。 + +* 函数将用 Python 语言编写,所以有编程或脚本经验者优先。 +* 安装推荐的代码编辑器/IDE [VSCode](https://code.visualstudio.com/download) +* 对于 Windows,安装[Git Bash](https://git-scm.com/downloads) +* 首选的操作系统。MacOS, Windows 10 Pro/Enterprise, Ubuntu Linux + +Docker。 + +* Docker CE for [Mac](https://store.docker.com/editions/community/docker-ce-desktop-mac)/[Windows](https://store.docker.com/editions/community/docker-ce-desktop-windows) **边缘版**。 +* Docker CE for Linux + +> 注意:作为最后的手段,如果你有一台不兼容的 PC,你可以在 上运行该研讨会。 + +## 教员指导的研讨会 + +如果你正在参加一个由教师指导的研讨会,那么我们将分享一个链接,以加入 OpenFaaS Slack 社区。使用研讨会的指定频道来讨论评论、问题和建议。 + +## 挑选你的路线 + +在实验室 1 中,你将选择你的路线,然后在整个实验室中注意你所需要的特殊命令。 + +### Kubernetes + +你也可以使用 OpenFaaS 学习 Kubernetes 上的 Serverless。 + +OpenFaaS 社区的建议是,你在生产中运行 Kubernetes,但你的所有知识都是可以转移的,函数也不必重新构建。 + +## [Lab 1 - Prepare for OpenFaaS](./lab1.md) + +* 安装前提条件 +* 用 Kubernetes 建立一个单节点集群 +* Docker Hub 账户 +* OpenFaaS CLI +* 部署 OpenFaaS + +## [Lab 2 - Test things out](./lab2.md) + +* 使用 UI 门户 +* 通过函数商店进行部署 +* 了解 CLI 的情况 +* 用 Prometheus 查找指标 + +## [Lab 3 - Introduction to Functions](./lab3.md) + +* 架构或生成一个新的函数 +* 建立 astronaut-finder 函数 +* 用`pip`添加依赖性 +* 故障排除:找到容器的日志 +* 故障排除:用`write_debug`进行粗略输出 +* 使用自定义和第三方语言模板 +* 使用模板商店发现社区模板 + +## [Lab 4 - Go deeper with functions](./lab4.md) + +* [通过环境变量注入配置](lab4.md#inject-configuration-through-environmental-variables) + * 在部署时使用 yaml + * 动态地使用 HTTP 上下文--查询字符串/头信息等 +* 安全性:只读的文件系统 +* [利用日志](lab4.md#making-use-of-logging) +* [创建工作流](lab4.md#creat-workflows) + * 在客户端串联函数 + * 从另一个函数中调用一个函数 + +## [Lab 5 - Create a GitHub bot](./lab5.md) + +> 建立 `issue-bot`--GitHub 问题的自动回复者 + +* 获得一个 GitHub 账户 +* 用 ngrok 建立一个隧道 +* 创建一个 webhook 接收器`issue-bot`。 +* 接收来自 GitHub 的 webhooks +* 部署 SentimentAnalysis 函数 +* 通过 GitHub 的 API 应用标签 +* 完成函数 + +## [Lab 6 - HTML for your functions](./lab6.md) + +* 从一个函数生成并返回基本的 HTML +* 从磁盘读取并返回一个静态 HTML 文件 +* 与其他函数协作 + +## [Lab 7 - Asynchronous Functions](./lab7.md) + +* 同步地与异步地调用一个函数 +* 查看队列工作者的日志 + +* 在 requestbin 和 ngrok 中使用`X-Callback-Url`。 + +## [Lab 8 - Advanced Feature - Timeouts](./lab8.md) + +* 用`read_timeout`调整超时时间 +* 适配长时间运行函数 + +## [Lab 9 - Advanced Feature - Auto-scaling](./lab9.md) + +* 查看自动缩放的操作 + * 关于最小和最大副本的一些见解 + * 发现并访问本地 Prometheus + * 执行和普罗米修斯查询 + * 使用 curl 调用一个函数 + * 观察自动缩放的启动 + +## [Lab 10 - Advanced Feature - Secrets](./lab10.md) + +* 调整 issue-bot 以使用一个secret + * 用 faas-cli 创建一个 Kubernetes secret + * 在函数中访问secret + +## [Lab 11 - Advanced feature - Trust with HMAC](./lab11.md) + +* 使用 HMAC 对函数应用信任 + +你可以从第一个实验室[Lab 1](lab1.md)开始。 + +## 拆解/清理 + +你可以找到如何停止和删除 OpenFaaS[这里](https://docs.openfaas.com/deployment/troubleshooting/#uninstall-openfaas) + +## 接下来的步骤 + +如果你在一个教师指导的研讨会上,并且已经完成了实验,你可能想回到实验室,编辑/修改代码和值,或者进行一些你自己的实验。 + +以下是一些后续任务/主题的想法。 + +### OpenFaaS 云 + +试试 OpenFaaS 的多用户管理体验--在社区集群上,或者通过托管你自己的 OpenFaaS 云。 + +* [Docs: OpenFaaS Cloud](https://docs.openfaas.com/openfaas-cloud/intro/) + +### TLS + +* [用 Kubernetes Ingress 在你的网关上启用 HTTPS](https://docs.openfaas.com/reference/ssl/kubernetes-with-cert-manager/) + +### CI/CD + +设置 Jenkins、Google Cloud Build 或 GitLab,使用 OpenFaaS CLI 构建和部署你自己的函数。 + +* [CI/CD 介绍](https://docs.openfaas.com/reference/cicd/intro/) + +### 存储/数据库 + +* [用 Minio 尝试开源对象存储](https://blog.alexellis.io/openfaas-storage-for-your-functions/) + +* [尝试用 Mongo 存储数据的 OpenFaaS](https://blog.alexellis.io/serverless-databases-with-openfaas-and-mongo/) + +### 仪器仪表/监控 + +* [探索 Prometheus 中可用的指标](https://docs.openfaas.com/architecture/metrics/#monitoring-functions) + +### 其他博文和教程 + +* [OpenFaaS 博客上的教程](https://www.openfaas.com/blog/) + +* [社区博客文章](https://github.com/openfaas/faas/blob/master/community.md) + +### 附录 + +[附录](./appendix.md)包含一些额外的内容。 + +## Acknowledgements + +感谢@iyovcheva, @BurtonR, @johnmccabe, @laurentgrangeau, @stefanprodan, @kenfdev, @templum & @rgee0 对实验室的贡献、测试和翻译。 diff --git a/translations/cn/lab1.md b/translations/cn/lab1.md new file mode 100644 index 0000000..de8aea9 --- /dev/null +++ b/translations/cn/lab1.md @@ -0,0 +1,98 @@ +# Lab 1 - 为 OpenFaaS 做准备 + + + +OpenFaaS 需要一个[Kubernetes](https://kubernetes.io)集群来运行。你可以使用一个单节点集群或多节点集群,不管是在你的笔记本电脑上还是在云端。 + +任何 OpenFaaS 函数的基本原件都是一个 Docker 镜像,它是使用`faas-cli`工具链构建的。 + +## 前提条件 + +让我们来安装 Docker、OpenFaaS CLI 以及设置 Kubernetes。 + +### Docker + +适用于 Mac + +- [Docker CE for Mac Edge Edition](https://store.docker.com/editions/community/docker-ce-desktop-mac) + +适用于 Windows + +- 仅使用 Windows 10 Pro 或企业版 +- 安装[Docker CE for Windows](https://store.docker.com/editions/community/docker-ce-desktop-windows) + +> 请确保通过使用 Windows 任务栏通知区的 Docker 菜单来使用**Linux**容器的 Docker 守护程序。 + +- 安装[Git Bash](https://git-scm.com/downloads) + +当你安装 git bash 时,选择以下选项:`install UNIX commands`和`use true-type font`。 + +> 注意:请在所有步骤中使用*Git Bash*:不要试图使用*PowerShell*、*WSL*或*Bash for Windows*。 + +Linux - Ubuntu 或 Debian + +- Docker CE for Linux + +> 你可以从[Docker Store]()安装 Docker CE。 + +注意:作为最后的手段,如果你有一台不兼容的 PC,你可以在上面体验。 + +### OpenFaaS CLI + +你可以使用官方的 bash 脚本来安装 OpenFaaS CLI,`brew`也可以使用,但可能会落后一到两个版本。 + +在 MacOS 或 Linux 下,在终端运行以下程序。 + +```sh +# MacOS users may need to run "bash" first if this command fails +$ curl -sLSf https://cli.openfaas.com | sudo sh +``` + +对于 Windows,在*Git Bash*中运行这个。 + +```sh +curl -sLSf https://cli.openfaas.com | sh +``` + +> 如果你遇到任何问题,你可以从[releases page](https://github.com/openfaas/faas-cli/releases)手动下载最新的`faas-cli.exe`。你可以把它放在本地目录或`C:\Windows\`路径中,这样它就可以从命令提示符中获得。 + +我们将使用`faas-cli`来搭建新的函数,构建、部署和调用函数。你可以通过`faas-cli --help`找到 cli 的可用命令。 + +测试 `faas-cli`:打开一个终端或 Git Bash 窗口,键入 + +```sh +faas-cli help +faas-cli version +``` + +## 配置 Docker Hub + +注册一个 Docker Hub 账户:[Docker Hub](https://hub.docker.com)允许你在互联网上发布你的 Docker 镜像,以便在多节点集群上使用或与更广泛的社区分享。我们将在研讨会期间使用 Docker Hub 来发布我们的函数。 + +你可以在这里注册:[Docker Hub](https://hub.docker.com) + +打开一个终端或 Git Bash 窗口,用你上面注册的用户名登录 Docker Hub。 + +```sh +docker login +``` + +> 注意:来自社区的提示--如果你在 Windows 机器上试图运行这个命令时遇到错误,那么点击任务栏中的 Docker for Windows 图标,在那里登录 Docker,而不是 `登录/创建 Docker ID`。 + +- 为新镜像设置你的 OpenFaaS 前缀 + +OpenFaaS 镜像存储在 Docker 注册表或 Docker Hub 中,我们可以设置一个环境变量,使你的用户名自动添加到你创建的新函数中。这将在研讨会过程中为你节省一些时间。 + +编辑`~/.bashrc`或`~/.bash_profile`--如果该文件不存在,则创建它。 + +现在添加以下内容--按照你上面看到的 URL 进行修改。 + +```sh +export OPENFAAS_PREFIX="" # Populate with your Docker Hub username +``` + +### 设置一个单节点集群 + +实验室使用 Kubernetes,Swarm 已经不再被 OpenFaaS 社区支持。有些实验室可以用于 faasd,但你可能需要改变命令,而且当使用 faasd 的时候,我们不提供对该实验室的支持。 + +- Kubernetes。[Lab 1b](./lab1b.md) diff --git a/translations/cn/lab10.md b/translations/cn/lab10.md new file mode 100644 index 0000000..2f3c11e --- /dev/null +++ b/translations/cn/lab10.md @@ -0,0 +1,93 @@ +# Lab 10 - 高级函数 - secret + + + +在开始本实验室之前,为你的文件创建一个新的文件夹。由于本实验室是建立在先前的实验室基础上的,因此请复制 lab5。 + +```plain +$ cp -r lab5 lab10\ + && cd lab10 +``` + +## 使用secret + +[实验室 5](./lab5.md)研究了`issue-bot`如何从环境变量(`auth_token`)获得 GitHub 的个人访问令牌。 另一种方法是使用**机密**来存储敏感信息。 + +来自 Docker 文档。 +> ... secret是一团数据,如密码、SSH 私钥、SSL 证书或其他数据,不应通过网络传输或未经加密存储在 Docker 文件或应用程序的源代码中。 + +这是一个比环境变量更安全的选择。环境变量更容易使用,但最适合于非保密的配置项目。 似乎很适合用于存储`auth_token`值。 + +请参阅[docs](https://docs.openfaas.com/reference/secrets/)中关于secret的更多信息和它的设计。 + +### 创建一个secret + +> secret名称必须遵循 DNS-1123 惯例,由小写字母数字字符或'-'组成,并且必须以一个字母数字字符开始和结束 + +从一个终端运行以下命令。 + +```plain +$ echo -n | faas-cli secret create auth-token +``` + +测试secret是否被创建。 + +```plain +$ faas-cli secret ls +``` +> 注意:请记住,`-g`标志可以在网关之间轻松切换。 这也适用于secret。 + +```plain +kubectl get secret auth-token -n openfaas-fn -o json +``` + +> 注意:如果你在远程网关上部署你的函数,确保你在你用于网关的虚拟机上创建你的secret。 + +当secret被函数挂载时,它将以文件形式出现在`/var/openfaas/secrets/auth-token`下。这可以由`handler.py`读取,以获得 GitHub 的*个人访问令牌*。 + +### 更新 issue-bot.yml + +用一个指令取代对`env.yml`的引用,使`auth-token`的secret对函数可用。 + +```yml +provider: + name: openfaas + gateway: http://127.0.0.1:8080 + +functions: + issue-bot: + lang: python3 + handler: ./issue-bot + image: /issue-bot + environment: + write_debug: true + gateway_hostname: "gateway.openfaas" + positive_threshold: 0.25 + secrets: + - auth-token +``` + +### 更新`issue-bot`函数 + +函数处理程序需要改变,以使其读取`auth-token`secret,而不是环境变量。 这只是一个单行的改动,在这里。 + +python +g = Github(os.getenv("auth_token")) +```plain +被替换为 +```python +with open("/var/openfaas/secrets/auth-token", "r") as authToken: + g = Github(authToken.read()) +``` + +> 完整的源代码可在[issue-bot-secrets/bot-handler/handler.py](./issue-bot-secrets/bot-handler/handler.py) + +* 构建和部署 + +使用 CLI 来构建和部署该函数。 + +```plain +$ faas-cli up -f issue-bot.yml +``` + +现在转到[Lab 11](lab11.md)。 \ No newline at end of file diff --git a/translations/cn/lab11.md b/translations/cn/lab11.md new file mode 100644 index 0000000..2c5dd90 --- /dev/null +++ b/translations/cn/lab11.md @@ -0,0 +1,203 @@ +# Lab 11 - 高级函数 - 使用 HMAC 的信任 + + + +## 前言 + +用于微服务的传统认证策略与函数的工作原理完全相同。在这个实验室中,我们将讨论使用共享secret和基于哈希的消息验证码(HMAC)的几种可用方法之一。有关其他认证策略和想法,请参见。[openfaas-function-auth](https://github.com/openfaas-incubator/openfaas-function-auth/blob/master/README.md) + +这绝不是一个广泛的清单,安全和认证是一个复杂的领域,最好留给专家使用经过试验的方法。 + +## 准备好你的环境 + +在开始这个实验之前,创建一个新的文件夹 + +```bash +mkdir -p lab11\`bash + && cd lab11 +``` + +也要确保你的`faas-cli'版本是`0.7.4'或以上,使用以下命令。 + +```plain +$ faas-cli version +``` + +## 什么是 HMAC + +如果没有任何形式的认证或信任,我们的函数可能会暴露给任何能猜到其 URL 的人。如果我们的函数可以在互联网或本地网络上访问,那么它们就可能被坏的行为者调用。默认情况下,函数会对任何请求做出响应。然而,如果我们想控制对函数的访问,我们可以使用基于哈希的消息验证码(HMAC)来验证信息的来源。 + +来自[alexellis/hmac](https://github.com/alexellis/hmac)。 +> HMAC 使用发送方/接收方提前共享的对称密钥。发送方在想要传输信息时将产生一个哈希值--该数据与有效载荷一起发送。然后,收件人将用共享密钥签署有效载荷,如果哈希值匹配,则假定有效载荷来自发件人。 + +这样我们就可以避免我们的函数被无效的甚至是危险的信息所调用。 + +## 使用 HMAC + +我们将使用 faas-cli 提供的`--sign`标志来包含一个头,其中包含使用我们用`--key`标志提供的共享密钥创建的散列信息。 + +> 注意: `--sign`和`--key`必须同时存在。 + +让我们首先通过部署`-env`函数来检查该标志的作用,该函数将打印函数中可访问的所有环境变量。 + +```bash +$ faas-cli deploy --name env --fprocess="env" --image="function/alpine:new" +``` + +* 调用不带`--sign`标志的函数。 + +```plain +$ echo "The message" | faas-cli invoke env +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/sbin:/bin +HOSTNAME=d2c1a2cb20c2 +fprocess=env +HOME=/root +Http_X_Call_Id=b84947c6-2970-4fcf-ba3b-66dde6943999 +Http_X_Forwarded_For=10.255.0.2:34974 +Http_X_Forwarded_Host=127.0.0.1:8080 +Http_Content_Length=0 +Http_Accept_Encoding=gzip +Http_Content_Type=text/plain +Http_User_Agent=Go-http-client/1.1 +Http_X_Start_Time=1538725657952768349 +... +``` + +* 再次调用该函数,但这次有`--sign`标志。 + +```plain +$ echo -n "The message" | faas-cli invoke env --sign=HMAC --key=cookie +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +HOSTNAME=d2c1a2cb20c2 +fprocess=env +HOME=/root +Http_User_Agent=Go-http-client/1.1 +Http_Content_Length=0 +Http_Accept_Encoding=gzip +... +Http_Hmac=sha1=9239edfe20185eafd7a5513c303b03d207d22f64 +... +``` + +我们看到`HMAC`被作为环境变量`Http_Hmac`提供。生成的值是用钥匙`cookie`签名后的`消息`的哈希值,然后用散列方法`sha1`进行预处理。 + +## HMAC 在行动 + +为了我们的目的,我们将创建一个新的 Python 3 函数。让我们把它叫做`hmac-protected`。 + +```bash +$ faas-cli new --lang python3 hmac-protected --prefix="" +``` + +添加`payload-secret`,它将作为哈希有效载荷的密钥。 + +像我们在[lab10](https://github.com/openfaas/workshop/blob/master/lab10.md)中那样创建`payload-secret`。 + +```bash +$ echo -n "" ! | faas-cli secret create payload-secret +``` + +> 注意:记住你放在""位置的字符串。 + +我们的 `hmac-protected.yml`应该看起来像。 + +```yml +provider: + name: openfaas + gateway: http://127.0.0.1:8080 + +functions: + hmac-protected: + lang: python3 + handler: ./hmac-protected + image: /hmac-protected:latest + secrets: + - payload-secret +``` + +用以下代码替换`handler.py`的内容。 + +```python +import os, hmac, hashlib + +def validateHMAC(message, secret, hash): + + # GitHub and the sign flag prefix the hash with "sha1=" + receivedHash = getHash(hash) + + # Hash message with secret + expectedMAC = hmac.new(secret.encode(), message.encode(), hashlib.sha1) + createdHash = expectedMAC.hexdigest() + + return receivedHash == createdHash + +def getHash(hash): + if "sha1=" in hash: + hash=hash[5:] + return hash + +def handle(req): + # We receive the hashed message in form of a header + messageMAC = os.getenv("Http_Hmac") + + # Read secret from inside the container + with open("/var/openfaas/secrets/payload-secret","r") as secretContent: + payloadSecret = secretContent.read() + + # Function to validate the HMAC + if validateHMAC(req, payloadSecret, messageMAC): + return "Successfully validated: " + req + return "HMAC validation failed." +``` + +> 源代码也可在[hmac-protected/hmac-protected/handler.py](./hmac-protected/hmac-protected/handler.py) + +* 通过使用`faas-cli up`在一个命令中构建、推送和部署该函数。 + +```plain +$ faas-cli up -f ./hmac-protected.yml +``` + +### 调用函数 + +我们将通过发送两个值来调用该函数。 + +* 正常的请求信息 + +* 一个包含同一消息的哈希值的头,当用`--key`标志的值签名时 + +在收到请求后,该函数将使用`payload-secret`以与发送者相同的方式签署请求信息。这将创建第二个 HMAC,并与传输的头信息 `Http-Hmac`进行比较。 + +这里我们比较生成和接收的哈希值。 + +```python +... + # Function to validate the HMAC + if validateHMAC(req, payloadKey, receivedHMAC): + return "Successfully validated: " + req + return "HMAC validation failed." +... +``` + +* 用标志来调用该函数。 + +```bash +$ echo -n "This is a message" | faas-cli invoke hmac-protected --sign hmac --key= +``` + +检查响应并确认它与所传达的信息相符。在我们的例子中,我们应该得到。 + +```plain +Successfully validated: This is a message +``` + +* 用错误的`--key`调用函数,检查失败信息。 + +```bash +$ echo -n "This is a message" | faas-cli invoke hmac-protected --sign hmac --key=wrongkey +HMAC validation failed. +``` + +作为后续任务,你可以应用 HMAC 来保护你在[实验室 5](https://github.com/openfaas/workshop/blob/master/lab5.md)的`issue-bot`上的端点。 + +你已经完成了实验,可以返回到[主页](./README.md)。 \ No newline at end of file diff --git a/translations/cn/lab1b.md b/translations/cn/lab1b.md new file mode 100644 index 0000000..38c8d3f --- /dev/null +++ b/translations/cn/lab1b.md @@ -0,0 +1,301 @@ +# Lab 1 - 用 Kubernetes 设置 OpenFaaS + + + +## 安装最新的 `kubectl` + +使用下面的说明或[官方文档](https://kubernetes.io/docs/tasks/tools/install-kubectl/)为你的操作系统安装`kubectl`。 + +- Linux + +```sh +export VER=$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt) +curl -LO https://storage.googleapis.com/kubernetes-release/release/$VER/bin/linux/amd64/kubectl +chmod +x kubectl +mv kubectl /usr/local/bin/ +``` + +- MacOS + +```sh +export VER=$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt) +curl -LO https://storage.googleapis.com/kubernetes-release/release/$VER/bin/darwin/amd64/kubectl +chmod +x kubectl +mv kubectl /usr/local/bin/ +``` + +- Windows + +```sh +export VER=$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt) +curl -LO https://storage.googleapis.com/kubernetes-release/release/$VER/bin/windows/amd64/kubectl.exe +chmod +x kubectl.exe +mkdir -p $HOME/bin/ +mv kubectl $HOME/bin/ +``` + +## 设置一个 Kubernetes 集群 + +你可以在使用 Kubernetes 的同时按照实验进行操作,但你可能需要沿途做一些小改动。网关的服务地址从`http://gateway:8080`改为`http://gateway.openfaas:8080`。这些差异已经尽可能地被记录下来,每个实验室都提供了替代方案。 + +### 在你的笔记本电脑上创建一个本地集群 + +#### _k3s 使用 k3d_ + +如果你的电脑上有 Docker,那么你可以使用 Rancher 实验室托管的`k3d`工具。它安装了一个轻量级的 Kubernetes 版本,叫做`k3s`,并在 Docker 容器中运行,这意味着它可以在任何有 Docker 的电脑上运行。 + +- [安装 k3d](https://github.com/rancher/k3d) + +- 启动一个集群 + +1. `k3d cluster create CLUSTER_NAME`创建一个新的单节点集群(=1 个运行 k3s 的容器+1 个负载均衡器容器) +2. 2.kubectl 的上下文会自动更新,你可以用`kubectl config get-contexts`来检查。 +3. 执行一些命令,如`kubectl get pods --all-namespaces`。 + 如果你想删除默认集群`k3d cluster delete CLUSTER_NAME`。 + +#### _Docker for Mac_ + +- [安装 Docker for Mac](https://docs.docker.com/v17.12/docker-for-mac/install/) + +> 请注意,Kubernetes 仅在 Docker for Mac 17.12 CE 及以上版本中可用。 + +#### _使用 Minikube_ + +- 要安装 Minikube,请根据你的平台从[最新版本](https://github.com/kubernetes/minikube/releases)下载适当的安装程序。 + +- 现在运行 Minikube + +```sh +minikube start +``` + +minikube 虚拟机通过一个仅限主机的 IP 地址暴露给主机系统。用`minikube ip`检查这个 IP。 +这是你以后将用于网关 URL 的 IP。 + +> 注意:Minikube 还需要一个 Hypervisor,如 VirtualBox 或 Hyperkit(在 MacOS 上)。按照 minikube 的说明和文件 + +### 在云上创建一个远程集群 + +你可以在云端创建一个远程集群,享受与本地开发一样的体验,同时节省 RAM/CPU 和电池。运行一个集群 1-2 天的费用是最低的。 + +#### _在 DigitalOcean 的 Kubernetes 服务上运行_ + +你可以使用免费点数通过 DigitalOcean 的用户界面创建一个集群。 + +然后 DigitalOcean 的仪表板将指导你如何配置你的`kubectl`和`KUBECONFIG`文件,以便在实验室中使用。 + +- [申请你的免费点数--30 天内有 50 美元的点数。](https://m.do.co/c/8d4e75e9886f) + +即使你已经申请了免费学分,一个 2-3 个节点的集群 24-48 小时的运行费用也是可以忽略不计的。 + +*点击仪表板左侧面板上的 Kubernetes*,然后点击 `启用有限访问` + +*一旦登录,点击 Kubernetes*菜单项并创建一个集群。 + +建议使用最新的 Kubernetes 版本,并选择离你最近的数据中心区域,以尽量减少延时。 + +- 在 `添加节点池`下 + +使用 2 个 4GB / 2vCPU + +> 注意:如果需要,你可以在以后添加更多的容量 + +- 下载[doctl](https://github.com/digitalocean/doctl#installing-doctl)CLI 并把它放在你的路径中。 + +- 在您的 DigitalOcean 仪表板上创建一个[API 密钥](https://cloud.digitalocean.com/account/api/tokens/new) + +追踪您的 API 密钥(将其复制到剪贴板)。 + +- 认证 CLI + +```sh +doctl auth init +``` + +粘贴你的 API 密钥 + +- 现在获得集群的名称。 + +```sh +$ doctl k8s cluster list +GUID workshop-lon1 nyc1 1.13.5-do.1 provisioning workshop-lon1-1 +``` + +- 保存一个配置文件,使`kubectl`指向新集群。 + +```sh +doctl k8s cluster kubeconfig save workshop-lon1 +``` + +现在你需要切换你的 Kubernetes 上下文以指向新的集群。 + +用`kubectl config get-contexts`找到集群名称,如果它没有突出显示,则输入`kubectl config set-context `。 + +#### _在 GKE(谷歌 Kubernetes 引擎)上运行_ + +登录到谷歌云,创建一个项目,并为其启用计费。如果你没有账户,你可以[在这里](https://cloud.google.com/free/)注册,获得免费点数。 + +安装[Google Cloud SDK](https://cloud.google.com/sdk/docs) - 这将使`gcloud`和`kubectl`命令可用。 +对于 Windows,请按照[文档](https://cloud.google.com/sdk/docs/#windows)中的说明。 + +安装 gcloud 命令行工具后,用`gcloud init`配置你的项目,并设置默认项目、计算区域和区域(用你自己的项目替换`PROJECT_ID`)。 + +```sh +gcloud config set project PROJECT_ID +gcloud config set compute/region us-central1 +gcloud config set compute/zone us-central1-a +``` + +启用 Kubernetes 服务。 + +```sh +gcloud services enable container.googleapis.com +``` + +安装 kubectl。 + +```sh +gcloud components install kubectl +``` + +创建一个 Kubernetes 集群。 + +```sh +$ gcloud container clusters create openfaas \ +--zone=us-central1-a \ +--num-nodes=1 \ +--machine-type=n1-standard-2 \ +--disk-size=30 \ +--no-enable-cloud-logging +``` + +为 `kubectl`设置凭证。 + +```sh +gcloud container clusters get-credentials openfaas +``` + +创建一个集群管理员角色绑定: + +```sh +$ kubectl create clusterrolebinding "cluster-admin-$(whoami)" \ +--clusterrole=cluster-admin \ +--user="$(gcloud config get-value core/account)" +``` + +现在验证`kubectl`已经配置到 GKE 集群。 + +```plain +$ kubectl get nodes +NAME STATUS ROLES AGE VERSION +gke-name-default-pool-eceef152-qjmt Ready 1h v1.10.7-gke.2 +``` + +## 部署 OpenFaaS + +部署 OpenFaaS 的说明会时常改变,因为我们努力使其更加简单。 + +### 安装 OpenFaaS + +有三种方式来安装 OpenFaaS,你可以选择对你和你的团队有意义的方式。在这个研讨会上,我们将使用官方的安装程序`arkade`。 + +- `arkade应用安装` - arkade 使用其官方舵手图安装 OpenFaaS。它还可以通过用户友好的 CLI 提供其他软件,如`cert-manager`和`nginx-ingress`。这是最简单和最快速的方式来启动和运行。 + +- 舵手图 - 理智的默认值,易于通过 YAML 或 CLI 标志进行配置。安全选项,如 `Helm 模板`或 `Helm 3`,也适用于那些在限制性环境中工作的人。 + +- 普通 YAML 文件 - 硬编码的设置/值。像 Kustomize 这样的工具可以提供自定义设置 + +#### 用`arkade`安装 + +- 获取 arkade + +对于 MacOS / Linux: + +```sh +# MacOS users may need to run "bash" first if this command fails +curl -SLsf https://dl.get-arkade.dev/ | sudo sh +``` + +对于 Windows。 + +```sh +curl -SLsf https://dl.get-arkade.dev/ | sh +``` + +- 安装 OpenFaaS 应用程序 + +如果你使用的是提供 LoadBalancers 的管理云 Kubernetes 服务,那么运行以下内容。 + +```sh +arkade install openfaas --load-balancer +``` + +> 注意:`--load-balancer`标志的默认值是`false`,所以通过该标志,安装将向你的云提供商请求一个。 + +如果你使用的是本地 Kubernetes 集群或虚拟机,那么请运行。 + +```sh +arkade install openfaas +``` + +在后面的实验室中,我们将向你展示如何使用 Kubernetes Ingress 设置一个带有 TLS 的自定义域。 + +#### 或者用 helm 安装(高级) + +如果你愿意,你可以使用[helm chart](https://github.com/openfaas/faas-netes/blob/master/chart/openfaas/README.md)的说明来安装 OpenFaaS。 + +### 登录你的 OpenFaaS 网关 + +- 检查网关是否准备好了 + +```sh +kubectl rollout status -n openfaas deploy/gateway +``` + +如果你使用你的笔记本电脑,虚拟机,或任何其他类型的 Kubernetes 分布,请运行以下内容。 + +```sh +kubectl port-forward svc/gateway -n openfaas 8080:8080 +``` + +这个命令将打开一个从 Kubernetes 集群到本地计算机的隧道,这样你就可以访问 OpenFaaS 网关。还有其他方法可以访问 OpenFaaS,但这已经超出了本次研讨会的范围。 + +你的网关 URL 是:`http://127.0.0.1:8080` + +如果你使用的是管理云 Kubernetes 服务,那么从下面的命令中的`EXTERNAL-IP`字段中获取 LoadBalancer 的 IP 地址或 DNS 条目。 + +```sh +kubectl get svc -o wide gateway-external -n openfaas +``` + +你的 URL 将是上面的 IP 或 DNS 条目,端口为`8080`。 + +- 登录。 + +```sh +export OPENFAAS_URL="" # Populate as above + +# This command retrieves your password +PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo) + +# This command logs in and saves a file to ~/.openfaas/config.yml +echo -n $PASSWORD | faas-cli login --username admin --password-stdin +``` + +- 检查`faas-cli list`是否工作。 + +```sh +faas-cli list +``` + +### 永久保存你的 OpenFaaS URL + +编辑`~/.bashrc`或`~/.bash_profile`--如果该文件不存在,则创建它。 + +现在添加以下内容--按照你上面看到的 URL 进行修改。 + +```sh +export OPENFAAS_URL="" # populate as above +``` + +现在转到[实验室 2](lab2.md) diff --git a/translations/cn/lab2.md b/translations/cn/lab2.md new file mode 100644 index 0000000..94294bf --- /dev/null +++ b/translations/cn/lab2.md @@ -0,0 +1,176 @@ +# 实验室 2--测试东西 + + + +在开始这个实验之前,创建一个新的文件夹。 + +```sh +$ mkdir -p lab2 \ + && cd lab2 +``` + +## 使用 UI 门户 + +现在你可以测试一下 OpenFaaS 的用户界面了。 + +如果你已经设置了一个`$OPENFAAS_URL`,那么就可以得到这个 URL,然后点击它。 + +```sh +echo $OPENFAAS_URL +http://127.0.0.1:31112 +``` + +如果你没有设置"$OPENFAAS_URL",那么默认情况下是这样的。[http://127.0.0.1:8080](http://127.0.0.1:8080). + +我们可以部署一些样本函数,然后用它们来测试一下。 + +```sh +faas-cli deploy -f https://raw.githubusercontent.com/openfaas/faas/master/stack.yml +``` + +![](../../screenshot/markdown_portal.png) + +你可以在用户界面中试用它们,比如将 Markdown 代码转换为 HTML 的 Markdown 函数。 + +在*Request*字段中键入以下内容。 + +```sh +## The **OpenFaaS** _workshop_ +``` + +现在点击*Invoke*,看到响应出现在屏幕的下半部分。 + +即。 + +```sh +

The OpenFaaS workshop

+``` + +你将看到以下字段显示。 + +- 状态 - 该函数是否准备好运行。在状态显示准备好之前,你将不能从用户界面调用该函数。 +- Replicas - 在集群中运行的函数的副本数量 +- 镜像 - 发布在 Docker Hub 或 Docker 资源库中的 Docker 图像名称和版本 +- 调用次数 - 这显示了该函数被调用的次数,每 5 秒更新一次 + +点击*Invoke*若干次,看到*Invocation count*的增加。 + +## 通过函数库进行部署 + +你可以从 OpenFaaS 商店中部署一个函数。该商店是一个由社区维护的免费函数集合。 + +- 点击 部署新的函数 +- 点击 from store + +- 点击 _Figlet_ 或在搜索栏中输入 _figlet_ ,然后点击 _Deploy_ 。 + +Figlet 函数现在将出现在你左边的函数列表中。给它一点时间从 Docker Hub 下载,然后输入一些文本,像我们对 Markdown 函数所做的那样,点击 Invoke。 + +你会看到一个 ASCII 码的标志,像这样生成。 + +```sh + _ ___ ___ _ __ +/ |/ _ \ / _ (_)/ / +| | | | | | | |/ / +| | |_| | |_| / /_ +|_|\___/ \___/_/(_) +``` + +## 了解 CLI 的情况 + +你现在可以测试一下 CLI 了,但首先要注意一下备用网关的 URL。 + +如果你的*网关没有*部署在,那么你将需要指定替代位置。有几种方法来实现这一点。 + +1. 设置环境变量`OPENFAAS_URL`,`faas-cli`将指向当前 shell 会话中的那个端点。例如:`export OPENFAAS_URL http://openfaas.endpoint.com:8080`。如果你是按照 Kubernetes 的指示,这已经在[Lab 1](./lab1.md)中设置好了。 +2. 用 `g`或`--gateway`标志在线指定正确的端点: `faas deploy --gateway http://openfaas.endpoint.com:8080`。 +3. 在你的部署 YAML 文件中,改变`gateway:`对象在`provider:`下指定的值。 + +### 列出已部署的函数 + +这将显示这些函数,你有多少个副本和调用次数。 + +```sh +faas-cli list +``` + +你应该看到*markdown*函数是 `markdown`,*figlet*函数也被列出来了,还有你调用了多少次。 + +现在试试使用 verbose 标志 + +```sh +faas-cli list --verbose +``` + +或 + +```sh +faas-cli list -v +``` + +现在你可以看到 Docker 镜像以及函数的名称。 + +### 调用一个函数 + +从你在`faas-cli list`上看到的函数中挑选一个,比如`markdown`。 + +```sh +faas-cli invoke markdown +``` + +现在你会被要求输入一些文本。完成后点击 Control + D。 + +或者你可以使用一个命令,如`echo`或`curl`作为`invoke`命令的输入,该命令通过使用管道工作。 + +```sh +$ echo "# Hi" | faas-cli invoke markdown + +$ curl -sLS https://raw.githubusercontent.com/openfaas/faas/master/README.md\。 + | faas-cli invoke markdown +``` + +## 监测仪表板 + +OpenFaaS 使用 Prometheus 自动跟踪你的函数的指标。这些指标可以通过免费的开源工具变成一个有用的仪表盘,比如[Grafana](https://grafana.com)。 + +在 OpenFaaS Kubernetes 命名空间运行 Grafana。 + +```sh +kubectl -n openfaas run \ +--image=stefanprodan/faas-grafana:4.6.3 \ +--port=3000 \ +grafana +``` + +用 NodePort 暴露 Grafana。 + +```sh +kubectl -n openfaas expose pod grafana \ +--type=NodePort \ +--name=grafana +``` + +找到 Grafana 节点的端口地址。 + +```sh +GRAFANA_PORT=$(kubectl -n openfaas get svc grafana -o jsonpath="{.spec.ports[0].nodePort}") +GRAFANA_URL=http://IP_ADDRESS:$GRAFANA_PORT/dashboard/db/openfaas +``` + +其中`IP_ADDRESS`是你在 Kubernetes 的对应 IP。 + +或者你可以运行这个端口转发命令,以便能够在`http://127.0.0.1:3000`上访问 Grafana。 + +```sh +kubectl port-forward pod/grafana 3000:3000 -n openfaas +``` + +如果你使用的是 Kubernetes 1.17 或更早的版本,请使用`deploy/grafana`而不是上面命令中的`pod/`。 + +服务创建后,在浏览器中打开 Grafana,用用户名`admin`密码`admin`登录,并导航到预先制作的 OpenFaaS 仪表板`$GRAFANA_URL`。 + + + +_图:使用 Grafana 的 OpenFaaS 仪表板的例子_。 + +现在转到[实验室 3](./lab3.md) diff --git a/translations/cn/lab3.md b/translations/cn/lab3.md new file mode 100644 index 0000000..9900477 --- /dev/null +++ b/translations/cn/lab3.md @@ -0,0 +1,548 @@ +# 实验 3--函数介绍 + + + +在开始这个实验之前,为你的文件创建一个新的文件夹。 + +```sh +$ mkdir -p lab3\`s + && cd lab3 +``` + +## 创建一个新的函数 + +有两种方法来创建一个新的函数。 + +* 使用一个内置的或社区的代码模板建立一个函数(默认情况下) +* 使用一个现有的二进制文件并将其作为你的函数(高级) + +### 构建或生成一个新函数 + +在用模板创建新函数之前,请确保你从 GitHub 上提取了[模板](https://github.com/openfaas/templates)。 + +```sh +$ faas-cli template pull + +Fetch templates from repository: https://github.com/openfaas/templates.git + Attempting to expand templates from https://github.com/openfaas/templates.git +2021/08/25 15:58:10 Fetched 13 template(s) : [csharp dockerfile go java11 java11-vert-x node node12 node14 php7 python python3 python3-debian ruby] from https://github.com/openfaas/templates.git +``` + +之后,要想知道哪些语言是可用的,请键入。 + +```sh +$ faas-cli new --list +Languages available as templates: +- csharp +- dockerfile +- go +- java11 +- java11-vert-x +- node +- node12 +- node14 +- php7 +- python +- python3 +- python3-debian +- ruby +``` + +或者创建一个包含`Dockerfile`的文件夹,然后在 YAML 文件中选择 `Dockerfile`语言类型。 + +在这一点上,你可以为 Python、Python 3、Ruby、Go、Node、CSharp 等创建一个新函数。 + +* 关于我们的例子的说明 + +我们这次研讨会的所有例子都经过了 OpenFaaS 社区对*Python 3*的全面测试,但也应该与*Python 2.7*兼容。 + +如果你喜欢使用 Python 2.7 而不是 Python 3,那么把`faas-cli new --lang python3`换成`faas-cli new --lang python`。 + +### Python 中的 Hello world + +我们将在 Python 中创建一个 hello-world 函数,然后转到也使用额外依赖的东西上。 + +* 构建函数的脚手架 + +```sh +faas-cli new --lang python3 hello-openfaas --prefix="" +``` + +参数`--prefix`将更新`image:`--prefix`参数将更新`hello-openfaas.yml`中的值,其前缀应该是你的Docker Hub账号。对于[OpenFaaS](https://hub.docker.com/r/functions)来说,这是`image: functions/hello-openfaas`,参数将是`--prefix="function"`。 + +如果你在创建函数时没有指定前缀,那么在创建后编辑 YAML 文件。 + +这将创建三个文件和一个目录。 + +```sh +./hello-openfaas.yml +./hello-openfaas +./hello-openfaas/handler.py +./hello-openfaas/requirements.txt +``` + +YAML (.yml) 文件是用来配置 CLI 来构建、推送和部署你的函数。 + +> 注意:每当你需要在 Kubernetes 或远程 OpenFaaS 实例上部署一个函数时,你必须在构建函数后推送它。在这种情况下,你也可以用一个环境变量覆盖默认的网关 URL,即 127.0.0.1:8080`。`export OPENFAAS_URL=127.0.0.1:31112`. + +下面是 YAML 文件的内容。 + +```yaml +provider: + name: openfaas + gateway: http://127.0.0.1:8080 + +functions: + hello-openfaas: + lang: python3 + handler: ./hello-openfaas + image: hello-openfaas +``` + +* 函数的名称由`functions`下的键表示,即`hello-openfaas`。 +* 语言由 `lang` 字段表示。 +* 用于构建的文件夹被称为 `handler`,它必须是一个文件夹而不是一个文件。 +* 要使用的 Docker 镜像名称在`image`字段下。 + +请记住,`gateway`URL 可以在 YAML 文件中(通过编辑`provider:`下的`gateway:`值)或在 CLI 上(通过使用`--gateway`或设置`OPENFAAS_URL`环境变量)进行覆盖。 + +下面是`handler.py`文件的内容。 + +```python +def handle(req): + """handle a request to the function + Args: + req (str): request body + """ + + return req +``` + +这个函数将只是返回输入,所以它实际上是一个`echo`函数。 + +编辑信息,使其返回 `Hello OpenFaaS`,例如。 + +```python + return "Hello OpenFaaS" +``` + +任何返回到 stdout 的值都会随后返回到调用程序。另外,也可以使用`print()`语句,它将表现出类似的流向,并传递给调用程序。 + +这是本地开发人员对函数的工作流程。 + +```sh +faas-cli up -f hello-openfaas.yml +``` + +> 注意:在运行这个命令之前,请确保你已经用`docker login`命令登录了 docker 注册中心。 + +> 注意: `faas-cli up`命令将`faas-cli`的构建、推送和部署命令合并为一条命令。 + +随后通过用户界面、CLI、`curl`或其他应用程序调用该函数。 + +该函数将始终获得一个路由,例如。 + +```sh +$OPENFAAS_URL/function/(函数名)。 +$OPENFAAS_URL/function/figlet +$OPENFAAS_URL/function/hello-openfaas +``` + +> 提示:如果你把 YAML 文件重命名为`stack.yml`,那么你就不需要向任何命令传递`-f`标志。 + +函数只能通过`GET`或`POST`方法来调用。 + +* 调用你的函数 + +用`faas-cli invoke`测试函数,查看`faas-cli invoke --help`获取更多选项。 + +### 示例函数:astronaut-finder + +我们将创建一个名为 `astronaut-finder` 的函数,在国际空间站(ISS)上随机拉出一个太空人的名字。 + +```sh +faas-cli new --lang python3 astronaut-finder --prefix="" +``` + +这将为我们写三个文件。 + +```sh +./astronaut-finder/handler.py +``` + +函数的处理程序--你会得到一个带有原始请求的`req`对象,并可以将函数的结果打印到控制台。 + +```sh +./astronaut-finder/requirements.txt +``` + +这个文件用来管理函数--它有函数的名称、Docker 镜像和任何其他需要的定制。 + +```sh +./astronaut-finder.yml +``` + +使用该文件列出你要安装的任何`pip`模块,如`requests`或`urllib`。 + +* 编辑`./astronaut-finder/requirements.txt`。 + +```sh +requests +``` + +这告诉函数它需要使用一个名为[requests](http://docs.python-requests.org/en/master/)的第三方模块,用于通过 HTTP 访问网站。 + +* 编写该函数的代码。 + +我们将从以下地方拉入数据: + +下面是一个结果的例子。 + +```json +{"number": 6, "people": [{"craft": "ISS", "name": "Alexander Misurkin"}, {"craft": "ISS", "name": "Mark Vande Hei"}, {"craft": "ISS", "name": "Joe Acaba"}, {"craft": "ISS", "name": "Anton Shkaplerov"}, {"craft": "ISS", "name": "Scott Tingle"}, {"craft": "ISS", "name": "Norishige Kanai"}], "message": "success"} +``` + +更新`handler.py`。 + +```python +import requests +import random + +def handle(req): + r = requests.get("http://api.open-notify.org/astros.json") + result = r.json() + index = random.randint(0, len(result["people"])-1) + name = result["people"][index]["name"] + + return "%s is in space" % (name) +``` + +> 注意:在这个例子中,我们没有使用参数`req`,但必须把它放在函数的头部。 + +现在建立这个函数。 + +```sh +faas-cli build -f ./astronaut-finder.yml +``` + +> 提示。试着把 astronaut-finder.yml 重命名为`stack.yml`,然后只调用`faas-cli build`。`stack.yml`是 CLI 的默认文件名。 + +推送函数。 + +```sh +faas-cli push -f ./astronaut-finder.yml +``` + +部署该函数。 + +```sh +faas-cli deploy -f ./astronaut-finder.yml +``` + +调用该函数 + +```sh +$ echo | faas-cli invoke astronaut-finder +安东-史卡普勒夫在太空中 + +$ echo | faas-cli invoke astronaut-finder +乔-阿卡巴在太空中 +``` + +## 故障排除:找到容器的日志 + +你可以通过容器的日志找到你的函数的每次调用的高级信息。 + +```sh +kubectl logs deployment/astronaut-finder -n openfaas-fn +``` + +## 故障排除:使用`write_debug'的 verbose 输出 + +让我们为你的函数打开 verbose 输出。这在默认情况下是关闭的,这样我们就不会用数据淹没你的函数的日志--这在处理二进制数据时尤其重要,因为二进制数据在日志中没有意义。 + +这是标准的 YAML 配置。 + +```yaml +provider: + name: openfaas + gateway: http://127.0.0.1:8080 + +functions: + astronaut-finder: + lang: python3 + handler: ./astronaut-finder + image: astronaut-finder +``` + +为该函数编辑 YAML 文件,并添加一个 `environment` 部分。 + +```yaml + astronaut-finder: + lang: python3 + handler: ./astronaut-finder + image: astronaut-finder + environment: + write_debug: true +``` + +现在用`faas-cli deploy -f ./astronaut-finder.yml`再次部署你的函数。 + +调用该函数,然后再次检查日志,查看函数的响应。 + +```sh +kubectl logs deployment/astronaut-finder -n openfaas-fn +``` + +### 管理多个函数 + +CLI 的 YAML 文件允许将函数分组为堆栈,这在处理一组相关函数时很有帮助。 + +为了了解它是如何工作的,生成两个函数。 + +```sh +faas-cli new --lang python3 first +``` + +对于第二个函数使用`--append`标志。 + +```sh +faas-cli new --lang python3 second --append=./first.yml +``` + +为了方便起见,我们把`first.yml`改名为`example.yml`。 + +```sh +mv first.yml example.yml +``` + +现在看看这个文件。 + +```yaml +provider: + name: openfaas + gateway: http://127.0.0.1:8080 + +functions: + first: + lang: python3 + handler: ./first + image: first + second: + lang: python3 + handler: ./second + image: second +``` + +这里有几个标志,在处理函数堆栈时有帮助。 + +* 以并行方式构建。 + +```sh +faas-cli build -f ./example.yml --parallel=2 +``` + +* 只建立/推送一个函数。 + +```sh +faas-cli build -f ./example.yml --filter=second +``` + +花点时间来探索`build`/`push`和`deploy`的选项。 + +* `faas-cli build --help`。 +* `faas-cli push --help`。 +* `faas-cli deploy --help`。 + +要同时运行`faas-cli build &&faas-cli push &&faas-cli deploy`,请使用`faas-cli up`代替。 + +> 专业提示:如果你不想传递`-f`参数,`stack.yml`是 faas-cli 寻找的默认名称。 + +你也可以使用`faas-cli deploy -f https://....`通过 HTTP(s)部署远程函数栈(yaml)文件。 + +### 自定义模板 + +如果你有自己的一套分叉模板或自定义模板,那么你可以把它们拉下来,用 CLI 使用。 + +下面是一个获取 Python 3 模板的例子,它使用 Debian Linux。 + +使用 `git` URL 拉取模板。 + +```sh +faas-cli template pull https://github.com/openfaas-incubator/python3-debian +``` + +现在键入 `faas-cli new --list`。 + +```sh +$ faas-cli new --list | grep python +- python +- python3 +- python3-debian +``` + +这些新模板会被保存在你当前的工作目录下`./templates/`。 + +#### 自定义模板。模板商店 + +模板商店*是一个类似于*函数商店*的概念,它使用户可以通过分享他们的模板来进行协作。模板商店也意味着你不必记住任何 URL 来利用你喜欢的社区或项目模板。 + +你可以使用以下两个命令来搜索和发现模板。 + +```sh +$ faas-cli template store list +$ faas-cli template store list -v + +NAME SOURCE DESCRIPTION +csharp openfaas Classic C# template +dockerfile openfaas Classic Dockerfile template +go openfaas Classic Golang template +... +``` + +为了获得更多的细节,你可以使用`--verbose`标志,或者`describe`命令。 + +让我们找到一个具有 HTTP 格式的 Golang 模板。 + +```bash +faas-cli template store list | grep golang + +golang-http openfaas +Golang HTTP template +golang-middleware openfaas +Golang Middleware template +``` + +然后查看其上游仓库。 + +```sh +$ faas-cli template store describe golang-http + +Name: golang-http +Platform: x86_64 +Language: Go +Source: openfaas +Description: Golang HTTP template +Repository: https://github.com/openfaas/golang-http-template +Official Template: true +``` + +把模板拉下来。 + +```sh +faas-cli template store pull golang-http +``` + +现在你可以通过输入以下内容用这个模板创建一个函数。 + +bash +faas-cli new --lang golang-http NAME + +```plain + +为了比运行`faas-cli template store pull golang-http`来创建函数更容易,你可以在你的stack.yml文件中附加以下内容。 + +```yaml +configuration: + templates: + - name: golang-http +``` + +然后运行以下内容,而不是指定模板名称。 + +```bash +faas-cli template store pull +``` + +也请参见。 + +* [OpenFaaS YAML 参考指南](https://docs.openfaas.com/reference/yaml/) +* [函数与模板存储](https://github.com/openfaas/store/) + +### YAML 文件中的变量替换(可选练习) + +用于配置 CLI 的`.yml`文件能够进行变量替换,这样你就能够使用同一个`.yml`文件进行多种配置。 + +其中一个例子是,当开发和生产图像有不同的注册表时,这就很有用。你可以使用变量替换,使本地和测试环境使用默认账户,而 CI 服务器可以被配置为使用生产账户。 + +> 这是由[envsubst 库]()提供的。遵循该链接可以看到支持的变量的例子 + +编辑你的`astronaut-finder.yml`以匹配以下内容。 + +```yml + astronaut-finder: + lang: python3 + handler: ./astronaut-finder + image: ${DOCKER_USER:-development}/astronaut-finder + environment: + write_debug: true +``` + +你会注意到`image`属性已被更新,包括一个变量定义(`DOCKER_USER`)。该值将被替换为同名的环境变量的值。如果环境变量不存在,或为空,将使用默认值(`development`)。 + +该变量将在整个文件中被替换成该值。所以,如果你的`.yml`文件中有几个函数,所有对`DOCKER_USER`变量的引用将被替换为该环境变量的值 + +运行下面的命令并观察输出。 + +`faas-cli build -f ./astronaut-finder.yml`。 + +输出应该显示,构建的镜像被标记为`development/astronaut-finder:latest`。 + +现在,将环境变量设置为你的 Docker Hub 账户名(在这个例子中,我们将使用 OpenFaaS 的 `function`账户)。 + +```sh +export DOCKER_USER=functions +``` + +运行与之前相同的构建命令,观察输出。 + +`faas-cli build -f ./astronaut-finder.yml`。 + +现在输出应该显示,镜像是用更新的标签 `functions/astronaut-finder:latest`构建的。 + +### 自定义二进制文件作为函数(可选练习) + +自定义二进制文件或容器可以作为函数使用,但大多数时候,使用语言模板应该涵盖所有最常见的情况。 + +为了使用自定义二进制文件或 Dockerfile,使用`dockerfile`语言创建一个新函数。 + +```sh +faas-cli new --lang dockerfile sorter --prefix="" +``` + +你会看到一个名为 `sorter`和 `sorter.yml`的文件夹被创建。 + +编辑`sorter/Dockerfile`并更新设置`fprocess'的那一行。让我们把它改成内置的bash命令`sort`。我们可以用它来对一个字符串列表按字母数字顺序进行排序。 + +```dockerfile +ENV fprocess="sort" +``` + +现在构建、推送和部署该函数。 + +```sh +faas-cli up -f sorter.yml +``` + +现在通过用户界面或 CLI 来调用该函数。 + +```sh +$ echo -n ' +elephant +zebra +horse +aardvark +monkey'| faas-cli invoke sorter + +aardvark +elephant +horse +monkey +zebra +``` + +在这个例子中,我们使用了[BusyBox](https://busybox.net/downloads/BusyBox.html)中的`sort`,它是内置的函数。还有其他有用的命令,如`sha512sum`,甚至是`bash`或 shell 脚本,但你并不局限于这些内置命令。任何二进制或现有的容器都可以通过添加 OpenFaaS 函数看门狗而成为无服务器函数。 + +> 提示:你知道 OpenFaaS 也支持 Windows 二进制文件吗?比如 C#、VB 或 PowerShell? + +现在进入[实验室 4](lab4.md) diff --git a/translations/cn/lab4.md b/translations/cn/lab4.md new file mode 100644 index 0000000..b1b819c --- /dev/null +++ b/translations/cn/lab4.md @@ -0,0 +1,425 @@ +# 实验 4--更深入地使用函数 + + + +在开始本实验之前,为你的文件创建一个新的文件夹。由于本实验是建立在早期实验的基础上的,所以请复制 lab3。 + +```plain +$ cp -r lab3 lab4\ + && cd lab4 +``` + +## 通过环境变量注入配置 + +能够控制一个函数在运行时的行为方式是很有用的,我们至少可以通过两种方式来实现这一点。 + +### 在部署时 + +* 在部署时设置环境变量 + +我们在[Lab 3](./lab3.md)中用`write_debug`做了这个 - 你也可以在这里设置任何你想要的自定义环境变量 - 例如,如果你想为你的*hello world*函数配置一种语言,你可以引入一个`spoken_language`变量。 + +### 使用 HTTP 上下文--querystring / headers + +* 使用 querystring 和 HTTP headers + +另一个更动态的、可以在每个请求层面上改变的选项是使用查询字符串和 HTTP 头信息,两者都可以通过`faas-cli`或`curl`传递。 + +这些头信息通过环境变量暴露出来,所以它们很容易在你的函数中被使用。所以任何头信息都以`Http_`为前缀,所有`-`连字符都被替换成`_`下划线。 + +让我们用 querystring 和一个列出所有环境变量的函数来试试。 + +* 使用 BusyBox 的内置命令,部署一个打印环境变量的函数。 + +```plain +faas-cli deploy --name env --fprocess="env" --image="function/alpine:latest" +``` + +* 用一个查询字符串调用该函数。 + +```sh +$ echo "" | faas-cli invoke env --query workshop=1 +PATH=/usr/local/bin:/usr/local/bin:/usr/bin:/sbin:/bin +HOSTNAME=05e8db360c5a +fprocess=env +HOME=/root +Http_Connection=close +Http_Content_Type=text/plain +Http_X_Call_Id=cdbed396-a20a-43fe-9123-1d5a122c976d +Http_X_Forwarded_For=10.255.0.2 +Http_X_Start_Time=1519729562486546741 +Http_User_Agent=Go-http-client/1.1 +Http_Accept_Encoding=gzip +Http_Method=POST +Http_ContentLength=-1 +Http_Path=/ +... +Http_Query=workshop=1 +... +``` + +在 Python 代码中,你会输入`os.getenv("Http_Query")`。 + +* 将路径附加到你的函数 URL 上 + +用以下方法调用 env 函数。 + +```sh +$ curl -X GET $OPENFAAS_URL/function/env/some/path -d "" +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/sbin:/bin +HOSTNAME=fae2ac4b75f9 +fprocess=env +HOME=/root +Http_X_Forwarded_Host=127.0.0.1:8080 +Http_X_Start_Time=1539370471902481800 +Http_Accept_Encoding=gzip +Http_User_Agent=curl/7.54.0 +Http_Accept=*/* +Http_X_Forwarded_For=10.255.0.2:60460 +Http_X_Call_Id=bb86b4fb-641b-463d-ae45-af68c1aa0d42 +Http_Method=GET +Http_ContentLength=0 +... +Http_Path=/some/path +... +``` + +正如你所看到的,`Http_Path`头包含你的路径。 +如果你想在你的代码中使用它,只要用`os.getenv("Http_Path")`来获取它。 + +* 现在用标头来调用它。 + +```sh +$ curl $OPENFAAS_URL/function/env --header "X-Output-Mode: json" -d "" +PATH=/usr/local/bin:/usr/local/bin:/usr/bin:/sbin:/bin +HOSTNAME=05e8db360c5a +fprocess=env +HOME=/root +Http_X_Call_Id=8e597bcf-614f-4ca5-8f2e-f345d660db5e +Http_X_Forwarded_For=10.255.0.2 +Http_X_Start_Time=1519729577415481886 +Http_Accept=*/* +Http_Accept_Encoding=gzip +Http_Connection=close +Http_User_Agent=curl/7.55.1 +Http_Method=GET +Http_ContentLength=0 +Http_Path=/ +... +Http_X_Output_Mode=json +... +``` + +在 Python 代码中,你会输入`os.getenv("Http_X_Output_Mode")'。 + +你可以看到所有其他的 HTTP 上下文也被提供了,比如当 `Http_Method`是 `POST`时的 `Content-Length`,`User_Agent`,Cookies 和其他你期望从 HTTP 请求中看到的东西。 + +## 安全:只读文件系统 + +OpenFaaS 可以使用的容器安全特性之一是使我们执行环境的根文件系统只读的能力。如果一个函数被破坏,这可以减少攻击面。 + +生成一个函数,将文件保存到函数的文件系统中。 + +```sh +faas-cli new --lang python3 ingest-file --prefix=your-name +``` + +更新处理程序。 + +```python +import os +import time + +def handle(req): + # Read the path or a default from environment variable + path = os.getenv("save_path", "/home/app/") + + # generate a name using the current timestamp + t = time.time() + file_name = path + str(t) + + # write a file + with open(file_name, "w") as f: + f.write(req) + f.close() + + return file_name +``` + +建立这个例子。 + +```sh +faas-cli up -f ingest-file.yml +``` + +调用该例子。 + +```sh +echo "Hello function" > message.txt + +cat message.txt | faas-cli invoke -f ingest-file.yml ingest-file +``` + +该文件将被写入`/home/app`路径中。 + +现在编辑 ingest-file.yml 并使该函数为只读。 + +```yaml +... +functions: + ingest-file: + lang: python3 + handler: ./ingest-file + image: alexellis2/ingest-file:latest + readonly_root_filesystem: true +``` + +> 也请参见。[YAML 参考](https://docs.openfaas.com/reference/yaml/#function-read-only-root-filesystem) + +再次部署。 + +```sh +faas-cli up -f ingest-file.yml +``` + +现在这将会失败。 + +```sh +echo "Hello function" > message.txt + +cat message.txt | faas-cli invoke -f ingest-file.yml ingest-file +``` + +请看错误。 + +```sh +Server returned unexpected status code: 500 - exit status 1 +Traceback (most recent call last): + File "index.py", line 19, in + ret = handler.handle(st) + File "/home/app/function/handler.py", line 13, in handle + with open(file_name, "w") as f: +OSError: [Errno 30] Read-only file system: '/home/app/1556714998.092464' +``` + +为了写到一个临时区域,设置环境变量`save_path`。 + +```yaml +... +functions: + ingest-file: + lang: python3 + handler: ./ingest-file + image: alexellis2/ingest-file:latest + readonly_root_filesystem: true + environment: + save_path: "/tmp/" +``` + +现在你可以再运行一次`faas-cli up -f ingest-file.yml`来测试这个修正,文件将被写入`/tmp/`。 + +我们现在有能力锁定我们的函数代码,使其不能被意外改变或恶意更新。 + +## 利用日志记录 + +OpenFaaS 看门狗通过标准 I/O 流`stdin`和`stdout`传入 HTTP 请求和读取 HTTP 响应来运行。这意味着作为一个函数运行的进程不需要知道任何关于网络或 HTTP 的信息。 + +一个有趣的情况是,当一个函数以非零退出代码退出时,`stderr`不是空的。 +默认情况下,一个函数的`stdout/stderr`是合并的,`stderr`不被打印到日志中。 + +让我们用[Lab 3](./lab3.md#hello-world-in-python)中的`hello-openfaas`函数来检查。 + +将`handler.py`的代码改为 + +```python +import sys +import json + +def handle(req): + + sys.stderr.write("This should be an error message.\n") + return json.dumps({"Hello": "OpenFaaS"}) +``` + +构建和部署 + +```sh +faas-cli up -f hello-openfaas.yml +``` + +现在用以下方法调用该函数 + +```sh +echo | faas-cli invoke hello-openfaas +``` + +你应该看到合并输出。 + +```plain +This should be an error message. +{"Hello": "OpenFaaS"} +``` + +> 注意:如果你用`docker service logs hello-openfaas`检查容器日志(或者`kubectl logs deployment/hello-openfaas -n openfaas-fn`),你应该看不到 stderr 输出。 + +在这个例子中,我们需要这个函数返回有效的 JSON,可以被解析。不幸的是,日志信息使输出无效。 +所以我们需要将这些信息从 stderr 重定向到容器的日志中。 +OpenFaaS 提供了一个解决方案,所以你可以将错误信息打印到日志中,并保持函数响应的清晰,只返回`stdout`。 +为此你应该使用`combine_output`标志。 + +让我们来试试。打开`hello-openfaas.yml`文件,添加这些行。 + +```yaml + environment: + combine_output: false +``` + +部署并调用该函数。 + +输出应该是。 + +```plain +{"Hello": "OpenFaaS"} +``` + +检查容器日志中的`stderr`。你应该看到类似的信息。 + +```plain +hello-openfaas.1.2xtrr2ckkkth@linuxkit-025000000001 | 2018/04/03 08:35:24 stderr: This should be an error message. +``` + +## 创建工作流 + +在有些情况下,把一个函数的输出作为另一个函数的输入是很有用的。 这在客户端和通过 API 网关都可以实现。 + +### 客户端上的连锁函数 + +你可以使用`curl`、`faas-cli`或一些你自己的代码将一个函数的结果输送到另一个函数。这里有一个例子。 + +优点。 + +* 不需要代码 - 可以用 CLI 程序完成 +* 快速开发和测试 +* 容易在代码中建模 + +缺点。 + +* 额外的延迟 - 每个函数都要返回到服务器上 +* 聊天(更多的信息) + +例子。 + +* 从*函数库*部署 NodeInfo 函数 + +* 然后通过 Markdown 转换器推送 NodeInfo 的输出 + +```sh +$ echo -n "" | faas-cli invoke nodeinfo | faas-cli invoke markdown +

Hostname: 64767782518c

+ +

Platform: linux +Arch: x64 +CPU count: 4 +Uptime: 1121466

+``` + +现在你会看到 NodeInfo 函数的输出被装饰成 HTML 标签,例如。`

`. + +另一个客户端函数链的例子可能是调用一个生成图像的函数,然后将该图像发送到另一个添加水印的函数中。 + +### 从另一个函数中调用一个函数 + +从另一个函数中调用一个函数的最简单方法是通过 OpenFaaS *API 网关*通过 HTTP 进行调用。这个调用不需要知道外部域名或 IP 地址,它可以简单地通过 DNS 条目将 API 网关称为`gateway`。 + +当从一个函数访问 API 网关等服务时,最好的做法是使用环境变量来配置主机名,这很重要,有两个原因--名称可能会改变,在 Kubernetes 中有时需要一个后缀。 + +优点。 + +* 函数之间可以直接利用对方 +* 低延迟,因为函数可以在同一网络上相互访问 + +缺点。 + +* 需要一个代码库来进行 HTTP 请求 + +例子。 + +在[实验室 3](./lab3.md)中,我们介绍了 request 模块,并使用它来调用一个远程 API,以获得国际空间站上的一个宇航员的名字。我们可以使用同样的技术来调用部署在 OpenFaaS 上的另一个函数。 + +* 使用用户界面,进入*函数商店*并部署*情感分析*函数。 + +或者使用 CLI。 + +```plain +faas-cli store deploy SentimentAnalysis +``` + +情感分析函数将告诉你任何句子的主观性和极性(积极性评级)。该函数的结果是以 JSON 格式显示的,如下面的例子。 + +```sh +$ echo -n "California is great, it's always sunny there." | faas-cli invoke sentimentanalysis +{"polarity": 0.8, "sentence_count": 1, "subjectivity": 0.75} +``` + +因此,结果显示我们的测试句子既非常主观(75%)又非常积极(80%)。这两个字段的值总是在`-1.00`和`1.00`之间。 + +下面的代码可以用来调用*情绪分析*函数或任何其他函数。 + +给网关主机加上`openfaas`命名空间的后缀。 + +```python + r = requests.get("http://gateway.openfaas:8080/function/sentimentanalysis", text= test_sentence) +``` + +或者通过一个环境变量。 + +```python + gateway_hostname = os.getenv("gateway_hostname", "gateway.openfaas") # uses a default of "gateway.openfaas" for when "gateway_hostname" is not set + test_sentence = "California is great, it's always sunny there." + r = requests.get("http://" + gateway_hostname + ":8080/function/sentimentanalysis", data= test_sentence) +``` + +由于结果总是以 JSON 格式出现,我们可以利用辅助函数`.json()`来转换响应。 + +```python + result = r.json() + if result["polarity"] > 0.45: + return "That was probably positive" + else: + return "That was neutral or negative" +``` + +现在,在 Python 中创建一个新的函数,并将其全部整合起来 + +```python +import os +import requests +import sys + +def handle(req): + """handle a request to the function + Args: + req (str): request body + """ + + gateway_hostname = os.getenv("gateway_hostname", "gateway.openfaas") # uses a default of "gateway" for when "gateway_hostname" is not set + + test_sentence = req + + r = requests.get("http://" + gateway_hostname + ":8080/function/sentimentanalysis", data= test_sentence) + + if r.status_code != 200: + sys.exit("Error with sentimentanalysis, expected: %d, got: %d\n" % (200, r.status_code)) + + result = r.json() + if result["polarity"] > 0.45: + return "That was probably positive" + else: + return "That was neutral or negative" +``` + +* 记得在你的`requirements.txt`文件中加入`requests`。 + +注意:你不需要修改或改变 SentimentAnalysis 函数的源代码,我们已经部署了它并将通过 API 网关访问它。 + +现在转到[实验室 5](lab5.md)。 diff --git a/translations/cn/lab5.md b/translations/cn/lab5.md new file mode 100644 index 0000000..923a6b2 --- /dev/null +++ b/translations/cn/lab5.md @@ -0,0 +1,414 @@ +# Lab 5 - 创建一个 GitHub 机器人 + + + +在开始这个实验之前,为你的文件创建一个新的文件夹。 + +```sh +$ mkdir -p lab5\ + && cd lab5 +``` + +我们将使用 OpenFaaS 的函数来创建一个名为 `issue-bot`的 GitHub 机器人。 + +问题机器人的工作是通过分析 `描述` 字段的情绪来分流新的问题,然后它将应用一个*积极*或*审查*的标签。这将有助于维护者在繁忙的工作中,可以优先考虑哪些问题需要首先处理。 + +问题机器人的图示](./diagram/issue-bot.png) + +## 获取一个 GitHub 账户 + +* 注册一个[GitHub 账户](https://github.com),如果你还没有一个账户。 + +* 创建一个新的仓库,并将其称为*bot-test*。 + +注意:我们将只使用这个仓库作为创建问题的测试场所。你不需要在那里提交任何代码。 + +## 建立一个带有入口的隧道 + +你需要接收来自 GitHub 的 webhooks。幸运的是,inlets 让这一切变得非常快速和简单。它可以按月或按年订阅,所以如果你不确定是否全年都需要它,你可以只付一个月的钱。 + +inlets 有一个叫做 inlets-operator 的 Kubernetes 集成。你可以用它来设置 LoadBalancers 或带有 TLS 的 Ingress。它的工作原理是为你创建一个云虚拟机,并在那里运行一个隧道服务器,然后为你运行一个隧道客户端作为一个 Pod,你就可以获得传入流量。 + +在你喜欢的云提供商(如 DigitalOcean)的 API 页面下创建一个写入访问令牌,然后将内容保存到`digital-ocean-api-token.txt`。 + +设置完订阅后,将你的密钥保存到`$HOME/.inlets/LICENSE`,然后运行以下程序。 + +```bash +arkade install inlets-operator \ + --provider digitalocean \ + --region lon1 \ + --token-file $HOME/digital-ocean-api-token.txt +``` + +这将部署 inlets-operator,并指示它在 DigitalOcean 上为你的隧道服务器配置新的主机到伦敦地区。其他供应商和地区也可以使用,[更多信息请见文档](https://docs.inlets.dev/reference/inlets-operator/)。 + +## 用网关的公共 IP 登录你的网关 + +用信息检索你的网关密码,从。 + +```bash +arkade info openfaas +``` + +LoadBalancer 的公共 IP 大约需要 10-30 秒才能出现。 + +```bash +kubectl get svc -n openfaas gateway-external +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +gateway-external LoadBalancer 10.96.29.46 8080:32278/TCP 5h56m +gateway-external LoadBalancer 10.96.29.46 165.227.233.227 8080:32278/TCP 5h56m +``` + +然后把它保存到环境变量中。 + +```bash +export OPENFAAS_URL=http://165.227.233.227:8080 +``` + +用给你的密码登录到公共 IP。 + +```bash +echo $PASSWORD | faas-cli login --password-stdin +``` + +最后测试远程 URL,如http://165.227.233.227:8080 + +你可以通过设置`OPENFAAS_URL`环境变量或使用`--gateway`标志来对远程网关运行命令。 + +如果你想用 TLS 证书和自定义域名来暴露 OpenFaaS,你可以按照这些说明来代替。 + +```bash +arkade install ingress-nginx +arkade install cert-manager +arkade install openfaas +arkade install openfaas-ingress \ + --email web@example.com \ + --domain openfaas.example.com +``` + +然后创建一个 DNS A 记录,指向 ingress-nginx 的 IP 地址。 + +```bash +kubectl get svc ingress-nginx-controller +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +ingress-nginx-controller LoadBalancer 10.96.179.20 80:30319/TCP,443:31591/TCP 20s +ingress-nginx-controller LoadBalancer 10.96.179.20 209.97.135.63 80:30319/TCP,443:31591/TCP 52s +``` + +现在你可以为`https://openfaas.example.com`提供一个自定义的 TLS 记录。 + +## 创建一个 webhook 接收器`issue-bot` + +```bash +export OPENFAAS_PREFIX="docker.io/your-username" +$ faas-cli new --lang python3 \ + issue-bot +``` + +现在编辑该函数的 YAML 文件`issue-bot.yml`并添加一个环境变量`write_debug: true`。 + +```yaml +provider: + name: openfaas + gateway: http://127.0.0.1:8080 + +functions: + issue-bot: + lang: python3 + handler: ./issue-bot + image: docker.io/your-username/issue-bot + environment: + write_debug: true +``` + +* 构建、推送和部署该函数,使用 + +```bash +$ faas-cli up -f ./issue-bot.yml +``` + +## 从 GitHub 接收 webhooks + +重新登录 GitHub 并导航到你的仓库*bot-tester*。 + +点击 *设置* -> *Webhooks* -> *添加 Webhook* + +![添加网络钩子](../../screenshot/add_github_webhook.png) + +现在输入你从 inlets 或你的自定义域中得到的 URL,在最后加上`/function/issue-bot`,例如。 + +```plain +https://openfaas.example.com +``` + +![添加webhook](../../screenshot/issue-bot-webhook.png) + +对于*Content-type*选择。*application/json* + +暂时将*Secret*留空。 + +并选择 `让我选择个别事件` + +对于事件选择**事件**和**事件评论**。 + +![设置事件](../../screenshot/WebhookEventsSettings.png) + +## 检查它是否有效 + +现在去 GitHub,创建一个新问题。在标题和描述中输入 `test`。 + +检查该函数被调用了多少次--这个数字至少应该是`1`。 + +```sh +$ faas-cli list +Function Invocations +issue-bot 2 +``` + +每次你创建一个问题,由于 GitHub 的 API 调用了该函数,计数会增加。 + +你可以通过输入`docker service logs -f issue-bot`(或`kubectl logs deployment/issue-bot -n openfaas-fn`)看到通过 GitHub 发送的有效载荷。 + +GitHub 的 Webhooks 页面也会在 `Recent Deliveries`下显示每条发送的消息,你可以在这里重放一条消息,看看你的函数返回的响应。 + +![Replaying an event](../../screenshot/github_replay.png) + +### 部署 SentimentAnalysis 函数 + +为了使用这个 issue-bot 函数,你将需要首先部署 SentimentAnalysis 函数。 +这是一个 python 函数,为通过 TextBlob 项目输入的每个句子提供正/负(极性-1.0-1.0)和主观性的评级。 + +如果你在[Lab 4](./lab4.md)中没有这样做,你可以从**函数商店**部署 `SentimentAnalysis`。 + +```sh +$ echo -n "I am really excited to participate in the OpenFaaS workshop." | faas-cli invoke sentimentanalysis +Polarity: 0.375 Subjectivity: 0.75 + +$ echo -n "The hotel was clean, but the area was terrible" | faas-cli invoke sentimentanalysis +Polarity: -0.316666666667 Subjectivity: 0.85 +``` + +### 更新`issue-bot`函数 + +打开`issue-bot/handler.py`,用这段代码替换模板。 + +```python +import requests, json, os, sys + +def handle(req): + + event_header = os.getenv("Http_X_Github_Event") + + if not event_header == "issues": + sys.exit("Unable to handle X-GitHub-Event: " + event_header) + return + + gateway_hostname = os.getenv("gateway_hostname", "gateway.openfaas") + + payload = json.loads(req) + + if not payload["action"] == "opened": + return + + #sentimentanalysis + res = requests.post('http://' + gateway_hostname + ':8080/function/sentimentanalysis', data=payload["issue"]["title"]+" "+payload["issue"]["body"]) + + if res.status_code != 200: + sys.exit("Error with sentimentanalysis, expected: %d, got: %d\n" % (200, res.status_code)) + + return res.json() +``` + +用 HTTP/HTTPs 的请求模块更新你的`requirements.txt`文件。 + +```plain +requests +``` + +在`issue-bot.yml`文件中添加`gateway_hostname`环境变量,并将其值设置为`gateway.openfaas`。 +```plain + ... + environment: + gateway_hostname: "gateway.openfaas" + ... +``` + +上面代码中的下面一行将 GitHub 问题的标题和正文作为文本发布给`sentimentanalysis`函数。响应将是 JSON 格式。 + +```python +res = requests.post('http://' + gateway_hostname + ':8080/function/sentimentanalysis', data=payload["issue"]["title"]+" "+payload["issue"]["body"]) +``` + +* 构建和部署 + +使用 CLI 来构建和部署该函数。 + +```plain +$ faas-cli up -f issue-bot.yml +``` + +现在在`bot-test`仓库中创建一个新问题。GitHub 将通过我们之前配置的 Inlets 隧道向你的函数发送一个 JSON 有效载荷。 + +你可以在 GitHub 上直接查看请求/响应--导航到*Settings* -> *Webhook*,如下所示。 + +![](../../screenshot/WebhookResponse.png) + +## 回复到 GitHub + +下一步是让我们贴上 `正面` 或 `评论` 的标签,但由于这个动作涉及到向仓库写入内容,我们需要从 GitHub 获得一个*个人访问令牌*。 + +### 为 GitHub 创建一个个人访问令牌 + +进入你的*GitHub 配置文件* -> *设置/开发者设置* -> *个人访问令牌*,然后点击*生成新令牌*。 + +![](../../screenshot/PersonalAccessTokens.png) + +勾选 `repo`的方框,允许访问你的存储库 + +![](../../screenshot/NewPAT.png) + +点击页面底部的 `Generate Token`按钮 + +在你的`issue-bot.yml`文件所在的目录中创建一个名为`env.yml`的文件,内容如下。 + +```yaml +environment: + auth_token: +``` + +用 GitHub 上的令牌更新`auth_token`变量。 + +现在更新你的 issue-bot.yml 文件,告诉它使用`env.yml`文件。 + +```yaml +provider: + name: openfaas + gateway: http://127.0.0.1:8080 + +functions: + issue-bot: + lang: python3 + handler: ./issue-bot + image: /issue-bot + environment: + write_debug: true + gateway_hostname: "gateway.openfaas" + positive_threshold: 0.25 + environment_file: + - env.yml +``` +> `positive_threshold`环境变量用于微调一个问题是否获得`positive`或`review`标签。 + +任何敏感信息都会被放在一个外部文件中(即`env.yml`),这样它就可以被包含在`.gitignore`文件中,这将有助于防止这些信息被存储在公共的 Git 仓库中。 + +OpenFaaS 也支持使用原生的 Docker 和 Kubernetes 的secret,详情请见[Lab 10](lab10.md) + +### 通过 GitHub 的 API 应用标签 + +你可以使用 API 来执行许多不同的任务,[文档在这里可以找到](https://github.com/PyGithub/PyGithub)。 + +下面是一个 Python 代码的例子,我们可以用它来应用标签,但你先不要把它添加到你的函数中。 + +```python +issue_number = 1 +repo_name = "alexellis/issue_bot" +auth_token = "xyz" + +g = Github(auth_token) +repo = g.get_repo(repo_name) +issue = repo.get_issue(issue_number) +``` + +这个用于 GitHub 的库是由社区提供的,不是官方的,但似乎很受欢迎。它可以通过我们的`requirements.txt`文件从`pip`调入。 + +## 完成函数 + +* 更新你的`issue-bot/requirements.txt`文件,为`PyGithub`添加一行内容 + +```plain +requests +PyGithub +``` + +* 打开`issue-bot/handler.py`,将代码替换为以下内容。 + +```python +import requests, json, os, sys +from github import Github + +def handle(req): + event_header = os.getenv("Http_X_Github_Event") + + if not event_header == "issues": + sys.exit("Unable to handle X-GitHub-Event: " + event_header) + return + + gateway_hostname = os.getenv("gateway_hostname", "gateway.openfaas") + + payload = json.loads(req) + + if not payload["action"] == "opened": + sys.exit("Action not supported: " + payload["action"]) + return + + # Call sentimentanalysis + res = requests.post('http://' + gateway_hostname + ':8080/function/sentimentanalysis', + data= payload["issue"]["title"]+" "+payload["issue"]["body"]) + + if res.status_code != 200: + sys.exit("Error with sentimentanalysis, expected: %d, got: %d\n" % (200, res.status_code)) + + # Read the positive_threshold from configuration + positive_threshold = float(os.getenv("positive_threshold", "0.2")) + + polarity = res.json()['polarity'] + + # Call back to GitHub to apply a label + apply_label(polarity, + payload["issue"]["number"], + payload["repository"]["full_name"], + positive_threshold) + + return "Repo: %s, issue: %s, polarity: %f" % (payload["repository"]["full_name"], payload["issue"]["number"], polarity) + +def apply_label(polarity, issue_number, repo, positive_threshold): + g = Github(os.getenv("auth_token")) + repo = g.get_repo(repo) + issue = repo.get_issue(issue_number) + + has_label_positive = False + has_label_review = False + for label in issue.labels: + if label == "positive": + has_label_positive = True + if label == "review": + has_label_review = True + + if polarity > positive_threshold and not has_label_positive: + issue.set_labels("positive") + elif not has_label_review: + issue.set_labels("review") +``` + +> 源代码也可在[issue-bot/bot-handler/handler.py](./issue-bot/bot-handler/handler.py) + +* 构建和部署 + +使用 CLI 来构建和部署该函数。 + +```plain +$ faas-cli up -f issue-bot.yml +``` + +现在通过在`bot-test`仓库中创建一些新的问题来试试。检查 `正面`和 `评论`标签是否被正确应用,如果你不确定信息是否被传递或怀疑有错误被抛出,请查阅 GitHub Webhooks 页面。 + +![](../../screenshot/bot_label_applied.png) + +> 注意:如果标签没有立即出现,请先尝试刷新页面。 + +## 用 HMAC 验证有效载荷 + +在[Lab 11](lab11.md)中,我们将学习如何通过使用 HMAC 保护无服务器函数不被篡改。 + +现在转到[Lab 6](lab6.md)。 diff --git a/translations/cn/lab6.md b/translations/cn/lab6.md new file mode 100644 index 0000000..727e20b --- /dev/null +++ b/translations/cn/lab6.md @@ -0,0 +1,356 @@ +# 实验 6--你的函数的 HTML + + + +在开始这个实验之前,为你的文件创建一个新的文件夹。 + +```plain +$ mkdir -p lab6\ + && cd lab6 +``` + +## 从一个函数中生成并返回基本的 HTML + +函数可以返回 HTML,并将`Content-Type`设置为`text/html`。因此,函数返回的 HTML 可以通过浏览器进行渲染。让我们创建一个简单的函数,生成并返回一个基本的 HTML。 + +```plain +$ faas-cli new --lang python3 show-html --prefix="" +``` + +编辑`handler.py`。 + +```python +def handle(req): + """handle a request to the function + Args: + req (str): request body + """ + + html = '

Hi, from your function!

' + + return html +``` + +这将返回 HTML 给调用者。 还有一件事我们应该做的是设置响应的`Content-Type'。我们100%确定这个函数将返回一个HTML,所以`Content-Type`应该总是`text/html`。我们可以利用`show-html.yml`文件中的`environment`部分来设置。 + +编辑`show-html.yml`。 + +```yaml +provider: + name: openfaas + gateway: http://127.0.0.1:8080 + +functions: + show-html: + lang: python3 + handler: ./show-html + image: /show-html + environment: + content_type: text/html + +``` + +`environment`中的`content_type`键将设置响应的`Content-Type`。 + +现在构建、推送和部署该函数。 + +```sh +$ faas-cli up -f show-html.yml +``` + +运行以下程序以获得函数的 URL。 + +```sh +faas-cli describe -f show-html.yml show-html + +URL: http://127.0.0.1:8080/function/show-html +``` + +HTML 应该被正确渲染。 + +## 从磁盘上读取并返回一个静态的 HTML 文件 + +一般来说,当你提供 HTML 服务时,你有一个静态的 HTML 文件在前面。让我们看看我们如何在函数中打包 HTML 文件,并从 HTML 文件中提供内容。 + +首先,让我们创建一个 HTML 文件。 + +创建一个名为`html`的目录,并放置一个名为`new.html`的文件,使其结构看起来像下面这样。 + +```plain +├── show-html +│ ├── __init__.py +│ ├── handler.py +│ ├── html +│ │ └── new.html +│ └── requirements.txt +└── show-html.yml +``` + +Edit `new.html` : + +```html + + + + + OpenFaaS + + +

Here's a new page!

+ + +``` + +现在把你的`handler.py`改为以下内容。 + +```python +import os + +def handle(req): + """handle a request to the function + Args: + req (str): request body + """ + + dirname = os.path.dirname(__file__) + path = os.path.join(dirname, 'html', 'new.html') + + with(open(path, 'r')) as file: + html = file.read() + + return html + +``` + +现在构建、推送和部署该函数。 + +```plain +$ faas-cli up -f show-html.yml +``` + +打开你的浏览器,访问http://127.0.0.1:8080/function/show-html。你应该看到一个 `这里有一个新的页面!` 在浏览器中呈现的 HTML 页面。 + +现在我们要为这个函数的 URL 添加一个路径。 + +在`html`文件夹中添加新的`list.html`文件,内容如下。 + +```html + + + + + OpenFaaS + + +

This is a list!

+
    +
  • One
  • +
  • Two
  • +
  • Three
  • +
+ + +``` + +将你的`handler.py`编辑成以下内容。 + +```python +import os + +def handle(req): + + path = os.environ['Http_Path'] + pathArr = path.split("/") + pageName = pathArr[1] + + dirname = os.path.dirname(__file__) + page = os.path.join(dirname, 'html', pageName + '.html') + + with(open(page, 'r')) as file: + html = file.read() + + return html +``` + +构建、推送和部署该函数。 + +```plain +$ faas-cli up -f show-html.yml +``` + +现在在http://127.0.0.1:8080/function/show-html/new 或 http://127.0.0.1:8080/function/show-html/list 上打开你的网页。 +这将输出。 +```html +

Here's a new page!

+``` +and +```html +

This is a list!

+
    +
  • One
  • +
  • Two
  • +
  • Three
  • +
+``` + +## 读取查询字符串并返回不同的 HTML + +现在我们已经了解了如何通过函数来提供 HTML,让我们动态地改变通过查询字符串提供的 HTML。正如我们在[实验室 4](./lab4.md)中学到的,查询字符串可以通过一个叫做`Http_Query`的环境变量来检索。假设我们做了一个看起来像这样的查询。 + + http://127.0.0.1:8080/function/show-html?action=new + +查询字符串是`action=new`,因此`Http_Query`的值将是`action=new`。我们也可以使用`urllib.parse`包中的`parse_qs`函数,轻松解析这个查询字符串。 + +我们的函数的目录结构看起来是这样的。 + +```plain +├── show-html +│ ├── __init__.py +│ ├── handler.py +│ ├── html +│ │ ├── list.html +│ │ └── new.html +│ └── requirements.txt +└── show-html.yml +``` + + +改变你的`handler.py`。 + +```python +import os +from urllib.parse import parse_qs + +def handle(req): + """handle a request to the function + Args: + req (str): request body + """ + + query = os.environ['Http_Query'] + params = parse_qs(query) + action = params['action'][0] + + dirname = os.path.dirname(__file__) + path = os.path.join(dirname, 'html', action + '.html') + + with(open(path, 'r')) as file: + html = file.read() + + return html +``` + +现在构建、推送和部署该函数。 + +```plain +$ faas-cli up -f show-html.yml +``` + +打开你的浏览器,首先访问。 + +http://127.0.0.1:8080/function/show-html?action=new + +你应该看到 `这里有一个新的页面!`就像你在上一节看到的那样。现在访问。 + +http://127.0.0.1:8080/function/show-html?action=list + +你应该看到一个显示列表的 HTML。 + +## 与其他函数协作 + +最后,让我们看看如何利用 JavaScript 和 Ajax 的优势,从 HTML 函数中与另一个函数(例如*figlet*函数)协作。 + +首先,让我们再创建一个名为`figlet.html`的 HTML 文件。所以现在的结构应该是这样的。 + +```plain +├── show-html +│ ├── __init__.py +│ ├── handler.py +│ ├── html +│ │ ├── figlet.html +│ │ ├── list.html +│ │ └── new.html +│ └── requirements.txt +└── show-html.yml +``` + +编辑`figlet.html`。 + +```html + + + + + OpenFaaS + + + + +

Figlet

+

+ Text: + +

+ + + + + + +``` + +如果你不太了解 JavaScript,请不要担心。这个页面所做的就是。 + +* 在 `input`中输入文字 +* 按下 `生成`按钮 +* 创建一个 Ajax 请求到*figlet*函数端点(`/function/figlet`)。 +* 将结果应用到 `textarea` 中。 + +没有必要改变`handler.py`,因为它可以动态地提供上一节中的 HTML。尽管没有改变`handler.py`,我们还是需要构建和推送函数镜像,因为我们需要在函数容器中打包新的`figlet.html`。 + +现在构建、推送和部署这个函数。 + +```plain +$ faas-cli up -f show-html.yml +``` + +本节假设你已经部署了[实验室 2](./lab2.md)中的*figlet*函数。 + +打开你的浏览器,首先访问。 + +http://127.0.0.1:8080/function/show-html?action=figlet + +你应该看到 `Figlet` 页面,并且应该看到一个输入。输入任何你想输入的文本,然后点击 `生成` 按钮。如果请求成功,`textarea` 应该包含你在 `input` 中输入的 figlet。这是一个微不足道的例子,但通过使用这种技术,你甚至可以用函数创建强大的 SPA(单页应用程序)。 + +在这个实验室中,你学到了如何从你的函数中提供 HTML,并设置响应的`Content-Type`。此外,你还学会了如何用 HTML+JavaScript 调用其他函数,以及用函数创建动态页面。 + +现在进入[实验室 7](lab7.md) diff --git a/translations/cn/lab7.md b/translations/cn/lab7.md new file mode 100644 index 0000000..887afa4 --- /dev/null +++ b/translations/cn/lab7.md @@ -0,0 +1,122 @@ +# 实验 7--异步函数 + + + +在开始这个实验之前,为你的文件创建一个新的文件夹。 + +```plain +$ mkdir -p lab7 \ + && cd lab7 +``` + +## 同步与异步地调用一个函数 + +当你同步调用一个函数时,一个连接会通过网关连接到你的函数,并且在整个执行过程中保持开放。同步调用是*阻塞的,所以你应该看到你的客户端暂停,变得不活跃,直到该函数完成其任务。 + +* 网关使用的路由是。`/function/`。 +* 你必须等待,直到它完成 +* 你在调用后得到结果 +* 你知道它是通过还是失败 + +异步任务以类似的方式运行,但有一些区别。 + +* 网关使用不同的路由:`/async-function/`。 +* 客户端从网关得到一个立即的*202 接受*的响应。 +* 该函数稍后使用一个队列工作器来调用 +* 默认情况下,结果被丢弃 + +让我们试一试快速演示。 + +```plain +$ faas-cli new --lang dockerfile long-task --prefix="" +``` + +编辑`long-task/Dockerfile`并将 fprocess 改为`sleep 1`。 + +现在构建、部署并同步调用你的函数 10 次,像这样。 + +```plain +echo -n "" | faas-cli invoke long-task +echo -n "" | faas-cli invoke long-task +echo -n "" | faas-cli invoke long-task +echo -n "" | faas-cli invoke long-task +echo -n "" | faas-cli invoke long-task +echo -n "" | faas-cli invoke long-task +echo -n "" | faas-cli invoke long-task +echo -n "" | faas-cli invoke long-task +echo -n "" | faas-cli invoke long-task +echo -n "" | faas-cli invoke long-task +``` + +现在异步调用该函数 10 次。 + +```plain +echo -n "" | faas-cli invoke long-task --async +echo -n "" | faas-cli invoke long-task --async +echo -n "" | faas-cli invoke long-task --async +echo -n "" | faas-cli invoke long-task --async +echo -n "" | faas-cli invoke long-task --async +echo -n "" | faas-cli invoke long-task --async +echo -n "" | faas-cli invoke long-task --async +echo -n "" | faas-cli invoke long-task --async +echo -n "" | faas-cli invoke long-task --async +echo -n "" | faas-cli invoke long-task --async +echo -n "" | faas-cli invoke long-task --async +``` + +你观察到了什么?第一个例子应该花了 10 秒,而第二个例子会在一秒或更短的时间内返回到你的提示。这项工作仍然需要 10x1 秒来完成,但现在要放在队列中延迟执行。 + +异步函数调用非常适用于那些可以推迟到以后执行的任务,或者你不需要客户端上的结果。 + +> 一个很好的例子是在接收 GitHub 的 webhooks 时--可能有一个最大的处理时间,GitHub 会允许你的连接保持开放,一个异步调用接受工作并立即返回。 + +## 查看队列工作者的日志 + +OpenFaaS 的默认栈使用 NATS 流来排队和延迟执行。你可以用以下命令查看日志。 + +```plain +kubectl logs deployment/queue-worker -n openfaas +``` + +## 使用一个`X-Callback-Url'与 requirebin + +如果你需要一个异步调用的函数的结果,你有两个选择。 + +* 改变它的代码,用它的结果通知一个端点或消息系统 + +这个选项可能不是在所有情况下都适用,并且需要编写额外的代码。 + +* 利用回调的内置行为 + +内置的回调允许对一个函数的调用提供一个 URL,队列工作器将自动报告函数的成功或失败,以及结果。 +一些额外的请求头被发送到回调,完整的列表见[回调请求头](https://docs.openfaas.com/reference/async/#callback-request-headers) + +前往 requestbin 并创建一个新的 `bin` --这将是公共互联网上的一个 URL,可以接收你的函数的结果。 + +> 为了这个实验室的目的,一定要取消勾选 `私有` 复选框,这将使你不需要登录。 + +https://requestbin.com/ + +现在复制 "Bin URL "并将其粘贴在下面。 + +例如(`http://requestbin.com/r/1i7i1we1`) + +```plain +$ echo -n "LaterIsBetter" | faas-cli invoke figlet --async --header "X-Callback-Url http://requestbin.com/r/1i7i1we1" +``` + +现在刷新 requestbin 站点上的页面,你将看到来自 `figlet` 的结果。 + + +```plain + _ _ ___ ____ _ _ +| | __ _| |_ ___ _ _|_ _|___| __ ) ___| |_| |_ ___ _ __ +| | / _` | __/ _ \ '__| |/ __| _ \ / _ \ __| __/ _ \ '__| +| |__| (_| | || __/ | | |\__ \ |_) | __/ |_| || __/ | +|_____\__,_|\__\___|_| |___|___/____/ \___|\__|\__\___|_| + +``` + +> 建议:也可以使用另一个函数作为 `X-Callback-Url` --这对于在异步工作负载被处理时通过 Slack 或 Email 通知自己是非常好的。要用结果调用另一个函数,将`X-Callback-Url`设置为`http://gateway:8080/function/`。 + +现在进入[实验室 8](lab8.md) diff --git a/translations/cn/lab8.md b/translations/cn/lab8.md new file mode 100644 index 0000000..7db56b2 --- /dev/null +++ b/translations/cn/lab8.md @@ -0,0 +1,89 @@ +# Lab 8 - 高级函数 - 超时 + + + +在开始这个实验之前,为你的文件创建一个新的文件夹。 + +```plain +$ mkdir -p lab8 \ + && cd lab8 +``` + +## 用`read_timeout`扩展超时时间 + +*timeout*对应于一个函数可以运行多长时间,直到被执行。它对防止分布式系统中的误操作很重要。 + +有几个地方可以为你的函数配置超时,在每个地方都可以通过使用环境变量来完成。 + +* 函数超时 + +* `read_timeout` - 允许函数通过 HTTP 读取一个请求的时间 +* `write_timeout` - 允许函数在 HTTP 上写一个响应的时间 +* `exec_timeout` - 一个函数在被终止前可以运行的最大时间。 + +API 网关的默认时间是 20 秒,所以我们来测试一下在一个函数上设置一个更短的超时时间。 + +```plain +$ faas-cli new --lang python3 sleep-for --prefix="" +``` + +编辑`handler.py`。 + +```python +import time +import os + +def handle(req): + """handle a request to the function + Args: + req (str): request body + """ + + sleep_duration = int(os.getenv("sleep_duration", "10")) + preSleep = "Starting to sleep for %d" % sleep_duration + time.sleep(sleep_duration) # Sleep for a number of seconds + postSleep = "Finished the sleep" + return preSleep + "\n" + postSleep +``` + +现在编辑`sleep-for.yml`文件,添加这些环境变量。 + +```yaml +provider: + name: openfaas + gateway: http://127.0.0.1:8080 + +functions: + sleep-for: + lang: python3 + handler: ./sleep-for + image: /sleep-for:0.1 + environment: + sleep_duration: 10 + read_timeout: "5s" + write_timeout: "5s" + exec_timeout: "5s" +``` + +使用 CLI 来构建、推送、部署和调用该函数。 + +```sh +$ echo | faas-cli invoke sleep-for +Server returned unexpected status code: 502 - +``` + +你应该看到它没有打印消息就终止了,因为`sleep_duration`比超时值高。 + +现在把`sleep_duration`设置为一个较低的数字,如`2`,然后再次运行`faas-cli deploy`。在编辑函数的 YAML 文件时,你不需要重建这个函数。 + +```sh +$ echo | faas-cli invoke sleep-for +Starting to sleep for 2 +Finished the sleep +``` + +* API 网关 + +要为你的函数设置超出默认限制的扩展超时,请遵循以下教程。[扩展的超时](https://docs.openfaas.com/tutorials/expanded-timeouts/) + +现在转到[实验室 9](lab9.md) \ No newline at end of file diff --git a/translations/cn/lab9.md b/translations/cn/lab9.md new file mode 100644 index 0000000..23334b5 --- /dev/null +++ b/translations/cn/lab9.md @@ -0,0 +1,165 @@ +# Lab 9 - 高级函数 - 自动缩放 + + + +## 自动缩放函数的应用 + +正如[文档](http://docs.openfaas.com/architecture/autoscaling/)中描述的那样,OpenFaaS 带有自动扩展函数。在这个实验室中,我们将看看自动扩展是如何运作的。 + +### 前提条件 + +* 在完成了[Lab 1](./lab1.md)中对 OpenFaaS 的设置后,你将拥有触发自动扩展所需的一切。 + +* 多个工具可以用来创建足够的流量来触发自动扩展 - 在这个例子中,`curl'将被使用,因为它很容易在 Mac 和 Linux 上使用,并在 Windows 上与 Git Bash 打包。 + +### 自动扩展的背景 + +开箱即用的 OpenFaaS 是这样配置的,它将根据 Prometheus 测量的 `每秒请求`指标进行自动扩展。 这个指标是在流量通过 API 网关的时候捕获的。如果超过了定义的 `每秒请求`的阈值,AlertManager 就会启动。这个阈值应该被重新配置为适合生产使用的水平,因为在这个例子中,为了演示,它被设置为一个低值。 + +> 在[文档网站](http://docs.openfaas.com/architecture/autoscaling/)中找到更多关于自动缩放的信息。 + +每次警报被 AlertManager 触发时,API 网关将把你的函数的一定数量的副本添加到集群中。OpenFaaS 有两个配置选项,允许指定副本的起始/最低数量,也允许停止副本的最大数量。 + +你可以通过设置`com.openfaas.scale.min`来控制函数的最小副本量,目前默认值为`1`。 + +你可以通过设置`com.openfaas.scale.max`来控制一个函数可以产生的最大副本量,目前默认值是`20`。 + +> 注意: 如果你把`com.openfaas.scale.min`和`com.openfaas.scale.max`设置成相同的值,你就会禁用自动缩放函数。 + +### 查看 Prometheus + +你需要运行这个端口转发命令,以便能够在`http://127.0.0.1:9090`访问 Prometheus。 +```plain +$ kubectl port-forward deployment/prometheus 9090:9090 -n openfaas +``` + +现在添加一个所有成功调用部署的函数的图。我们可以通过执行`rate( gateway_function_invocation_total{code="200"} [20s])`作为查询来实现。导致一个看起来像这样的页面。 + + ![](../../screenshot/prometheus_graph.png) + + 继续打开一个新的标签,在其中使用`http://127.0.0.1:9090/alerts`导航到警报部分。在这个页面上,你以后可以看到什么时候超过了 `每秒请求` 的阈值。 + + ![](../../screenshot/prometheus_alerts.png) + +### 触发缩放的 Go 函数 + +首先是 Alex Ellis 的 `echo-fn`函数。 + +```bash +$ git clone https://github.com/alexellis/echo-fn \ + && cd echo-fn \ + && faas-cli template store pull golang-http \ + && faas-cli deploy \ + --label com.openfaas.scale.max=10 \ + --label com.openfaas.scale.min=1 +``` + +现在检查用户界面,看什么时候 `go-echo`函数从 `不准备`变成 `准备`。你也可以用`faas-cli describe go-echo`来检查。 + +使用这个脚本反复调用 `go-echo` 函数,直到你看到副本数从 1 变成 5,以此类推。你可以在 Prometheus 中通过添加`gateway_service_count'的图表或在选择该函数的情况下查看 API 网关来监控这个值。 + +```bash +$ for i in {0..10000}; +do + echo -n "Post $i" | faas-cli invoke go-echo && echo; +done; +``` + +> 注意:如果你在 Kubernetes 上运行,使用`$OPENFAAS_URL`而不是`http://127.0.0.1:8080`。 + +### 监控警报 + +现在你应该可以看到,在之前创建的图表中,`go-echo`函数的调用量有所增加。移动到你打开警报页面的标签。一段时间后,你应该开始看到 `APIHighInvocationRate`的状态(和颜色)变为 "待定",然后再次变为 "发射"。你也可以使用`$ faas-cli list`或通过[ui](http://127.0.0.1:8080)看到自动缩放的情况。 + + ![](../../screenshot/prometheus_firing.png) + +现在你可以使用`$ docker service ps go-echo`来验证`go-echo`的新副本是否已经启动。 + +现在停止 bash 脚本,你会看到副本的数量在几秒钟后回到 1 个副本。 + +### 疑难解答 + +如果你认为你的自动扩展没有被触发,那么请检查以下内容。 + +* 普罗米修斯中的警报页面 - 这应该是红色/粉色的,并显示 `FIRING` - 即在http://127.0.0.1:9090/alerts。 +* 检查核心服务的日志,即网关、Prometheus / AlertManager。 + +为了获得核心服务的日志,运行`docker service ls`,然后`docker service logs `。 + +### 负载测试(可选) + +需要注意的是,在受控环境中应用科学方法和工具与在你自己的笔记本电脑上运行拒绝服务攻击是有区别的。你的笔记本电脑不适合做负载测试,因为一般来说,你是在 Windows 或 Mac 主机上的 Linux 虚拟机中运行 OpenFaaS,而这也是一个单节点。这并不代表生产部署。 + +请看[构建一个合适的性能测试](https://docs.openfaas.com/architecture/performance/)的文档。 + +如果`curl`没有为你的测试产生足够的流量,或者你想获得一些关于事情如何分解的统计数据,那么你可以试试`hey`工具。`hey`可以通过每秒的请求或给定的持续时间产生结构化的负载。 + +这里有一个在 1GHz 的 2016 年 12 英寸 MacBook 上运行的例子,带有 Docker Desktop。这是一台非常低功率的计算机,正如所描述的,不代表生产性能。 + +```bash +$ hey -z=30s -q 5 -c 2 -m POST -d=Test http://127.0.0.1:8080/function/go-echo +Summary: + Total: 30.0203 secs + Slowest: 0.0967 secs + Fastest: 0.0057 secs + Average: 0.0135 secs + Requests/sec: 9.9932 + + Total data: 1200 bytes + Size/request: 4 bytes + +Response time histogram: + 0.006 [1] | + 0.015 [244] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ + 0.024 [38] |■■■■■■ + 0.033 [10] |■■ + 0.042 [4] |■ + 0.051 [1] | + 0.060 [0] | + 0.069 [0] | + 0.078 [0] | + 0.088 [0] | + 0.097 [2] | + + +Latency distribution: + 10% in 0.0089 secs + 25% in 0.0101 secs + 50% in 0.0118 secs + 75% in 0.0139 secs + 90% in 0.0173 secs + 95% in 0.0265 secs + 99% in 0.0428 secs + +Details (average, fastest, slowest): + DNS+dialup: 0.0000 secs, 0.0057 secs, 0.0967 secs + DNS-lookup: 0.0000 secs, 0.0000 secs, 0.0000 secs + req write: 0.0001 secs, 0.0000 secs, 0.0016 secs + resp wait: 0.0131 secs, 0.0056 secs, 0.0936 secs + resp read: 0.0001 secs, 0.0000 secs, 0.0013 secs + +Status code distribution: + [200] 300 responses +``` + +以上模拟了两个活跃的用户`-c`,每秒 5 个请求`-q`,持续时间`-z`为 30 秒。 + +要使用`hey`,你必须在本地计算机上安装 Golang。 + +也请参见。[hey on GitHub](https://github.com/rakyll/hey) + +### 尝试从零开始扩展 + +如果你把你的函数规模缩小到 0 个副本,你仍然可以调用它。该调用将触发网关将函数缩放到一个非零值。 + +用下面的命令试试吧。 + +```plain +$ kubectl scale deployment --replicas=0 nodeinfo -n openfaas-fn +``` + +打开 OpenFaaS 用户界面,检查 nodeinfo 是否有 0 个副本,或者通过`kubectl get deployment nodeinfo -n openfaas-fn'。 + +现在调用该函数并检查它是否扩展到 1 个副本。 + +现在转到[Lab 10](lab10.md)。