Architecture in a Net

Cette page est à ce jour disponible en anglais uniquement.

When designing your infrastructure in the public Cloud, we recommend using a Net to allow isolation and network control within your infrastructure.

To ensure security while maintaining service accessibility, we usually design a Net in the same way we design n-tiers applications.

Designing Cloud Services

When designing your Cloud services, we recommend using the following guidelines and best practices:

  • Design for failure, and create self-healing application environments.

  • Always design applications with virtual machines (VMs) in at least two Subregions. For more information, see À propos des Régions, endpoints et Sous-régions.

  • Guarantee that you have "reserved" capacity in the event of an emergency by purchasing reserved VMs in a designated recovery Subregion. For more information, see À propos des VMs > Les VMs réservées.

  • Rigorously test to find single points of failure and apply high availability.

  • Use public IPs for fail over to "stand-by" VMs when auto-scaling and load balancing are not available. For more information, see À propos des IP publiques.

  • Have a disaster recovery and backup strategy that:

    • Uses multiple Regions.

    • Maintains up-to-date OMIs (and copies OMIs from one Region to another).

    • Copies BSU snapshots to other regions (and uses CRON jobs that take snapshots of BSU). For more information, see Copier un snapshot.

    • Automates everything in order to easily re-deploy resources in the event of a disaster.

    • Uses bootstrapping to quickly bring up new VMs with minimal configuration and allows for "generic" OMIs.

  • Decouple application components using Message Broker software when possible.

  • "Throw away" old or broken images.

  • Overuses telemetry and metrics to monitor infrastructure changes and health.

  • Uses Multipart upload for OOS upload (for objects over 100MiB). For more information, see Déposer une partie.

  • Protects your data in transit using HTTPS/SSL endpoints.

  • Protects data at rest using encrypted file systems.

  • Connects to VMs inside a Net using a bastion host or a VPN connection.

Implementing a 3-Tier Architecture with Public and Private Subnets

For the purpose of this example, we consider that almost all platforms are designed and deployed with two types of services:

  • Internal/private services: Only used by your platform to serve a higher purpose, also called backends.

  • External/public services: Used by the end-user as an interface, also called frontends (we call External/Public a machine that has a public IP attached).

You need to define public and private services before moving forward on the implementation on your Cloud infrastructure. The public services will be accessible from outside the Net by the users, while the private services will not be exposed outside and will be only accessible by other services within the Net.

scr ArchitectureInANet

For security, traceability and simplicity purposes, we follow these rules:

  • One service per VM

  • One service per Subnet

  • One security group per Subnet

  • One route table per Subnet

The demo platform is composed of:

  • NGINX fronts

  • Intel application handling the request and the load from the NGINX

  • Database VMs for data storage and queried by the Intels

Each layer only needs to communicate with the one above and the one below. The security groups are set accordingly, and you can see that we respected the rule "one service per VM, one service per Subnet, one service per security group".

Example

In this example, we use the OUTSCALE Python SDK.

Network setup
from osc_sdk_python import Gateway

gw = Gateway(**{"profile": "default"})


# Setup network
net = gw.CreateNet(IpRange="10.0.0.0/16")
net_id = net["Net"]["NetId"]
sub_db = gw.CreateSubnet(NetId=net_id, IpRange="10.0.3.0/24")
rt_db = gw.CreateRouteTable(NetId=net_id)
gw.LinkRouteTable(
    RouteTableId=rt_db["RouteTable"]["RouteTableId"],
    SubnetId=sub_db["Subnet"]["SubnetId"],
)

# Setup security
sg_nginx = gw.CreateSecurityGroup(
    NetId=net_id,
    SecurityGroupName="nginx",
    Description="Web front security group",
)
sg_intel = gw.CreateSecurityGroup(
    NetId=net_id,
    SecurityGroupName="intel",
    Description="Intel security group",
)
sg_db = gw.CreateSecurityGroup(
    NetId=net_id,
    SecurityGroupName="db",
    Description="Database security group",
)

# Now you need to allow traffic between applications
for port in [80, 443]:
    gw.CreateSecurityGroupRule(
        SecurityGroupId=sg_nginx["SecurityGroup"]["SecurityGroupId"],
        Flow="Inbound",
        FromPortRange=port,
        ToPortRange=port,
        IpProtocol="tcp",
        IpRange="0.0.0.0/0",
    )

gw.CreateSecurityGroupRule(
    SecurityGroupId=sg_intel["SecurityGroup"]["SecurityGroupId"],
    Flow="Inbound",
    Rules=[
        {
            "FromPortRange": 8080,
            "ToPortRange": 8080,
            "IpProtocol": "tcp",
            "SecurityGroupsMembers": [
                {"SecurityGroupId": sg_nginx["SecurityGroup"]["SecurityGroupId"]},
            ],
        },
    ],
)
gw.CreateSecurityGroupRule(
    SecurityGroupId=sg_db["SecurityGroup"]["SecurityGroupId"],
    Flow="Inbound",
    Rules=[
        {
            "FromPortRange": 3306,
            "ToPortRange": 3306,
            "IpProtocol": "tcp",
            "SecurityGroupsMembers": [
                {"SecurityGroupId": sg_intel["SecurityGroup"]["SecurityGroupId"]},
            ],
        },
    ],
)

This example suggests that we handled the SSL Termination on the Nginx, that we use classic HTTP port for our intel (8080) and that we implemented MySQL databases listening on port 3306.

We used security groups to access security groups instead of using CIDR of Subnets, even if in our case, both approach offer similar results. For more information, see À propos des security groups.

This architecture can be applied to more complex applications, and enforces the state of the art in terms of security and network control.

Related Pages