This folder contains an example of how to create EC2 instances with Elastic Network Interfaces
(ENIs) attached. This is useful for servers
that need IP addresses that remain static even if the underlying EC2 Instances change (e.g., ZooKeeper). Ideally, you
would attach these ENIs using Terraform's aws_network_interface_attachment
resource, but it does not work with
dynamic use cases, such as Auto Scaling Groups.
Therefore, this example includes a Packer template that installs the attach-eni script and uses
it to attach an ENI when the Instances are booting. One of the examples shows how to attach an ENI by ID and the other
by tag.
How do you run this example?
To run this example, you need to do the following:
Build an AMI using Packer
Deploy the AMI using Terraform
These steps are described in detail next.
Build an AMI using Packer
The code that runs the EC2 instance in this example is an Amazon Machine Image
(AMI) that has been defined in a Packer
template under packer/build.json. To build an AMI from this template:
Open up vars.tf and set secrets at the top of the file as environment variables and fill in any other variables in
the file that don't have defaults. This includes the ami variable which you should fill in with the ID of the
AMI you just built with Packer.
terraform get.
terraform plan.
If the plan looks good, run terraform apply.
Questions? Ask away.
We're here to talk about our services, answer any questions, give advice, or just to chat.
{"treedata":{"name":"root","toggled":true,"children":[{"name":".circleci","children":[{"name":"config.yml","path":".circleci/config.yml","sha":"edb2e1f7416276a2f1dcf8bc174bf805b235163c"}]},{"name":".github","children":[{"name":"ISSUE_TEMPLATE","children":[{"name":"bug_report.md","path":".github/ISSUE_TEMPLATE/bug_report.md","sha":"d2e87e27c601e423865ed660ec697082470ca60f"},{"name":"feature_request.md","path":".github/ISSUE_TEMPLATE/feature_request.md","sha":"023a33099be2336476930c96e17ff1ba5dc55348"}]},{"name":"pull_request_template.md","path":".github/pull_request_template.md","sha":"1ed18daca8d8613b91574ddd1641f2d129204f50"}]},{"name":".gitignore","path":".gitignore","sha":"1b77db107bd9abb565bd5adafce570dd59adf016"},{"name":".pre-commit-config.yaml","path":".pre-commit-config.yaml","sha":"6c5b735f0db5a0b8d732e9fc612255e3f181d7d5"},{"name":"CODEOWNERS","path":"CODEOWNERS","sha":"555c0c6e23a7502acbef94fb0b77bfa759ba11e8"},{"name":"LICENSE.txt","path":"LICENSE.txt","sha":"f4e3d9bd4717a044ed31ad847a300eee74371a78"},{"name":"README.adoc","path":"README.adoc","sha":"c2288c93a58bebc4cf4c6f7ff7de1134fe8f0f6e"},{"name":"_docs","children":[{"name":"aws-ec2.png","path":"_docs/aws-ec2.png","sha":"861e17a7d1df585b37d10e3211f71f6a6e182115"},{"name":"single-ec2-instance-architecture.png","path":"_docs/single-ec2-instance-architecture.png","sha":"c44f7efdb936c53fc4988f286ddcf31be8a6fdc9"}]},{"name":"core-concepts.md","path":"core-concepts.md","sha":"74ee29b0f03ed842c70a271d1a58be0c61b1c358"},{"name":"examples","children":[{"name":"attach-eni","children":[{"name":"README.md","path":"examples/attach-eni/README.md","sha":"86ce148cc900ce48f3debc490ce771ff5cd9fded","toggled":true},{"name":"main.tf","path":"examples/attach-eni/main.tf","sha":"97e8294ba1990b1c930810fd082317b5275c2e83"},{"name":"outputs.tf","path":"examples/attach-eni/outputs.tf","sha":"cf9472109a00b477ec4eb950e5b4e5ce9d21f4d1"},{"name":"packer","children":[{"name":"build.json","path":"examples/attach-eni/packer/build.json","sha":"c80651ff8b260e9edf73c8e8602d2e964575cebf"}]},{"name":"user-data","children":[{"name":"user-data-1.sh","path":"examples/attach-eni/user-data/user-data-1.sh","sha":"978ca952d47f3dcd84881deb3723614339edbd6f"},{"name":"user-data-2.sh","path":"examples/attach-eni/user-data/user-data-2.sh","sha":"898fd7a3c7179cc0c6d595b6ccbb4b92b1b2cedb"}]},{"name":"vars.tf","path":"examples/attach-eni/vars.tf","sha":"c8bd5aa7b155cf011bd03e3c6bf76a79fd1be4d5"}],"toggled":true},{"name":"bastion-host","children":[{"name":"README.md","path":"examples/bastion-host/README.md","sha":"0326f3c2c0707a3e2a67ffb6e002aec3eb30e1fa"},{"name":"main.tf","path":"examples/bastion-host/main.tf","sha":"86b9f77a4d50b5edee8837c579707ebc4d745820"},{"name":"outputs.tf","path":"examples/bastion-host/outputs.tf","sha":"5f0c2d739b9646c39e19bfd05cacb852c6080c0c"},{"name":"user-data.sh","path":"examples/bastion-host/user-data.sh","sha":"40484d6463cf88d4d5b174cbc3ca759548b9d788"},{"name":"vars.tf","path":"examples/bastion-host/vars.tf","sha":"cec5c3c5cc8041b2165059c3f8378a6415d72b3a"}]},{"name":"ec2-backup","children":[{"name":"README.md","path":"examples/ec2-backup/README.md","sha":"782667373dc4d7cf602fea0e05d6b78ed47d2c42"},{"name":"main.tf","path":"examples/ec2-backup/main.tf","sha":"a93b214edd82f1e36d0113d7727239c95e28bfac"},{"name":"outputs.tf","path":"examples/ec2-backup/outputs.tf","sha":"6023311f87f6757e60e5d47600095cbc6dce324a"},{"name":"variables.tf","path":"examples/ec2-backup/variables.tf","sha":"e6e9fa9520608ef0a5cc0aadc70d118775543b03"}]},{"name":"persistent-ebs-volume","children":[{"name":"README.md","path":"examples/persistent-ebs-volume/README.md","sha":"7acf321a8a3183bfe4d7187be94208ed281bcd66"},{"name":"main.tf","path":"examples/persistent-ebs-volume/main.tf","sha":"e38e758d9bb4d438633e840003478803e0a7cde8"},{"name":"outputs.tf","path":"examples/persistent-ebs-volume/outputs.tf","sha":"54f33c96b796373b12b9702f46d30a1c85043f65"},{"name":"packer","children":[{"name":"build.json","path":"examples/persistent-ebs-volume/packer/build.json","sha":"d9448a8beecb2b12a1e7ddfbb6ad59d9997988e9"}]},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/persistent-ebs-volume/user-data/user-data.sh","sha":"9c5d08f440596a978418d09aea275d8c0ffc16fb"}]},{"name":"vars.tf","path":"examples/persistent-ebs-volume/vars.tf","sha":"47a3c46579f095eaed913046ebd972edd7bb525e"}]},{"name":"route53-helpers","children":[{"name":"README.md","path":"examples/route53-helpers/README.md","sha":"6b212ee9299ea98770f423799c73583e617e07fa"},{"name":"main.tf","path":"examples/route53-helpers/main.tf","sha":"9c2307438841e137cd8de9e6885283c054290959"},{"name":"outputs.tf","path":"examples/route53-helpers/outputs.tf","sha":"4c3c3ccccf964155ffbce7546fcbc9ef6e886de6"},{"name":"packer","children":[{"name":"build.json","path":"examples/route53-helpers/packer/build.json","sha":"d36a48b043b3398dff52c286dd404f411054bacd"}]},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/route53-helpers/user-data/user-data.sh","sha":"fcd5070b46e6428d81dbb1e5ba5f4bef3b5b8c0c"}]},{"name":"vars.tf","path":"examples/route53-helpers/vars.tf","sha":"3c990b1e4ae4da54aac558cf24124e29cd362931"}]}],"toggled":true},{"name":"modules","children":[{"name":"attach-eni","children":[{"name":"README.md","path":"modules/attach-eni/README.md","sha":"5c32557105967e1b0e82f50fe693c12370e905cc"},{"name":"bin","children":[{"name":"attach-eni","path":"modules/attach-eni/bin/attach-eni","sha":"616849047aad575aca81659bbf45d99d72ec9e46"}]},{"name":"install.sh","path":"modules/attach-eni/install.sh","sha":"542cbd93ca08fd9cbe6f121f4d8fea2b1d76ca8b"}]},{"name":"disable-instance-metadata","children":[{"name":"README.md","path":"modules/disable-instance-metadata/README.md","sha":"eacec50007d78aec20335d85b05a9582200c9a66"},{"name":"bin","children":[{"name":"disable-instance-metadata","path":"modules/disable-instance-metadata/bin/disable-instance-metadata","sha":"a2b5e85b40225bc693a46978dd2ca2ea9406283f"}]},{"name":"install.sh","path":"modules/disable-instance-metadata/install.sh","sha":"bdce5d29adc4041375ffc9bf7eabb93a0059583c"}]},{"name":"ec2-backup","children":[{"name":"README.md","path":"modules/ec2-backup/README.md","sha":"e5f22ab6bdd9f34dacf71428bc04fef1d5415bad"},{"name":"main.tf","path":"modules/ec2-backup/main.tf","sha":"8153eee6c6285bdd67884372cc069a0cb4bf5fa8"},{"name":"outputs.tf","path":"modules/ec2-backup/outputs.tf","sha":"19b7bd464c3c0916e03bff6f4f2cf69b671041ed"},{"name":"variables.tf","path":"modules/ec2-backup/variables.tf","sha":"d590cf90b9a1060c9f003f64d82085d183c5e8f2"}]},{"name":"persistent-ebs-volume","children":[{"name":"README.md","path":"modules/persistent-ebs-volume/README.md","sha":"6d8c0c80d3e674fcda15a9a95a7fc2f4de7d6e9d"},{"name":"bin","children":[{"name":"mount-ebs-volume","path":"modules/persistent-ebs-volume/bin/mount-ebs-volume","sha":"1650101d5c5e7aeaa885bab9b80816b6417720e4"},{"name":"unmount-ebs-volume","path":"modules/persistent-ebs-volume/bin/unmount-ebs-volume","sha":"576ef38dc65ac1ef80c83b837efd6313bfd02741"}]},{"name":"install.sh","path":"modules/persistent-ebs-volume/install.sh","sha":"e0ce5862cd6975992dc011a6dfe94fdf14a9b607"}]},{"name":"require-instance-metadata-service-version","children":[{"name":"README.md","path":"modules/require-instance-metadata-service-version/README.md","sha":"e44bae312f899c7b88cb7745e0732cf71f28fe8e"},{"name":"bin","children":[{"name":"require-instance-metadata-service-version","path":"modules/require-instance-metadata-service-version/bin/require-instance-metadata-service-version","sha":"49481dbbd668025409ae6e9fa7903276f3145948"}]},{"name":"install.sh","path":"modules/require-instance-metadata-service-version/install.sh","sha":"b819422b6cd7475666945112202fb71adbc6bb60"}]},{"name":"route53-helpers","children":[{"name":"README.md","path":"modules/route53-helpers/README.md","sha":"52d0b942bba658065589567e9c9d78c98b4ca028"},{"name":"bin","children":[{"name":"add-dns-a-record","path":"modules/route53-helpers/bin/add-dns-a-record","sha":"2fd418252934a48c78f910a739b5d681d1585941"}]},{"name":"install.sh","path":"modules/route53-helpers/install.sh","sha":"535ed35d64611c5f12e9924b3cb8df0a77180ab8"}]},{"name":"single-server","children":[{"name":"README.md","path":"modules/single-server/README.md","sha":"afcb5405b0aca7dd4438538ddfa3d87b79846b4a"},{"name":"main.tf","path":"modules/single-server/main.tf","sha":"7cc8374d9ee72061cc84792d43e82b2618c505a1"},{"name":"outputs.tf","path":"modules/single-server/outputs.tf","sha":"e042d24d9e54a2df2011c736bfa462d9f1175be5"},{"name":"vars.tf","path":"modules/single-server/vars.tf","sha":"3d7a6911c59b3554cfa3699e7e58ae98c18dec2e"}]}]},{"name":"terraform-cloud-enterprise-private-module-registry-placeholder.tf","path":"terraform-cloud-enterprise-private-module-registry-placeholder.tf","sha":"ae586c0fe830819580e1009d41a9074f16e65bed"},{"name":"test","children":[{"name":"README.md","path":"test/README.md","sha":"ef26d3851db2fff0b36dfa61379724c0db9ff281"},{"name":"attach_eni_test.go","path":"test/attach_eni_test.go","sha":"6cff173ca858ec9765e837cdd7943489f1a0cc75"},{"name":"bastion_host_test.go","path":"test/bastion_host_test.go","sha":"f8d38f1cd893ef2097cababd4053bfd71710fa4d"},{"name":"ec2_backup_test.go","path":"test/ec2_backup_test.go","sha":"73ae620eb4bbec7771bfc614e676935956134e9d"},{"name":"go.mod","path":"test/go.mod","sha":"b275b1103e930e7ea7c08e9a3ca4a108f8efdee6"},{"name":"go.sum","path":"test/go.sum","sha":"76a7d496d54ca2743c46bd66a4ff7d260de9cb32"},{"name":"persistent_ebs_volume_test.go","path":"test/persistent_ebs_volume_test.go","sha":"ac3adb89e68c61e73b9cb31d179fefb13a404788"},{"name":"route53_helpers_test.go","path":"test/route53_helpers_test.go","sha":"6ab270f015bf4b8261278c8789a346159ee7eb9b"},{"name":"test_helpers.go","path":"test/test_helpers.go","sha":"16156727df11949125c635b75612ae6fa527df3d"},{"name":"validation","children":[{"name":"validate_all_modules_and_examples_test.go","path":"test/validation/validate_all_modules_and_examples_test.go","sha":"33d73c385b64c4fc870033e99427e683c31dc45a"}]}]}]},"detailsContent":"<h1 class=\"preview__body--title\" id=\"attach-eni-example\">Attach ENI Example</h1><div class=\"preview__body--border\"></div><p>This folder contains an example of how to create EC2 instances with <a href=\"http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html\" class=\"preview__body--description--blue\" target=\"_blank\">Elastic Network Interfaces\n(ENIs)</a> attached. This is useful for servers\nthat need IP addresses that remain static even if the underlying EC2 Instances change (e.g., ZooKeeper). Ideally, you\nwould attach these ENIs using Terraform's <a href=\"https://www.terraform.io/docs/providers/aws/r/network_interface_attachment.html\" class=\"preview__body--description--blue\" target=\"_blank\">aws_network_interface_attachment\nresource</a>, but it does not work with\ndynamic use cases, such as Auto Scaling Groups.</p>\n<p>Therefore, this example includes a Packer template that installs the <a href=\"/repos/v0.12.1/module-server/modules/attach-eni\" class=\"preview__body--description--blue\">attach-eni script</a> and uses\nit to attach an ENI when the Instances are booting. One of the examples shows how to attach an ENI by ID and the other\nby tag.</p>\n<h2 class=\"preview__body--subtitle\" id=\"how-do-you-run-this-example\">How do you run this example?</h2>\n<p>To run this example, you need to do the following:</p>\n<ol>\n<li>Build an AMI using Packer</li>\n<li>Deploy the AMI using Terraform</li>\n</ol>\n<p>These steps are described in detail next.</p>\n<h3 class=\"preview__body--subtitle\" id=\"build-an-ami-using-packer\">Build an AMI using Packer</h3>\n<p>The code that runs the EC2 instance in this example is an <a href=\"http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html\" class=\"preview__body--description--blue\" target=\"_blank\">Amazon Machine Image\n(AMI)</a> that has been defined in a <a href=\"https://www.packer.io/\" class=\"preview__body--description--blue\" target=\"_blank\">Packer\ntemplate</a> under <code>packer/build.json</code>. To build an AMI from this template:</p>\n<ol>\n<li>Install <a href=\"https://www.packer.io/\" class=\"preview__body--description--blue\" target=\"_blank\">Packer</a>.</li>\n<li>Set up your <a href=\"https://www.packer.io/docs/builders/amazon.html\" class=\"preview__body--description--blue\" target=\"_blank\">AWS credentials as environment variables</a>.</li>\n<li>Run <code>packer build build.json</code> to create the AMI in your AWS account. Note down the ID of this new AMI.</li>\n</ol>\n<h3 class=\"preview__body--subtitle\" id=\"deploy-the-ami-using-terraform\">Deploy the AMI using Terraform</h3>\n<p>Now that you have an AMI, use Terraform to deploy it:</p>\n<ol>\n<li>Install <a href=\"https://www.terraform.io/\" class=\"preview__body--description--blue\" target=\"_blank\">Terraform</a>.</li>\n<li>Open up <code>vars.tf</code> and set secrets at the top of the file as environment variables and fill in any other variables in\nthe file that don't have defaults. This includes the <code>ami</code> variable which you should fill in with the ID of the\nAMI you just built with Packer.</li>\n<li><code>terraform get</code>.</li>\n<li><code>terraform plan</code>.</li>\n<li>If the plan looks good, run <code>terraform apply</code>.</li>\n</ol>\n","repoName":"module-server","repoRef":"v0.13.8","serviceDescriptor":{"serviceName":"Single EC2 Instance","serviceRepoName":"module-server","serviceRepoOrg":"gruntwork-io","cloudProviders":["aws"],"description":"Run a single EC2 instance for stateless or stateful apps. Supports IAM roles, EBS volumes, ENIs, and EIPs.","imageUrl":"single-service.png","licenseType":"subscriber","technologies":["Terraform","Bash"],"compliance":[],"tags":[""]},"serviceCategoryName":"Server orchestration","fileName":"README.md","filePath":"/examples/attach-eni","title":"Repo Browser: Single EC2 Instance","description":"Browse the repos in the Gruntwork Infrastructure as Code Library."}