创建微服务
在本节中,我们将介绍创建 UCS 微服务所需的步骤。UCS 微服务使用 UCS 微服务构建器 CLI (msbuilder) 工具构建。该工具的输入是一个具有特定结构的目录和具有特定名称和格式的文件。该工具的输出是微服务的 UCS 微服务规范,以及可选的微服务使用的容器镜像和基于用例和 UCS 微服务构建器 CLI 工具的输入类型的微服务的 Helm Chart。
有关 UCS 微服务的更多信息,请参阅 - UCS 微服务。
有关 msbuilder 输入目录规范,请参阅 - 微服务构建器输入规范。
生成脚手架
UCS 微服务构建器 CLI service create
生成新服务的脚手架
$ ucf_ms_builder_cli service create [-h] [-d DESCRIPTION] [-o OUTPUT_DIR] -n NAME -i {container-image,container-config,helm-chart} [-c CHART]
该工具支持为三种类型的输入创建微服务
预构建容器镜像
容器构建配置
预构建 helm charts
预构建容器镜像
当容器镜像已可用于要构建的微服务时,可以使用此选项。使用此方法,该工具将生成
微服务的 Helm chart
微服务的 UCS 微服务规范
要使用此方法,请运行
$ ucf_ms_builder_cli service create -n myservice -d "my service description" -i container-image
此命令将在以下输出目录结构中生成模板微服务
myservice
├── changelog.txt
├── configs
├── endpoints
│ ├── http-api.yaml
│ └── myservice-endpoint-name.yaml
├── LICENSE.txt
├── manifest.yaml
├── manual_compliance_test_results.yaml
├── README.md
├── scripts
└── tests
└── dev
├── app.yaml
└── params1.yaml
容器构建配置
当必须与微服务一起构建容器镜像时,可以使用此选项。使用此方法,该工具将生成
微服务的容器镜像
微服务的 Helm chart
微服务的 UCS 微服务规范
要使用此方法,请运行
$ ucf_ms_builder_cli service create -n myservice -d "my service description" -i container-config
此命令将在以下输出目录结构中生成模板微服务
myservice
├── changelog.txt
├── configs
├── containers
│ └── cb_config.yaml
├── endpoints
│ ├── http-api.yaml
│ └── myservice-endpoint-name.yaml
├── LICENSE.txt
├── manifest.yaml
├── manual_compliance_test_results.yaml
├── README.md
├── scripts
├── target_x86_64.yaml
└── tests
└── dev
├── app.yaml
└── params1.yaml
预构建 Helm Chart
当微服务的 helm chart 已可用,但需要创建 UCS 微服务规范时,可以使用此选项。使用此方法,该工具将生成
微服务的 UCS 微服务规范
要使用此方法,请运行
$ ucf_ms_builder_cli service create -n myservice -d "my service description" -i helm-chart -c <helm chart link>
此命令将在以下输出目录结构中生成模板微服务
myservice
├── changelog.txt
├── endpoints
│ ├── http-api.yaml
│ └── myservice-endpoint-name.yaml
├── LICENSE.txt
├── manifest.yaml
├── manual_compliance_test_results.yaml
├── README.md
├── tests
│ └── dev
│ ├── app.yaml
│ └── params1.yaml
└── values.yaml
更新微服务构建器输入
如上一节所示,输入将根据用例和工具的输入类型略有不同。本节将介绍如何更新所有用例的输入目录结构中的文件。
更新 configs
将微服务所需的任何配置文件添加到此目录。此目录中的文件可以包含占位符,这些占位符将被 UCS 应用程序覆盖。
当使用预构建 Helm Chart 时,不使用此目录中的文件。
包含占位符的 configs
目录中的文件 app_cfg.yaml
示例
redis:
host: $egress.redis.address
port: $egress.redis.port
log_level: 5
timeout: $params.timeout
configs
目录中的文件 app_cfg.yaml
将挂载到微服务包含的容器中的 /opt/configs/app_cfg.yaml
,并使用实际值更新占位符。
当构建和部署包含此微服务(连接了 redis
出口端点并且 timeout
参数设置为 10
)的应用程序时,文件 /opt/configs/app_cfg.yaml
将挂载到微服务包含的容器,其内容如下
redis:
host: redis-svc
port: 6739
log_level: 5
timeout: 10
更新 scripts
将微服务所需的任何脚本文件添加到此目录。
当使用预构建 Helm Chart 时,不使用此目录中的文件。
例如,scripts
目录中名为 run.sh
的文件将挂载到微服务包含的容器中的 /opt/scripts/run.sh
,内容完全相同。
将 容器构建 配置文件添加到 containers
对于必须与微服务一起构建的任何容器,将 容器构建 配置文件添加到 containers
目录并进行更新。
当使用预构建 Helm Chart 或使用预构建容器镜像时,不使用此目录中的文件。
更新 endpoints
每个入口/出口端点的端点定义文件可以根据 UCS MS 规范添加到 endpoints
目录下。文件名必须是 <endpoint-name>.<ext>
。文件的扩展名和内容将取决于端点的方案。
有关端点定义文件的内容、格式和文件名的更多详细信息,请参阅 UCS 端点方案。
更新 manual_compliance_test_results.yaml
开发人员必须按照 UCS 微服务合规性 中的规定运行手动合规性检查,并在 manual_compliance_test_results.yaml
中将各个合规性规则的结果(布尔值)更新为 true
/ false
。
添加测试
tests
目录包含 UCS 应用程序,这些应用程序基本上是微服务的测试。测试应用程序遵循 UCS 应用程序图文件规范 - UCS Tools 应用程序。
这些测试理想情况下应该作为一个整体测试微服务,即微服务的 helm chart 是否正常工作,而不是微服务内部运行的应用程序的单元测试。
例如,它可以测试通过微服务端点访问 API 是否有效,当应用程序通过 Kubernetes 容器化和部署时,通过使用已知输入和相应的已知输出调用 API,应用程序是否正常工作。
如果正在构建的微服务依赖于其他微服务,则这些其他微服务可以替换为存根微服务或更简单的功能等效微服务,以在测试时消除对其他微服务的依赖。
更新 values.yaml
仅当使用预构建 Helm Chart 时,才使用此文件。
它采用标准 Helm values.yaml
的形式,并包含必须覆盖的预构建 helm chart 的值。该文件可以包含 $params
、$egress
和 $secrets
占位符,这些占位符将在构建和部署应用程序时替换为实际值。
当使用预构建 Helm Chart 类型生成脚手架时,values.yaml 从 helm chart 中拉取并放置在此处。微服务开发人员可以修剪和更新该文件,仅保留那些需要被微服务或使用微服务的应用程序覆盖的值。
例如,当为 helm chart 生成脚手架时,values.yaml
可能如下所示
applicationSpecs:
myservice-deployment:
apptype: stateless
containers:
myservice-container:
env:
- name: REDIS_ENDPOINT
value: redis-svc:6379
command:
- sleep
- '1000'
image:
repository: ubuntu
tag: latest
ports:
- containerPort: 1000
name: http
restartPolicy: Always
securityContext:
runAsGroup: 1000
runAsUser: 1000
services:
myservice-service:
ports:
- name: http-api
port: 1000
image:
pullPolicy: IfNotPresent
imagePullSecrets: []
ingress:
enabled: false
微服务开发人员可以更新它以删除不需要覆盖的值,并添加 $params
和 $egress
等占位符
applicationSpecs:
myservice-deployment:
apptype: stateless
containers:
myservice-container:
env:
- name: REDIS_ENDPOINT
value: $egress.redis.address:$egress.redis.port
command:
- sleep
- '1000'
image:
repository: ubuntu
tag: $params.stringToEcho
更新文档
微服务构建器工具接受四种文档
README.md - 有关微服务的详细信息。由
service create
命令生成的模板具有多个部分,例如详细描述、使用信息、性能 KPI、支持的平台和部署要求、已知问题等。微服务开发人员必须根据需要填写这些部分中的信息。LICENSE.txt - 包含微服务中使用的任何第三方软件的许可证文本。这包括容器内运行的应用程序中使用的第三方软件的许可证,以及添加到容器文件系统的任何第三方软件包的许可证。
changelog.txt - 当前版本与以前版本相比的更改列表。
更新 Manifest 文件 manifest.yaml
manifest.yaml
包含用于描述微服务、helm chart 实现和容器构建配置详细信息的信息。
为三个用例生成的模板 manifest 略有不同。本节将介绍如何更新第一个用例(即 预构建容器镜像)的 manifest 文件,然后描述其他用例的差异(如果适用)。
以下是为 预构建容器镜像 用例生成的模板 manifest.yaml
文件示例
type: msapplication
specVersion: 2.5.0
name: ucf.svc.myservice
chartName: myservice
description: default description
version: 0.0.1
tags: []
keywords: []
publish: false
egress-endpoints:
- name: myservice-endpoint-name
description: Short description of endpoint
protocol: TCP # Or UDP
scheme: asyncio # Or grpc / rtsp / asyncio / none
mandatory: True # Or False
data-flow: in-out # Or in or out
ingress-endpoints:
- name: http-api
description: Short description of http-api ingress endpoint
scheme: http
data-flow: in-out # Or in or out
secrets:
- name: some-secret-name
description: Description for the secret
mandatory: True
mountPath: /secrets
fileName: someSecretFileName
params:
stringToEcho: someString
#> type: string
#> enum_values: someString, someOtherString
#> description: String to echo in init container
timeToSleep: 1000000
#> type: integer
#> maximum: 2000000
#> minimum: 1000000
#> description: String to echo in init container
#> flags: mandatory
metrics:
- portName: metrics # Name of pod container port which implements prometheus metrics
path: /metrics # HTTP path where metrics are available
# List of metrics exported by the microservice endpoint and their details
details:
- name: latency
description: Average latency of handling HTTP requests in milliseconds
labels: [request-type]
# recommendedMin: 5 # Optional
# recommendedMax: 50 # Optional
# Optional. Selector for pods that implement the metrics endpoint
# podSelectorLabels:
# app: myservice-myservice-deployment
# Files and directories will be mounted with prefix /opt/ext-files/
externalFiles:
- name: some-config.yaml # File will be available in containers at /opt/ext-files/some-config.yaml
description: Some Configuration file
mandatory: True
isDirectory: False
tests:
- name: dev-params1
app: tests/dev/app.yaml
params: tests/dev/params1.yaml
ciTrigger: false
timeout: 10
duration: 10
installPreReqs: true # Wether to install foundational services
namespace: default # Kubernetes namespace
gpuNodeLabels: ""
watchAllPods: true # OR set to false and set list of pods to watch below
watchPods:
- <pod-name-regex>
testerPods: # At least one tester pod is required
- name: testpod1 # Name of the test pod
startSignature: <START> # Signature to look for in the logs indicating start of tests. Regex is accepted
endSignature: <END> # Signature to look for in the logs indicating end of tests. Regex is accepted
errorSignatures: # Signatures that indicate test failures. Regex is accepted
- <REGEX1>
- <REGEX2>
---
spec:
- name: myservice-deployment
type: ucf.k8s.app.deployment
parameters:
apptype: stateless
- name: myservice-init-container
type: ucf.k8s.initcontainer
parameters:
image: ubuntu
imagePullPolicy: IfNotPresent
args: [echo, $params.stringToEcho]
- name: "myservice-container"
type: ucf.k8s.container
parameters:
image:
repository: ubuntu
tag: "latest"
command: ["sleep", "$params.timeToSleep"]
ports:
- containerPort: 0 # <PORT>
name: http
startupProbe:
httpGet:
path: /healthz
port: http
failureThreshold: 30
periodSeconds: 10
livenessProbe:
httpGet:
path: /healthz
port: http
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
- name: myservice-service
type: ucf.k8s.service
parameters:
annotations:
test-svc-annotation: annotation-value
labels:
test-svc-label: label-value
ports:
- port: 0 # <OUT_PORT>
name: http-api
#externalTrafficPolicy: # Cluster / Local. Allowed when service type is NodePort or LoadBalancer
根据 manifest 规范更新以下部分
规范
微服务的实现(即它的 helm chart)可以在 spec
字段下指定。作为 UCS 微服务构建器工具 的一部分,微服务实现必须使用可组合组件完成。
当使用预构建 Helm Chart 时,必须省略此部分。MSBuilder 忽略此字段,因为它不构建微服务 helm chart。
组件
组件定义了微服务实现的一小部分,例如容器、服务、卷。可以使用以下命令查看可用组件列表
$ ucf_ms_builder_cli component list
List of available components:
=============================
ucf.appspec.app.workload
ucf.appspec.defaultVolumeMount
ucf.k8s.app.deployment
ucf.k8s.configmap
ucf.k8s.container
ucf.k8s.imagepullsecret
ucf.k8s.initcontainer
ucf.k8s.podAnnotations
ucf.k8s.podLabels
ucf.k8s.podSecurityContext
ucf.k8s.pvc
ucf.k8s.restartPolicy
ucf.k8s.service
ucf.k8s.volume
...
要查看有关组件的详细信息,请运行
$ ucf_ms_builder_cli component info -c ucf.k8s.service
type: ucf.k8s.service
description: Service
properties:
pod: (string ), Service pod. [Mandatory:False]
ports: (array ), An explanation about the purpose of this instance. [Mandatory:True]
port: (integer), Service port. [Mandatory:True]
name: (string ), Name for service port (this is used as endpoint name) [Mandatory:False]
targetPort: (['string', 'integer']), Target port number or name. [Mandatory:False]
nodePort: (integer), Target port number or name. [Mandatory:False]
range: (integer), Range of ports. 0-<range - 1> will be added added to port/targetPort/nodePort [Mandatory:False]
type: (string ), Service type [Mandatory:False, Allowed Values:{ ClusterIP, NodePort }]
externalTrafficPolicy: (string ), Route external traffic to node-local or cluster-wide endpoints [Mandatory:False, Allowed Values:{ Cluster, Local }]
nameOverride: (boolean), Enable to set service name as set as <appname>-<service-name> [Mandatory:False]
fullNameOverride: (boolean), Enable to set service name as set as <service-name> [Mandatory:False]
extraSpecs: (object ), Extra specs to set on the service [Mandatory:False]
annotations: (object ), Annotations to set on the service [Mandatory:False]
labels: (object ), Labels to set on the service [Mandatory:False]
常用组件
下表列出了常用组件及其用途
组件 |
用途 |
---|---|
ucf.appspec.defaultVolumeMount |
添加默认 volumeMount。此 volumeMount 将添加到 pod 中的所有容器/initContainer |
ucf.appspec.ingress |
添加入口资源 |
ucf.k8s.app.deployment |
定义部署工作负载及其类型(例如 |
ucf.k8s.configmap |
向微服务添加 configmap |
ucf.k8s.container |
向微服务 pod/pod 模板添加容器 |
ucf.k8s.dnsPolicy |
为微服务 pod/pod 模板设置 DNS 策略 |
ucf.k8s.initcontainer |
向微服务 pod/pod 模板添加 initContainer |
ucf.k8s.podAnnotations |
在 pod/pod 模板上设置注释 |
ucf.k8s.podLabels |
在 pod/pod 模板上设置自定义标签 |
ucf.k8s.podSecurityContext |
为 pod/pod 模板设置 securityContext |
ucf.k8s.pvc |
为微服务添加 PVC 资源 |
ucf.k8s.restartPolicy |
为 pod/pod 模板设置重启策略 |
ucf.k8s.service |
向以下项添加 Kubernetes 服务 |
ucf.k8s.volume |
向 pod/pod 模板添加卷 |
向规范添加组件
组件必须作为列表添加到 spec
下,并附带其参数。参数值必须遵循组件的参数模式,可以使用如上所示的 component info
命令查看该模式。占位符 $params
、$egress
和 $secrets
可用于参数值中,分别引用参数、出口端点和密钥。这些占位符保留在构建的微服务 helm chart 中,但在应用程序构建期间被替换。
添加带有占位符的组件的示例是
spec:
- name: myservice-deployment
type: ucf.k8s.app.deployment
parameters:
apptype: stateless
- name: "myservice-container"
type: ucf.k8s.container
parameters:
image:
repository: ubuntu
tag: "latest"
env:
- name: HTTP_API_CA_CERT_PATH
value: $secrets.ca-cert.path
command: ["curl", "$egress.http-api.address:$egress.http-api.port",
"--connect-timeout", $params.connectTimeout, "--cacert", $(HTTP_API_CA_CERT_PATH)]
startupProbe:
httpGet:
path: /healthz
port: http
failureThreshold: 30
periodSeconds: 10
livenessProbe:
httpGet:
path: /healthz
port: http
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
注意
对于规范中定义的组件,参数必须遵守每种类型特定的组件模式,如上所示。
在一个 yamldoc 中只能指定一种工作负载类型(例如 stateless
、stateful
、job
、cronjob
、daemonset
、static-pod
)。要向微服务添加多种工作负载类型(例如两个 stateless
(即 Deployment
)),请执行以下操作
---
spec:
- name: app-deployment-1
type: ucf.k8s.app.deployment
parameters:
apptype: stateless
...
---
spec:
- name: app-deployment-2
type: ucf.k8s.app.deployment
parameters:
apptype: stateless
...
使用容器构建器配置
对于使用 容器构建 选项来构建容器以及微服务,请修改 ucf.k8s.container
和 ucf.k8s.initcontainer
组件的 image 参数,以指定容器构建器配置文件路径。路径相对于 manifest.yaml
文件。例如
spec:
- name: myservice-init-container
type: ucf.k8s.initcontainer
parameters:
image:
config_path: containers/init-container.yaml
...
- name: myservice-container
type: ucf.k8s.container
parameters:
image:
config_path: containers/app-container.yaml
...
模板容器构建器配置文件在 containers/cb_config.yaml
生成。必须至少进行以下更改才能使配置正常工作。
更新
base_image
更新
local_copy_files
和stage_copy_files
或完全删除它们更新
http_archives
或完全删除
在
docker_build
下更新image_name
到将要上传镜像的位置。
构建微服务
一旦微服务构建器工具的输入准备就绪,就可以使用以下命令构建微服务
$ ucf_ms_builder_cli service build -d <msbuilder-input-dir>
$ ucf_ms_builder_cli service build -d myservice/
2022-12-05 14:54:13,927 - Registry - INFO - Building: myservice/
2022-12-05 14:54:15,943 - MsBuilder - INFO - Helm chart generated in myservice/output/helm
2022-12-05 14:54:15,962 - MsBuilder - INFO - MS spec generated in myservice/output/msspec
2022-12-05 14:54:17,034 - MsBuilder - WARNING - Mandatory compliance checks failed. Check myservice/output/compliance_test_logs.txt for more information
2022-12-05 14:54:17,176 - MsBuilder - INFO - MS spec generated in myservice/output/msspec
2022-12-05 14:54:17,185 - MsBuilder - INFO - Building test application 'dev-params1'
2022-12-05 14:54:17,327 - MsBuilder - INFO - Syncing any missing service versions to cache...
2022-12-05 14:54:17,329 - MsBuilder - INFO - Validating application ...
2022-12-05 14:54:17,335 - MsBuilder - INFO - Building application myservice-dev-params1-0.0.1 ...
2022-12-05 14:54:17,671 - MsBuilder - INFO - Application compliance report generated at myservice/output/tests/dev-params1/compliance_report.json
2022-12-05 14:54:17,758 - MsBuilder - INFO - Application Helm Chart generated in myservice/output/tests/dev-params1
2022-12-05 14:54:17,759 - MsBuilder - INFO - Tests generated in myservice/output/tests
2022-12-05 14:54:17,902 - Registry - INFO - Generating service helm chart package...
2022-12-05 14:54:17,993 - Registry - INFO - Generating test helm chart packages...
2022-12-05 14:54:18,152 - MsBuilder - INFO - Added microservice 'ucf.svc.myservice:0.0.1' to local repository
如果使用 容器构建 选项,则必须添加额外的参数 -t <target-file>
。
$ ucf_ms_builder_cli service build -d myservice/ -t myservice/target_x86_64.yaml
示例目标文件 <msbuilder-input-dir>/target_x86_64.yaml
及其以下内容作为模板微服务生成的一部分添加
---
platform:
arch: x86_64
os: linux
distribution: ubuntu_22.04
compute:
cuda: 11.8
tensorrt: 8.5.1
cudnn: 8.6.0
deepstream: 6.2
triton: null
vpi: 2.1.6
如果需要,可以使用以下命令手动上传工具构建的容器镜像
.. code-block:: text
$ docker images # 列出所有镜像并找到使用工具构建的镜像 $ docker push <image>
注意
如果镜像在本地 docker 缓存中,则某些 Kubernetes 配置将无法拉取镜像,因为 Kubernetes 可能有自己的容器运行时实例正在运行,并且不使用本地 docker 缓存。在这种情况下,必须将容器镜像推送到 Kubernetes 可以从中拉取镜像的容器注册表中。如果需要指向新的存储库,则必须在 manifest 文件中进行相应的更改。当使用 Microk8s 时,可以使用其内置注册表:https://microk8s.io/docs/registry-built-in。
构建输出
构建微服务会根据用例生成以下输出
微服务的 UCS 微服务规范
Helm Chart - 适用于 预构建容器镜像 和 容器构建 用例
容器镜像 - 适用于 容器构建 用例
测试应用程序 Helm Chart - 适用于
manifest.yaml
中提到的每个测试微服务的 合规性报告
合规性检查日志 在
<msbuilder-input-dir>/output/compliance_test_logs.txt
生成
一旦微服务成功构建,它将自动添加到本地存储库,并准备好在 UCS 应用程序中使用。
可以使用 查看微服务信息 查看有关构建的微服务的信息。
有关合规性的更多信息,请参阅 UCS 微服务合规性。微服务开发人员可以参考 <msbuilder-input-dir>/output/compliance_test_logs.txt
中的日志文件,了解任何合规性失败的原因。