Im zweiten Teil zur Erstellung eines Skripts werden die restlichen Netzwerk-Ressourcen erzeugt.
Die Liste der zu erzeugenden Komponenten umfasst nach der Skizze im ersten Teil:
- 1 „network“
- 1 „subnet“
- 1 „router“
- 4 „ports“
- 3 „server“
Das „network“ und das „subnet“ wurden schon angelegt, als nächstes sollen die 4 „ports“ und der „router“ konfiguriert werden.
Über Ports werden in Neutron alle Filter und Sicherhheitsregeln zugewiesen und so benötigt dieser Bereich etwas mehr Aufmerksamkeit, als man es von der Analogie eines „Switch-Ports“ erwarten würde. Gleichzeitig ist es dadurch möglich, die Filter sehr genau für jede Ressource zu kontrollieren. Wie bei einer realen Switch auch, muss jede Ressource an einen Port binden.
Der Prototyp für die „ports“ umfasst:
type: OS::Neutron::Port properties: admin_state_up: Boolean allowed_address_pairs: [{"ip_address": String, "mac_address": String}, {"ip_address": String, "mac_address": String}, ...] device_id: String device_owner: String fixed_ips: [{"subnet_id": String, "subnet": String, "ip_address": String}, {"subnet_id": String, "subnet": String, "ip_address": String}, ...] mac_address: String name: String network: String security_groups: [Value, Value, ...] value_specs: {...}
„admin_state_up“ bedeutet, wenn true, dass die Komponente zur Verfügung steht. Über „fixed_ips“ können IPs z.B. für Ressourcen reserviert werden, die eine IP nicht über DHCP, sondern statisch zugewiesen bekommen sollen.
Für den ersten Teil ergibt sich für jeden „port“:
my_port1: type: OS::Neutron::Port properties: admin_state_up: true name: Port01 network_id: { get_resource: my_first_network } security_groups: []
Das „network“ wurde schon im ersten Teil dieses Beitrags vereinbart und so kann es mit „get_resource“ wieder abgefragt werden. Für die Erstellung der „ports“ fehlen jedoch noch die Sicherheitsregeln mit einzelnen „security_group“-Angaben.
Die Vorlage hierfür sieht so aus:
type: OS::Neutron::SecurityGroup properties: description: String name: String rules: [{"remote_group_id": String, "direction": String, "remote_ip_prefix": String, "port_range_min": Integer, "remote_mode": String, "ethertype": String, "port_range_max": Integer, "protocol": String}, {"remote_group_id": String, "direction": String, "remote_ip_prefix": String, "port_range_min": Integer, "remote_mode": String, "ethertype": String, "port_range_max": Integer, "protocol": String}, ...]
Im Beispiel soll eine Basis-Regel für ICMP, und SSH und eine zusätzliche Regel für HTTP-Server definiert werden. Das Skript erweitert sich dadurch um:
my_basic_security_group: type: OS::Neutron::SecurityGroup properties: description: Allow ICMP, SSH name: BasicRules rules: [ {remote_ip_prefix: 0.0.0.0/0, direction: ingress, protocol: tcp, port_range_min: 22, port_range_max: 22}, {remote_ip_prefix: 0.0.0.0/0, direction: ingress, protocol: icmp}, {remote_ip_prefix: 0.0.0.0/0, direction: egress, protocol: icmp}] my_http_security_group: type: OS::Neutron::SecurityGroup properties: description: Allow HTTP name: HTTPRules rules: [ {remote_ip_prefix: 0.0.0.0/0, direction: ingress, protocol: tcp, port_range_min: 80, port_range_max: 80}]
Zwei Server sollen den einfachen Regelsatz, ein Server zusätzlich den HTTP-Regelsatz zugewiesen bekommen. Der Router bekommt eine eigene Regel über Port4.
my_port1: type: OS::Neutron::Port properties: admin_state_up: true name: Port01 network_id: { get_resource: my_first_network } security_groups: [ {get_resource: my_basic_security_group }, { get_resource: my_http_security_group } ] my_port2: type: OS::Neutron::Port properties: admin_state_up: true name: Port02 network_id: { get_resource: my_first_network } security_groups: [ { get_resource: my_basic_security_group } ] my_port3: type: OS::Neutron::Port properties: admin_state_up: true name: Port03 network_id: { get_resource: my_first_network } security_groups: [ { get_resource: my_basic_security_group } ] my_port4: type: OS::Neutron::Port properties: admin_state_up: true name: Port04 network_id: { get_resource: my_first_network } fixed_ips: [{ "subnet_id": { get_resource: my_first_subnet }, "ip_address": { get_param: gateway_address } }] security_groups: [ { get_resource: my_router_security_group } ]
Da der Router auch als Gateway nach außen eingesetzt werden soll, darf die IP-Adresse nicht wie bei den Servern per DHCP vergeben werden, sondern soll statisch auf die Netzwerkbasisadresse gelegt werden, die vom Anwender abgefragt wurde. Dies geschieht hier über „fixed_ips:“ unter Angabe des „subnet“ und der „gateway_address“.
Nun fehlt nur noch der Router selbst als Ressource.
Die Vorlage für Router sieht folgendermaßen aus:
my_router: type: OS::Neutron::Router properties: admin_state_up: Boolean external_gateway_info: {"enable_snat": Boolean, "network": String} l3_agent_id: String name: String value_specs: {...}
weiterhin benötigt der Router eine Gateway-Angabe und ein Interface nach innen. Die Gateway-Vorlage ist
type: OS::Neutron::RouterGateway properties: network: String router_id: String
(„OS::Neutron::RouterGateway“ ist deprecated und es sollte „external_gateway_info“ aus „OS::Neutron::Router“ benutzt werden, dies hat im ersten Anlauf hier jedoch nicht funktioniert. Vielleicht bei dem kommenden JUNO-Release?)
Die Vorlage für ein Router-Interface ist
type: OS::Neutron::RouterInterface properties: port_id: String router_id: String subnet: String
der komplette Skript-Teil hierfür ist dann:
my_router: type: OS::Neutron::Router properties: admin_state_up: true name: MyRouter my_router_gateway: type: OS::Neutron::RouterGateway properties: network_id: { get_param: external_net_id } router_id: { get_resource: my_router } my_router_int: type: OS::Neutron::RouterInterface properties: router_id: { get_resource: my_router } port_id: { get_resource: my_port4 }
Für das Router Gateway ist die Angabe der ID des externen Netzwerks notwendig. Diese wird zu Beginn des Skripts abgefragt. Für das Router-Interface ist hier nur ein „port“ anstelle eines „subnet“ angegeben, um direkt auf die statisch vergebene IP zu verweisen.
Der Stack sieht nun schon etwas komplexer aus: