发布于 2026-01-06 0 阅读
0

书评:面向无服务器应用程序的 DevOps(附教程)

书评:面向无服务器应用程序的 DevOps(附教程)

在成为全栈开发人员的道路上,我决定选择无服务器架构作为我的后端开发方向。为了了解如何维护系统的稳定运行,我尝试学习一些 DevOps 方面的知识,于是阅读了《无服务器应用程序的 DevOps》这本书。

DevOps(“开发”和“运维”的缩写)是一种软件开发方法论,它将软件开发(Dev)与信息技术运维(Ops)相结合。DevOps 的目标是在缩短系统开发生命周期的同时,频繁地交付功能、修复和更新,并使其与业务目标紧密契合。(维基百科

我喜欢《面向无服务器应用程序的 DevOps》这本书的地方

作者探讨了多种框架和云服务提供商,而不仅仅是“Serverless 和 AWS”。这使他能够讨论每种方法之间的细微差别,并让读者对 DevOps 有更全面的了解。

他还深入探讨了无服务器系统的监控和故障排除最佳实践,以便读者能够借鉴作者的经验。我认为这些章节也是本书最精彩的部分。“没错,乍一看这样做似乎是个好主意,但千万别这么做,几个月后你会后悔的!”

我不喜欢《面向无服务器应用程序的 DevOps》这本书的地方

我觉得这本书本来可以写得更短一些,不是因为很多页都是无用的文字,而是因为它讲的内容太多了。

当然,作者运用了这么多框架和平台,让我对该做什么以及为什么要这样做有了清晰的思路,这很好。而且所有这些平台都非常出色,足以支撑所有想法。对我这个AWS用户来说,我觉得在小节中提及谷歌和IBM的无服务器平台就足够了,没必要用整章篇幅来介绍。

但这只是个人偏好,如果你有兴趣了解整个生态系统,读这本书绝对没错。:)

教程

承蒙作者惠允,我特地准备了一份教程,供您参考,以便您了解他的风格。Shashikant Bangera 将讲解如何“为 kubeless 添加 DevOps 风格”。

为 Kubernetes 无 Kubernetes 库添加 DevOps 特性

什么是 Kubeless?

Kubeless 是一个基于 Kubernetes 的开源无服务器框架。它允许你部署和执行一段代码,而无需担心底层基础设施。它利用 Kubernetes 的资源提供自动扩缩容、路由和监控功能。

部署后的功能可以通过发布/订阅、HTTP 和调度来触发。发布/订阅事件通过 Kafka 集群进行管理,Kafka 集群是 Kubeless 的一个开箱即用组件,它包含一个基本的 Kafka 集群、一个代理和一个 ZooKeeper。HTTP 触发器可通过 Kubernetes 服务获得,而调度功能则对应于 cron 作业。

Kubeless 支持的语言/运行时环境有:

  • Python 2.7/3.4/3.6
  • nodejs6/8/distroless8
  • ruby2.4
  • php7.2
  • go1.10
  • .NET Core 2.0
  • Java 1.8
  • 芭蕾舞演员0.980.0
  • jvm1.8
  • Kubeless 还支持 HTTP、NATS、Kafka、cron 和流触发器。

无 Kubernetes 架构

Kubeless 使用自定义资源定义,这意味着当您创建自定义资源定义时,Kubernetes API 服务器会为每个指定的版本创建一个资源路径。

自定义资源定义 (CRD) 可以设置命名空间或集群范围,因此 CRD 被称为函数。这意味着无 Kubernetes 函数可以像普通的 Kubernetes 资源一样在后台创建,并创建一个控制器。该控制器会监视这些自定义资源,并在运行时需要时启动它们。

如何设置 Kubeless

Kubeless 的配置非常简单。首先,从发布页面下载 Kubeless,创建一个命名空间,然后通过发布页面上的 YAML 清单文件,创建函数的自定义资源定义并启动控制器。如果您在个人笔记本电脑上配置 Kubeless,则需要使用 minikube 来完成这些操作。

首先,访问https://github.com/kubernetes/minikube安装 minikube 。安装完成后,您应该能够在虚拟机中运行一个单节点 Kubernetes 集群。您还可以通过命令提示符执行 minikube 命令。

创建一个集群,然后在该集群中创建 Kubeless 资源。接下来,创建一个简单的 Kubeless 函数,然后部署并调用它。您还需要为 minikube 设置一个仪表盘,并查看控制器和函数的创建和部署过程。以下是具体实现步骤:

(1)创建 minikube 本地 Kubernetes 集群:

$ minikube start
Starting local Kubernetes v1.9.0 cluster...
Starting VM...
Getting VM IP address...
Moving files into cluster...
Setting up certs...
Connecting to cluster...
Setting up kubeconfig...
Starting cluster components...
Kubectl is now configured to use the cluster.
Loading cached images from config file.
Enter fullscreen mode Exit fullscreen mode

(2) 接下来,使用以下命令创建 minikube 控制面板。该命令将打开一个浏览器窗口显示控制面板。控制面板将显示服务、Pod 和管理器。

$ minikube dashboard
Enter fullscreen mode Exit fullscreen mode

(3) 现在您已经创建了一个集群,接下来需要将 Kubeless 部署到该集群上。Kubeless 提供了多个清单文件,适用于多种 Kubernetes 环境(非 RBAC、RBAC 和 OpenShift)。这里,您将使用适用于非 RBAC(非基于角色的访问控制)环境的清单文件。

$ export RELEASE=$(curl -sk
https://api.github.com/repos/kubeless/kubeless/releases/latest | grep tag_name |
cut -d '"' -f 4)
$ kubectl create ns kubeless
$ echo $RELEASE
$ kubectl create -f
https://github.com/kubeless/kubeless/releases/download/v1.0.0-alpha.8/kubeless-
non-rbac-v1.0.0-alpha.8.yaml
serviceaccount "controller-acct" created
customresourcedefinition "functions.kubeless.io" created
customresourcedefinition "httptriggers.kubeless.io" created
customresourcedefinition "cronjobtriggers.kubeless.io" created
configmap "kubeless-config" created
deployment "kubeless-controller-manager" created
Enter fullscreen mode Exit fullscreen mode

(4)既然 Kubeless 已经部署完成,请检查它是否部署成功:

$ kubectl get pods -n kubeless
NAME READY STATUS RESTARTS AGE
kubeless-controller-manager-c6b69df76-65gsh 1/1 Running 0 2m
$ kubectl get deployment -n kubeless
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
kubeless-controller-manager 1 1 1 1 3m
$ kubectl get customresourcedefinition
NAME AGE
cronjobtriggers.kubeless.io 3m
functions.kubeless.io 3m
httptriggers.kubeless.io 3m
Enter fullscreen mode Exit fullscreen mode

(5)接下来,在本地安装 Kubeless CLI,用于部署、调用和删除 Kubeless 函数:

$ export OS=$(uname -s| tr '[:upper:]' '[:lower:]')
$ curl -OL
https://github.com/kubeless/kubeless/releases/download/$RELEASE/kubeless_$OS-
amd64.zip
$ unzip kubeless_$OS-amd64.zip
$ sudo mv bundles/kubeless_$OS-amd64/kubeless /usr/local/bin/
Enter fullscreen mode Exit fullscreen mode

(6)现在,创建一个函数并部署它。以下是一个简单的 Python 函数,您将部署并调用它。创建一个名为 `function` 的函数,test.py并包含以下内容:

def hello(event, context):
  print event
  return event['data']
Enter fullscreen mode Exit fullscreen mode

(7)现在部署该函数。刷新 minikube 控制面板后,您应该能够看到hello已部署的函数:

$ kubeless function deploy hello --runtime python2.7--from-file test.py --handler test.hello --namespace kubeless
INFO[0000] Deploying function...
INFO[0000] Function hello submitted for deployment
INFO[0000] Check the deployment status executing 'kubeless function ls hello'
Enter fullscreen mode Exit fullscreen mode

以下列表解释了前面代码的各个组成部分:

  • kubeless function deploy hello指示 Kubeless 注册一个名为 `<function_name>` 的新函数hello。该函数将可通过此名称在 Web 上访问。请注意,此名称不必与代码中使用的函数名称相同。
  • --trigger-http告诉 Kubeless 该函数将通过 HTTP 调用。
  • --runtime python2.7指示 Kubeless 使用 Python 2.7 执行代码。目前也支持 Node.js 作为运行时环境,未来还将支持更多平台。
  • --handler test.hello告诉 Kubeless 要在代码模块中调用的函数名称。您可以在前面的 Python 代码中看到该函数被调用hello
  • --from-file /tmp/hello.py指示 Kubeless 上传该/tmp/hello.py文件并将其用作函数的源文件。也可以通过其他方式传递函数。

您将看到通过以下命令创建的功能自定义资源:

$ kubectl get functions
NAME AGE
hello 2m

$ kubeless function ls --namespace kubeless
NAME NAMESPACE HANDLER RUNTIME DEPENDENCIES STATUS
hello kubeless test.hello python2.7 1/1 READY
Enter fullscreen mode Exit fullscreen mode

(8)现在,按如下方式调用该函数:

$ kubeless function call hello --data 'Hello Serverless!' --namespace kubeless
Hello Serverless!
Enter fullscreen mode Exit fullscreen mode

(9)您也可以按如下方式删除该功能:

$ kubeless function delete hello --namespace kubeless
$ kubeless function ls --namespace kubeless
NAME NAMESPACE HANDLER RUNTIME DEPENDENCIES STATUS
Enter fullscreen mode Exit fullscreen mode

到目前为止,您已经完成了在本地安装 Kubeless、创建简单函数、部署、调用和取消部署的操作。下一节,您将学习如何使用 Serverless Framework 实现自动化部署。

设置持续集成和部署

您将使用 Serverless Framework 来快速启动 Kubeless 函数的开发和部署。Serverless Framework 提供了许多功能,让您能够轻松采用 Kubeless。以下是 Serverless 提供的各种功能的概览。

创建服务

使用该create命令,通过传递运行时环境来创建基本服务并path创建目录。目前提供两种运行时环境——Python 和 Node.js。因此,如果您运行带有path参数的以下命令,它将创建一个包含简单无服务器函数的文件夹。当前可用的运行时环境为 Pythonkubeless-pythonkubeless-nodejsNode.js。

$ serverless create --template kubeless-python --path myKubelessFunc
Enter fullscreen mode Exit fullscreen mode

create命令将创建一个服务,每个服务配置将包含以下三个文件:

  • serverless.yml该文件的主要职责是声明服务、定义提供程序、自定义插件(在本例中为 serverless-kubeless 插件)、函数将执行的事件或触发器,以及使用 serverless 变量配置文件。
  • handler.py此文件将包含函数代码。函数定义serverless.yml将指向handler.py.
  • package.json这是函数的 npm 包定义文件,其中包含所有依赖项和 kubeless-serverless 插件。

请按照以下代码所示,使用您的函数和配置更新这些文件。您正在更新一个函数,用于从通过 JSON 公开的站点信息流中搜索自行车站点。该代码也可在 GitHub 存储库中找到https://github.com/shzshi/kubeless-serverless.git

#handler.py
import urllib2
import json
def find(event, context):
  term = event['data']['term']
  url = "https://feeds.capitalbikeshare.com/stations/stations.json"
  response = urllib2.urlopen(url)
  stations = json.loads(response.read())
  hits = []
  for station in stations["stationBeanList"]:
    if station["stAddress1"].find(term) > -1: hits.append(station)
  return json.dumps(hits)
Enter fullscreen mode Exit fullscreen mode

serverless.yaml请将以下内容替换为:

# serverless.yml
service:bikesearch
provider:
  name:kubeless
  runtime:python2.7
plugins:
  -serverless-kubeless
functions:
  bikesearch:
    handler:handler.find
Enter fullscreen mode Exit fullscreen mode

部署该功能

由于所需文件是通过模板创建的,您可以根据需要进行修改,然后在需要时部署并调用它们。使用 Serverless 部署它们;这样npm install就会获取 Serverless 所需的依赖项,例如kubeless-serverless插件。然后,您可以部署该函数,如下面的代码所示:

$ npm install
$ serverless deploy -v
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Deploying function bikesearch...
Serverless: Pods status: {"waiting":{"reason":"PodInitializing"}}
Serverless: Function bikesearch successfully deployed
Serverless: Skipping ingress rule generation
Enter fullscreen mode Exit fullscreen mode

调用该函数

Kubeless 函数可以通过命令行或 Kubeless 提供的用户界面调用。Kubeless 用户界面可以通过以下方式配置:下载文件到本地并运行、使用 Docker 镜像和 Dockerfile,或者使用仓库中提供的 Kubernetes 清单文件。这里使用的是 Kubernetes 清单文件,如下面的代码所示:

$ kubectl create -f https://raw.githubusercontent.com/kubeless/kubeless-ui/master/k8s.yaml
serviceaccount "ui-acct" created
clusterrole "kubeless-ui" created
clusterrolebinding "kubeless-ui" created
deployment "ui" created
service "ui" created
$ minikube service ui -n kubeless
Enter fullscreen mode Exit fullscreen mode

minikube命令将弹出浏览器并打开一个用户界面。该用户界面可以创建、编辑、调用和删除函数,因此请调用您已部署的函数。添加{"term":"New York"}请求textarea,选择请求类型为 POST,然后单击“运行函数”。函数将成功执行,并显示站点数据响应输出。

您也可以通过 Serverless Framework 调用相同的函数,该函数将执行并获取所需数据,如下面的代码所示:

$ serverless invoke --function bikesearch --data '{"term":"Albemarle"}' -l
Serverless: Calling function: bikesearch...
--------------------------------------------------------------------
[ { availableDocks: 12,
totalDocks: 15,
city: '',
altitude: '',
stAddress2: '',
longitude: -77.079382,
lastCommunicationTime: '2018-08-15 04:16:15 PM',
postalCode: '',
statusValue: 'In Service',
testStation: false,
stAddress1: 'Tenleytown / Wisconsin Ave &amp; Albemarle St NW',
stationName: 'Tenleytown / Wisconsin Ave &amp; Albemarle St NW',
landMark: '',
latitude: 38.947607,
statusKey: 1,
availableBikes: 1,
id: 80,
location: '' } ]
Enter fullscreen mode Exit fullscreen mode

如果出现错误怎么办?虽然你没有设置错误处理机制,但可以通过在调用函数时传入错误信息来测试日志记录功能。因此,请像以下代码所示,在数据中传入错误信息来调用该函数:

$serverless invoke --function bikesearch --data '{"trm":"Albemarle"}' -l
Serverless: Calling function: bikesearch...

  Error --------------------------------------------------

  Internal Server Error

    For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.

  Get Support --------------------------------------------
    Docs: docs.serverless.com
    Bugs: github.com/serverless/serverless/issues
    Forums: forum.serverless.com
    Chat: gitter.im/serverless/serverless

  Your Environment Information -----------------------------
    OS: darwin
    Node Version: 6.10.3
    Serverless Version: 1.26.1
Enter fullscreen mode Exit fullscreen mode

Serverless 返回了一个 500 服务器错误代码,这符合 Web 框架的预期行为。但是,查看 Python 堆栈跟踪信息有助于更好地调试错误根源。因此,请获取日志以查看错误详情:

$ serverless logs -f bikesearch
Hit Ctrl-C to quit.
172.17.0.1 - - [15/Aug/2018:20:17:18 +0000] "POST / HTTP/1.1" 200 460 "" "" 0/934928
172.17.0.1 - - [15/Aug/2018:20:17:18 +0000] "GET /healthz HTTP/1.1" 200 2 "" "kube-probe/." 0/133
172.17.0.1 - - [15/Aug/2018:20:17:48 +0000] "GET /healthz HTTP/1.1" 200 2 "" "kube-probe/." 0/72
172.17.0.1 - - [15/Aug/2018:20:18:18 +0000] "GET /healthz HTTP/1.1" 200 2 "" "kube-probe/." 0/108
172.17.0.1 - - [15/Aug/2018:20:18:48 +0000] "GET /healthz HTTP/1.1" 200 2 "" "kube-probe/." 0/123
172.17.0.1 - - [15/Aug/2018:20:19:18 +0000] "GET /healthz HTTP/1.1" 200 2 "" "kube-probe/." 0/74
172.17.0.1 - - [15/Aug/2018:20:19:48 +0000] "GET /healthz HTTP/1.1" 200 2 "" "kube-probe/." 0/138
172.17.0.1 - - [15/Aug/2018:20:20:18 +0000] "GET /healthz HTTP/1.1" 200 2 "" "kube-probe/." 0/75
172.17.0.1 - - [15/Aug/2018:20:20:48 +0000] "GET /healthz HTTP/1.1" 200 2 "" "kube-probe/." 0/149
172.17.0.1 - - [15/Aug/2018:20:21:18 +0000] "GET /healthz HTTP/1.1" 200 2 "" "kube-probe/." 0/187
172.17.0.1 - - [15/Aug/2018:20:21:48 +0000] "GET /healthz HTTP/1.1" 200 2 "" "kube-probe/." 0/147
172.17.0.1 - - [15/Aug/2018:20:22:18 +0000] "GET /healthz HTTP/1.1" 200 2 "" "kube-probe/." 0/71
172.17.0.1 - - [15/Aug/2018:20:22:47 +0000] "POST / HTTP/1.1" 200 2131 "" "" 1/232988
Traceback (most recent call last):
 File "/usr/local/lib/python2.7/dist-packages/bottle.py", line 862, in _handle
return route.call(**args)
 File "/usr/local/lib/python2.7/dist-packages/bottle.py", line 1740, in wrapper
 rv = callback(*a, **ka)
 File "/kubeless.py", line 76, in handler
 raise res
KeyError: 'term'
Enter fullscreen mode Exit fullscreen mode

从KeyError语句可以明显看出,函数失败的原因是键名错误,这让你能够了解问题所在。但在生产环境中,你需要更完善的错误处理方法。

与 Jenkins 进行持续集成

对于 Kubeless,使用 Serverless Framework 时,只有在本地部署了 Kubernetes 集群(minikube)、Serverless Framework 和 Jenkins 之后才能进行部署。Serverless Framework 目前不支持远程部署。但随着 Serverless Framework 和 Kubeless 的不断完善,这些功能将会逐步添加。这里,我们将创建
用于本地部署的文件。

如果您克隆https://github.com/shzshi/kubeless-continuous-integration.git这个仓库,您应该可以使用此模板在本地设置持续集成。当然,您也可以在笔记本电脑上本地运行这些文件,前提是您已安装并配置了 Serverless Framework。

具体操作方法如下:

$ git clone https://github.com/shzshi/kubeless-continuous-integration.git
$ cd kubeless-continuous-integration
Enter fullscreen mode Exit fullscreen mode

你应该在这个文件夹中看到六个文件和一个目录,但本教程中不会用到 Dockerfiles 和 Jenkinsfiles。只有在可以使用 Serverless Framework for Kubeless 进行远程部署后,才能使用它们,如下面的代码所示:

$ npm install
$ npm test
> kubeless-nodejs@1.0.0 test /Users/shashi/Documents/packt/chapter7/kubeless-
continuous-integration
> mocha ./test/*.js
kubelesshello
✓ should return 0 when "Hello Kubeless" is present
1 passing (8ms)
Enter fullscreen mode Exit fullscreen mode

您运行了命令npm install来获取 Serverless Framework 和 Node.js 应用程序及测试所需的依赖项。之后,您运行了 npm 测试,并为此创建了一个简单的单元测试,以便在将其部署到集群之前检查函数的完整性,如下面的代码所示:

$ serverless deploy -v
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Deploying function kubelesshello...
Serverless: Pods status: {"waiting":{"reason":"PodInitializing"}}
Serverless: Pods status: {"waiting":{"reason":"PodInitializing"}}
Serverless: Function kubelesshello successfully deployed
Serverless: Skipping ingress rule generation
Enter fullscreen mode Exit fullscreen mode

因此,您的 Node.js 函数将成功部署,您可以在本地或通过 Kubeless UI 调用它并进行测试。调用后,您应该会得到Hello Kubeless如下代码所示的输出:

$ serverless invoke -f kubelesshello -l
Serverless: Calling function: kubelesshello...
--------------------------------------------------------------------
Hello Kubeless
Enter fullscreen mode Exit fullscreen mode

监控 Kubeless

您可以使用 Prometheus 监控该kubeless函数。Prometheus 内置运行时支持,会自动收集每个函数的指标。Prometheus 会将这些指标显示在默认仪表板上。

可以通过 Grafana 可视化 Prometheus 指标。可以通过 Kubeless 提供的示例仪表板 JSON 文件配置 Grafana 仪表板,该文件
位于https://github.com/kubeless/kubeless/blob/master/docs/misc/kubeless-grafana-dashboard.json

如果您觉得这篇文章有趣,可以探索“面向无服务器应用程序的 DevOps”课程,学习如何运用 DevOps 原则为您的无服务器应用程序搭建完整的 CI/CD 流水线。“面向无服务器应用程序的 DevOps”课程将带您了解各种 DevOps 相关场景,为您打下坚实的无服务器部署基础。

文章来源:https://dev.to/kayis/book-review-devops-for-serverless-applications-with-tutorial-ii3