ETSI NFV-SOL CNF (容器化 VNF) 部署¶
本节介绍如何使用 Kubernetes VIM 在 Tacker v2 API 中部署 ETSI NFV-SOL 容器化 VNF。
有关支持的 Kubernetes 版本的信息,请参阅 Tacker 架构。
概述¶
下图显示了 CNF 部署的概述。
请求创建 VNF
用户通过上传 VNF 包并请求
create VNF,使用 tacker-client 向 tacker-server 请求创建 VNF。VNF 包应包含CNF 定义,除了VNFD之外。有关CNF 定义和VNFD的详细说明,请参阅 2. 创建 Kubernetes 对象文件 和 5. 创建 VNFD。请求实例化 VNF
用户通过请求
instantiate VNF并提供实例化参数,向 tacker-server 请求实例化创建的 VNF。调用 Kubernetes API
收到 tacker-client 的请求后,tacker-server 会将其重定向到 tacker-conductor。在 tacker-conductor 中,请求会根据实例化参数的内容再次重定向到适当的 infra-driver(在本例中为 Kubernetes infra-driver)。然后,Kubernetes infra-driver 调用 Kubernetes API 以创建 Pod 作为 VNF。
创建 Pod
Kubernetes Master 根据 API 调用创建 Pod。
准备 Kubernetes VIM¶
1. 创建配置文件¶
在将 Kubernetes VIM 注册到 tacker 之前,我们应该创建配置文件。以下 vim-k8s.yaml 文件提供注册 Kubernetes VIM 的必要信息。此示例指定了可以从 Kubernetes Master-node 获取的 bearer_token 和 ssl_ca_cert 参数的值。有关获取“bearer_token”和“ssl_ca_cert”的具体方法,请参阅 Kubernetes VIM 安装。
$ cat vim-k8s.yaml
auth_url: "https://192.168.56.10:6443"
bearer_token: "eyJhbGciOiJSUzI1NiIsImtpZCI6IkdVazBPakx4Q2NsUjJjNHhsZFdaaXJMSHVQMUo4NkdMS0toamlSaENiVFUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tazhzdmltIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJhNTIzYzFhMi1jYmU5LTQ1Y2YtYTc5YS00ZDA4MDYwZDE3NmEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpkZWZhdWx0In0.BpKAAQLjXMIpJIjqQDsGtyh1a-Ij8e-YOVRv0md_iOGXd1KLR-qreM6xA-Ni8WFILzq3phaZU6npET8PlfhQ6csF5u20OT2SoZ7iAotHXpCcYkRdrUd2oO5KxSFTkOhasaN1pQ3pZyaFYUZbwwmLK3I31rG4Br2VbZQ7Qu8wFOXUK-syBGF48vIPZ5JQ3K00KNxpuEcGybMK5LtdSKZ25Ozp_I2oqm3KBZMPMfWwaUnvuRnyly13tsiXudPt_9H78AxLubMo3rcvECJU2y_zZLiavcZKXAz-UmHulxtz_XZ80hMu-XOpYWEYrOB0Lt0hB59ZoY1y3OvJElTfPyrwWw"
ssl_ca_cert: "-----BEGIN CERTIFICATE-----
MIIDBTCCAe2gAwIBAgIIa76wZDxLNAowDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE
AxMKa3ViZXJuZXRlczAeFw0yMzExMDYwMDA3MzBaFw0zMzExMDMwMDEyMzBaMBUx
EzARBgNVBAMTCmt1YmVybmV0ZXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQDd0LBXGxVexr09mVFNSXWQq3TN66IIcXCBAMbIWI4EiQ8Y0zI4hSwADdK2
ltYSdWw7wq3/YTFHK8/YTY7Jvd9/k3UJrqkZ6kBtL20pJUPXNJVLE/hRzsqEnHHv
cfqYZTHvTY4g7qNcMOcfl/oDUGUMfpQT2gs6xoNl0WX/1+QeQbadx1kWaD2Ii45F
d8TR+c4wccxNaLArk3ok4h1PNeAwra4mRmBHQQ2wFjkTYGl4+ss3v1yoUJkrQjXL
RgzLufeXaz8eRTi36HkjudGKfS3OnUeke3uBN7usW58FFJ8TdKOhuoguRm53kj6+
TwXtZCOPzn4gNxq6xJE1Xj2hwFfpAgMBAAGjWTBXMA4GA1UdDwEB/wQEAwICpDAP
BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRdmQ4r63pXBHIO8ODqxROE7x+aizAV
BgNVHREEDjAMggprdWJlcm5ldGVzMA0GCSqGSIb3DQEBCwUAA4IBAQBeQ/9+bzRe
qbA02MfYnN3vycGhDObcAoiDIMIutojFTpx4hGZjqVgTRpLH5ReddwR4kkxn3NRg
weCVkNkhzyGze64nb11qZG71olaOQRMYzyN2hYfmbq7MXSvmJQQYIr1OewaRk+xl
TyG1XRXoD2IEaHEvG0+pQJlDerd5Z6S1fkPaKZtcRbM/E6y5VXMV6hegN4MwHZSI
Ll1uEBTxUzzTm3dnl1KL8GDg05ajoYcyL3X/0aWsb/MFhtIlXe2CMxu5qUkLBhzy
fCfX4cZpI5KFxMgdmAEoaGbNy7iqsGrLFtEmub2gdEBIVNr7vgOk4OeQ9Uodj6K7
jK97z+cupc5G
-----END CERTIFICATE-----"
project_name: "admin"
type: "kubernetes"
除了使用 bearer_token 进行 Kubernetes 身份验证外,还支持 OpenID Connect Tokens。以下示例指定了 oidc_token_url、client_id、client_secret、username、password,而不是用于 OpenID 令牌身份验证的 bearer_token。
在使用 OpenID 令牌身份验证之前,需要进行其他设置。请参阅 Kubernetes VIM OpenID 令牌身份验证使用指南,以及如何获取 oidc_token_url、client_id、client_secret、username、password 和 ssl_ca_cert 参数的文档。
Kubernetes 和 OpenID 提供商的 SSL 证书在 ssl_ca_cert 中连接。
$ cat vim-k8s.yaml
auth_url: "https://192.168.33.100:6443"
project_name: "default"
oidc_token_url: "https://192.168.33.100:8443/realms/oidc/protocol/openid-connect/token"
client_id: "tacker"
client_secret: "A93HfOUpySm6BjPug9PJdJumjEGUJMhc"
username: "end-user"
password: "end-user"
ssl_ca_cert: "-----BEGIN CERTIFICATE-----
MIICwjCCAaqgAwIBAgIBADANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDEwdrdWJl
LWNhMB4XDTIwMDgyNjA5MzIzMVoXDTMwMDgyNDA5MzIzMVowEjEQMA4GA1UEAxMH
a3ViZS1jYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALxkeE16lPAd
pfJj5GJMvZJFcX/CD6EB/LUoKwGmqVoOUQPd3b/NGy+qm+3bO9EU73epUPsVaWk2
Lr+Z1ua7u+iib/OMsfsSXMZ5OEPgd8ilrTGhXOH8jDkif9w1NtooJxYSRcHEwxVo
+aXdIJhqKdw16NVP/elS9KODFdRZDfQ6vU5oHSg3gO49kgv7CaxFdkF7QEHbchsJ
0S1nWMPAlUhA5b8IAx0+ecPlMYUGyGQIQgjgtHgeawJebH3PWy32UqfPhkLPzxsy
TSxk6akiXJTg6mYelscuxPLSe9UqNvHRIUoad3VnkF3+0CJ1z0qvfWIrzX3w92/p
YsDBZiP6vi8CAwEAAaMjMCEwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB/wQFMAMB
Af8wDQYJKoZIhvcNAQELBQADggEBAIbv2ulEcQi019jKz4REy7ZyH8+ExIUBBuIz
InAkfxNNxV83GkdyA9amk+LDoF/IFLMltAMM4b033ZKO5RPrHoDKO+xCA0yegYqU
BViaUiEXIvi/CcDpT9uh2aNO8wX5T/B0WCLfWFyiK+rr9qcosFYxWSdU0kFeg+Ln
YAaeFY65ZWpCCyljGpr2Vv11MAq1Tws8rEs3rg601SdKhBmkgcTAcCzHWBXR1P8K
rfzd6h01HhIomWzM9xrP2/2KlYRvExDLpp9qwOdMSanrszPDuMs52okXgfWnEqlB
2ZrqgOcTmyFzFh9h2dj1DJWvCvExybRmzWK1e8JMzTb40MEApyY=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIC7TCCAdWgAwIBAgIUQK2k5uNvlRLx43LI/t3a2/A/3iQwDQYJKoZIhvcNAQEL
BQAwFTETMBEGA1UEAxMKa3ViZXJuZXRlczAeFw0yMjA4MDQwNjIwNTFaFw0yMzA4
MDQwNjIwNTFaMBMxETAPBgNVBAMMCEtleWNsb2FrMIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAni7HWLn2IpUImGO1sbBf/XuqATkXSeIIRuQuFymwYPoX
BP7RowzrbfF9KUwdIKlz9IXjqb1hplumiqNy1Sc7MmrTY9Fj87MNAMlnCIvyWkjE
XVXWxGef49mqc85P2K1iuAsr2R7sDrv7SC0ch+lHclOjGDmCjKOk8qF3kD1LATWg
zf42aXb4nNF9kyIOPEbI+jX4PWhAQpEz5nIG+xIRjTHGfacjpeg0+XOK21wLAuQB
fqebJ6GxX4OzB37ZtLLgrKyBYWaWuYkWbexVRM3wEvQu8ENkvhV017iPuPHSxNWx
Y8z072XMs9j8XRQD65EVqObXyizotPRJF4slEJ9qMQIDAQABozcwNTAJBgNVHRME
AjAAMAsGA1UdDwQEAwIF4DAbBgNVHREEFDAShwR/AAABhwTAqAIhhwQKCgCMMA0G
CSqGSIb3DQEBCwUAA4IBAQBebjmNHd8sJXjvPQc3uY/3KSDpk9AYfYzhUZvcvLNg
z0llFqXHaFlMqHTsz1tOH4Ns4PDKKoRT0JIKC1FkvjzqgL+X2jWFS0NRoNyd3W3B
yHLEL7MdQqDR+tZX02EGfaGXjuy8GHIU4J2hXhohmpn6ntfiRONfY8jaEjIecPFS
IwZWXNhsDESa1zuDe0PatES/Ati8bAUpN2rb/7rsE/AeM5GXpQfOKV0XxdIeBZ82
Vf5cUDWPipvq2Q9KS+yrTvEObGtA6gKhQ4bpz3MieU3N8AtQpEKtROH7mJWMHyl2
roD1k8KeJlfvR/XcVTGFcgIdNLfKIdd99Xfi4gSaIKuw
-----END CERTIFICATE-----"
type: "kubernetes"
2. 注册 Kubernetes VIM¶
我们可以通过运行以下命令将 Kubernetes VIM 注册到 tacker
$ openstack vim register --config-file CONFIG_FILE KUBERNETES_VIM_NAME --fit-width
第 1 章中的配置文件需要通过参数 –config-file 输入。执行成功后,将显示 VIM 信息。例如,id。我们还可以使用用户名和密码等身份验证方法来注册 Kubernetes VIM。有关详细信息,请参阅第 1 章中的超链接。
$ openstack vim register --config-file vim-k8s.yaml test-vim-k8s --fit-width --is-default
+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| auth_cred | { |
| | "bearer_token": "***", |
| | "ssl_ca_cert": "b'gAAAAABlVGfZpWGEYn2hjBEVpkFOTZ4lt8xtMagfzpmoaHNXMzCwKX8Sd8eDCBnwXnsN-whaBvcOu0qb9DCyo2BjqR8fBmtxhbOVDNUofPtbebkgmVFnwFUyacZxLBk- |
| | l8AHqQnQOK5wkIUWabsCYhZcA7r800jH9ZysLHRmW5pTRAc_n6CtSvgXoShqzL0L1AlxA5omgac2gXkrulBvJDpnKJhXSCnYkWsJyWtDTDnwTTt8IZvuec_Rh9C0b4bAFLNCmwSw2KRtJTepQcsHtL9vXRZOcS2WJcgg3J_DxNGIcxAUacAcTc8CX7MB5c_DSMOD5lrLPk93Sr- |
| | 0XzODPib4ar4C8Kzs4fiYki6BWnwWHbcmZMtXClnTZIu3iLhKDG_GNAp9dhMrRUNFX3I8HRfWzMmp7EComQGkkE0vlJ8LRavWPRspKTx92ubwkatYrfKlyVoS2uBsc8jBum94hsquERInVSoUrKwlnyNfn7ecSr2W_1M4LWo2GU8joEYBBUM6oHomV_Sl0yIdXpEofd- |
| | kYWWP0PO7CY9KgNrJU7Iqyn4ZgKBWhH6qfL-xEmGndgE2Xt4ZKPKdWWquXXhXtz7fz51LmpQwGvZR4-qFYa9B6XEC0odvQVW0xzZl36C6nTREP4TuOodos3iMUy89iKDzk52JgLUDkU-k-MtROzdA0BwNqlLKzwslOFuaXe7P1Khf7oS7TjgG1vMdr9t_K2dacMdNhJEtwb- |
| | lTlFr6JEAbsd852EM45rUegG3_PKqxv5XgKczCrcAsJhTRW-RhxyWk_bpSS1skJGUJdMEhEvQss0ilZfnOw3TunKZXk66c-2LG9EG4e49B15nUQ6H6V-8G-POSBg0qpDVeaniIxmKSiExrQEzrh7lfR- |
| | avvGst02FuqEzsg82hojgpMbDSW643JYjGRgcSFrcFvydsYVNCPg8BJatGnXd4tqPeniDXJOOIg5qgj3_ful7PeMY08mjHfPHaiaI3xLszmJGLP1pCz-IPliaogi77ZNegvU7Z5_FtQE56J9pWF2NUZRyP92OveEKfTpQbPSLSiLUofxTq7oYoWVZfZnEOaewV0z8A- |
| | b7VrG267kgWS7mboQb0sIeegpzQgA3HMX0wG8FCuBxqvmxyIWUf7M1rPa6QcTfv8ZBFCs5lbxjs8tNw86pCKELa1FfuIwuVu9yGPHDrAoUWH_Lq93SAl9VYEJbvVo05OxA8kxLU3qFxLP0A6DBGxoOhIDznrY5WzMLJ6K53PI1D8-ESYhhIukSHlgClcopMk0ywsF1URyF8HO4TaIf4N0- |
| | HJFq95pZArLlmtBr6WmXXrpkDuH-ASGVnObTMLp7oQuJY1kQNmktlstuo54MW5FiLvL0pod2Og0k46_UofpA3mkYGM2dE6DtajACPpOQl7DR7NFFtY-9MGzvf8s3OiOWkq7I3mZnag2fYfMERcly5_a0ipIGoTcQkNCmIn9seC8x- |
| | 3odxGHUwIilhr7mnuXNKvHzuVvmXrYiBVnzgwuajZ37VYKY4y9K90BeIWPEF63vZRwlXuRoDTP9WGwbojv2PJkPHHn8Tg=='", |
| | "auth_url": "https://192.168.56.10:6443", |
| | "username": "None", |
| | "key_type": "barbican_key", |
| | "secret_uuid": "***" |
| | } |
| auth_url | https://192.168.56.10:6443 |
| created_at | 2023-11-15 06:40:25.544685 |
| description | |
| extra | |
| id | 290ae639-5b47-42b6-b1b0-c1623f6d856a |
| is_default | True |
| name | test-vim-k8s |
| placement_attr | { |
| | "regions": [ |
| | "default", |
| | "kube-node-lease", |
| | "kube-public", |
| | "kube-system" |
| | ] |
| | } |
| project_id | ebbc6cf1a03d49918c8e408535d87268 |
| status | ACTIVE |
| type | kubernetes |
| updated_at | None |
| vim_project | { |
| | "name": "admin" |
| | } |
+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
我们还可以通过 openstack vim list 命令检查 VIM 的状态是否为 ACTIVE。
$ openstack vim list
+--------------------------------------+--------------+----------------------------------+------------+------------+--------+
| ID | Name | Tenant_id | Type | Is Default | Status |
+--------------------------------------+--------------+----------------------------------+------------+------------+--------+
| 290ae639-5b47-42b6-b1b0-c1623f6d856a | test-vim-k8s | ebbc6cf1a03d49918c8e408535d87268 | kubernetes | True | ACTIVE |
+--------------------------------------+--------------+----------------------------------+------------+------------+--------+
准备 VNF 包¶
例如,您可以按如下方式创建 VNF 包。 在本文档中,TACKER_ROOT 是服务器上 tacker 仓库的根目录。
$ cd TACKER_ROOT/samples/tests/functional/sol_kubernetes_v2/test_instantiate_cnf_resources
$ python3 pkggen.py
$ ll
...
drwxr-xr-x 6 stack stack 4096 Nov 5 23:46 contents/
-rw-r--r-- 1 stack stack 3921 Nov 5 23:46 pkggen.py
-rw-rw-r-- 1 stack stack 28783 Nov 15 07:15 test_instantiate_cnf_resources.zip
...
注意
此工具需要一些 Tacker 模块,因此需要在安装了 Tacker 的环境中运行它,例如使用 devstack 的 python 虚拟环境。如果已在 python 虚拟环境中安装了 Tacker,请在使用该工具之前激活它,如下所示。
$ source /opt/stack/data/venv/bin/activate
(venv) $ python3 pkggen.py
完成上述操作后,您将拥有示例 VNF 包 test_instantiate_cnf_resources.zip。
注意
如果存在与正在生成的 zip 文件同名的文件,该工具将失败。 再次运行该工具以生成 zip 文件时,请删除或重命名旧的 zip 文件。
您也可以按照以下步骤手动创建 VNF 包。
1. 创建 VNF 包的目录¶
TOSCA YAML CSAR 文件是使用 ZIP 文件格式的归档文件,其结构符合 TOSCA Simple Profile YAML v1.2 规范。以下是构建 VNF 包 CSAR 目录的示例
$ mkdir -p deployment/{TOSCA-Metadata,Definitions,Files/kubernetes}
2. 创建 Kubernetes 对象文件¶
CSAR VNF 包应具有一个对象文件,该文件定义要部署的 Kubernetes 资源。文件名应具有“.yaml”扩展名。根据不同 yaml 文件的内容,可以创建不同的 Kubernetes api 资源。
注意
请参阅 Kubernetes API 资源,以获取每个资源的示例 yaml 文件。
以下是 deployment 资源的简单示例。
$ cat ./deployment/Files/kubernetes/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: vdu1
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: webserver
template:
metadata:
labels:
app: webserver
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
protocol: TCP
strategy:
type: RollingUpdate
注意
metadata.name 文件应与部署 flavor 定义文件中的相应 VDU 的 properties.name 相同。在本过程的示例中,metadata.name 与 sample_cnf_df_simple.yaml 文件中的 topology_template.node_templates.VDU1.properties.name 相同。
3. 创建 TOSCA.meta 文件¶
TOSCA.meta 文件包含 TOSCA.meta 文件、CSAR、Definitions 文件和 artifact 文件的版本信息。TOSCA.meta 文件需要 artifact 文件的名称、content-Type、加密方法和哈希值。
$ cat ./deployment/TOSCA-Metadata/TOSCA.meta
TOSCA-Meta-File-Version: 1.0
Created-by: dummy_user
CSAR-Version: 1.1
Entry-Definitions: Definitions/sample_cnf_top.vnfd.yaml
Name: Files/kubernetes/deployment.yaml
Content-Type: test-data
Algorithm: SHA-256
Hash: 36cab1efa2e3e0fb983816010450dbccf491ae905ba4012778a351cc73b420a7
4. 下载 ETSI 定义文件¶
下载官方文档。ETSI GS NFV-SOL 001 [i.4] 规定了基于 TOSCA 规范的 VNFD 的结构和格式。
$ cd deployment/Definitions
$ wget https://forge.etsi.org/rep/nfv/SOL001/raw/v2.6.1/etsi_nfv_sol001_common_types.yaml
$ wget https://forge.etsi.org/rep/nfv/SOL001/raw/v2.6.1/etsi_nfv_sol001_vnfd_types.yaml
5. 创建 VNFD¶
如何创建由多个部署 flavor 组成的 VNFD 在基于 ETSI NFV-SOL001 的 VNF 描述符 (VNFD) 中有描述,请参阅 基于 ETSI NFV-SOL001 的 VNF 描述符 (VNFD)。
VNFD 不会包含任何 Kubernetes 资源信息,例如 VDU、连接点、虚拟链路,因为 CNF 的所有必需组件都将在 Kubernetes 资源文件中指定。
以下是包含 VNF 定义的 VNFD 文件的示例。
$ cat sample_cnf_top.vnfd.yaml
tosca_definitions_version: tosca_simple_yaml_1_2
description: Sample VNF
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
- sample_cnf_types.yaml
- sample_cnf_df_simple.yaml
topology_template:
inputs:
selected_flavour:
type: string
description: VNF deployment flavour selected by the consumer. It is provided in the API
node_templates:
VNF:
type: company.provider.VNF
properties:
flavour_id: { get_input: selected_flavour }
descriptor_id: b1bb0ce7-ebca-4fa7-95ed-4840d7000000
provider: Company
product_name: Sample VNF
software_version: '1.0'
descriptor_version: '1.0'
vnfm_info:
- Tacker
requirements:
#- virtual_link_external # mapped in lower-level templates
#- virtual_link_internal # mapped in lower-level templates
sample_cnf_types.yaml 文件定义了 VNF 的参数类型和默认值。
$ cat sample_cnf_types.yaml
tosca_definitions_version: tosca_simple_yaml_1_2
description: VNF type definition
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
node_types:
company.provider.VNF:
derived_from: tosca.nodes.nfv.VNF
properties:
descriptor_id:
type: string
constraints: [ valid_values: [ b1bb0ce7-ebca-4fa7-95ed-4840d7000000 ] ]
default: b1bb0ce7-ebca-4fa7-95ed-4840d7000000
descriptor_version:
type: string
constraints: [ valid_values: [ '1.0' ] ]
default: '1.0'
provider:
type: string
constraints: [ valid_values: [ 'Company' ] ]
default: 'Company'
product_name:
type: string
constraints: [ valid_values: [ 'Sample VNF' ] ]
default: 'Sample VNF'
software_version:
type: string
constraints: [ valid_values: [ '1.0' ] ]
default: '1.0'
vnfm_info:
type: list
entry_schema:
type: string
constraints: [ valid_values: [ Tacker ] ]
default: [ Tacker ]
flavour_id:
type: string
constraints: [ valid_values: [ simple,complex ] ]
default: simple
flavour_description:
type: string
default: ""
requirements:
- virtual_link_external:
capability: tosca.capabilities.nfv.VirtualLinkable
- virtual_link_internal:
capability: tosca.capabilities.nfv.VirtualLinkable
interfaces:
Vnflcm:
type: tosca.interfaces.nfv.Vnflcm
sample_cnf_df_simple.yaml 定义了 VNF 输入的参数类型。
$ cat sample_cnf_df_simple.yaml
tosca_definitions_version: tosca_simple_yaml_1_2
description: Simple deployment flavour for Sample VNF
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
- sample_cnf_types.yaml
topology_template:
inputs:
descriptor_id:
type: string
descriptor_version:
type: string
provider:
type: string
product_name:
type: string
software_version:
type: string
vnfm_info:
type: list
entry_schema:
type: string
flavour_id:
type: string
flavour_description:
type: string
substitution_mappings:
node_type: company.provider.VNF
properties:
flavour_id: simple
requirements:
virtual_link_external: []
node_templates:
VNF:
type: company.provider.VNF
properties:
flavour_description: A simple flavour
VDU1:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: vdu1
description: VDU1 compute node
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 3
policies:
- scaling_aspects:
type: tosca.policies.nfv.ScalingAspects
properties:
aspects:
vdu1_aspect:
name: vdu1_aspect
description: vdu1 scaling aspect
max_scale_level: 2
step_deltas:
- delta_1
- VDU1_initial_delta:
type: tosca.policies.nfv.VduInitialDelta
properties:
initial_delta:
number_of_instances: 2
targets: [ VDU1 ]
- VDU1_scaling_aspect_deltas:
type: tosca.policies.nfv.VduScalingAspectDeltas
properties:
aspect: vdu1_aspect
deltas:
delta_1:
number_of_instances: 1
targets: [ VDU1 ]
- instantiation_levels:
type: tosca.policies.nfv.InstantiationLevels
properties:
levels:
instantiation_level_1:
description: Smallest size
scale_info:
vdu1_aspect:
scale_level: 1
instantiation_level_2:
description: Largest size
scale_info:
vdu1_aspect:
scale_level: 2
default_level: instantiation_level_1
- VDU1_instantiation_levels:
type: tosca.policies.nfv.VduInstantiationLevels
properties:
levels:
instantiation_level_1:
number_of_instances: 2
instantiation_level_2:
number_of_instances: 3
targets: [ VDU1 ]
注意
VDU1.properties.name 应与在 Kubernetes 对象文件中定义的 metadata.name 相同。因此,VDU1.properties.name 应遵循 Kubernetes 资源名称的命名规则。有关命名规则的详细信息,请参阅 Kubernetes 文档 DNS 子域名。
6. 压缩 VNF 包¶
CSAR 包应压缩为 ZIP 文件进行上传。以下命令是压缩 VNF 包的示例
$ cd -
$ cd ./deployment
$ zip deployment.zip -r Definitions/ Files/ TOSCA-Metadata/
adding: Definitions/ (stored 0%)
adding: Definitions/sample_cnf_top.vnfd.yaml (deflated 54%)
adding: Definitions/sample_cnf_df_simple.yaml (deflated 76%)
adding: Definitions/etsi_nfv_sol001_vnfd_types.yaml (deflated 83%)
adding: Definitions/etsi_nfv_sol001_common_types.yaml (deflated 76%)
adding: Definitions/sample_cnf_types.yaml (deflated 70%)
adding: Files/ (stored 0%)
adding: Files/kubernetes/ (stored 0%)
adding: Files/kubernetes/deployment.yaml (deflated 50%)
adding: TOSCA-Metadata/ (stored 0%)
adding: TOSCA-Metadata/TOSCA.meta (deflated 23%)
$ ls deployment
deployment.zip Definitions Files TOSCA-Metadata
创建并上传 VNF 包¶
我们需要在 tacker 中创建一个空的 VNF 包对象,并上传之前章节中创建的压缩 VNF 包。
1. 创建 VNF 包¶
可以使用命令 openstack vnf package create 创建一个空的 vnf 包。成功创建 VNF 包后,将返回一些信息,包括 ID、链接、Onboarding 状态、Operational 状态和 Usage 状态。当 Onboarding 状态为 CREATED,Operational 状态为 DISABLED,Usage 状态为 NOT_IN_USE 时,表示创建成功。
$ openstack vnf package create
+-------------------+-------------------------------------------------------------------------------------------------+
| Field | Value |
+-------------------+-------------------------------------------------------------------------------------------------+
| ID | ea4d29b3-bf2c-437c-a4a2-69b37208d21a |
| Links | { |
| | "self": { |
| | "href": "/vnfpkgm/v1/vnf_packages/ea4d29b3-bf2c-437c-a4a2-69b37208d21a" |
| | }, |
| | "packageContent": { |
| | "href": "/vnfpkgm/v1/vnf_packages/ea4d29b3-bf2c-437c-a4a2-69b37208d21a/package_content" |
| | } |
| | } |
| Onboarding State | CREATED |
| Operational State | DISABLED |
| Usage State | NOT_IN_USE |
| User Defined Data | {} |
+-------------------+-------------------------------------------------------------------------------------------------+
2. 上传 VNF 包¶
通过运行以下命令将上述创建的 VNF 包上传到 VNF 包:openstack vnf package upload --path <vnf 包路径> <vnf 包 ID>。以下是上传 VNF 包的示例
$ openstack vnf package upload --path deployment.zip VNF_PACKAGE_ID
Upload request for VNF package ea4d29b3-bf2c-437c-a4a2-69b37208d21a has been accepted.
3. 检查 VNF 包状态¶
通过 openstack vnf package list 命令检查 VNF 包状态。找到 id 与创建的 vnf 包 id 相同的项目,当 Onboarding 状态为 ONBOARDED、Operational 状态为 ENABLED、Usage 状态为 NOT_IN_USE 时,表示 VNF 包已成功上传。
$ openstack vnf package list
+--------------------------------------+------------------+------------------+-------------+-------------------+-------------------------------------------------------------------------------------------------+
| Id | Vnf Product Name | Onboarding State | Usage State | Operational State | Links |
+--------------------------------------+------------------+------------------+-------------+-------------------+-------------------------------------------------------------------------------------------------+
| ea4d29b3-bf2c-437c-a4a2-69b37208d21a | Sample VNF | ONBOARDED | NOT_IN_USE | ENABLED | { |
| | | | | | "self": { |
| | | | | | "href": "/vnfpkgm/v1/vnf_packages/ea4d29b3-bf2c-437c-a4a2-69b37208d21a" |
| | | | | | }, |
| | | | | | "packageContent": { |
| | | | | | "href": "/vnfpkgm/v1/vnf_packages/ea4d29b3-bf2c-437c-a4a2-69b37208d21a/package_content" |
| | | | | | } |
| | | | | | } |
+--------------------------------------+------------------+------------------+-------------+-------------------+-------------------------------------------------------------------------------------------------+
创建 VNF¶
1. 获取 VNFD ID¶
可以通过 openstack vnf package show <VNF 包 ID> 命令找到上传的 vnf 包的 VNFD ID。以下是检查 VNFD-ID 值的示例
$ openstack vnf package show VNF_PACKAGE_ID
+----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| Additional Artifacts | [ |
| | { |
| | "artifactPath": "Files/kubernetes/deployment.yaml", |
| | "checksum": { |
| | "algorithm": "SHA-256", |
| | "hash": "36cab1efa2e3e0fb983816010450dbccf491ae905ba4012778a351cc73b420a7" |
| | }, |
| | "metadata": {} |
| | } |
| | ] |
| Checksum | { |
| | "hash": "3ab4ea9ee8c125b52dd1fd1cb656a17668173b18a9f1d7fe18146e310e940851cddc2a07a9d081cf8a2a239b4d3b8025d4d328951b87e535d3f8fc788f15d6ea", |
| | "algorithm": "sha512" |
| | } |
| ID | ea4d29b3-bf2c-437c-a4a2-69b37208d21a |
| Links | { |
| | "self": { |
| | "href": "/vnfpkgm/v1/vnf_packages/ea4d29b3-bf2c-437c-a4a2-69b37208d21a" |
| | }, |
| | "packageContent": { |
| | "href": "/vnfpkgm/v1/vnf_packages/ea4d29b3-bf2c-437c-a4a2-69b37208d21a/package_content" |
| | } |
| | } |
| Onboarding State | ONBOARDED |
| Operational State | ENABLED |
| Software Images | |
| Usage State | NOT_IN_USE |
| User Defined Data | {} |
| VNF Product Name | Sample VNF |
| VNF Provider | Company |
| VNF Software Version | 1.0 |
| VNFD ID | b1bb0ce7-ebca-4fa7-95ed-4840d7000000 |
| VNFD Version | 1.0 |
+----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
2. 执行创建 VNF 命令¶
我们可以通过运行 openstack vnflcm create <VNFD ID> 创建 VNF。执行该命令后,生成的 ID 是 VNF 实例 ID。
$ openstack vnflcm create VNFD_ID --os-tacker-api-version 2
+-----------------------------+------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+-----------------------------+------------------------------------------------------------------------------------------------------------------+
| ID | 431b94b5-d7ba-4d1c-aa26-ecec65d7ee53 |
| Instantiation State | NOT_INSTANTIATED |
| Links | { |
| | "self": { |
| | "href": "http://127.0.0.1:9890/vnflcm/v2/vnf_instances/431b94b5-d7ba-4d1c-aa26-ecec65d7ee53" |
| | }, |
| | "instantiate": { |
| | "href": "http://127.0.0.1:9890/vnflcm/v2/vnf_instances/431b94b5-d7ba-4d1c-aa26-ecec65d7ee53/instantiate" |
| | } |
| | } |
| VNF Configurable Properties | |
| VNF Instance Description | |
| VNF Instance Name | |
| VNF Product Name | Sample VNF |
| VNF Provider | Company |
| VNF Software Version | 1.0 |
| VNFD ID | b1bb0ce7-ebca-4fa7-95ed-4840d7000000 |
| VNFD Version | 1.0 |
+-----------------------------+------------------------------------------------------------------------------------------------------------------+
实例化 VNF¶
1. 设置请求参数文件中的值¶
获取目标 VIM 的 ID。
$ openstack vim list
+--------------------------------------+--------------+----------------------------------+------------+------------+--------+
| ID | Name | Tenant_id | Type | Is Default | Status |
+--------------------------------------+--------------+----------------------------------+------------+------------+--------+
| 290ae639-5b47-42b6-b1b0-c1623f6d856a | test-vim-k8s | ebbc6cf1a03d49918c8e408535d87268 | kubernetes | True | ACTIVE |
+--------------------------------------+--------------+----------------------------------+------------+------------+--------+
实例化容器化 VNF 时,应提供包含 Kubernetes 资源定义文件路径和 Kubernetes VIM 信息的 json 文件。以下是 json 文件的示例
additionalParams 包含 Kubernetes 资源定义文件的路径,请注意 lcm-kubernetes-def-files 应该是一个列表。用户还可以指定资源需要部署的 namespace。
注意
VNF 实例化的 namespace 由以下优先级确定:
如果在实例化请求的 additionalParams 中指定了
namespace,则使用指定的namespace。如果未通过第 1 步中描述的方法指定
namespace,则使用在 2. 创建 Kubernetes 对象文件 中定义的 metadata 下的namespace。如果未通过第 2 步中描述的方法指定
namespace,则使用默认命名空间,即default。
警告
如果通过第 2 节中描述的方法在 manifest 中指定了多个命名空间,则 VNF 实例化将失败。
vimConnectionInfo 包含可以自主定义的 id 值、vimId 和 vimType。
$ cat ./instance_kubernetes.json
{
"flavourId": "simple",
"vimConnectionInfo": {
"vim1": {
"vimId": "290ae639-5b47-42b6-b1b0-c1623f6d856a",
"vimType": "ETSINFV.KUBERNETES.V_1"
}
},
"additionalParams": {
"lcm-kubernetes-def-files": [
"Files/kubernetes/deployment.yaml"
]
}
}
注意
此操作可以指定 VNF 实例的 vimConnectionInfo。即使此操作指定与一个 VNF 实例关联的多个 vimConnectionInfo,也只会使用其中一个用于生命周期管理操作。
注意
资源按照 lcm-kubernetes-def-files 列表的顺序创建。因此,要求用户以正确的顺序指定 lcm-kubernetes-def-files 列表。
2. 执行实例化命令¶
执行以下 CLI 命令来实例化 VNF 实例。
$ openstack vnflcm instantiate VNF_INSTANCE_ID \
instance_kubernetes.json --os-tacker-api-version 2
Instantiate request for VNF Instance 431b94b5-d7ba-4d1c-aa26-ecec65d7ee53 has been accepted.
VNF_INSTANCE_ID 是执行 create 命令后生成的 ID。可以在 2. 执行创建 VNF 命令 章中找到它。
3. 检查实例化状态¶
我们可以通过运行以下命令检查实例化状态。当实例化状态为 INSTANTIATED 时,表示实例化成功。
$ openstack vnflcm show VNF_INSTANCE_ID \
-c 'Instantiation State' --os-tacker-api-version 2
+---------------------+--------------+
| Field | Value |
+---------------------+--------------+
| Instantiation State | INSTANTIATED |
+---------------------+--------------+
4. 检查 Kubernetes 中的部署¶
要测试容器化 VNF 是否正在目标 Kubernetes VIM 环境中运行,我们可以通过运行以下命令进行检查。当 READY 为 2/2 时,表示部署创建成功。
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
vdu1 2/2 2 2 7m35s
如果要在默认命名空间中检查资源是否部署,可以在命令行中追加 -A。
$ kubectl get deploy -A
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
default vdu1 2/2 2 2 8m46s
kube-system coredns 2/2 2 2 28h
注意
如果在实例化期间为命名空间指定了除 default 之外的其他值,则部署的资源将在相应的命名空间中实例化。
终止 VNF¶
1. 执行终止命令¶
执行以下 CLI 命令以终止 VNF 实例。
$ openstack vnflcm terminate VNF_INSTANCE_ID --os-tacker-api-version 2
Terminate request for VNF Instance '431b94b5-d7ba-4d1c-aa26-ecec65d7ee53' has been accepted.
2. 检查实例化状态¶
我们可以通过运行以下命令检查实例化状态。当实例化状态为 NOT_INSTANTIATED 时,表示终止成功。
$ openstack vnflcm show VNF_INSTANCE_ID \
-c 'Instantiation State' --os-tacker-api-version 2
+---------------------+------------------+
| Field | Value |
+---------------------+------------------+
| Instantiation State | NOT_INSTANTIATED |
+---------------------+------------------+
删除 VNF 标识符¶
1. 执行删除命令¶
执行以下 CLI 命令以删除 VNF 实例。
$ openstack vnflcm delete VNF_INSTANCE_ID --os-tacker-api-version 2
Vnf instance '431b94b5-d7ba-4d1c-aa26-ecec65d7ee53' is deleted successfully
2. 检查状态¶
执行以下 CLI 命令并确认 VNF 实例删除成功。
确认 VNF 包的“Usage State”为“NOT_IN_USE”。
确认未找到 VNF 实例。
$ openstack vnf package show VNF_PACKAGE_ID -c 'Usage State'
+-------------+------------+
| Field | Value |
+-------------+------------+
| Usage State | NOT_IN_USE |
+-------------+------------+
$ openstack vnflcm show VNF_INSTANCE_ID --os-tacker-api-version 2
VnfInstance 431b94b5-d7ba-4d1c-aa26-ecec65d7ee53 not found.