从 Kyma ​​官网​​ 得知,Kyma 是一个云原生应用程序运行环境,它将 Kubernetes 提供的强大容器编排功能与若干世界级的开源组件和工具相结合,使开发人员能够开发、运行和操作安全且可扩展的云原生应用程序。

在 Kyma 云原生平台上开发并部署 Node.js 应用_kubernetes

Kubernetes 提供了一个框架,用于运行基于容器的分布式系统。 我们可以将容器视为一个非常轻量级的虚拟机,其中包含一小块应用逻辑,这些逻辑服务于一些更大的应用程序,也就是微服务。 Kubernetes 提供了许多用于管理容器生命周期的组件,让开发人员可以选择应用程序依赖项,例如消息传递总线、监控、日志记录等。

Kyma 构建于 Kubernetes 之上,解决了与微服务架构、事件消费、身份验证、日志记录、跟踪、监控和警报相关的需求。 此外,服务目录允许使用开放服务代理轻松使用超大规模提供商提供的云服务,以及使用应用程序连接器连接到 Kyma 的服务。 应用程序连接器允许开发人员轻松连接任何应用程序并以安全的方式公开其 API 和事件。

本文通过一个 Node.js 应用开发和部署的例子,来介绍 Kyma 这个云原生平台的使用方式。

1. Kyma 环境的 provision

登录 SAP BTP 控制台,点击 ​​Enable Kyma​​ 按钮,启用平台对 Kyma 运行环境的支持:

在 Kyma 云原生平台上开发并部署 Node.js 应用_云原生_02

创建一个 Kyma 实例:

在 Kyma 云原生平台上开发并部署 Node.js 应用_docker_03

在后台,正在建立一个新的 Kubernetes 集群,Kyma 运行时及其所有组件将在其中运行。
要打开 Kyma 运行时控制台 UI,单击子账户概览页面的 Kyma 环境部分下的链接到仪表板。

在 Kyma 云原生平台上开发并部署 Node.js 应用_node.js_04

仪表板或 Kyma 控制台 UI 是开发者在 Kyma 运行时管理和部署应用程序或服务的图形界面。 使用仪表板,开发人员不仅可以部署或删除部署,还可以对它们进行扩展管理,通过自定义 API 规则公开它们等等。

在 Kyma 云原生平台上开发并部署 Node.js 应用_docker_05

当然,Kyma 运行时是一个 Kubernetes 集群,因此我们也可以使用工具 kubectl 通过命令行管理资源和配置。

kubectl 工具依赖于一个名为 kubeconfig 的配置文件来配置对集群的访问。

在 Kyma 控制台下载这个 ​​kybeconfig​​ 配置文件:

在 Kyma 云原生平台上开发并部署 Node.js 应用_应用程序_06

在 Kyma 云原生平台上开发并部署 Node.js 应用_kubernetes_07

然后设置环境变量即可。

  • Linux:​​export KUBECONFIG=<KUBECONFIG_FILE_PATH>​
  • Windows:​​$ENV:KUBECONFIG=<KUBECONFIG_FILE_PATH>​

2. 使用 Express Generator 创建 Node.js 应用

使用 Express Generator 创建一个 Node.js 应用程序框架,并将一些片段作为基本应用程序添加到后端。

使用命令行:

​npx express-generator --view=jade kyma-multitenant-node​

在 Kyma 云原生平台上开发并部署 Node.js 应用_node.js_08

创建好的应用层级结构如下:

在 Kyma 云原生平台上开发并部署 Node.js 应用_云原生_09

Node.js 应用的路由(​​Routing​​)是指确定应用程序如何响应客户端对特定端点的请求,该端点是 URI(或路径)和特定的 HTTP 请求方法(GET、POST 等)。

每个路由可以有一个或多个处理函数,当路由匹配时执行。

路由定义采用以下结构:

​app.METHOD(PATH, HANDLER)​

增加下列的路由实现,我们就得到了一个最简单的 Hello World 级别的 Node.js 应用:

router.get("/", function(req, res,) {
try {
var line1 = "Hello " + req.authInfo.getLogonName();
var line2 = "your tenant sub-domain is " + req.authInfo.getSubdomain();
var line3 = "your tenant zone id is " + req.authInfo.getZoneId();
var responseMsg = line1 + "; " + line2 + "; " + line3;
res.send(responseMsg);
} catch (e) {
console.log("AuthInfo object undefined.");
var responseMsg = "Hello World!";
res.send(responseMsg);
}
});

3. 部署 Node.js 应用到 Kyma 云原生平台

在 SAP BTP 控制台上,找到要部署的 tenant 的 subdomain:

在 Kyma 云原生平台上开发并部署 Node.js 应用_云原生_10

在 Kyma 仪表板中,在下载的 kubeconfig.yml 文件或 Kyma 仪表板的 URL 中找到完整的 Kyma 集群域。

在 Kyma 云原生平台上开发并部署 Node.js 应用_node.js_11

为了在 Kyma Runtime(或任何基于 Kubernetes 的平台)上运行代码,我们需要为步骤2 开发的 Node.js 应用程序提供一个 OCI 映像(也称为 Docker 映像)。 原则上可以自由选择映像构建工具,本文使用 Cloud Native Buildpacks (CNB)。

命令行工具包支持提供 buildpack 和本地源代码并从中创建 OCI 映像。

首先安装命令行工具 ​​pack​​:

​brew install buildpacks/tap/pack​

当我们谈到存储库名称时,我们指的是 Docker Hub 中常见的帐户和存储库名称的组合:

​<docker-hub-account>/<repo-name>​​。

比如 tiaxu/multitenant-kyma-backend.

由于只能在 free 的 Docker hub 帐户中创建一个私有存储库,因此存储在 Docker hub 中的 Docker 映像将具有不同的标记名称,以便它们可以存储在一个存储库下。 因此,寻址图像将包括标签名称:​​<docker-hub-account>/<repo-name>:<tag-name>​​​。 一个例子是 ​​tiaxu/multitenant-kyma-backend:v1​​。

使用如下命令行构建镜像文件:

  • ​pack build multitenant-kyma-backend --builder paketobuildpacks/builder:full​
  • ​docker tag multitenant-kyma-backend <docker-hub-account>/multitenant-kyma-backend:v1​

下面将构建好的镜像文件发布到 Docker Hub:

首先登录 Docker:

​docker login -u <docker-id> -p <password>​

然后进行镜像发布:

​docker push <docker-hub-account>/multitenant-kyma-backend:v1​

由于 OCI 映像存储在 Docker Hub 中,因此我们需要提供对 Kyma 集群的访问信息,以便可以从这些存储库中提取映像,并根据 Docker 帐户替换占位符值:

​kubectl -n multitenancy-ns create secret docker-registry registry-secret --docker-server=https://index.docker.io/v1/ --docker-username=<docker-id> --docker-password=<password> --docker-email=<email> ​

对应的 yaml 文件如下:

imagePullSecrets:
- name: registry-secret # replace with your own registry secret

创建 Kyma 部署描述文件,这也是一个 yaml 格式的文件:

---
apiVersion: gateway.kyma-project.io/v1alpha1
kind: APIRule
metadata:
creationTimestamp: null
labels:
app: kyma-multitenant-node-multitenancy
release: multitenancy
name: kyma-multitenant-node-multitenancy
spec:
gateway: kyma-gateway.kyma-system.svc.cluster.local
rules:
- accessStrategies:
- handler: allow
methods:
- GET
- POST
- PUT
- PATCH
- DELETE
- HEAD
path: /.*
service:
host: <subaccount-subadomain>-node.<cluster-domain> # replace with the values of your account
name: kyma-multitenant-node-multitenancy
port: 8080
status: {}

---
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: kyma-multitenant-node-multitenancy
release: multitenancy
name: kyma-multitenant-node-multitenancy
spec:
replicas: 1
selector:
matchLabels:
app: kyma-multitenant-node-multitenancy
release: multitenancy
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: kyma-multitenant-node-multitenancy
release: multitenancy
spec:
automountServiceAccountToken: true
imagePullSecrets:
- name: registry-secret # replace with your own registry secret
containers:
- env:
- name: PORT
value: "8080"
- name: TMPDIR
value: /tmp
image: <docker-hub-account>/multitenant-kyma-backend:v1 # replace with your Docker Hub account name
livenessProbe:
exec:
command:
- nc
- -z
- localhost
- "8080"
failureThreshold: 1
initialDelaySeconds: 60
periodSeconds: 30
successThreshold: 1
timeoutSeconds: 60
name: kyma-multitenant-node-multitenancy
ports:
- containerPort: 8080
readinessProbe:
exec:
command:
- nc
- -z
- localhost
- "8080"
failureThreshold: 1
initialDelaySeconds: 60
periodSeconds: 30
successThreshold: 1
timeoutSeconds: 60
resources:
limits:
ephemeral-storage: 256M
memory: 256M
requests:
cpu: 100m
ephemeral-storage: 256M
memory: 256M
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: false
volumeMounts:
- mountPath: /tmp
name: tmp
securityContext:
runAsNonRoot: true
volumes:
- emptyDir: {}
name: tmp
status: {}

---
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: kyma-multitenant-node-multitenancy
release: multitenancy
name: kyma-multitenant-node-multitenancy
spec:
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
app: kyma-multitenant-node-multitenancy
release: multitenancy
status:
loadBalancer: {}

---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
creationTimestamp: null
labels:
release: multitenancy
name: multitenancy
spec:
ingress:
- from:
- namespaceSelector:
matchLabels:
name: istio-system
podSelector:
matchLabels:
app: istio-ingressgateway
podSelector:
matchLabels:
release: multitenancy
policyTypes:
-

使用下列的命令行进行部署:

​kubectl -n multitenancy-ns apply -f k8s-deployment-backend.yaml​

部署成功后,回到 Kyma 控制台,找到自动生成的能访问该 Node.js 应用的 url:

在 Kyma 云原生平台上开发并部署 Node.js 应用_应用程序_12

至此,Node.js 应用的开发,以及部署到 Kyma 云原生平台的步骤就介绍完毕。