When architecting distributed systems on AWS EC2, two critical challenges emerge:
1. Secure communication channels between instances
2. Persistent addressing despite dynamic private IPs
Traditional SSH tunneling works but introduces overhead. Let's explore modern alternatives.
For web-to-database communication, consider these encrypted options:
# Example MySQL SSL configuration in my.cnf
[client]
ssl-ca=/etc/mysql/ssl/ca-cert.pem
ssl-cert=/etc/mysql/ssl/client-cert.pem
ssl-key=/etc/mysql/ssl/client-key.pem
# Apache to MySQL SSL connection string
$db = new mysqli('db.internal.example.com', 'user', 'password', 'database',
null, '/path/to/mysql.sock',
MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT);
AWS provides multiple approaches to handle dynamic IPs:
# Using AWS CLI to programmatically discover private IPs
INSTANCE_IP=$(aws ec2 describe-instances \
--filters "Name=tag:Name,Values=prod-db" \
--query "Reservations[].Instances[].PrivateIpAddress" \
--output text)
# DNS-based solution with Route53 private hosted zones
resource "aws_route53_record" "db" {
zone_id = aws_route53_zone.private.zone_id
name = "db.service.private"
type = "A"
ttl = "60"
records = [aws_instance.database.private_ip]
}
For microservices architectures, implement discovery patterns:
# Consul service registration example
{
"service": {
"name": "web",
"port": 80,
"connect": {
"sidecar_service": {
"proxy": {
"upstreams": [{
"destination_name": "db",
"local_bind_port": 3306
}]
}
}
}
}
}
Always combine communication protocols with proper security groups:
# Terraform security group allowing specific instance communication
resource "aws_security_group" "internal_comms" {
name_prefix = "internal-comms-"
ingress {
from_port = 0
to_port = 0
protocol = "-1"
self = true
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
security_groups = [aws_security_group.bastion.id]
}
}
Implement visibility into instance communications:
# VPC Flow Logs configuration
resource "aws_flow_log" "vpc_flow_log" {
log_destination = aws_s3_bucket.flow_logs.arn
log_destination_type = "s3"
traffic_type = "ALL"
vpc_id = aws_vpc.main.id
log_format = "$${version} $${account-id} $${interface-id} $${srcaddr} $${dstaddr}"
}
When configuring communication between EC2 instances in a distributed environment, we need to address three critical aspects:
- Cost optimization (avoiding Elastic IP transfer fees)
- Security (encrypted communication channels)
- Service discovery (handling dynamic private IPs)
Using private IPs for inter-instance communication eliminates data transfer costs. While these IPs may change upon instance restart, we can implement several solutions:
# Example of retrieving private IP in Ubuntu
PRIVATE_IP=$(hostname -I | awk '{print $1}')
echo "Using private IP: $PRIVATE_IP"
Proper security group setup is crucial for secure communication. Here's an example for web-to-database communication:
# Web server security group (inbound rules)
Type: MySQL/Aurora
Protocol: TCP
Port Range: 3306
Source: sg-0abcdef123 (DB security group ID)
To handle dynamic IPs, consider these approaches:
1. Route53 Private Hosted Zones
# Example DNS record
db.internal.example.com. 300 IN A 10.0.1.25
2. AWS Systems Manager Parameter Store
# Storing IP address
aws ssm put-parameter \
--name "/prod/database/ip" \
--value "10.0.1.25" \
--type String
While SSH is secure, it's not always the most efficient solution. Consider:
- VPC endpoints for AWS services
- Mutual TLS for service-to-service communication
- SSH tunnels for legacy applications
Here's how to configure a PHP application to use dynamic database hosts:
<?php
// Retrieve DB host from Parameter Store
$db_host = shell_exec('aws ssm get-parameter --name "/prod/database/ip" --query "Parameter.Value" --output text');
$dsn = "mysql:host=$db_host;dbname=appdb";
$conn = new PDO($dsn, $username, $password);
?>
For Bacula, use instance tags for dynamic client discovery:
# Bacula Director config using AWS CLI
clients=$(aws ec2 describe-instances \
--filters "Name=tag:Backup,Values=true" \
--query "Reservations[].Instances[].PrivateIpAddress" \
--output text)
Implement these practices to ensure reliability:
- CloudWatch alarms for connectivity issues
- Lambda functions to update DNS records on instance changes
- Regular security group audits