Skip to content

Lab 02 — Secure Amazon EKS Worker Nodes

Item Details
Lab ID AWS-EKS-SEC-LAB-02
Difficulty Advanced
Estimated Time 5–7 Hours
AWS Services Amazon EKS, Amazon EC2, IAM, VPC, KMS, Systems Manager, CloudWatch, GuardDuty, AWS Config
Platform AWS
Cost AWS Charges May Apply
Primary Role Cloud Security Engineer
Supporting Roles Kubernetes Administrator, Platform Engineer, DevSecOps Engineer, SOC Analyst
Module Amazon EKS Security
Previous Lab Lab 01 — Secure Amazon EKS
Next Lab Lab 03 — Secure Amazon EKS Networking

CloudNova Technologies has deployed its first secure Amazon EKS cluster.

The control plane has been configured with:

  • IAM-based authentication
  • Kubernetes RBAC
  • Control-plane logging
  • AWS KMS encryption
  • CloudTrail monitoring
  • GuardDuty protection
  • Private networking
  • Amazon ECR integration

During the production-readiness review, the Cloud Security team identified that the worker-node security baseline is incomplete.

The current worker nodes present several potential risks:

  • Nodes may have unnecessary IAM permissions.
  • EC2 instance metadata protections have not been validated.
  • Root Amazon EBS volumes are not governed centrally.
  • Node operating-system patching is not formally scheduled.
  • Workloads with different trust levels can run on the same nodes.
  • SSH access has not been formally restricted.
  • Node security groups allow broader communication than required.
  • Runtime monitoring is inconsistent.
  • Node replacement and incident-isolation procedures are undocumented.
  • Node groups do not have standard security labels, taints, or ownership tags.
  • Sensitive workloads are not isolated onto dedicated node groups.
  • Node configuration changes are not consistently recorded.

The CISO has directed the Kubernetes Security team to create and validate an enterprise Amazon EKS worker-node security baseline.

Your mission is to deploy, assess, harden, monitor, and govern Amazon EKS worker nodes before production workloads are approved.

By completing this lab, you will learn how to:

  • Explain the Amazon EKS worker-node security model
  • Review managed node-group architecture
  • Create a secure node IAM role
  • Apply least-privilege permissions
  • Configure a secure EC2 launch template
  • Require modern instance metadata protections
  • Encrypt node storage with AWS KMS
  • Deploy worker nodes in private subnets
  • Restrict node security-group access
  • Disable unnecessary remote administration
  • Review node bootstrap configuration
  • Apply Kubernetes labels and taints
  • Isolate sensitive workloads
  • Configure resource reservations
  • Review kubelet security
  • Validate container-runtime configuration
  • Implement node patching and replacement
  • Enable AWS Systems Manager access
  • Configure CloudWatch node monitoring
  • Enable GuardDuty Runtime Monitoring
  • Validate node-drain procedures
  • Isolate a compromised node
  • Review node autoscaling security
  • Collect enterprise security evidence
  • Produce a worker-node hardening report
AWS Production Account
Amazon VPC
┌────────────────────────────────────────────────────┐
│ │
│ Private Subnets │
│ │
│ ┌────────────────────────────────────────────┐ │
│ │ Amazon EKS Managed Node Group │ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ Worker Node │ │ Worker Node │ │ │
│ │ │ │ │ │ │ │
│ │ │ Hardened OS │ │ Hardened OS │ │ │
│ │ │ Encrypted EBS│ │ Encrypted EBS│ │ │
│ │ │ IMDSv2 │ │ IMDSv2 │ │ │
│ │ │ SSM Access │ │ SSM Access │ │ │
│ │ │ Runtime Agent│ │ Runtime Agent│ │ │
│ │ └──────────────┘ └──────────────┘ │ │
│ └────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
AWS KMS CloudWatch Logs GuardDuty
│ │ │
└─────────────────┼─────────────────┘
Security Operations
AWS Responsibility
• Physical infrastructure
• EKS managed control plane
• Underlying AWS facilities
• EC2 hardware and hypervisor
Customer Responsibility
• Node IAM role
• Operating-system lifecycle
• Launch-template settings
• Instance metadata protection
• Security groups
• EBS encryption
• Node labels and taints
• Workload placement
• Runtime monitoring
• Patch and replacement process
• Access control
• Incident response
Discover Existing Nodes
Review Node IAM Permissions
Create Secure Launch Template
Enable Storage and Metadata Protection
Deploy Private Managed Node Group
Apply Labels and Taints
Validate Kubelet and Runtime Security
Enable Monitoring and Runtime Detection
Test Drain, Replacement and Isolation
Collect Evidence and Report

By the end of this lab, you will have:

  • Assessed existing Amazon EKS worker nodes
  • Created a dedicated node IAM role
  • Reviewed node-role permissions
  • Created a secure EC2 launch template
  • Required secure instance metadata access
  • Enabled encrypted Amazon EBS storage
  • Restricted remote-administration exposure
  • Deployed a private managed node group
  • Applied node ownership labels
  • Applied workload-isolation taints
  • Deployed a workload to a dedicated node group
  • Reviewed kubelet configuration
  • Validated container-runtime configuration
  • Configured Systems Manager access
  • Enabled node monitoring
  • Reviewed GuardDuty Runtime Monitoring
  • Tested node cordon and drain
  • Documented compromised-node isolation
  • Reviewed node-group update controls
  • Created a worker-node risk register
  • Produced an enterprise hardening report

This lab creates AWS resources that may incur charges.

Use only:

  • An authorised AWS account
  • A non-production EKS cluster
  • Approved AWS Regions
  • Approved IAM identities
  • Approved container images

Do not:

  • Run destructive commands in production
  • Terminate nodes without validating workload impact
  • expose SSH to the internet
  • Place AWS access keys on worker nodes
  • Attach administrative policies to node roles
  • Modify node bootstrap settings without testing
  • Drain critical workloads without reviewing disruption controls
  • store sensitive information in user data
  • weaken instance metadata protection
  • retain resources after the lab unless formally approved

Before starting, ensure that you have:

  • Completed Lab 01 — Secure Amazon EKS
  • An existing Amazon EKS cluster
  • AWS CLI
  • kubectl
  • eksctl
  • jq
  • Helm
  • Git Bash or PowerShell
  • IAM permissions to manage EKS node groups
  • IAM permissions to manage roles and policies
  • EC2 launch-template permissions
  • AWS KMS permissions
  • CloudWatch permissions
  • Systems Manager permissions
  • Access to an approved evidence repository
Tool Purpose
AWS CLI AWS resource configuration and assessment
kubectl Kubernetes node and workload administration
eksctl Managed node-group deployment
IAM Node identity and permission management
EC2 Launch Templates Secure node configuration
AWS KMS Amazon EBS encryption
Systems Manager Controlled node administration
CloudWatch Node logging and monitoring
GuardDuty Runtime threat detection
AWS Config Configuration compliance
jq JSON analysis
Helm Security-agent deployment
VS Code Configuration and reporting
lab-02-secure-eks-worker-nodes/
├── configuration/
│ ├── environment.sh
│ ├── nodegroup-config.yaml
│ ├── launch-template.json
│ └── cloudwatch-config.json
├── iam/
│ ├── node-trust-policy.json
│ ├── node-role-policies.md
│ └── permission-review.md
├── manifests/
│ ├── secure-workload.yaml
│ ├── sensitive-workload.yaml
│ ├── pod-disruption-budget.yaml
│ └── node-maintenance-job.yaml
├── assessment/
│ ├── node-inventory.md
│ ├── kubelet-review.md
│ ├── runtime-review.md
│ ├── network-review.md
│ ├── patching-review.md
│ └── incident-isolation-plan.md
├── evidence/
│ ├── aws-identity.json
│ ├── cluster-details.json
│ ├── nodegroups.json
│ ├── nodes.yaml
│ ├── node-role.json
│ ├── launch-template.json
│ ├── security-groups.json
│ ├── volumes.json
│ ├── node-labels.txt
│ ├── kubelet-config.txt
│ └── monitoring-status.txt
└── reports/
├── findings-register.md
├── risk-register.md
├── remediation-plan.md
└── worker-node-security-report.md
Terminal window
mkdir -p lab-02-secure-eks-worker-nodes/{configuration,iam,manifests,assessment,evidence,reports}
cd lab-02-secure-eks-worker-nodes
Terminal window
New-Item -ItemType Directory -Force `
-Path lab-02-secure-eks-worker-nodes\configuration
New-Item -ItemType Directory -Force `
-Path lab-02-secure-eks-worker-nodes\iam
New-Item -ItemType Directory -Force `
-Path lab-02-secure-eks-worker-nodes\manifests
New-Item -ItemType Directory -Force `
-Path lab-02-secure-eks-worker-nodes\assessment
New-Item -ItemType Directory -Force `
-Path lab-02-secure-eks-worker-nodes\evidence
New-Item -ItemType Directory -Force `
-Path lab-02-secure-eks-worker-nodes\reports
Set-Location lab-02-secure-eks-worker-nodes
Terminal window
export AWS_REGION="ap-south-1"
export CLUSTER_NAME="ghc-secure-eks"
export NODEGROUP_NAME="ghc-secure-workers"
export NODE_ROLE_NAME="ghc-eks-node-role"
export LAUNCH_TEMPLATE_NAME="ghc-secure-eks-node-template"
export KMS_ALIAS="alias/ghc-eks-node-storage"

Save the variables.

Terminal window
cat > configuration/environment.sh <<EOF
export AWS_REGION="${AWS_REGION}"
export CLUSTER_NAME="${CLUSTER_NAME}"
export NODEGROUP_NAME="${NODEGROUP_NAME}"
export NODE_ROLE_NAME="${NODE_ROLE_NAME}"
export LAUNCH_TEMPLATE_NAME="${LAUNCH_TEMPLATE_NAME}"
export KMS_ALIAS="${KMS_ALIAS}"
EOF
Terminal window
$env:AWS_REGION = "ap-south-1"
$env:CLUSTER_NAME = "ghc-secure-eks"
$env:NODEGROUP_NAME = "ghc-secure-workers"
$env:NODE_ROLE_NAME = "ghc-eks-node-role"
$env:LAUNCH_TEMPLATE_NAME = "ghc-secure-eks-node-template"
$env:KMS_ALIAS = "alias/ghc-eks-node-storage"
Terminal window
aws sts get-caller-identity \
> evidence/aws-identity.json

Review:

Terminal window
cat evidence/aws-identity.json

Confirm:

  • AWS account is authorised
  • Role or user is expected
  • No root identity is being used
  • Region is approved
  • Permissions are sufficient

Update kubeconfig.

Terminal window
aws eks update-kubeconfig \
--name "${CLUSTER_NAME}" \
--region "${AWS_REGION}"

Verify the context.

Terminal window
kubectl config current-context

Check cluster information.

Terminal window
kubectl cluster-info

Save evidence.

Terminal window
aws eks describe-cluster \
--name "${CLUSTER_NAME}" \
--region "${AWS_REGION}" \
> evidence/cluster-details.json

Task 05 — Discover Existing Managed Node Groups

Section titled “Task 05 — Discover Existing Managed Node Groups”
Terminal window
aws eks list-nodegroups \
--cluster-name "${CLUSTER_NAME}" \
--region "${AWS_REGION}" \
> evidence/nodegroups.json

Review:

Terminal window
aws eks list-nodegroups \
--cluster-name "${CLUSTER_NAME}" \
--region "${AWS_REGION}" \
--output table

For each node group, record:

Field Details
Node-group name
Status
Capacity type
Instance types
Minimum size
Desired size
Maximum size
Node IAM role
Subnets
Launch template
AMI type
Kubernetes version
Release version

Export node information.

Terminal window
kubectl get nodes \
-o wide
Terminal window
kubectl get nodes \
-o yaml \
> evidence/nodes.yaml

Create assessment/node-inventory.md.

Node Node Group Instance Type Availability Zone OS Runtime Status

Task 07 — Map Kubernetes Nodes to EC2 Instances

Section titled “Task 07 — Map Kubernetes Nodes to EC2 Instances”

Retrieve instance-provider identifiers.

Terminal window
kubectl get nodes \
-o custom-columns='NODE:.metadata.name,PROVIDER-ID:.spec.providerID'

Retrieve EKS node-group labels.

Terminal window
kubectl get nodes \
-L eks.amazonaws.com/nodegroup \
-L node.kubernetes.io/instance-type \
-L topology.kubernetes.io/zone

Save evidence.

Terminal window
kubectl get nodes \
-L eks.amazonaws.com/nodegroup \
-L node.kubernetes.io/instance-type \
-L topology.kubernetes.io/zone \
> evidence/node-labels.txt

Task 08 — Review Existing Node IAM Roles

Section titled “Task 08 — Review Existing Node IAM Roles”

Describe the node group.

Terminal window
aws eks describe-nodegroup \
--cluster-name "${CLUSTER_NAME}" \
--nodegroup-name "<existing-node-group>" \
--region "${AWS_REGION}"

Identify the node IAM role.

Review attached policies.

Terminal window
aws iam list-attached-role-policies \
--role-name "<existing-node-role>"

Review inline policies.

Terminal window
aws iam list-role-policies \
--role-name "<existing-node-role>"

Create iam/permission-review.md.

Check whether the node role has:

  • Only required EKS worker-node permissions
  • Required container-registry pull permissions
  • Required networking permissions
  • Systems Manager permissions only when approved
  • No administrator policy
  • No broad business-service permissions
  • No unrestricted access to AWS Secrets Manager
  • No unrestricted access to Amazon S3
  • No direct application permissions
  • No permissions intended for Kubernetes Pods

Application permissions should be provided through workload-specific AWS identity mechanisms rather than the EC2 node role.

Task 10 — Create the Node IAM Trust Policy

Section titled “Task 10 — Create the Node IAM Trust Policy”

Create iam/node-trust-policy.json.

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}

Create the role.

Terminal window
aws iam create-role \
--role-name "${NODE_ROLE_NAME}" \
--assume-role-policy-document file://iam/node-trust-policy.json

Attach the organisation-approved policies required by the node group.

Example:

Terminal window
aws iam attach-role-policy \
--role-name "${NODE_ROLE_NAME}" \
--policy-arn arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
Terminal window
aws iam attach-role-policy \
--role-name "${NODE_ROLE_NAME}" \
--policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPullOnly

Attach the networking policy only according to the organisation’s selected EKS networking and identity architecture.

Document every attached policy and its justification.

Where approved, attach controlled Systems Manager permissions to the node role.

Terminal window
aws iam attach-role-policy \
--role-name "${NODE_ROLE_NAME}" \
--policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore

Systems Manager should be preferred over unrestricted inbound SSH access.

Confirm the organisation permits this managed policy or replace it with an approved custom policy.

Terminal window
aws iam get-role \
--role-name "${NODE_ROLE_NAME}" \
> evidence/node-role.json
Terminal window
aws iam list-attached-role-policies \
--role-name "${NODE_ROLE_NAME}"

Validate:

  • Trusted principal is EC2
  • No users can directly assume the role
  • No wildcard trust relationship exists
  • Attached permissions are documented
  • Application permissions are absent

Task 14 — Create a KMS Key for Node Storage

Section titled “Task 14 — Create a KMS Key for Node Storage”

Create a customer-managed KMS key.

Terminal window
aws kms create-key \
--description "CloudNova Amazon EKS worker node storage encryption" \
--key-usage ENCRYPT_DECRYPT \
--origin AWS_KMS \
> evidence/node-kms-key.json

Retrieve the key ID.

Terminal window
export NODE_KMS_KEY_ID=$(jq -r '.KeyMetadata.KeyId' evidence/node-kms-key.json)

Create an alias.

Terminal window
aws kms create-alias \
--alias-name "${KMS_ALIAS}" \
--target-key-id "${NODE_KMS_KEY_ID}"

Validate:

  • Key administrators are separate from key users
  • Key rotation is enabled where required
  • Key policy follows least privilege
  • Node role receives only necessary cryptographic permissions
  • CloudTrail records KMS activity
  • Key deletion requires a controlled process
  • Production and non-production keys are separated

Enable rotation where applicable.

Terminal window
aws kms enable-key-rotation \
--key-id "${NODE_KMS_KEY_ID}"

Task 16 — Design the Secure Launch Template

Section titled “Task 16 — Design the Secure Launch Template”

The launch template should govern:

  • Instance metadata settings
  • Encrypted root storage
  • KMS key
  • Security groups
  • Monitoring
  • Instance tags
  • No public IP requirement through subnet design
  • No SSH key unless formally approved
  • Approved instance profile
  • Approved user data

Create configuration/launch-template.json.

{
"LaunchTemplateName": "ghc-secure-eks-node-template",
"VersionDescription": "Secure Amazon EKS worker-node baseline",
"LaunchTemplateData": {
"MetadataOptions": {
"HttpEndpoint": "enabled",
"HttpTokens": "required",
"HttpPutResponseHopLimit": 1,
"InstanceMetadataTags": "disabled"
},
"Monitoring": {
"Enabled": true
},
"BlockDeviceMappings": [
{
"DeviceName": "/dev/xvda",
"Ebs": {
"DeleteOnTermination": true,
"Encrypted": true,
"VolumeSize": 30,
"VolumeType": "gp3"
}
}
],
"TagSpecifications": [
{
"ResourceType": "instance",
"Tags": [
{
"Key": "Environment",
"Value": "training"
},
{
"Key": "Owner",
"Value": "cloud-security"
},
{
"Key": "ManagedBy",
"Value": "eks"
},
{
"Key": "DataClassification",
"Value": "internal"
}
]
},
{
"ResourceType": "volume",
"Tags": [
{
"Key": "Environment",
"Value": "training"
},
{
"Key": "Owner",
"Value": "cloud-security"
}
]
}
]
}
}

Add the approved KMS key to the EBS configuration before deployment.

Task 17 — Require Secure Instance Metadata Access

Section titled “Task 17 — Require Secure Instance Metadata Access”

Confirm the launch template requires:

"HttpTokens": "required"

This prevents use of unauthenticated instance-metadata requests.

Review the hop limit.

"HttpPutResponseHopLimit": 1

The selected value must align with the organisation’s container-networking and workload-identity architecture.

Document any approved deviation.

Task 18 — Prevent Unnecessary SSH Access

Section titled “Task 18 — Prevent Unnecessary SSH Access”

Do not specify an EC2 key pair unless remote SSH access has been formally approved.

Confirm:

  • No port 22 rule from 0.0.0.0/0
  • No shared private key
  • No personal key pairs
  • Systems Manager is available for controlled administration
  • Emergency access is logged
  • Node access follows change control
Terminal window
aws ec2 create-launch-template \
--cli-input-json file://configuration/launch-template.json \
> evidence/launch-template.json

Review:

Terminal window
aws ec2 describe-launch-templates \
--launch-template-names "${LAUNCH_TEMPLATE_NAME}"

Task 20 — Review Launch-Template Security

Section titled “Task 20 — Review Launch-Template Security”

Validate:

Control Expected
Metadata tokens Required
Metadata endpoint Enabled only where needed
Hop limit Approved
Root volume Encrypted
KMS key Approved
Delete on termination Enabled
Volume type Approved
Detailed monitoring Enabled
Public IP Not assigned through private subnet
SSH key Not configured unless approved
Security group Restricted
Tags Complete
User data No credentials

Retrieve EKS cluster subnets.

Terminal window
aws eks describe-cluster \
--name "${CLUSTER_NAME}" \
--region "${AWS_REGION}" \
--query 'cluster.resourcesVpcConfig.subnetIds' \
--output text

Review each subnet.

Terminal window
aws ec2 describe-subnets \
--subnet-ids <subnet-id-1> <subnet-id-2>

Confirm private node subnets:

  • Do not automatically assign public IP addresses
  • Have appropriate routes
  • Use approved NAT or VPC endpoints
  • Are distributed across Availability Zones
  • Have required EKS subnet tags
  • Do not expose nodes directly to the internet

Assess whether private nodes can use VPC endpoints for approved AWS services, such as:

  • Amazon ECR API
  • Amazon ECR Docker registry
  • Amazon S3 where required by image operations
  • AWS Systems Manager
  • Systems Manager Messages
  • EC2 Messages where applicable
  • CloudWatch Logs
  • AWS STS
  • AWS KMS

VPC endpoints can reduce reliance on broad internet egress.

Task 23 — Review the Cluster Security Group

Section titled “Task 23 — Review the Cluster Security Group”

Retrieve cluster security-group details.

Terminal window
aws eks describe-cluster \
--name "${CLUSTER_NAME}" \
--region "${AWS_REGION}" \
--query 'cluster.resourcesVpcConfig.clusterSecurityGroupId' \
--output text

Export security-group evidence.

Terminal window
aws ec2 describe-security-groups \
--group-ids <cluster-security-group-id> \
> evidence/security-groups.json

Task 24 — Review Node Security-Group Rules

Section titled “Task 24 — Review Node Security-Group Rules”

Validate:

  • Node-to-control-plane communication is allowed only as required
  • Node-to-node traffic follows the selected networking architecture
  • No unnecessary inbound internet access exists
  • Administrative ports are restricted
  • Outbound access is reviewed
  • Security-group references are used where appropriate
  • Rules have documented owners and purposes

Task 25 — Create the Managed Node-Group Configuration

Section titled “Task 25 — Create the Managed Node-Group Configuration”

Create configuration/nodegroup-config.yaml.

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: ghc-secure-eks
region: ap-south-1
managedNodeGroups:
- name: ghc-secure-workers
minSize: 2
desiredCapacity: 2
maxSize: 4
privateNetworking: true
instanceTypes:
- t3.medium
iam:
instanceRoleARN: arn:aws:iam::<AWS-ACCOUNT-ID>:role/ghc-eks-node-role
launchTemplate:
id: <LAUNCH-TEMPLATE-ID>
version: "<LAUNCH-TEMPLATE-VERSION>"
labels:
workload-tier: standard
environment: training
security-zone: restricted
owner: cloud-security
taints:
- key: workload-tier
value: standard
effect: NoSchedule
tags:
Environment: training
Owner: cloud-security
ManagedBy: eksctl
SecurityBaseline: hardened

Replace all placeholders before deployment.

Task 26 — Validate the Configuration File

Section titled “Task 26 — Validate the Configuration File”

Review the configuration for:

  • Correct cluster name
  • Correct Region
  • Correct node IAM role
  • Correct launch-template ID
  • Correct launch-template version
  • Private networking
  • Approved instance types
  • Minimum two nodes where resilience is required
  • Labels
  • Taints
  • Ownership tags

Task 27 — Create the Secure Managed Node Group

Section titled “Task 27 — Create the Secure Managed Node Group”
Terminal window
eksctl create nodegroup \
-f configuration/nodegroup-config.yaml

Monitor the node group.

Terminal window
aws eks describe-nodegroup \
--cluster-name "${CLUSTER_NAME}" \
--nodegroup-name "${NODEGROUP_NAME}" \
--region "${AWS_REGION}" \
--query 'nodegroup.status'
Terminal window
kubectl get nodes \
-o wide

Review EKS node-group labels.

Terminal window
kubectl get nodes \
-L eks.amazonaws.com/nodegroup \
-L workload-tier \
-L security-zone \
-L owner

Confirm:

  • Nodes are Ready
  • Nodes belong to the expected node group
  • Labels are present
  • Taints are present
  • Nodes use approved instance types
  • Nodes are distributed across Availability Zones
Terminal window
kubectl describe nodes \
| grep -A3 "Taints"

Or inspect a specific node.

Terminal window
kubectl describe node <node-name>

Confirm the intended taint exists.

workload-tier=standard:NoSchedule

Task 30 — Deploy a Workload Without a Toleration

Section titled “Task 30 — Deploy a Workload Without a Toleration”

Create manifests/secure-workload.yaml.

apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-web
namespace: default
labels:
app: secure-web
spec:
replicas: 2
selector:
matchLabels:
app: secure-web
template:
metadata:
labels:
app: secure-web
spec:
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: web
image: nginxinc/nginx-unprivileged:stable
ports:
- containerPort: 8080
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 250m
memory: 256Mi
volumeMounts:
- name: cache
mountPath: /tmp
- name: nginx-cache
mountPath: /var/cache/nginx
volumes:
- name: cache
emptyDir: {}
- name: nginx-cache
emptyDir: {}

Apply the workload.

Terminal window
kubectl apply \
-f manifests/secure-workload.yaml

Review scheduling.

Terminal window
kubectl get pods \
-o wide

The Pods should not schedule onto the tainted node group without a matching toleration.

Task 31 — Add a Toleration and Node Selector

Section titled “Task 31 — Add a Toleration and Node Selector”

Update the Pod specification.

spec:
template:
spec:
nodeSelector:
workload-tier: standard
tolerations:
- key: workload-tier
operator: Equal
value: standard
effect: NoSchedule

Reapply.

Terminal window
kubectl apply \
-f manifests/secure-workload.yaml

Validate placement.

Terminal window
kubectl get pods \
-o wide

Task 32 — Create a Dedicated Sensitive-Workload Node Group

Section titled “Task 32 — Create a Dedicated Sensitive-Workload Node Group”

Create a separate node-group design for sensitive workloads.

Recommended controls:

  • Dedicated node IAM role
  • Dedicated node-group labels
  • Dedicated taints
  • Restricted security group
  • Approved instance family
  • Encrypted storage
  • Stronger monitoring
  • Limited workload eligibility
  • Separate scaling policy

Example labels:

labels:
workload-tier: sensitive
data-classification: confidential
security-zone: high

Example taint:

taints:
- key: dedicated
value: sensitive
effect: NoSchedule

Create manifests/sensitive-workload.yaml.

apiVersion: apps/v1
kind: Deployment
metadata:
name: sensitive-api
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: sensitive-api
template:
metadata:
labels:
app: sensitive-api
spec:
automountServiceAccountToken: false
nodeSelector:
workload-tier: sensitive
tolerations:
- key: dedicated
operator: Equal
value: sensitive
effect: NoSchedule
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: api
image: nginxinc/nginx-unprivileged:stable
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 250m
memory: 256Mi
volumeMounts:
- name: temporary-data
mountPath: /tmp
volumes:
- name: temporary-data
emptyDir: {}

Deploy only after the sensitive node group exists.

Task 34 — Review Node Operating-System Details

Section titled “Task 34 — Review Node Operating-System Details”
Terminal window
kubectl get nodes \
-o custom-columns='NODE:.metadata.name,OS-IMAGE:.status.nodeInfo.osImage,KERNEL:.status.nodeInfo.kernelVersion,RUNTIME:.status.nodeInfo.containerRuntimeVersion,KUBELET:.status.nodeInfo.kubeletVersion'

Assess:

  • Approved EKS-optimised image
  • Supported operating system
  • Supported kernel
  • Supported container runtime
  • Consistent kubelet version
  • No unexpected custom images

Describe the node group.

Terminal window
aws eks describe-nodegroup \
--cluster-name "${CLUSTER_NAME}" \
--nodegroup-name "${NODEGROUP_NAME}" \
--region "${AWS_REGION}" \
--query 'nodegroup.{amiType:amiType,releaseVersion:releaseVersion,version:version}'

Confirm:

  • AMI type is approved
  • Release version is current according to organisational policy
  • Custom AMIs follow a secure build process
  • Image provenance is documented
  • Vulnerability scanning is completed
  • Old node images are replaced

Use an approved administrative method such as Systems Manager to inspect a non-production node.

Review:

  • Anonymous authentication
  • Authorisation mode
  • Read-only port
  • TLS configuration
  • Certificate rotation
  • Configuration-file permissions
  • Event limits
  • Resource reservations
  • Logging
  • Node registration settings

Create assessment/kubelet-review.md.

Node:
Kubelet Version:
Anonymous Authentication:
Authorisation Mode:
Read-Only Port:
Client Certificate Rotation:
Server Certificate Configuration:
Configuration Ownership:
Configuration Permissions:
Reserved Resources:
Eviction Thresholds:
Findings:
Risk:

Task 37 — Review Container Runtime Security

Section titled “Task 37 — Review Container Runtime Security”

Create assessment/runtime-review.md.

Assess:

  • Container runtime version
  • Runtime configuration ownership
  • Runtime socket access
  • Runtime logging
  • Image garbage collection
  • Registry configuration
  • Untrusted registry access
  • Runtime monitoring
  • Supported version
  • Patch status

Do not expose the runtime socket to ordinary workloads.

Check whether workloads can access:

  • Host filesystem
  • Container runtime socket
  • Host networking
  • Host process namespace
  • Host IPC namespace
  • Device interfaces
  • Kernel modules
  • Privileged mode

Use policy controls to prevent unauthorised host access.

Terminal window
kubectl get daemonsets \
-A \
-o wide

Assess each DaemonSet for:

  • Owner
  • Purpose
  • Privileges
  • HostPath mounts
  • Host namespaces
  • Service Account
  • Image source
  • Resource limits
  • Update strategy
  • Security context

Security agents may need elevated access, but every privilege must be justified.

Task 40 — Validate Amazon EBS Encryption

Section titled “Task 40 — Validate Amazon EBS Encryption”

Map worker nodes to EC2 instances and volumes.

Terminal window
aws ec2 describe-instances \
--filters "Name=tag:eks:cluster-name,Values=${CLUSTER_NAME}" \
> evidence/worker-instances.json

Review attached volumes.

Terminal window
aws ec2 describe-volumes \
--filters "Name=tag:eks:cluster-name,Values=${CLUSTER_NAME}" \
> evidence/volumes.json

Confirm:

  • Encrypted is true
  • Approved KMS key is used
  • Volume tags are present
  • Volumes delete with terminated nodes where appropriate
  • No unmanaged data volumes exist

Task 41 — Validate Instance Metadata Configuration

Section titled “Task 41 — Validate Instance Metadata Configuration”

Retrieve metadata options.

Terminal window
aws ec2 describe-instances \
--filters "Name=tag:eks:cluster-name,Values=${CLUSTER_NAME}" \
--query 'Reservations[].Instances[].{InstanceId:InstanceId,HttpTokens:MetadataOptions.HttpTokens,HttpEndpoint:MetadataOptions.HttpEndpoint,HopLimit:MetadataOptions.HttpPutResponseHopLimit}' \
--output table

Expected:

  • HttpTokens is required
  • Endpoint state matches policy
  • Hop limit matches approved design
  • No node uses legacy metadata settings

Task 42 — Verify Nodes Are Not Publicly Addressable

Section titled “Task 42 — Verify Nodes Are Not Publicly Addressable”
Terminal window
aws ec2 describe-instances \
--filters "Name=tag:eks:cluster-name,Values=${CLUSTER_NAME}" \
--query 'Reservations[].Instances[].{InstanceId:InstanceId,PrivateIP:PrivateIpAddress,PublicIP:PublicIpAddress,Subnet:SubnetId}' \
--output table

Confirm worker nodes do not have public IP addresses.

Task 43 — Validate Systems Manager Registration

Section titled “Task 43 — Validate Systems Manager Registration”
Terminal window
aws ssm describe-instance-information \
--query 'InstanceInformationList[].{InstanceId:InstanceId,PingStatus:PingStatus,Platform:PlatformName,AgentVersion:AgentVersion}' \
--output table

Confirm:

  • Nodes appear as managed instances
  • Agent status is online
  • No inbound SSH is required
  • Session activity is logged
  • Access is limited to approved administrators

Task 44 — Review Systems Manager Session Governance

Section titled “Task 44 — Review Systems Manager Session Governance”

Validate:

  • Named users or roles
  • MFA
  • Session logging
  • Approved log destination
  • Encryption
  • Limited session duration
  • Change ticket requirement
  • Emergency-access procedure
  • Post-session review

Create assessment/patching-review.md.

Document:

Node Group:
Operating System:
AMI Type:
Current Release:
Approved Release:
Patch Owner:
Patch Frequency:
Emergency Patch SLA:
Testing Environment:
Maintenance Window:
Drain Procedure:
Replacement Procedure:
Rollback Plan:
Evidence Location:

Amazon EKS managed node groups should be updated through a controlled replacement process rather than relying on uncontrolled manual changes.

Task 46 — Review the Node-Group Update Configuration

Section titled “Task 46 — Review the Node-Group Update Configuration”
Terminal window
aws eks describe-nodegroup \
--cluster-name "${CLUSTER_NAME}" \
--nodegroup-name "${NODEGROUP_NAME}" \
--region "${AWS_REGION}" \
--query 'nodegroup.updateConfig'

Assess:

  • Maximum unavailable nodes
  • Maximum unavailable percentage
  • Workload resilience
  • PodDisruptionBudgets
  • Maintenance window
  • Rollback readiness

Task 47 — Create a Pod Disruption Budget

Section titled “Task 47 — Create a Pod Disruption Budget”

Create manifests/pod-disruption-budget.yaml.

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: secure-web-pdb
namespace: default
spec:
minAvailable: 1
selector:
matchLabels:
app: secure-web

Apply:

Terminal window
kubectl apply \
-f manifests/pod-disruption-budget.yaml

Validate:

Terminal window
kubectl get poddisruptionbudgets \
-A

Select a non-critical training node.

Terminal window
kubectl cordon <node-name>

Validate:

Terminal window
kubectl get nodes

The node should show:

SchedulingDisabled

Review workload impact first.

Terminal window
kubectl get pods \
-A \
-o wide \
--field-selector spec.nodeName=<node-name>

Drain the approved training node.

Terminal window
kubectl drain <node-name> \
--ignore-daemonsets \
--delete-emptydir-data

Validate workload rescheduling.

Terminal window
kubectl get pods \
-A \
-o wide
Terminal window
kubectl uncordon <node-name>

Validate:

Terminal window
kubectl get nodes

Document:

  • Drain duration
  • Workloads disrupted
  • Pods rescheduled
  • PodDisruptionBudget behaviour
  • Errors
  • Recovery result

Task 51 — Simulate a Compromised-Node Response

Section titled “Task 51 — Simulate a Compromised-Node Response”

Do not intentionally compromise the node.

Create assessment/incident-isolation-plan.md.

Document the authorised response process:

1. Confirm the alert.
2. Identify the affected node.
3. Preserve logs and metadata.
4. Cordon the node.
5. Assess workload impact.
6. Drain safe workloads.
7. Isolate network access.
8. Capture approved forensic evidence.
9. Revoke exposed credentials.
10. Terminate and replace the node.
11. Scan affected images and workloads.
12. Review node IAM-role activity.
13. Review CloudTrail and GuardDuty.
14. Validate replacement node.
15. Complete incident review.

Task 52 — Review Credential Exposure Risk

Section titled “Task 52 — Review Credential Exposure Risk”

Assess whether a compromised node could access:

  • Node IAM credentials
  • Kubernetes node credentials
  • Pod credentials
  • Secrets mounted to workloads
  • Container-registry tokens
  • Systems Manager channels
  • Attached volumes
  • Runtime socket
  • Kubelet API

Document controls that reduce credential exposure.

Task 53 — Review Workload Identity Separation

Section titled “Task 53 — Review Workload Identity Separation”

Verify application Pods do not rely on the EC2 node role for business-service permissions.

Assess:

  • Workload-specific AWS identity
  • Kubernetes Service Account ownership
  • Least-privilege role
  • Namespace restrictions
  • Token audience
  • Trust conditions
  • Credential rotation
  • CloudTrail attribution

Task 54 — Enable CloudWatch Node Monitoring

Section titled “Task 54 — Enable CloudWatch Node Monitoring”

Review available node and container telemetry.

Monitor:

  • CPU
  • Memory
  • Disk
  • Network
  • Node readiness
  • Pod failures
  • Filesystem pressure
  • Memory pressure
  • PID pressure
  • Kubelet errors
  • Container runtime errors

Store the approved CloudWatch agent or observability configuration in:

configuration/cloudwatch-config.json
Terminal window
kubectl describe nodes

Review:

  • Ready
  • MemoryPressure
  • DiskPressure
  • PIDPressure
  • NetworkUnavailable

Create an evidence file.

Terminal window
kubectl get nodes \
-o json \
| jq '.items[] | {
node: .metadata.name,
conditions: .status.conditions
}' \
> evidence/node-conditions.json

Recommended alerts:

  • Node becomes NotReady
  • Node reports disk pressure
  • Node reports memory pressure
  • Unexpected node joins cluster
  • Unexpected node-group scaling
  • EC2 instance metadata setting changes
  • Security-group rule changes
  • Node IAM-role policy changes
  • Root-volume encryption disabled
  • Systems Manager session initiated
  • GuardDuty runtime finding
  • Repeated kubelet authentication failures

Task 57 — Review GuardDuty Runtime Monitoring

Section titled “Task 57 — Review GuardDuty Runtime Monitoring”

Verify GuardDuty coverage for the EKS environment.

Review:

  • Runtime monitoring status
  • Required agent deployment
  • Node coverage
  • Findings destination
  • Notification workflow
  • SIEM integration
  • Suppression rules
  • Finding ownership

Do not suppress findings without a documented investigation and approval process.

Terminal window
aws guardduty list-detectors

Using the approved detector ID:

Terminal window
aws guardduty list-findings \
--detector-id <detector-id>

Review findings associated with:

  • EKS
  • EC2 worker nodes
  • Runtime activity
  • Credential use
  • Network communication
  • Malware or suspicious processes

Search for events involving:

  • CreateNodegroup
  • UpdateNodegroupVersion
  • UpdateNodegroupConfig
  • DeleteNodegroup
  • CreateLaunchTemplate
  • CreateLaunchTemplateVersion
  • ModifyInstanceMetadataOptions
  • AuthorizeSecurityGroupIngress
  • AttachRolePolicy
  • PutRolePolicy
  • StartSession
  • TerminateInstances

Confirm:

  • Events are captured
  • Identity is attributable
  • Logs are retained
  • Alerts exist for sensitive changes
  • Changes map to approved tickets

Assess whether AWS Config records:

  • EC2 instances
  • Security groups
  • IAM roles
  • Launch templates
  • EBS volumes
  • KMS keys
  • EKS clusters
  • EKS node groups

Recommended compliance checks should identify:

  • Unencrypted volumes
  • Public security-group access
  • Insecure metadata settings
  • Unapproved instance types
  • Missing tags
  • IAM-policy changes
  • Unsupported node configurations

Task 61 — Review Node Autoscaling Security

Section titled “Task 61 — Review Node Autoscaling Security”

Assess whether node autoscaling is configured securely.

Review:

  • Autoscaler IAM permissions
  • Service Account identity
  • Node-group scope
  • Minimum and maximum capacity
  • Tag-based discovery
  • Scaling-event logging
  • Instance-type restrictions
  • Availability Zone distribution
  • Denial-of-service risk
  • Cost alarms

Task 62 — Review Node-Group Capacity Types

Section titled “Task 62 — Review Node-Group Capacity Types”

Document whether the node group uses:

  • On-Demand capacity
  • Spot capacity
  • Mixed capacity

Assess:

  • Workload criticality
  • Interruption tolerance
  • PodDisruptionBudgets
  • Minimum availability
  • Sensitive-workload placement
  • Capacity-diversity requirements
  • Business-continuity impact

Critical workloads should not depend solely on interruptible capacity without approved resilience controls.

Task 63 — Review Node Resource Reservations

Section titled “Task 63 — Review Node Resource Reservations”

Assess kubelet reservations for:

  • Kubernetes system processes
  • Operating-system processes
  • Eviction thresholds
  • Pod density
  • CPU
  • Memory
  • Ephemeral storage
  • PID availability

Improper reservations can create node instability and denial-of-service risk.

Review:

  • Instance type
  • Networking plugin configuration
  • Maximum Pods per node
  • IP-address capacity
  • Workload density
  • Blast radius
  • Resource overcommitment

High workload density can increase the impact of a node failure or compromise.

Task 65 — Review Node Labels for Trust Decisions

Section titled “Task 65 — Review Node Labels for Trust Decisions”

Identify labels used for scheduling.

Terminal window
kubectl get nodes \
--show-labels

Assess whether:

  • Security-sensitive labels are centrally managed
  • Developers cannot modify protected node labels
  • Admission policies validate workload selectors
  • Labels identify environment and ownership
  • Labels do not expose unnecessary sensitive information
  • Scheduling decisions do not rely on untrusted labels

Document:

Taint Purpose Workload Class Owner Exception Process

Validate that tolerations are granted only to authorised workloads.

Required tags may include:

  • Environment
  • Owner
  • CostCentre
  • BusinessUnit
  • DataClassification
  • ManagedBy
  • Cluster
  • NodeGroup
  • SecurityBaseline
  • BackupClassification
  • IncidentPriority

Check tags.

Terminal window
aws ec2 describe-instances \
--filters "Name=tag:eks:cluster-name,Values=${CLUSTER_NAME}" \
--query 'Reservations[].Instances[].{InstanceId:InstanceId,Tags:Tags}' \
--output json

For custom node images, confirm:

  • Source image is approved
  • Build pipeline is controlled
  • Build logs are retained
  • Vulnerability scanning is completed
  • Malware scanning is completed
  • Image is signed where supported
  • Software inventory is retained
  • Unnecessary packages are removed
  • Credentials are absent
  • Image expiration is defined
  • Rebuild schedule exists

Task 69 — Review Node Bootstrap Governance

Section titled “Task 69 — Review Node Bootstrap Governance”

Assess node bootstrap configuration for:

  • Cluster endpoint
  • Cluster certificate authority
  • Kubelet arguments
  • Node labels
  • Node taints
  • DNS configuration
  • Reserved resources
  • Maximum Pods
  • Log configuration
  • No embedded credentials

User data must not contain long-lived secrets or private keys.

Task 70 — Perform the Worker-Node Security Assessment

Section titled “Task 70 — Perform the Worker-Node Security Assessment”

Complete the assessment matrix.

Security Domain Expected Control Status
Node IAM role Least privilege
Application identity Separate from node role
Trust policy EC2 only
Metadata service Token required
Root storage Encrypted
KMS key Approved and governed
Subnets Private
Public IP Disabled
Security groups Restricted
SSH Disabled or tightly governed
Systems Manager Controlled and logged
Operating system Supported
Node AMI Approved
Kubelet Hardened
Container runtime Supported and protected
Node labels Governed
Node taints Applied
Workload isolation Implemented
Patch management Documented
Managed node update Controlled
Pod disruption Protected
CloudWatch monitoring Enabled
GuardDuty monitoring Enabled
CloudTrail logging Enabled
AWS Config Enabled
Incident isolation Documented and tested
Autoscaling Least privilege and governed
Resource reservations Reviewed
Tags Complete

Rate each control as:

  • Effective
  • Partially Effective
  • Ineffective
  • Not Applicable
  • Not Verified

Create reports/findings-register.md.

Finding ID Finding Severity Resource Owner Due Date Status
EKS-NODE-001 Open

Use the following template:

Finding ID:
Title:
Affected Cluster:
Affected Node Group:
Affected Instances:
Security Domain:
Description:
Evidence:
Business Impact:
Security Impact:
Likelihood:
Severity:
Root Cause:
Recommended Remediation:
Compensating Controls:
Owner:
Due Date:
Validation Method:
Status:

Examples:

  • Worker nodes have public IP addresses and unrestricted administrative access
  • Node role has administrator permissions
  • Nodes contain long-lived AWS access keys
  • Unauthorised workloads can access the container-runtime socket
  • Root volumes containing sensitive data are unencrypted
  • Compromised nodes cannot be isolated
  • Node credentials are shared
  • Unsupported nodes contain known exploitable vulnerabilities

Examples:

  • Legacy instance metadata access is permitted
  • Node IAM role includes application permissions
  • Security groups allow excessive inbound access
  • SSH is open to broad networks
  • Nodes are not patched within the required SLA
  • Sensitive workloads share general-purpose nodes
  • Runtime monitoring is unavailable
  • Custom node AMIs are not governed
  • Nodes operate in public subnets

Examples:

  • Missing node labels
  • Missing taints
  • Incomplete CloudWatch alarms
  • Systems Manager sessions are not centrally logged
  • Node-group update settings are weak
  • Resource reservations are incomplete
  • Tags are inconsistent
  • Autoscaling permissions are broader than required

Examples:

  • Minor tag-format issue
  • Missing documentation
  • Inconsistent naming
  • Non-critical monitoring improvement
  • Evidence-file naming issue

Create reports/risk-register.md.

Risk ID Risk Severity Likelihood Impact Owner Treatment
EKS-NODE-RISK-001 Node role contains excessive AWS permissions High Medium High Remediate
EKS-NODE-RISK-002 Instance metadata tokens are not required High Medium High Remediate
EKS-NODE-RISK-003 Sensitive workloads share standard nodes Medium Medium Medium Reduce
EKS-NODE-RISK-004 Node patching evidence is incomplete Medium High Medium Remediate

Create reports/remediation-plan.md.

  • Remove administrative permissions from node roles.
  • Revoke exposed or embedded AWS credentials.
  • Restrict public SSH access.
  • Isolate compromised or untrusted nodes.
  • Encrypt unencrypted node volumes.
  • Prevent unauthorised runtime-socket access.
  • Remove nodes with unsupported critical vulnerabilities.
  • Restore runtime-monitoring coverage.
  • Require secure instance metadata tokens.
  • Move nodes to private subnets.
  • Restrict node security groups.
  • Implement Systems Manager administration.
  • Separate application permissions from node roles.
  • Create dedicated sensitive-workload node groups.
  • Implement node labels and taints.
  • Update node AMIs.
  • Configure node alerts.
  • Automate node-image validation.
  • Implement regular managed node-group replacement.
  • Standardise launch templates.
  • Automate configuration-compliance checks.
  • Improve node-drain testing.
  • Integrate runtime findings with the SIEM.
  • Standardise node tagging.
  • Improve autoscaling governance.
  • Establish enterprise node-image pipelines.
  • Implement continuous worker-node compliance.
  • Automate insecure-node isolation.
  • Create multi-cluster node-security dashboards.
  • Integrate node risks with GRC systems.
  • Implement automated node lifecycle governance.
  • Conduct regular worker-node incident simulations.

Collect:

  • AWS identity
  • Cluster details
  • Node-group inventory
  • Node IAM role
  • Attached IAM policies
  • Launch-template configuration
  • Instance metadata settings
  • EBS encryption details
  • KMS key details
  • Node security groups
  • Private subnet evidence
  • Node labels
  • Node taints
  • Node AMI details
  • Kubelet configuration
  • Container-runtime configuration
  • Systems Manager registration
  • CloudWatch monitoring
  • GuardDuty status
  • AWS Config status
  • CloudTrail events
  • Drain test
  • Incident-isolation plan
  • Findings register
  • Risk register
  • Remediation plan

Suggested evidence filenames:

01-aws-identity.json
02-cluster-details.json
03-nodegroups.json
04-nodes.yaml
05-node-role.json
06-node-role-policies.json
07-launch-template.json
08-instance-metadata.json
09-volumes.json
10-kms-key.json
11-security-groups.json
12-private-subnets.json
13-node-labels.txt
14-node-taints.txt
15-node-ami.json
16-kubelet-review.md
17-runtime-review.md
18-ssm-registration.json
19-cloudwatch-status.txt
20-guardduty-status.json
21-aws-config-status.json
22-cloudtrail-events.json
23-drain-test.md
24-incident-isolation-plan.md
25-findings-register.md
26-risk-register.md
27-remediation-plan.md
28-worker-node-security-report.md

Generate hashes for key evidence.

Terminal window
sha256sum evidence/* \
> evidence/evidence-hashes.txt
Terminal window
Get-ChildItem evidence -File |
Get-FileHash -Algorithm SHA256 |
Format-Table |
Out-File evidence\evidence-hashes.txt

Confirm:

  • Files are time stamped
  • Evidence is attributable
  • Storage is access controlled
  • Sensitive values are removed
  • Hashes are retained
  • Evidence cannot be casually modified

Task 77 — Create the Worker-Node Security Report

Section titled “Task 77 — Create the Worker-Node Security Report”

Create reports/worker-node-security-report.md.

Assessment Title:
Amazon EKS Worker-Node Security Assessment
Assessment ID:
Assessment Date:
Assessor:
Organisation:
AWS Account:
AWS Region:
Cluster Name:
Node Groups Reviewed:
Worker Nodes Reviewed:
Kubernetes Version:
AMI Types:
Node IAM Roles:
Launch Templates:
Private Subnet Status:
Public IP Status:
Instance Metadata Status:
Root-Volume Encryption Status:
KMS Key:
SSH Access Status:
Systems Manager Status:
Node Security-Group Status:
Node Operating-System Status:
Kubelet Security Status:
Container-Runtime Status:
Node Label Governance:
Node Taint Governance:
Sensitive-Workload Isolation:
Patch-Management Status:
Node-Group Update Status:
Drain-Test Result:
CloudWatch Monitoring Status:
GuardDuty Runtime Status:
AWS Config Status:
CloudTrail Status:
Critical Findings:
High Findings:
Medium Findings:
Low Findings:
Immediate Remediation:
Short-Term Remediation:
Medium-Term Remediation:
Residual Risk:
Overall Node Security Status:
Approved
Conditionally Approved
Rejected
Production Recommendation:
Reassessment Date:
Approvals:
Cloud Security Engineer:
Kubernetes Security Engineer:
Platform Engineering:
DevSecOps:
SOC:
Risk Owner:
Terminal window
kubectl delete \
-f manifests/secure-workload.yaml \
--ignore-not-found
Terminal window
kubectl delete \
-f manifests/sensitive-workload.yaml \
--ignore-not-found
Terminal window
kubectl delete \
-f manifests/pod-disruption-budget.yaml \
--ignore-not-found

Task 79 — Decide Whether to Retain the Node Group

Section titled “Task 79 — Decide Whether to Retain the Node Group”

Retain the node group only when:

  • It is authorised for continued use
  • Costs are approved
  • Security review is complete
  • Ownership is assigned
  • Monitoring is enabled
  • Patch management is defined
  • Cleanup is not required by the training plan

Otherwise, delete it.

Terminal window
eksctl delete nodegroup \
--cluster "${CLUSTER_NAME}" \
--region "${AWS_REGION}" \
--name "${NODEGROUP_NAME}"

After deleting the node group, review and remove unused:

  • Launch templates
  • Launch-template versions
  • IAM roles
  • Attached policies
  • KMS aliases
  • KMS keys
  • Security groups
  • CloudWatch log groups
  • Alarms
  • Test manifests
  • Temporary evidence containing sensitive data

Do not schedule KMS-key deletion until all encrypted dependencies have been confirmed and formal approval has been obtained.

Control Status
Assessment workspace created
AWS identity verified
Cluster access validated
Node groups inventoried
Kubernetes nodes inventoried
Nodes mapped to EC2 instances
Node IAM roles reviewed
Dedicated node role created
Node-role trust policy validated
Least-privilege policies attached
Application permissions removed from node role
KMS key created and governed
Secure launch template created
Instance metadata tokens required
Metadata hop limit reviewed
Root EBS volume encrypted
SSH access restricted
Systems Manager configured
Private subnets validated
Public IP addresses absent
VPC endpoints reviewed
Cluster security group reviewed
Node security groups reviewed
Managed node group deployed
Node labels validated
Node taints validated
Workload scheduling tested
Sensitive workload isolation reviewed
Operating-system version reviewed
Node AMI reviewed
Kubelet security reviewed
Container runtime reviewed
DaemonSets reviewed
Instance metadata configuration validated
EBS encryption validated
Systems Manager registration validated
Session governance reviewed
Patch process documented
Node-group update configuration reviewed
PodDisruptionBudget created
Node cordon tested
Node drain tested
Node returned to service
Incident-isolation plan documented
Credential exposure assessed
Workload identity separation reviewed
CloudWatch monitoring enabled
Node conditions reviewed
Node alerts defined
GuardDuty Runtime Monitoring reviewed
GuardDuty findings reviewed
CloudTrail events reviewed
AWS Config coverage reviewed
Autoscaling security reviewed
Capacity-type risk reviewed
Resource reservations reviewed
Pod density reviewed
Label governance reviewed
Taint governance reviewed
Tagging reviewed
Node image governance reviewed
Bootstrap governance reviewed
Findings register completed
Risk register completed
Remediation plan completed
Evidence collected
Evidence integrity validated
Final report completed
Cleanup completed

By completing this lab, you will be able to:

  • Assess Amazon EKS worker-node architecture
  • Design least-privilege node IAM roles
  • Create secure EC2 launch templates
  • Protect EC2 instance metadata
  • Encrypt node storage with AWS KMS
  • Deploy worker nodes in private subnets
  • Restrict worker-node security groups
  • Replace SSH with controlled Systems Manager access
  • Apply Kubernetes node labels and taints
  • Isolate sensitive workloads
  • Review EKS-optimised node images
  • Assess kubelet security
  • Assess container-runtime security
  • Implement node patch and replacement processes
  • Configure node monitoring and detection
  • Test node cordon and drain operations
  • Design compromised-node isolation procedures
  • Review autoscaling security
  • Produce enterprise worker-node security evidence
  • Create remediation and risk reports

Why should Amazon EKS worker nodes use a dedicated IAM role?

Answer: A dedicated role limits node permissions to the infrastructure actions required by the node and prevents unrelated application permissions from being shared across all workloads.

Why should application Pods avoid using the EC2 node role?

Answer: Every Pod on the node may otherwise gain access to the same AWS permissions, increasing credential exposure and violating least privilege.

Why should modern EC2 instance metadata tokens be required?

Answer: Token-based metadata access reduces the risk of unauthorised metadata requests and helps protect temporary instance credentials.

Why should worker nodes be deployed in private subnets?

Answer: Private subnets reduce direct internet exposure and allow node access to be controlled through approved network paths, NAT, VPC endpoints, and management services.

Why is Systems Manager preferred over open SSH access?

Answer: Systems Manager can provide identity-based, logged, and controlled administrative sessions without exposing an inbound SSH service or distributing private keys.

What is the purpose of Kubernetes node taints?

Answer: Taints prevent workloads from scheduling onto selected nodes unless the workload has an approved matching toleration.

How do node labels support workload isolation?

Answer: Labels allow workloads to select approved node groups based on trust level, data classification, hardware requirements, or security zone.

Why should node patching generally use controlled node replacement?

Answer: Replacement provides a repeatable way to deploy an approved image, reduces configuration drift, and avoids relying on uncontrolled manual changes to long-running nodes.

Why must node-drain procedures be tested?

Answer: Drain testing confirms workloads can move safely during patching, incident response, scaling, or node replacement without unacceptable service disruption.

What should happen when a worker node is suspected of compromise?

Answer: The node should be identified, cordoned, investigated, safely drained where appropriate, isolated, replaced, and reviewed for credential, workload, image, and network exposure.

In this lab, you secured the Amazon EKS worker-node layer.

You implemented and assessed:

  • Node IAM roles
  • Least-privilege permissions
  • Secure role trust
  • EC2 launch templates
  • Instance metadata protection
  • Encrypted Amazon EBS storage
  • AWS KMS governance
  • Private subnet deployment
  • Restricted security groups
  • Systems Manager access
  • Managed node groups
  • Node labels
  • Node taints
  • Sensitive-workload isolation
  • Operating-system security
  • Node-image governance
  • Kubelet security
  • Container-runtime security
  • Patch management
  • Node-group updates
  • Pod disruption controls
  • Node cordon and drain
  • Compromised-node isolation
  • CloudWatch monitoring
  • GuardDuty Runtime Monitoring
  • CloudTrail auditing
  • AWS Config compliance
  • Autoscaling security
  • Evidence and reporting

Amazon EKS worker nodes process application workloads, hold temporary credentials, run the container runtime, connect to the Kubernetes control plane, and provide access to application data.

A compromised or poorly governed worker node can therefore affect:

  • Multiple Pods
  • AWS identities
  • Kubernetes credentials
  • Network communication
  • Persistent data
  • Runtime security
  • Cluster availability
  • Compliance evidence

Secure worker nodes require more than patched operating systems.

They require:

  • Strong identity controls
  • Private networking
  • Encrypted storage
  • Secure metadata access
  • Controlled administration
  • Workload isolation
  • Runtime monitoring
  • Repeatable replacement
  • Incident readiness
  • Enterprise governance

Next Lab: Lab 03 — Secure Amazon EKS Networking

In the next lab, you will secure Amazon EKS networking by reviewing VPC architecture, private subnets, cluster endpoint access, security groups, network ACLs, Amazon VPC CNI controls, Kubernetes NetworkPolicies, ingress security, egress governance, load balancers, DNS security, VPC Flow Logs, and Zero Trust network segmentation.