Tech ONTAP Blogs
Tech ONTAP Blogs
AWS Outposts is a fully managed service that extends AWS infrastructure, services, APIs, and tools to customer premises. By providing local access to AWS-managed infrastructure, AWS Outposts enables customers to build and run workloads on-premises using the same application programming interfaces (APIs) as in AWS Regions, while leveraging local compute and storage resources to deliver lower latency and support local data processing.
This article covers an example of how customers can deploy workloads on AWS Outposts servers while integrating with NetApp iSCSI storage for on-premises data. While we present an example for Outposts servers, many of the same concepts apply to Outposts' rack deployments. Please note that management of external storage, including its high availability and security posture, is the customer's responsibility.
This article assumes you are familiar with AWS Outposts, including local network interface (LNI) functionality for Outposts servers. If you would like to get more familiar with AWS Outposts, the user guide, What is AWS Outposts, is a great place to start.
For AWS Outposts server:
Storage Requirements
Network Requirements
The integration connects EC2 instances running on AWS Outposts to storage arrays using iSCSI over your local network. This allows you to:
The external storage integration with AWS Outposts follows these key design principles:
The Internet Small Computer System Interface (iSCSI) is a protocol used in Storage Area Networks (SANs) to share block-level storage resources over a network. Employing a client-server architecture, iSCSI facilitates the transmission of SCSI commands between two primary components: the initiator and the target. The iSCSI Target is a service hosted on an iSCSI server that grants access to shared storage. Conversely, the iSCSI Initiator functions as the client, establishing a connection to the target to access shared storage resources.
Customer has an application that requires block storage served by an on-premises SAN appliance.
Assumptions:
If you're using NetApp storage, follow these steps to configure your storage system:
vserver create -vserver iscsi_svm \
-rootvolume iscsi_root \
-rootvolume-security-style unix \
-language C.UTF-8 \
-ipspace Default
volume create -vserver iscsi_svm \
-volume vol_iscsi \
-aggregate aggr1 \
-size 1TB \
-state online \
-policy default \
-unix-permissions ---rwxr-xr-x \
-type RW
iscsi create -vserver iscsi_svm
iscsi start -vserver iscsi_svm
lun create -vserver iscsi_svm \
-volume vol_iscsi \
-lun lun1 \
-size 100GB \
-ostype linux \
-space-reserve disabled
network interface create -vserver iscsi_svm \
-lif iscsi_lif \
-role data \
-data-protocol iscsi \
-home-node node1 \
-home-port e0c \
-address 10.5.4.160 \
-netmask 255.255.255.0
igroup create -vserver iscsi_svm \
-igroup ig_linux \
-protocol iscsi \
-ostype linux \
-initiator iqn.2024-02.com.example:instance-i-01234567890abcdef
lun mapping create -vserver iscsi_svm \
-path /vol/vol_iscsi/lun1 \
-igroup ig_linux \
-lun-id 0
The user-data script is used to pass along commands to the EC2 instance at the time of first launch.
iscsi_client.txt
#!/bin/bash
# Define variables for configuration
ISCSI_TARGET=10.5.4.160
MY_LOCAL_IP=10.44.0.20
# Disable cloud-init network configuration to prevent overwriting our settings
echo 'network: {config: disabled}' > /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg
# Configure ENI (ens5) without default route to VPC
# Add specific route to VPC subnet via the ENI gateway
sed -i -e "/ens5/,/ens5/ s/route-metric: 100/use-routes: false\n routes:\n - to: 172.31.223.0\/24\n via: 172.31.239.1/" /etc/netplan/50-cloud-init.yaml
# Configure LNI (ens6) with static IP address
# Set default route to on-premises network and add route to iSCSI storage
sed -i -e "/ens6/,/ens6/ s/dhcp4: true/dhcp4: false\n addresses:\n - $MY_LOCAL_IP\/24\n nameservers:\n addresses: [8.8.8.8, 8.8.4.4]\n routes:\n - to: default\n via: 10.44.0.1\n - to: 10.5.4.0\/24\n via: 10.44.0.1/" /etc/netplan/50-cloud-init.yaml
# Apply network configuration changes
netplan apply
# Update package lists and install iSCSI initiator
apt update -y
apt install open-iscsi -y
# Enable CHAP authentication in iSCSI configuration
# Note: In a production environment, set actual username and password values
sed -i -e "s/#node.session.auth.authmethod/node.session.auth.authmethod/" /etc/iscsi/iscsid.conf
sed -i -e "s/#node.session.auth.username =/node.session.auth.username =/" /etc/iscsi/iscsid.conf
sed -i -e "s/#node.session.auth.password =/node.session.auth.password =/" /etc/iscsi/iscsid.conf
# Restart iSCSI services to apply changes
systemctl restart open-iscsi iscsid
# Discover available iSCSI targets
iscsiadm -m discovery -t sendtargets -p $ISCSI_TARGET
# Login to iSCSI target
iscsiadm -m node --login -p $ISCSI_TARGET
# Configure iSCSI connection to persist across reboots
iscsiadm -m node -p $ISCSI_TARGET -o update -n node.startup -v automatic
The script configures an EC2 instance to connect to an external iSCSI storage system.
|
Script Breakdown |
Details |
|
Network configuration |
Define the iSCSI target IP address and assign a static IP to the instance |
|
Network setup |
Disable cloud-init's network management to prevent overwrites, configure the ENI for VPC connectivity, set a static IP on the LNI, and apply changes |
|
iSCSI initiator setup |
Update the system, install open-iscsi, enable CHAP authentication, and restart services |
|
iSCSI target connection |
Discover targets on the iSCSI server, login to establish a connection, and configure it to auto-reestablish after reboots |
Now that we have created the user-data script, we can use it to initialize our EC2 instance. Our command to launch an instance like this:
aws ec2 run-instances \
--image-id ami-080e1f13689e07408 \
--count 1 \
--instance-type c6id.xlarge \
--key-name mykey \
--user-data file://iscsi_client.txt \
--network-interfaces '[ \
{ "DeviceIndex":0, "SubnetId":"subnet-0ca6abe6b34adfcce", "Groups": ["sg-0a9f8c2200c0a56f1"] }, \
{ "DeviceIndex":1, "SubnetId":"subnet-0ca6abe6b34adfcce", "Groups": ["sg-0a9f8c2200c0a56f1"] }]' \
--tag-specifications '[{ "ResourceType":"instance","Tags":[{ "Key":"Name", "Value":"iscsi-client1" }] }]'
Let's break down the parameters:
|
Parameter |
Description |
|
--image-id ami-080e1f13689e07408 |
Specifies the Amazon machine image (AMI) ID for Ubuntu 22.04 from us-east-1 |
|
--count 1 |
Specifies how many EC2 instances to launch |
|
--instance-type c6id.xlarge |
Specifies the instance type. Default: Outposts 2U servers with c6id.8xlarge, Outposts 1U servers with c6gd.8xlarge. Modify in the AWS console |
|
--key-name mykey |
Specifies the public RSA key to be added to your EC2 instance |
|
--user-data file://iscsi_client.txt |
Specifies the filename that contains your user-data script |
|
--network-interfaces '[ { "DeviceIndex":0, "SubnetId":"subnet-0ca6abe6b34adfcce", "Groups": ["sg-0a9f8c2200c0a56f1"] }, { "DeviceIndex":1, "SubnetId":"subnet-0ca6abe6b34adfcce", "Groups": ["sg-0a9f8c2200c0a56f1"] }]' |
Specifies the network interface configuration. DeviceIndex:0 for the ENI, DeviceIndex:1 for the LNI |
|
--tag-specifications '[{ "ResourceType":"instance","Tags":[{ "Key":"Name", "Value":"iscsi-client1" }] }]' |
Assigns a name to the EC2 instance |
After launching the instance and executing the user-data script, you can verify that the iSCSI block volume is attached:
ubuntu@ip-172-31-239-206:~$ sudo iscsiadm -m session -o show
tcp: [1] 10.5.4.160:3260,1 iqn.2024-01.example.com:lun1 (non-flash)
ubuntu@ip-172-31-239-206:~$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
loop0 7:0 0 24.9M 1 loop /snap/amazon-ssm-agent/7628
loop1 7:1 0 63.9M 1 loop /snap/core20/2182
loop2 7:2 0 55.7M 1 loop /snap/core18/2812
loop3 7:3 0 87M 1 loop /snap/lxd/27037
loop4 7:4 0 40.4M 1 loop /snap/snapd/20671
sda 8:0 0 20G 0 disk
└─sda1 8:1 0 20G 0 part
nvme0n1 259:0 0 220.7G 0 disk
├─nvme0n1p1 259:1 0 220.6G 0 part /
├─nvme0n1p14 259:2 0 4M 0 part
└─nvme0n1p15 259:3 0 106M 0 part /boot/efi
In the output above, sda is the block device that appears as a separate 20G disk.
To make the iSCSI volume usable, format it and create a mount point:
sudo mkfs.xfs /dev/sda
sudo mkdir -p /mnt/iscsi
sudo mount /dev/sda /mnt/iscsi
To make the mount persistent across reboots, add an entry to /etc/fstab:
echo '/dev/sda /mnt/iscsi xfs _netdev 0 0' | sudo tee -a /etc/fstab
Since EC2 instances on Outposts racks have a single network interface, the configuration process is simpler. There is no need to make OS-level network changes in the user-data script to adjust for your LAN. Instead, the EC2 instance uses the local gateway (LGW) to connect to the NetApp storage appliance. Only the iSCSI initiator and volume settings are required.
To ensure secure connections between AWS Outposts instances and storage systems, implement the Challenge Handshake Authentication Protocol (CHAP), which provides password-based authentication at the connection layer. Configure unique initiator names for each server or application to access the storage, enabling precise identification and access control. Implement regular credential rotation practices to minimize risk.
For enhanced security, consider using AWS Secrets Manager to store CHAP passwords:
# Store CHAP credentials in AWS Secrets Manager
aws secretsmanager create-secret \
--name "iscsi-chap-credentials" \
--description "CHAP credentials for iSCSI connection" \
--secret-string '{"username":"chap-user","password":"chap-password"}'
# Retrieve CHAP credentials in user-data script
CHAP_CREDS=$(aws secretsmanager get-secret-value --secret-id iscsi-chap-credentials --query SecretString --output text)
CHAP_USER=$(echo $CHAP_CREDS | jq -r .username)
CHAP_PASS=$(echo $CHAP_CREDS | jq -r .password)
# Configure CHAP in iscsid.conf
sed -i -e "s/node.session.auth.username =/node.session.auth.username = $CHAP_USER/" /etc/iscsi/iscsid.conf
sed -i -e "s/node.session.auth.password =/node.session.auth.password = $CHAP_PASS/" /etc/iscsi/iscsid.conf
The network architecture supporting the iSCSI integration requires multiple layers of security:
# Example security group configuration for iSCSI
aws ec2 create-security-group \
--group-name iSCSI-SG \
--description "Security group for iSCSI traffic" \
--vpc-id vpc-1234567890abcdef
aws ec2 authorize-security-group-ingress \
--group-id sg-0a9f8c2200c0a56f1 \
--protocol tcp \
--port 3260 \
--source-prefix-list-id pl-1234567890abcdef
For NetApp storage systems, you can configure Quality of Service (QoS) policies to ensure consistent performance:
# Create QoS policy
qos policy-group create -policy-group pg_iscsi \
-vserver iscsi_svm \
-max-throughput 500MB/s
# Apply QoS to LUNs
lun modify -vserver iscsi_svm \
-volume vol_iscsi \
-lun lun1 \
-qos-policy-group pg_iscsi
Using the deployment scenario outlined in this guide, we have demonstrated that you can augment high-performance instance storage on AWS Outposts with on-premises external iSCSI storage to meet your need for data resiliency and durability while leveraging existing storage infrastructure. This hybrid approach provides the best of both worlds: the consistency and programmability of AWS services with the performance and data locality of on-premises storage.