The first choice to make when creating a zone in Apache CloudStack is the network type: basic or advanced. The blurb for “Advanced” promises “sophisticated network topologies”, while Basic promises “AWS-style networking”. Those who cut their teeth on the AWS cloud in 2008 may fondly remember what AWS now calls “EC2 classic platform“.
Platform Introduced In Description EC2-Classic The original release of Amazon EC2 Your instances run in a single, flat network that you share with other customers. EC2-VPC The original release of Amazon VPC Your instances run in a virtual private cloud (VPC) that’s logically isolated to your AWS account.
With a few differences, these map to CloudStack’s “Basic” and “Advanced” networking.
The fundamental network isolation technique in Basic zone is security groups. By default all network access to a VM is denied. When you launch an instance (VM), you deploy it in one or more security groups.
Using cloudmonkey:
> deploy virtualmachine securitygroupnames=management,web displayname=web0001 templateid=7464f3a6-ec56-4893-ac51-d120a71049dd serviceofferingid=48f813b7-2061-4270-93b2-c873a0fac336 zoneid=c78c2018-7181-4c7b-ab08-57204bc2eed3
Of course you have to create the security groups first:
> create securitygroup name=web > create securitygroup name=management
Security groups are containers for firewall rules.
> authorize securitygroupingress securitygroupname=web protocol=tcp startport=80 endport=80 cidrlist=0.0.0.0/0 > authorize securitygroupingress securitygroupname=management protocol=tcp startport=22 endport=22 cidrlist=192.168.1.0/24
In a basic zone, all network access to a VM is denied by default. These two rules allow access to our VM on the HTTP port (80) from anywhere and on the SSH port (22) only from computers in the 192.168.1.0/24 subnet.
Let’s start another web VM with these security groups
> deploy virtualmachine securitygroupnames=management,web displayname=web0002 ...
We can log in to web0002 over ssh when our ssh client is in the 192.168.1.0/24 subnet. But when we try to login to web0001 from web0002 over ssh, we get denied, since neither of the ingress rules we wrote above allow that. We can fix that:
> authorize securitygroupingress securitygroupname=management protocol=tcp startport=22 endport=22 securitygroupname=management
As long as the ssh client is on a VM in the management security group ssh access is allowed to any other VM in the management security group.
Let’s create some more:
Create appserver group and a db group
> create securitygroup name=appserver > create securitygroup name=db
Let’s add these rules: Allow web VMs access to the app servers on port 8080. Allow app servers access to the DB VMs on the MySQL port (3306)
> authorize securitygroupingress securitygroupname=appserver protocol=tcp startport=8080 endport=8080 securitygroupname=web > authorize securitygroupingress securitygroupname=db protocol=tcp startport=3306 endport=3306 securitygroupname=appserver
Deploy some virtual machines (instances) in these groups….
> deploy virtualmachine securitygroupnames=management,appserver displayname=app0001 ... > deploy virtualmachine securitygroupnames=management,appserver displayname=app0002 ... > deploy virtualmachine securitygroupnames=management,db displayname=db0001 ...
The network security architecture now looks like
Pretty complicated, with just a handful of rules. The beauty of it is that it captures the intent accurately. After all, as a network admin you want to exactly say “allow app VMs access to the DB VMs on tcp port 3306″.
In a traditional network, you’d create subnets and insert security devices between them. On the security device you would have entered complicated ACLs. The ACLs may have to be changed any time you created / destroyed VMs. In a Basic Zone, once you define the groups and rules, everything is taken care of automatically. You can even edit the rules after the VMs are running. Let’s allow ICMP pings to all the VMs from our management subnet:
> authorize securitygroupingress securitygroupname=management protocol=icmp icmptype=-1 icmpcode=-1
To do the inverse:
> revoke securitygroupingress securitygroupname=management protocol=icmp ...
A significant difference from EC2-classic is that CloudStack allows you to create egress rules as well:
> authorize securitygroupegress securitygroupname=management protocol=icmp ...
This controls traffic out of the VMs. The egress rules only take effect the first time an egress rule is added to the security group. Once the first rule is added, egress is by default ‘deny all’ and only the specific egress rules allow traffic out of the VM.
Security group rules are stateful. This means that you don’t have to define a corresponding egress rule for every ingress rule. For example, when someone from the internet connects on port 80 to a web VM, response traffic (out of the web VM) associated with that connection is automatically allowed. Stateful connection tracking also apply to stateless protocols such as UDP and ICMP.
While ‘Basic’ Zone might seem well, basic, it offers powerful network isolation techniques that directly map your intent. The simple interface actually masks a sophisticated implementation which I hope to describe in a future post. I hope I have convinced you that ‘Basic’ is indeed sophisticated!
Read on for a deeper dive.
