Running an application with block mounts
Block mounts allow persisting data inside an enclave.
Block
mounts are created and managed by the Anjuna Nitro Runtime.
This page describes the steps required to set up a block
mount.
Limitations
Each parent instance can only have one enclave that uses a block
mount,
and neither the parent instance nor another enclave can mount a volume
that is being used by an enclave.
You can create multiple volumes of differing sizes, but a single enclave can mount only one volume at a time.
Block
mounts are not supported in EKS.
Example
In this example,
you will learn how to work with persistent storage with the Anjuna Nitro Runtime.
You will configure a MongoDB server inside an AWS Nitro Enclave
to use persistent block
mounts.
Persistent storage mounts can be used with any application, and MongoDB is used here as an example.
This example is focused on using persistent storage only and should not be used in production. For production MongoDB deployments, Anjuna recommends configuring encryption at rest, TLS, and using attestation to securely deliver the related encryption keys. |
Estimated time: 10 minutes
Build the required tools for block mounts
Block
mounts for the Anjuna Nitro Runtime are based on the
DRBD project,
which must be built locally.
Run the following commands to build the tools:
$ cd /opt/anjuna/nitro/drbd/
$ ./parent-drbd-setup.sh --build
Create a persistent volume disk file
When using block
mounts,
data is persisted to a volume disk file.
To create a new volume disk file, run the following command:
$ cd /opt/anjuna/nitro/drbd/
# Create a 2048 MB disk file for the volume
$ ./parent-drbd-setup.sh --mem 2048 --disk-create ~/nitro-disk.img
Start the parent filesystem proxy
Then, you can start the filesystem proxy using the following command:
$ ./parent-drbd-setup.sh --start ~/nitro-disk.img
This proxy will communicate with the enclave over the vsock
and persist data into the file ~/nitro-disk.img
.
Install MongoDB Shell
Before running the MongoDB server, you will download a tool that will allow you to interact with the MongoDB server.
Create a file at /etc/yum.repos.d/mongodb-org-5.0.repo
.
You will need root
access to write that file,
so you can run sudo vim /etc/yum.repos.d/mongodb-org-5.0.repo
.
Copy the following contents into the file and save it:
-
Amazon Linux 2023
-
Amazon Linux 2
[mongodb-org-5.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/amazon/2023/mongodb-org/5.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-5.0.asc
[mongodb-org-5.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/amazon/2/mongodb-org/5.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-5.0.asc
Now you can install the MongoDB Shell:
$ sudo yum install -y mongodb-org-shell
Building the enclave
In this section, you will build a MongoDB enclave that uses a block
mount.
Create an enclave configuration file and name it enclave-config.yaml
. This file configures MongoDB
to bind to all IPs, sets a default username and password for the database, and mounts the volume
to /data/db
, where Mongo expects the DB files to be.
version: 1.8
# Run mongodb, bind to all IPs
command: [docker-entrypoint.sh, mongod, --auth, --port=27017, --bind_ip=0.0.0.0]
# Set a default MongoDB username and password
environment:
- MONGO_INITDB_ROOT_USERNAME=anjuna
- MONGO_INITDB_ROOT_PASSWORD=anjuna
# Set a persistent block mount
mounts:
- type: block
name: db-volume
mountPath: /data/db
Build and run the enclave:
$ echo "Building enclave..."
# Build the enclave using the mongo:5-focal Docker image,
# enclave-config.yaml as the enclave configuration file,
# and save it to mongo-nitro.eif
$ anjuna-nitro-cli build-enclave --docker-uri mongo:5-focal --enclave-config-file enclave-config.yaml --output-file mongo-nitro.eif
# Start the network agent
$ anjuna-nitro-netd-parent --expose 27017 --daemonize
$ sleep 3
# Start the enclave you just created
$ anjuna-nitro-cli run-enclave --cpu-count 2 --memory 4096 --eif-path mongo-nitro.eif --debug-mode
The number of vCPU cores must be an even number due to hyperthreading. If the agent is already running, it should be killed before starting the enclave. |
Connecting to the database
After a few seconds of initialization, you should be able to connect to the MongoDB. Now you will connect and add some data. If you are unable to connect, wait a few more seconds and try again.
$ mongo -u anjuna -p anjuna 'mongodb://localhost'
> use demo
> db.data.insert({"hello_world":1})
> db.data.findOne()
{ "_id" : ObjectId("..."), "hello_world" : 1 }
> exit
You have added some data and you are able to query it.
Now, you can check that data is persisted when the enclave is restarted. To do so, you can terminate the enclave and run it again.
$ anjuna-nitro-cli terminate-enclave --all
$ pkill -f anjuna-nitro-netd-parent
$ /opt/anjuna/nitro/drbd/parent-drbd-setup.sh --stop
$ /opt/anjuna/nitro/drbd/parent-drbd-setup.sh --start ~/nitro-disk.img
$ anjuna-nitro-netd-parent --expose 27017 --daemonize
$ anjuna-nitro-cli run-enclave --cpu-count 2 --memory 4096 --eif-path mongo-nitro.eif --debug-mode
After 20-30 seconds, you should be able to connect to the DB and fetch the data you inserted before terminating the enclave:
$ mongo -u anjuna -p anjuna 'mongodb://localhost'
> use demo
> db.data.findOne()
> exit
You should be able to see the entry you created before:
{ "_id" : ObjectId("…"), "hello_world" : 1 }
.
Congratulations! You have successfully set up an AWS Nitro Enclave with a persistent storage volume.