Tacker部署与使用详解

Tacker - OpenStack NFV Orchestration

Tacker is an official OpenStack project building a Generic VNF Manager (VNFM) and a NFV Orchestrator (NFVO) to deploy and operate Network Services and Virtual Network Functions (VNFs) on an NFV infrastructure platform like OpenStack. It is based on ETSI MANO Architectural Framework and provides a functional stack to Orchestrate Network Services end-to-end using VNFs.

Tacker的部署

环境说明:
· Centos7.2.1511
· Openstack Liberty
· Tacker stable/newton

安装代码

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@controller ~]# git clone -b stable/newton https://github.com/openstack/tacker.git
[root@controller ~]# cd tacker/
[root@controller tacker]# pip install -r requirements.txt
[root@controller tacker]# python setup.py install

# 上述步骤完成后,检查下oslo依赖包的版本。oslo.config的版本最好与下面所示一致。(或不低于3.19.0)
[root@controller ~]# pip list|grep -i oslo.config
oslo.config (3.21.0)
# 检查keystonemiddleware的版本,最好与下面所示一致。
[root@controller ~]# pip list|grep -i keystonemiddleware
keystonemiddleware (4.10.0)

[root@controller tacker]# mkdir -p /etc/tacker /var/log/tacker

生成配置文件

参考:https://docs.openstack.org/developer/tacker/install/manual_installation.html#installing-tacker-server

1
2
3
4
5
6
7
8
9
10
11
12
# 进入tacker源码目录
[root@netscaler tacker]# ./tools/generate_config_file_sample.sh
[root@netscaler tacker]# cp -r etc/tacker/ /etc/

# 配置tacker.conf,要在keystone_authtoken session中添加以下参数项:
[keystone_authtoken]
admin_tenant_name = services
admin_password = tacker
admin_user = tacker
auth_protocol = http
identity_uri = http://{keystone_ip}:5000
auth_url = http://{keystone_ip}:35357

准备数据库

1
2
3
4
5
6
7
8
9
10
11
MariaDB [(none)]> create database tacker;
Query OK, 1 row affected (0.01 sec)

MariaDB [(none)]> grant all on tacker.* to tacker@'localhost' identified by 'tacker';
Query OK, 0 rows affected (0.04 sec)

MariaDB [(none)]> grant all on tacker.* to tacker@'%' identified by 'tacker';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

创建user & service & endpoint

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[root@controller ~(keystone_admin)]# keystone user-create --name tacker --tenant services --pass tacker --enabled true
+----------+----------------------------------+
| Property | Value |
+----------+----------------------------------+
| email | |
| enabled | True |
| id | 5b61a259246f436894657e7b950b2467 |
| name | tacker |
| tenantId | e0b5c56b294d4c89b3d593b09166fcd1 |
| username | tacker |
+----------+----------------------------------+
[root@controller ~(keystone_admin)]# keystone service-create --type nfv-orchestration --name tacker --description "Tacker Service"
+-------------+----------------------------------+
| Property | Value |
+-------------+----------------------------------+
| description | Tacker Service |
| enabled | True |
| id | da24c187a9f74572bbc7e3ee674b9d71 |
| name | tacker |
| type | nfv-orchestration |
+-------------+----------------------------------+
# 赋heat的使用权限
[root@controller ~(keystone_admin)]# keystone user-role-add --user 5b61a259246f436894657e7b950b2467 --role heat_stack_owner --tenant services

[root@controller ~(keystone_admin)]# keystone endpoint-create --region RegionOne --service da24c187a9f74572bbc7e3ee674b9d71 --publicurl http://{tacker_ip}:9890 --adminurl http://{tacker_ip}:9890 --internalurl http://{tacker_ip}:9890
+-------------+----------------------------------+
| Property | Value |
+-------------+----------------------------------+
| adminurl | http://{tacker_ip}:9890 |
| id | dfb0530729964cb2b69e1665d002e728 |
| internalurl | http://{tacker_ip}:9890 |
| publicurl | http://{tacker_ip}:9890 |
| region | RegionOne |
| service_id | da24c187a9f74572bbc7e3ee674b9d71 |
+-------------+----------------------------------+

初始化数据库

1
2
# 初始化tacker的数据库
[root@controller ~]# tacker-db-manage --config-file /etc/tacker/tacker.conf upgrade head

启动服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@controller ~]# cat > /usr/lib/systemd/system/openstack-tacker-server.service << EOF
> [Unit]
> #Description=OpenStack Nova API Server
> #After=syslog.target network.target
>
> [Service]
> Type=notify
> NotifyAccess=all
> TimeoutStartSec=0
> Restart=always
> User=root
>
> ExecStart=/usr/bin/tacker-server --config-file /etc/tacker/tacker.conf --log-file /var/log/tacker/tacker.log
>
> [Install]
> WantedBy=multi-user.target
> EOF

[root@controller ~]# systemctl start openstack-tacker-server

Tacker的使用

依次创建VIM & VNFD & VNF

创建VIM,先写一个config.yaml,内容如下,变量根据实际情况替换:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[root@controller ~(keystone_admin)]# cat > /root/config.yaml << EOF
> auth_url: http://$KEYSTONE_IP:5000/v2.0
> username: $TACKER_USER
> password: $TACKER_PASSWORD
> project_name: $PROJECT_NAME
> EOF

[root@controller ~(keystone_admin)]# tacker vim-register --is-default --config-file config.yaml test_vim
Created a new vim:
+----------------+-----------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+----------------+-----------------------------------------------------------------------------------------------------------------------------------+
| auth_cred | {"username": $username, "tenant_id": "", "password": $password, "auth_url": $auth_url, "tenant_name": $project_name} |
| auth_url | $auth_url |
| created_at | 2017-02-07 18:29:58.040460 |
| description | |
| id | d64301b4-bfcd-4033-95cf-e5bc95974825 |
| is_default | True |
| name | test_vim |
| placement_attr | {"regions": ["RegionOne"]} |
| status | REACHABLE |
| tenant_id | 058ad720c0bc4cd496e1e0462cdd1ac8 |
| type | openstack |
| updated_at | |
| vim_project | {"project_domain_name": "", "id": "", "name": $project_name} |
+----------------+-----------------------------------------------------------------------------------------------------------------------------------+

创建VNFD,即vnf集合的描述文件,此处的test_vnfs.yaml为模板文件,以下有详细介绍:

1
[root@controller ~(keystone_admin)]# tacker vnfd-create --vnfd-file ./test_vnfs.yaml test_vnfd

创建VNF:

1
[root@controller ~(keystone_admin)]# tacker vnf-create --vnfd-name test_vnfd --vim-name test_vim test_vnf

VNFD模板详解


图为tosca定义的vnfd数据模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# tosca版本信息描述
tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0

# 模板描述
description: test vnfd

metadata:
template_name: test_vnf

# vnfd拓扑结构
topology_template:
# 传入参数信息,需要结合环境变量文件传入,具体可以参考tacker vnf-create命令的说明
inputs:
cp1_mgmt_ip:
type: string

# 表示node的拓扑结构模板
node_templates:
# 此处定义了一个vdu,对应openstack中的虚拟机,即nfv设备;VDU1是自定义的名字
VDU1:
# vdu的type
type: tosca.nodes.nfv.VDU.Tacker
# 定义虚拟机的能力,如cpu、内存、磁盘等参数
capabilities:
nfv_compute:
properties:
num_cpus: 1
mem_size: 2048 MB
disk_size: 200 GB
# 定义其他属性,如镜像、镜像的管理驱动(用于在虚拟机内部做配置)等
properties:
image: cirros
# tacker已集成的一个mgmt_driver是openwrt,后面会有介绍
mgmt_driver: noop

# 此处定义了一个cp,Connection Point,对应openstack中的neutron port;CP1_MGMT是自定义的名字
CP1_MGMT:
# cp的type
type: tosca.nodes.nfv.CP.Tacker
# 网卡的属性,可以定义网卡顺序、ip地址等
properties:
management: true
order: 0
anti_spoofing_protection: false
# 可以指定ip地址,不写则表示根据dhcp分配
ip_address: {get_input: cp1_mgmt_ip}
# 此处表示了与CP相连的节点和之间的连接关系,即一个网卡将出自哪个网络,以及将要绑定至哪个虚拟机
requirements:
# vl侧接上了VL1
- virtualLink:
node: VL1
# vb侧接上了VDU1
- virtualBinding:
node: VDU1

# 此处定义了一个vl,Virtual Link,对应openstack中的neutron network;VL1是自定义的名字
VL1:
type: tosca.nodes.nfv.VL
# 网络的属性,名字、提供者等
properties:
network_name: net_mgmt
vendor: Tacker

Tacker VNF scale

参考:https://docs.openstack.org/developer/tacker/devref/scale_usage_guide.html
tacker的scale需要在模板中配置以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 定义策略,此节点与node_templates同级
policies:
# 此处定义了一个scale策略;SP1为自定义的名字
- SP1:
# scale策略的type
type: tosca.policy.tacker.Scaling
# 定义了策略的详细内容
properties:
# 每次伸缩的数量
increment: 1
# 下一次操作的冷却时间
cooldown: 0
# 总量的下限
min_instances: 1
# 总量的上限
max_instances: 3
# 初始的数量
default_instances: 2
# 要伸缩的目标,vdu、cp均可伸缩
targets: [VDU1]

重新定义了vnfd后,根据此vnfd创建vnf,之后即可以执行以下命令进行伸缩操作(out表示扩展,in表示收缩):

1
[root@controller ~(keystone_admin)]# tacker vnf-scale --vnf-name test_vnf --scaling-policy-name SP1 --scaling-type out

Tacker 与 Mistral

参考:https://docs.openstack.org/developer/tacker/devref/mistral_workflows_usage_guide.html
将tacker的模板当作json格式的body传入mistral的模板中,即可以在mistral中进行编排。
也可以使用mistral的cron-trigger(定时任务)来做tacker的自动伸缩。
mistral的相关介绍在此:Mistral部署与使用

Tacker 与 openwrt

1
2
3
4
5
6
7
8
9
10
11
12
VDU1:
type: tosca.nodes.nfv.VDU.Tacker
capabilities:
nfv_compute:
properties:
num_cpus: 1
mem_size: 2048 MB
disk_size: 200 GB
properties:
image: cirros
# 使用openwrt
mgmt_driver: openwrt

模板可以参考:https://github.com/openstack/tacker/blob/master/samples/tosca-templates/vnfd/tosca-vnfd-openwrt.yaml
之后在创建vnf的时候,将想要做的配置放在config里传进去:
配置的样式参考:https://github.com/openstack/tacker/blob/master/samples/tosca-templates/vnfd/tosca-config-openwrt-with-firewall.yaml

1
[root@controller ~(keystone_admin)]# tacker vnf-create --vnfd-name test_vnfd --vim-name test_vim --config-file *** test_vnf

这里可以看下tacker中的mgmt_driver:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
@log.log
def _config_service(self, mgmt_ip_address, service, config):
# 从配置中能读取openwrt镜像的用户名和密码
user = cfg.CONF.openwrt.user
password = cfg.CONF.openwrt.password
try:
# 通过ssh登录到vdu上进行配置
cmd = "uci import %s; /etc/init.d/%s restart" % (service, service)
LOG.debug(_('execute command: %s'), (cmd))
commander = cmd_executer.RemoteCommandExecutor(user,
password,
mgmt_ip_address)
commander.execute_command(cmd, input_data=config)
except Exception as ex:
LOG.error(_("While executing command on remote: %s"), ex)
raise exceptions.MgmtDriverException()

@log.log
def mgmt_call(self, plugin, context, vnf, kwargs):
if (kwargs[mgmt_constants.KEY_ACTION] !=
mgmt_constants.ACTION_UPDATE_VNF):
return
dev_attrs = vnf.get('attributes', {})

# 获取mgmt_url,这个是vnf创建完成之后返回的vdu的ip地址
mgmt_url = jsonutils.loads(vnf.get('mgmt_url', '{}'))
if not mgmt_url:
return

# 从vnfd模板中获取到config信息,也就是vnf-create的时候传入的config-file内容
vdus_config = dev_attrs.get('config', '')
config_yaml = yaml.load(vdus_config)
if not config_yaml:
return

# 找到vdus,根据vdus的信息配置对应的vdu,如VDU1的配置对应到VDU1上生效
vdus_config_dict = config_yaml.get('vdus', {})
for vdu, vdu_dict in vdus_config_dict.items():
config = vdu_dict.get('config', {})
for key, conf_value in config.items():
KNOWN_SERVICES = ('firewall', )
if key not in KNOWN_SERVICES:
continue
mgmt_ip_address = mgmt_url.get(vdu, '')
if not mgmt_ip_address:
LOG.warning(_('tried to configure unknown mgmt '
'address %s'),
vdu)
continue
# 配置执行函数
self._config_service(mgmt_ip_address, key, conf_value)

按照openwrt mgmt_driver的原理,可以写一个自定义的driver用来管理非openwrt镜像的vdu。

参考