Use separate VPCs for different environments
One of the best practices for enhancing the security of your AWS resources is to use separate VPCs and even separate AWS accounts for different environments. This approach ensures that, unlike subnet segregation within a single VPC, where routing between all subnets is inherently allowed, routing across different VPCs is restricted by default. This inherent lack of inter-VPC routing without explicit, connectivity mechanisms provides a stronger segregation level and reduces the risk of potential cross-contamination between environments.
In a typical application life cycle, you have different environments, such as development, testing, and production. Each of these environments has different requirements and risk profiles. For instance, the development environment is where new code is written and tested, and it may be more prone to vulnerabilities and bugs. On the other hand, the production environment hosts the live application and is expected to be stable and secure. This deployment allows for more granular control over permissions and security controls for each environment based on their specific needs. You can have stricter security group rules and NACLs in the production environment to protect your live application while allowing more flexibility in development for testing and debugging purposes.
Separating VPCs for different stages of the application life cycle is just one example of how this strategy can be applied. In architectures such as microservices, you might find different services operating within distinct VPCs, and even across different AWS accounts, especially if they are managed by different teams. By using VPC peering, you can ensure that these services can communicate with each other securely and efficiently, on an as-needed basis.
Use multiple AZs for high availability
For high availability and to ensure resilience against the failure of a single location, AWS resources should be spread across multiple AZs within a region.
However, the use of multiple AZs should be done judiciously. Once an AZ has been assigned to a subnet, this assignment cannot be altered. Consequently, if a change in AZ assignment is necessary, you will need to establish a new subnet in the desired AZ and migrate or recreate the resources associated with the old subnet.
While distributing resources across AZs is beneficial, the architecture of your application should also be taken into account. For instance, if you have a multi-tier application with one tier running in a single AZ and another tier running in a different AZ, a failure in any of the two AZs could render the entire application unavailable. This is due to the interdependencies between the tiers for the application to function correctly.
In terms of practical guidelines, if high availability is a requirement for your application, implementing at least two AZs is recommended. This allows for failover and redundancy in case one AZ experiences an issue. If cost is a primary concern and high availability is not a requirement, you might choose to place all resources in a single AZ. However, be aware that this increases the risk of application downtime if the AZ experiences an issue. For applications with very high availability requirements, you might consider using three or more different AZs to further reduce the risk of downtime. Remember, the choice of how many AZs to use should be based on a careful analysis of your specific availability requirements and cost constraints.
The following table (Table 2.1) simulates the availability of a three-tier application spread across different AZs with different deployment options. Note that the application’s availability is calculated solely based on the likelihood of AZ failures for this simulation:
Table 2.1 – Availability calculation of a three-tier application spread across different AZs