Skip to content

aws-samples/amazon-eks-custom-amis

Amazon EKS Custom AMIs

This repository contains Packer configurations to create custom AMIs based on the Amazon EKS optimized AMI. The Amazon EKS Optimized AMI remains the preferred way to deploy containers on Amazon EKS. The configurations provided in this project are intended to help support scenarios where further control and customization is required on EKS AMIs.

Support & Feedback

This project is maintained by AWS Solution Architects and Consultants. It is not part of an AWS service and best-effort support is provided by the maintainers. To post feedback, submit feature ideas, or report bugs, please use the Issues section of this repo. If you are interested in contributing, please see the Contribution guide.

Scripts and artifacts created by this repository do not guarantee compliance. It is up to users to review and validate for their individual use cases.

Supported Distributions & Configurations

The following AMI distributions and configuration are supported by this repository.

Distribution Configuration Architecture Variable File Available
EKS AL2 CIS Benchmark amd64 al2_amd64.pkrvars.hcl âś…
EKS AL2 CIS Benchmark arm64 al2_arm64.pkrvars.hcl âś…
EKS AL2 NVIDIA GPU amd64 al2_amd64_gpu.pkrvars.hcl âś…

Prerequisites

Build an AMI

Users will need to have a default VPC in the region where the AMI will be created, or provide a subnet ID via the subnet_id variable. The remaining variables are optional and can be modified to suit; either through the appropriate *.pkrvars.hcl file or by passing via -var 'key=value' on the Packer CLI. See the variables.pkr.hcl file for variables that are available for customization.

First, initialize the project:

packer init -upgrade .

To build an amd64 based architecture AMI:

packer build -var-file=al2_amd64.pkrvars.hcl -var 'subnet_id=subnet-01abc23' .

To build an arm64 based architecture AMI:

packer build -var-file=al2_arm64.pkrvars.hcl -var 'subnet_id=subnet-01abc23' .

Use AMI

The AMI can be used with self-managed node groups and EKS managed node groups within EKS. The AMIs built in this repository use the same bootstrap script used in the EKS Optimized AMI. To join the cluster, run the following command on boot:

/etc/eks/bootstrap.sh <cluster name> --kubelet-extra-args '--node-labels=eks.amazonaws.com/nodegroup=<node group name>,eks.amazonaws.com/nodegroup-image=<ami id>'

Requirements

No requirements.

Providers

Name Version
amazon-parameterstore n/a

Modules

No modules.

Resources

Name Type
amazon-parameterstore_amazon-parameterstore.this data source

Inputs

Name Description Type Default Required
access_key The access key used to communicate with AWS string null no
ami_block_device_mappings The block device mappings attached when booting a new instance from the AMI created list(map(string))
[
{
"delete_on_termination": true,
"device_name": "/dev/xvda",
"volume_size": 10,
"volume_type": "gp3"
}
]
no
ami_description The description to use when creating the AMI string "Amazon EKS Kubernetes AMI based on AmazonLinux2 OS" no
ami_groups A list of groups that have access to launch the resulting AMI(s). By default no groups have permission to launch the AMI. all will make the AMI publicly accessible. AWS currently doesn't accept any value other than all list(string) null no
ami_name_prefix The prefix to use when creating the AMI name. i.e. - <ami_name_prefix>-<eks_version>-<timestamp> string "amazon-eks" no
ami_org_arns A list of Amazon Resource Names (ARN) of AWS Organizations that have access to launch the resulting AMI(s). By default no organizations have permission to launch the AMI list(string) null no
ami_ou_arns A list of Amazon Resource Names (ARN) of AWS Organizations organizational units (OU) that have access to launch the resulting AMI(s). By default no organizational units have permission to launch the AMI list(string) null no
ami_regions A list of regions to copy the AMI to. Tags and attributes are copied along with the AMI. AMI copying takes time depending on the size of the AMI, but will generally take many minutes list(string) null no
ami_type The type of AMI to create. Valid values are amazon-linux-2 or amazon-linux-2-arm64 string "amazon-linux-2" no
ami_users A list of account IDs that have access to launch the resulting AMI(s). By default no additional users other than the user creating the AMI has permissions to launch it list(string) null no
ami_virtualization_type The type of virtualization used to create the AMI. Can be one of hvm or paravirtual string "hvm" no
associate_public_ip_address If using a non-default VPC, public IP addresses are not provided by default. If this is true, your new instance will get a Public IP bool null no
assume_role If provided with a role ARN, Packer will attempt to assume this role using the supplied credentials map(string) {} no
aws_polling Polling configuration for the AWS waiter. Configures the waiter for resources creation or actions like attaching volumes or importing image map(string) {} no
capacity_reservation_group_arn Provide the EC2 Capacity Reservation Group ARN that will be used by Packer string null no
capacity_reservation_id Provide the specific EC2 Capacity Reservation ID that will be used by Packer string null no
capacity_reservation_preference Set the preference for using a capacity reservation if one exists. Either will be open or none. Defaults to none string null no
communicator The communicator to use to communicate with the EC2 instance. Valid values are none, ssh, winrm, and ssh+winrm string "ssh" no
custom_endpoint_ec2 This option is useful if you use a cloud provider whose API is compatible with aws EC2 string null no
decode_authorization_messages Enable automatic decoding of any encoded authorization (error) messages using the sts:DecodeAuthorizationMessage API bool null no
deprecate_at The date and time to deprecate the AMI, in UTC, in the following format: YYYY-MM-DDTHH:MM:SSZ. If you specify a value for seconds, Amazon EC2 rounds the seconds to the nearest minute string null no
disable_stop_instance If this is set to true, Packer will not stop the instance but will assume that you will send the stop signal yourself through your final provisioner bool null no
ebs_optimized Mark instance as EBS Optimized. Default false bool null no
eks_version The EKS cluster version associated with the AMI created string "1.27" no
ena_support Enable enhanced networking (ENA but not SriovNetSupport) on HVM-compatible AMIs bool null no
enable_nitro_enclave Enable support for Nitro Enclaves on the instance bool null no
enable_unlimited_credits Enabling Unlimited credits allows the source instance to burst additional CPU beyond its available CPU Credits for as long as the demand exists bool null no
encrypt_boot Whether or not to encrypt the resulting AMI when copying a provisioned instance to an AMI. By default, Packer will keep the encryption setting to what it was in the source image bool null no
fleet_tags Key/value pair tags to apply tags to the fleet that is issued map(string) null no
force_delete_snapshot Force Packer to delete snapshots associated with AMIs, which have been deregistered by force_deregister. Default false bool null no
force_deregister Force Packer to first deregister an existing AMI if one with the same name already exists. Default false bool null no
iam_instance_profile The name of an IAM instance profile to launch the EC2 instance with string null no
imds_support Enforce version of the Instance Metadata Service on the built AMI. Valid options are unset (legacy) and v2.0 string "v2.0" no
insecure_skip_tls_verify This allows skipping TLS verification of the AWS EC2 endpoint. The default is false bool null no
instance_type The EC2 instance type to use while building the AMI, such as m5.large string "c5.xlarge" no
kms_key_id ID, alias or ARN of the KMS key to use for AMI encryption. This only applies to the main region -- any regions the AMI gets copied to copied will be encrypted by the default EBS KMS key for that region, unless you set region-specific keys in region_kms_key_ids string null no
launch_block_device_mappings The block device mappings to use when creating the AMI. If you add instance store volumes or EBS volumes in addition to the root device volume, the created AMI will contain block device mapping information for those volumes. Amazon creates snapshots of the source instance's root volume and any other EBS volumes described here. When you launch an instance from this new AMI, the instance automatically launches with these additional volumes, and will restore them from snapshots taken from the source instance list(map(string))
[
{
"delete_on_termination": true,
"device_name": "/dev/xvda",
"volume_size": 10,
"volume_type": "gp3"
}
]
no
max_retries This is the maximum number of times an API call is retried, in the case where requests are being throttled or experiencing transient failures. The delay between the subsequent API calls increases exponentially number null no
metadata_options Configures the metadata options for the instance launched map(string)
{
"http_endpoint": "enabled",
"http_put_response_hop_limit": 1,
"http_tokens": "required"
}
no
mfa_code The MFA TOTP code. This should probably be a user variable since it changes all the time string null no
pause_before_connecting We recommend that you enable SSH or WinRM as the very last step in your guest's bootstrap script, but sometimes you may have a race condition where you need Packer to wait before attempting to connect to your guest string null no
pause_before_ssm The time to wait before establishing the Session Manager session string null no
placement Describes the placement of an instance map(string) {} no
profile The profile to use in the shared credentials file for AWS string null no
region The name of the region, such as us-east-1, in which to launch the EC2 instance to create the AMI string "us-west-2" no
region_kms_key_ids regions to copy the ami to, along with the custom kms key id (alias or arn) to use for encryption for that region. Keys must match the regions provided in ami_regions map(string) null no
run_tags Key/value pair tags to apply to the generated key-pair, security group, iam profile and role, snapshot, network interfaces and instance that is launched to create the EBS volumes. The resulting AMI will also inherit these tags map(string) null no
run_volume_tags Tags to apply to the volumes that are launched to create the AMI. These tags are not applied to the resulting AMI map(string) null no
secret_key The secret key used to communicate with AWS string null no
security_group_filter Filters used to populate the security_group_ids field. security_group_ids take precedence over this list(map(string)) [] no
security_group_ids A list of security group IDs to assign to the instance. By default this is not set and Packer will automatically create a new temporary security group to allow SSH access list(string) null no
session_manager_port Which port to connect the local end of the session tunnel to. If left blank, Packer will choose a port for you from available ports. This option is only used when ssh_interface is set session_manager number null no
shared_credentials_file Path to a credentials file to load credentials from string null no
shell_provisioner1 Values passed to the first shell provisioner map {} no
shell_provisioner2 Values passed to the second shell provisioner map {} no
shell_provisioner3 Values passed to the third/last shell provisioner map {} no
shutdown_behavior Automatically terminate instances on shutdown in case Packer exits ungracefully. Possible values are stop and terminate. Defaults to stop string null no
skip_credential_validation Set to true if you want to skip validating AWS credentials before runtime bool null no
skip_metadata_api_check Skip Metadata Api Check bool null no
skip_profile_validation Whether or not to check if the IAM instance profile exists. Defaults to false bool null no
skip_region_validation Set to true if you want to skip validation of the ami_regions configuration option. Default false bool null no
skip_save_build_region If true, Packer will not check whether an AMI with the ami_name exists in the region it is building in. It will use an intermediary AMI name, which it will not convert to an AMI in the build region. Default false bool null no
snapshot_groups A list of groups that have access to create volumes from the snapshot(s). By default no groups have permission to create volumes from the snapshot(s). all will make the snapshot publicly accessible list(string) null no
snapshot_tags Key/value pair tags to apply to snapshot. They will override AMI tags if already applied to snapshot map(string) null no
snapshot_users A list of account IDs that have access to create volumes from the snapshot(s). By default no additional users other than the user creating the AMI has permissions to create volumes from the backing snapshot(s) list(string) null no
sriov_support Enable enhanced networking (SriovNetSupport but not ENA) on HVM-compatible AMIs bool null no
ssh_agent_auth If true, the local SSH agent will be used to authenticate connections to the source instance. No temporary keypair will be created, and the values of ssh_password and ssh_private_key_file will be ignored. The environment variable SSH_AUTH_SOCK must be set for this option to work properly bool null no
ssh_bastion_agent_auth If true, the local SSH agent will be used to authenticate with the bastion host. Defaults to false bool null no
ssh_bastion_certificate_file Path to user certificate used to authenticate with bastion host. The ~ can be used in path and will be expanded to the home directory of current user string null no
ssh_bastion_host A bastion host to use for the actual SSH connection string null no
ssh_bastion_interactive If true, the keyboard-interactive used to authenticate with bastion host bool null no
ssh_bastion_password The password to use to authenticate with the bastion host string null no
ssh_bastion_port The port of the bastion host. Defaults to 22 number null no
ssh_bastion_private_key_file Path to a PEM encoded private key file to use to authenticate with the bastion host. The ~ can be used in path and will be expanded to the home directory of current user string null no
ssh_bastion_username The username to connect to the bastion host string null no
ssh_certificate_file Path to user certificate used to authenticate with SSH. The ~ can be used in path and will be expanded to the home directory of current user string null no
ssh_ciphers This overrides the value of ciphers supported by default by Golang. The default value is ["aes128-gcm@openssh.com", "chacha20-poly1305@openssh.com", "aes128-ctr", "aes192-ctr", "aes256-ctr"] list(string) null no
ssh_clear_authorized_keys If true, Packer will attempt to remove its temporary key from ~/.ssh/authorized_keys and /root/.ssh/authorized_keys bool null no
ssh_disable_agent_forwarding If true, SSH agent forwarding will be disabled. Defaults to false bool null no
ssh_file_transfer_method How to transfer files, Secure copy (scp default) or SSH File Transfer Protocol (sftp) string null no
ssh_handshake_attempts The number of handshakes to attempt with SSH once it can connect. This defaults to 10, unless a ssh_timeout is set number null no
ssh_host The address to SSH to. This usually is automatically configured by the builder string null no
ssh_interface One of public_ip, private_ip, public_dns, private_dns or session_manager. If set, either the public IP address, private IP address, public DNS name or private DNS name will be used as the host for SSH. The default behavior if inside a VPC is to use the public IP address if available, otherwise the private IP address will be used. If not in a VPC the public DNS name will be used string "public_dns" no
ssh_keep_alive_interval How often to send "keep alive" messages to the server. Set to a negative value (-1s) to disable. Defaults to 5s string null no
ssh_key_exchange_algorithms If set, Packer will override the value of key exchange (kex) algorithms supported by default by Golang. Acceptable values include: curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group14-sha1, and diffie-hellman-group1-sha1 list(string) null no
ssh_keypair_name If specified, this is the key that will be used for SSH with the machine. The key must match a key pair name loaded up into the remote string null no
ssh_local_tunnels A list of local tunnels to use when connecting to the host list(string) null no
ssh_password A plaintext password to use to authenticate with SSH string null no
ssh_port The port to connect to SSH. This defaults to 22 number null no
ssh_private_key_file Path to a PEM encoded private key file to use to authenticate with SSH. The ~ can be used in path and will be expanded to the home directory of current user string null no
ssh_proxy_host A SOCKS proxy host to use for SSH connection string null no
ssh_proxy_password The optional password to use to authenticate with the proxy server string null no
ssh_proxy_port A port of the SOCKS proxy. Defaults to 1080 number null no
ssh_proxy_username The optional username to authenticate with the proxy server string null no
ssh_pty If true, a PTY will be requested for the SSH connection. This defaults to false bool null no
ssh_read_write_timeout The amount of time to wait for a remote command to end. This might be useful if, for example, packer hangs on a connection after a reboot. Example: 5m. Disabled by default string null no
ssh_remote_tunnels A list of remote tunnels to use when connecting to the host list(string) null no
ssh_timeout The time to wait for SSH to become available. Packer uses this to determine when the machine has booted so this is usually quite long. This defaults to 5m, unless ssh_handshake_attempts is set string null no
ssh_username The username to connect to SSH with. Required if using SSH string "ec2-user" no
subnet_filter Filters used to populate the subnet_id field. subnet_id take precedence over this list(map(string)) [] no
subnet_id f using VPC, the ID of the subnet, such as subnet-12345def, where Packer will launch the EC2 instance. This field is required if you are using an non-default VPC string null no
tags Key/value pair tags applied to the AMI map(string) {} no
temporary_key_pair_bits Specifies the number of bits in the key to create. For RSA keys, the minimum size is 1024 bits and the default is 4096 bits. Generally, 3072 bits is considered sufficient number null no
temporary_key_pair_type Specifies the type of key to create. The possible values are 'dsa', 'ecdsa', 'ed25519', or 'rsa'. Default is rsa string null no
temporary_security_group_source_cidrs A list of IPv4 CIDR blocks to be authorized access to the instance, when packer is creating a temporary security group. The default is [0.0.0.0/0] list(string) null no
temporary_security_group_source_public_ip When enabled, use public IP of the host (obtained from https://checkip.amazonaws.com) as CIDR block to be authorized access to the instance, when packer is creating a temporary security group. Defaults to false bool null no
token The access token to use. This is different from the access key and secret key string null no
user_data User data to apply when launching the instance string null no
user_data_file Path to a file that will be used for the user data when launching the instance string null no
vpc_filter Filters used to populate the vpc_id field. vpc_id take precedence over this list(map(string)) [] no
vpc_id If launching into a VPC subnet, Packer needs the VPC ID in order to create a temporary security group within the VPC. Requires subnet_id to be set. If this field is left blank, Packer will try to get the VPC ID from the subnet_id string null no

Outputs

No outputs.

License

This library is licensed under the MIT-0 License. See the LICENSE file.